Skip to content

Commit

Permalink
Use single backticks for inline code blocks.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kangz authored Aug 25, 2017
1 parent caba864 commit 68a1b6f
Showing 1 changed file with 42 additions and 42 deletions.
84 changes: 42 additions & 42 deletions design/Pipelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ For example this document uses C structures when a C++ API might want to use bui
## Creating pipeline objects

For type safety, compute and graphics pipeline are separate types.
To create a pipeline, a structure containing all the relevant information is passed to ```DeviceCreate<TYPE>Pipeline```.
To create a pipeline, a structure containing all the relevant information is passed to `DeviceCreate<TYPE>Pipeline`.

## Compute pipeline creation

To create a compute pipeline the only things needed are some shader code present in a ```ShaderModule``` object, and a ```PipelineLayout``` object describing how the pipeline interacts with the binding model.
To create a compute pipeline the only things needed are some shader code present in a `ShaderModule` object, and a `PipelineLayout` object describing how the pipeline interacts with the binding model.

```cpp
struct ComputePipelineDescriptor {
Expand All @@ -24,27 +24,27 @@ ComputePipeline CreateComputePipeline(Device device, const ComputePipelineDescri
```
Translation to the backing APIs would be the following:
- **D3D12**: Translates to ```ID3D12::CreateComputePipelineState```, a ```D3D12_SHADER_BYTECODE``` is created from the ```(module, entryPoint)``` pair, and the ```ID3D12RootSignature``` is equivalent to the ```PipelineLayout```.
- **Metal**: Translates to ```MTLDevice::makeComputePipelineState```, the ```MTLFunction``` is created from the ```(module, entryPoint, layout)``` tuple by adapting the generated MSL to the resource slot allocation done in ```layout```.
- **Vulkan**: Translates to ```vkCreateComputePipelines``` with one pipeline. The ```vkShaderStageInfo``` corresponds to ```(module, entryPoint)``` and the ```vkPipelineLayout``` corresponds to ```layout```.
- **D3D12**: Translates to `ID3D12::CreateComputePipelineState`, a `D3D12_SHADER_BYTECODE` is created from the `(module, entryPoint)` pair, and the `ID3D12RootSignature` is equivalent to the `PipelineLayout`.
- **Metal**: Translates to `MTLDevice::makeComputePipelineState`, the `MTLFunction` is created from the `(module, entryPoint, layout)` tuple by adapting the generated MSL to the resource slot allocation done in `layout`.
- **Vulkan**: Translates to `vkCreateComputePipelines` with one pipeline. The `vkShaderStageInfo` corresponds to `(module, entryPoint)` and the `vkPipelineLayout` corresponds to `layout`.
Open questions:
How do we take advantage of the pipeline caching present in D3D12 and Vulkan?
Do we expose it to the application or is it done magically in the WebGPU implementation?
## Render pipeline creation
Render pipelines need ```ShaderModule``` and a ```PipelineLayout``` like compute pipelines and in addition require information about:
Render pipelines need `ShaderModule` and a `PipelineLayout` like compute pipelines and in addition require information about:
- Layout for vertex inputs
- Layout for fragment outputs
- All the fixed-function state
For simplicity we assume most fixed-function state is created in separate object.
For example a ```DepthStencilState``` object would be allocated and a pointer to it would be stored in the ```RenderPipelineDescriptor```. This is part of the UX of the API and could be replaced with chained structure like Vulkan or member structure like D3D12.
For example a `DepthStencilState` object would be allocated and a pointer to it would be stored in the `RenderPipelineDescriptor`. This is part of the UX of the API and could be replaced with chained structure like Vulkan or member structure like D3D12.
Mismatch:
- Metal has primitive restart always enabled.
- D3D12 needs to know whether the primitive restart index is ```0xFFFF``` or ```0xFFFFFFFF``` at pipeline creation time.
- D3D12 needs to know whether the primitive restart index is `0xFFFF` or `0xFFFFFFFF` at pipeline creation time.
- Metal doesn’t have a sample mask.
- Vulkan can have some state like scissor and viewport set on the pipeline as an optimization on some GPUs.
- Vulkan allows creating pipelines in bulk, this is not only a UX things but allows reusing some results for faster creation.
Expand Down Expand Up @@ -75,11 +75,11 @@ RenderPipeline CreateRenderPipeline(Device device, const RenderPipelineDescripto
```

Translation to the backing APIs would be the following:
- **D3D12**: Translates to ```ID3D12::CreateGraphicsPipelineState```. ```IBStripCutValue``` will always be set.
- **Metal**: Translates to ```MTLDevice::makeRenderPipelineState```
- **Vulkan**: Translates to ```vkCreateGraphicsPipelines```. ```VkPipelineInputAssemblyStateCreateInfo```'s ```primitiveRestartEnable``` is always set to true. All dynamic states are set on all pipelines.
- **D3D12**: Translates to `ID3D12::CreateGraphicsPipelineState`. `IBStripCutValue` will always be set.
- **Metal**: Translates to `MTLDevice::makeRenderPipelineState`
- **Vulkan**: Translates to `vkCreateGraphicsPipelines`. `VkPipelineInputAssemblyStateCreateInfo`'s `primitiveRestartEnable` is always set to true. All dynamic states are set on all pipelines.

Open question: should the type of the indices be set in ```RenderPipelineDescriptor```? If not, how is the D3D12 ```IBStripCutValue``` chosen?
Open question: should the type of the indices be set in `RenderPipelineDescriptor`? If not, how is the D3D12 `IBStripCutValue` chosen?

The translation of individual members of RenderPipelineDescriptor is described below.

Expand All @@ -88,7 +88,7 @@ The translation of individual members of RenderPipelineDescriptor is described b
This describes how the vertex buffers are stepped through (stride, instance vs. vertex, instance divisor), and how the attributes are extracted from the buffers (buffer index, format, offset).

Mismatches:
- D3D12 takes the stride along with the vertex buffers in ```ID3D12GraphicsCommandList::IASetVertexBuffers``` whereas Vulkan and Metal take it at pipeline compilation time.
- D3D12 takes the stride along with the vertex buffers in `ID3D12GraphicsCommandList::IASetVertexBuffers` whereas Vulkan and Metal take it at pipeline compilation time.
- Vulkan doesn’t support a divisor for its step rate.

```cpp
Expand Down Expand Up @@ -119,35 +119,35 @@ InputState* CreateInputState(Device* device, InputStateDescriptor* descriptor);
```
Translation to the backing APIs would be the following:
- **D3D12**: Translates to a ```D3D12_INPUT_DESC```.
Each enabled attribute corresponds to a ```D3D12_INPUT_ELEMENT_DESC``` with ```InputSlot``` being the index of the attribute.
Other members of the ```D3D12_INPUT_ELEMENT_DESC``` are translated trivially.
The stride is looked up in the pipeline state before calls to ```ID3D12GraphicsCommandList::IASetVertexBuffers```.
```IASetVertexBuffers``` might be deferred until before a draw and vertex buffers might be invalidated by pipeline changes.
- **Metal**: Translates to a ```MTLVertexDescriptor```, with attributes corresponding to ```MTLVertexDescriptor::attributes``` and buffers corresponding to ```MTLVertexDescriptor::layouts```.
Attributes translate trivially to ```MTLVertexAttributeDescriptor``` structures and buffers to ```MTLVertexBufferLayoutDescriptor``` structures.
- **D3D12**: Translates to a `D3D12_INPUT_DESC`.
Each enabled attribute corresponds to a `D3D12_INPUT_ELEMENT_DESC` with `InputSlot` being the index of the attribute.
Other members of the `D3D12_INPUT_ELEMENT_DESC` are translated trivially.
The stride is looked up in the pipeline state before calls to `ID3D12GraphicsCommandList::IASetVertexBuffers`.
`IASetVertexBuffers` might be deferred until before a draw and vertex buffers might be invalidated by pipeline changes.
- **Metal**: Translates to a `MTLVertexDescriptor`, with attributes corresponding to `MTLVertexDescriptor::attributes` and buffers corresponding to `MTLVertexDescriptor::layouts`.
Attributes translate trivially to `MTLVertexAttributeDescriptor` structures and buffers to `MTLVertexBufferLayoutDescriptor` structures.
Extra care only needs to be taken to translate a zero stride to a constant step rate.
- **Vulkan**: Translates to a ```VkPipelineVertexInputStateCreateInfo```.
Buffers translate trivially to ```VkVertexInputBindingDescription``` and attributes to ```VkVertexInputAttributeDescription```.
- **Vulkan**: Translates to a `VkPipelineVertexInputStateCreateInfo`.
Buffers translate trivially to `VkVertexInputBindingDescription` and attributes to `VkVertexInputAttributeDescription`.
Open questions:
Should the vertex attributes somehow be included in the ```PipelineLayout``` so vertex buffers are treated as other resources and changed in bulk with them?
Should the vertex attributes somehow be included in the `PipelineLayout` so vertex buffers are treated as other resources and changed in bulk with them?
### Render pass / render target format
The ```RenderPass``` will contain for each subpass a list of the attachment formats for color attachments and depth-stencil attachments.
Information from the ```RenderPass``` is used to fill the following:
- **D3D12**: ```RTVFormats```, ```DSVFormats``` and ```NumRenderTargets``` in ```D3D12_GRAPHICS_PIPELINE_STATE_DESC```.
- **Metal**: ```colorAttachments[N].pixelFormat```, ```depthAttachmentPixelFormat``` and ```stencilAttachmentPixelFormat``` in ```MTLRenderPipelineDescriptor```.
- **Vulkan**: ```renderPass``` and ```subpass``` in ```VkGraphicsPipelineCreateInfo```.
The `RenderPass` will contain for each subpass a list of the attachment formats for color attachments and depth-stencil attachments.
Information from the `RenderPass` is used to fill the following:
- **D3D12**: `RTVFormats`, `DSVFormats` and `NumRenderTargets` in `D3D12_GRAPHICS_PIPELINE_STATE_DESC`.
- **Metal**: `colorAttachments[N].pixelFormat`, `depthAttachmentPixelFormat` and `stencilAttachmentPixelFormat` in `MTLRenderPipelineDescriptor`.
- **Vulkan**: `renderPass` and `subpass` in `VkGraphicsPipelineCreateInfo`.
Open question:
does the sample count of the pipeline state come from the RenderPass too?
### Primitive topology
Mismatch:
- Metal and D3D12 only require “point vs. line vs. triangle” at pipeline compilation time, the exact topology is set via ```ID3D12GraphicsCommandList::IASetPrimitiveTopology``` or passed in the ```MTLRenderCommandEncoder::draw*```.
- Metal and D3D12 only require “point vs. line vs. triangle” at pipeline compilation time, the exact topology is set via `ID3D12GraphicsCommandList::IASetPrimitiveTopology` or passed in the `MTLRenderCommandEncoder::draw*`.
Vulkan requires the exact topology at compilation time.
- Vulkan supports triangle fans but Metal and D3D12 don’t.
Expand All @@ -162,15 +162,15 @@ enum PrimitiveTopology {
```

Translation to the backing APIs would be the following:
- **D3D12 and Metal**: The primitive topology type is set on the ```D3D12_GRAPHICS_PIPELINE_STATE_DESC``` and ```MTLRenderPipelineDescriptor```.
- **D3D12 and Metal**: The primitive topology type is set on the `D3D12_GRAPHICS_PIPELINE_STATE_DESC` and `MTLRenderPipelineDescriptor`.
At draw-time, the exact topology is queried from the pipeline.
- **Vulkan**: The primitive topology type is set in the ```VkGraphicsPipelineCreateInfo```.
- **Vulkan**: The primitive topology type is set in the `VkGraphicsPipelineCreateInfo`.

### Blend state

Mismatch:
- In Vulkan per-attachment blending and dual source blending are exposed as optional features.
```independentBlend``` is supported almost everywhere but Adreno 4XX while ```dualSrcBlend``` is also not supported on Mali GPUs.
`independentBlend` is supported almost everywhere but Adreno 4XX while `dualSrcBlend` is also not supported on Mali GPUs.
- Metal doesn’t have logic ops.

```cpp
Expand Down Expand Up @@ -212,11 +212,11 @@ BlendState* CreateBlendState(Device* device, BlendStateDescriptor* descriptor);
```
Translation to backing APIs would be the following:
- **D3D12**: when filling the ```D3D12_GRAPHICS_PIPELINE_DESC```, ```BlendState``` will be filled with data coming from the ```BlendStates``` referenced in the ```RenderPipelineDescriptor```.
Translation from a ```BlendState``` to a ```D3D12_RENDER_TARGET_BLEND_DESC``` is trivial.
- **Metal**: the ```BlendStates``` will be used to fill all of the data for a ```MTLRenderPipelineColorAttachmentDescriptor``` but ```pixelFormat```.
- **D3D12**: when filling the `D3D12_GRAPHICS_PIPELINE_DESC`, `BlendState` will be filled with data coming from the `BlendStates` referenced in the `RenderPipelineDescriptor`.
Translation from a `BlendState` to a `D3D12_RENDER_TARGET_BLEND_DESC` is trivial.
- **Metal**: the `BlendStates` will be used to fill all of the data for a `MTLRenderPipelineColorAttachmentDescriptor` but `pixelFormat`.
Translation of individual members is trivial.
- **Vulkan**: the ```BlendStates``` will be translated to elements of ```pAttachments``` in the ```VkPipelineColorBlendStateCreateInfo```.
- **Vulkan**: the `BlendStates` will be translated to elements of `pAttachments` in the `VkPipelineColorBlendStateCreateInfo`.
Translation of individual members is trivial.
Open question:
Expand Down Expand Up @@ -270,13 +270,13 @@ DepthStencilState* CreateDepthStencilState(Device* device, DepthStencilDescripto
```

Translation to backing APIs would be the following:
- **D3D12**: ```DepthStencilState``` translates trivially to a ```D3D12_DEPTH_STENCIL_DESC```.
```DepthEnable``` would be set as ```depthCompare != Always```.
- **Metal**: ```DepthStencilState``` translates trivially to ```MTLDepthStencilDescriptor``` except that front and back stencil masks have to be set to the single stencil mask value from WebGPU.
- **D3D12**: `DepthStencilState` translates trivially to a `D3D12_DEPTH_STENCIL_DESC`.
`DepthEnable` would be set as `depthCompare != Always`.
- **Metal**: `DepthStencilState` translates trivially to `MTLDepthStencilDescriptor` except that front and back stencil masks have to be set to the single stencil mask value from WebGPU.
When a pipeline is bound, the corresponding depth-stencil state is bound at the same time.
- **Vulkan**: ```DepthStencilState``` translates trivially to ```VkPipelineDepthStencilStateCreateInfoxcept``` except that front and back stencil masks have to be set to the single stencil mask value from WebGPU.
```depthTestEnable``` would be set to ```depthCompare != Always```.
- **Vulkan**: `DepthStencilState` translates trivially to `VkPipelineDepthStencilStateCreateInfoxcept` except that front and back stencil masks have to be set to the single stencil mask value from WebGPU.
`depthTestEnable` would be set to `depthCompare != Always`.

Open question:
what about Vulkan’s ```VkPipelineDepthStencilStateCreateInfo::depthBoundTestEnable``` and D3D12's ```D3D12_DEPTH_STENCIL_DESC1::DepthBoundsTestEnable```?
what about Vulkan’s `VkPipelineDepthStencilStateCreateInfo::depthBoundTestEnable` and D3D12's `D3D12_DEPTH_STENCIL_DESC1::DepthBoundsTestEnable`?
Should “depth test enable” be implicit or explicit?

0 comments on commit 68a1b6f

Please sign in to comment.