Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Pipeline states investigation #26

@kvark

Description

@kvark

This document attempts to describe the differences between pipeline states in the current generation of graphics APIs. It also touches some adjacent features like stencil reference values and blend factors. The investigation uses materials from https://github.com/jdashg/vulkan-portability/blob/master/pipeline-state.md.

Information

The concept of a pipeline state is similar between Vulkan/D3D12/Metal. A graphics PSO (short for Pipeline State Object) is an opaque object encapsulating the following information:

  • shaders for active stages
  • primitive topology, vertex input layout, tessellation
  • rasterizer, blend, depth/stencil states, multi-sampling
  • render targets descriptions

Graphics and compute pipelines are represented with separate types and constructed from different states. We'll focus on the graphics one, considering the compute to use a subset of graphics states.

Differences between APIs are mostly laid out within the specification of render targets and the range of supported states within particular stages.

Vulkan

vkCreateGraphicsPipelineStates creates multiple pipeline states at once, each from a separate VkGraphicsPipelineCreateInfo struct. Users can provide a pipeline cache object in order to re-use internal parts (opaque to the user) between pipelines.

Instead of specifying the formats of render targets, the pipeline state is created for a specific sub-pass of a render pass. A pipeline can then be used with any compatible render pass, according to the rules.

Vulkan allows certain states to be either baked into PSO or set independently during command encoding:

typedef enum VkDynamicState {
    VK_DYNAMIC_STATE_VIEWPORT = 0,
    VK_DYNAMIC_STATE_SCISSOR = 1,
    VK_DYNAMIC_STATE_LINE_WIDTH = 2,
    VK_DYNAMIC_STATE_DEPTH_BIAS = 3,
    VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4,
    VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5,
    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
    VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
} VkDynamicState;

Vulkan multi-sampling state allows not only forcing sample shading on/off but also specifying the ratio of uniquely shaded samples. This is gated by sampleRateShading feature of the device. Similarly, independent blending is supported behind the independentBlend feature.

VkVertexInputRate does not seem to support instance rate values higher than 1, although it seems trivial to extend the range of accepted values for this type.

Direct3D 12

CreateGraphicsPipelineState creates a graphics PSO described by the D3D12_GRAPHICS_PIPELINE_STATE_DESC structure.

Color and depth render targets are described by their format.

The user can pass a cache blob of another PSO in order to re-use the internal compiled parts.

For multi-sampling, D3D12 exposes the DXGI_SAMPLE_DESC::Quality value, the semantics of which is rather opaque but the exposed capabilities are similar to Vulkan's minSampleShading. Comparing to Vulkan, various parts of multi-sampling state are spread over the rasterization state, blending, sample descriptors, and plain values in the PSO descriptor.

Limitations compared to Vulkan:

  • no VK_CULL_MODE_FRONT_AND_BACK
  • no VK_POLYGON_MODE_POINT
  • no VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
  • only integer constant depth bias
  • no separate stencil read/write masks and reference value
  • no configurable sample shading
  • 32bit sample mask

Extra features compared to Vulkan:

  • InstanceDataStepRate allows an advance of vertex attribute per N instances
  • conservative rasterization

Metal

A graphics PSO is created via makeRenderPipelineState from MTLRenderPipelineDescriptor.

There is no notion of pipeline cache as well as pipeline layout (aka root signature).

States that are surprisingly out of PSO:

  • depth bias
  • cull mode
  • triangle fill mode
  • depth/stencil

Limitations compared to Vulkan:

  • no VK_CULL_MODE_FRONT_AND_BACK
  • no VK_POLYGON_MODE_POINT
  • no VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
  • no variable shading
  • no sample mask (interesting, why?)
  • no depth bounds

Extra features compared to Vulkan:

  • MTLVertexBufferLayoutDescriptor::stepRate allows to configure the rate of an instanced attribute

Analysis

In both Vulkan and D3D12 there is a separate object describing resource binding layout and push/root constants, called VkPipelineLayout and ID3D12RootSignature correspondingly. It makes sense to have it in GPUWeb as well (related to #19).

Vulkan dynamic states are useful in order to match the PSO-baked states with D3D12 and Metal. Thus, we consider all of the dynamic states to be used at all times by the Vulkan backend of GPUWeb.

In terms of pipeline states, it seems reasonable to use the intersection of capabilities between the APIs, which happens to match D3D12 except for:

  • instance rate, which we can limit to 1 for the MVP and revise later
  • sample mask

I find it rather unfortunate if we had to drop support for the sample mask, thus perhaps we could patch the shader code in order to apply the mask in the shader specifically for Metal and support it uniformly.

The question of whether render target formats are needed in the PSO depends on #23. If render sub-passes are accepted, I believe following Vulkan model (of providing the pass and sub-pass index) is straightforward.

TODO:

  • tessellation
  • format of vertex data and color/depth/stencil targets

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions