19 EffectPipelineStateDescription
Chuck Walbourn редактировал(а) эту страницу 2022-09-15 11:51:56 -07:00
DirectXTK

When creating Pipeline State Objects (PSO), DirectX 12 requires the input layout, blend state, depth/stencil state, rasterizer state, and primitive topology along with the RenderTargetState that will be used for rendering. This information is wrapped up by this helper structure which is used by Effects or can be used directly providing your own shaders.

Related tutorial: Simple rendering, 3D shapes

Header

#include "EffectPipelineStateDescription.h"

Initialization

Typically used during resource creation such as the following, typically used with values from CommonStates:

RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(),
    m_deviceResources->GetDepthBufferFormat());

EffectPipelineStateDescription pd(
    &InputLayout,
    CommonStates::Opaque,
    CommonStates::DepthDefault,
    CommonStates::CullCounterClockwise,
    rtState);

Usage

The full parameter list is as follows:

EffectPipelineStateDescription(
    const D3D12_INPUT_LAYOUT_DESC* inputLayout,
    const D3D12_BLEND_DESC& blend,
    const D3D12_DEPTH_STENCIL_DESC& depthStencil,
    const D3D12_RASTERIZER_DESC& rasterizer,
    const RenderTargetState& renderTarget,
    D3D12_PRIMITIVE_TOPOLOGY_TYPE primitiveTopology
        = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
    D3D12_INDEX_BUFFER_STRIP_CUT_VALUE stripCutValue
        = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED)

You can set inputLayout to nullptr when the input layout comes from another source (see EffectFactory and Model) or if there's no vertex buffer being bound for rendering.

Creating Pipeline State Objects

While generally used by Effects internally, you can use this public method to create your own PSO based on the state description:

ComPtr<ID3D12PipelineState> pso;

// You provide the required root signature for your shaders
ID3D12RootSignature* rootSignature = ...;

D3D12_SHADER_BYTECODE vertexShader = { ... };
D3D12_SHADER_BYTECODE pixelShader= { ... };

pd.CreatePipelineState(
    device,
    rootSignature,
    vertexShader,
    pixelShader,
    &pso);

Advanced shaders

The helper method only supports providing the Vertex Shader and Pixel Shader stages as these are the most common ones used by the tool kit. If you need to use other stages like the Geometry Shader, Hull Shader, etc. then use can use ID3D12Device::CreateGraphicsPipelineState directly and the GetDesc method to get the basic parameters from the class.

ComPtr<ID3D12PipelineState> pso;

D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = pd.GetDesc();
psoDesc.pRootSignature = rootSignature;
// psoDesc.VS = { ... };
// psoDesc.PS = { ... };
// psoDesc.DS = { ... };
// psoDesc.HS = { ... };
// psoDesc.GS = { ... };
// psoDesc.StreamOutput = { ... };
DX::ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pso));

Compute shaders

For compute shaders, they don't use the data from EffectPipelineStateDescription:

D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.pRootSignature = rootSignature;
psoDesc.CS = { ... };
DX::ThrowIfFailed(device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&pso));

Mesh shaders

For Mesh/Amplifications Shaders (Windows 10 May 2020; Build 19041), you use d3dx12.h helpers to provide all the state. You can use the data from an EffectPipelineStateDescription as follows:

#include "d3dx12.h"

ComPtr<ID3D12PipelineState> pso;

D3DX12_MESH_SHADER_PIPELINE_STATE_DESC meshDesc = {};
meshDesc.pRootSignature = rootSignature;
// meshDesc.AS = { ... };
// meshDesc.MS = { ... };
// meshDesc.PS = { ... };
meshDesc.BlendState = pd.blendDesc;
meshDesc.SampleMask = pd.renderTargetState.sampleMask;
meshDesc.RasterizerState = pd.rasterizerDesc;
meshDesc.DepthStencilState = pd.depthStencilDesc;
meshDesc.IBStripCutValue = pd.stripCutValue;
meshDesc.PrimitiveTopologyType = pd.primitiveTopology;
meshDesc.NumRenderTargets = pd.renderTargetState.numRenderTargets;
memcpy_s(meshDesc.RTVFormats, sizeof(meshDesc.RTVFormats), pd.renderTargetState.rtvFormats, sizeof(DXGI_FORMAT) * D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT);
meshDesc.DSVFormat = pd.renderTargetState.dsvFormat;
meshDesc.SampleDesc = pd.renderTargetState.sampleDesc;
meshDesc.NodeMask = pd.renderTargetState.nodeMask;

D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {};
streamDesc.SizeInBytes = sizeof(meshDesc);
streamDesc.pPipelineStateSubobjectStream = &meshDesc;

DX::ThrowIfFailed(device->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&pso)));

Hash Function

Since the pipeline state description is a large structure, the EffectFactory relies on a hashing function to see if two descriptions are the same.

uint32_t hash = pd.ComputeHash();

This hash is a simple CRC32, and is not cryptographically secure.

Note that the hash currently ignores the input layout.

Threading model

Creation of resources is fully asynchronous, so you can create many PSOs at the same time.

Further reading

PSOs, Shaders, and Signatures

Managing Graphics Pipeline State in Direct3D 12

Root Signatures