News
Happy System Administrator Appreciation Day - to the true heroes of IT!
DF
March 18 2025
Updated August 30 2025

Pipeline State Object (PSO) in DirectX 12 and Vulkan - Optimization Guide

Pipeline State Object (PSO) is a fundamental concept in modern graphics APIs such as DirectX 12 and Vulkan. It represents an object that stores the state of the graphics pipeline and helps accelerate rendering by minimizing state change costs.

In this article, we will explore what PSO is, how it works, its benefits, and how to use it properly.

What is a Pipeline State Object?

In traditional graphics APIs like DirectX 11 and OpenGL, rendering states were set using multiple individual calls—for shaders, blending, rasterization, and other parameters. This approach introduced significant overhead for state changes.

PSO consolidates all these parameters into a single object that can be pre-created and quickly switched during rendering. This reduces overhead and improves performance.

Components of PSO

Depending on the API, a Pipeline State Object includes:

  • Shader programs (vertex, pixel, geometry, compute, etc.).
  • Vertex data formats (Vertex Input Layout).
  • Rasterization settings (depth, fill mode, culling, etc.).
  • Blending settings (color blending modes).
  • Depth and stencil testing settings.
  • Primitive topology type (such as points, lines, or triangles).
  • Formats for render targets and depth buffers.

Benefits of Using PSO

1. Improved Performance

Since PSOs are created in advance, they minimize state changes and reduce CPU overhead.

2. Optimized for Modern Hardware

Unlike older APIs where frequent state changes could slow down the GPU, PSOs allow the graphics processor to work more efficiently by having all states predefined.

3. Simplified State Management

Instead of multiple state-setting calls, we simply switch between predefined PSOs, making the code cleaner and more readable.

Using PSO in DirectX 12

1. Creating a Pipeline State Object

Example of creating a graphics PSO in DirectX 12:

D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.VS = { compiledVertexShader->GetBufferPointer(), compiledVertexShader->GetBufferSize() };
psoDesc.PS = { compiledPixelShader->GetBufferPointer(), compiledPixelShader->GetBufferSize() };
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
psoDesc.InputLayout = { inputLayout, _countof(inputLayout) };
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
psoDesc.SampleDesc.Count = 1;
psoDesc.SampleMask = UINT_MAX;
psoDesc.pRootSignature = rootSignature.Get();

ComPtr<ID3D12PipelineState> pipelineState;
device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState));

2. Applying PSO

After creating a PSO, it can be quickly switched during rendering:

commandList->SetPipelineState(pipelineState.Get());

Using PSO in Vulkan

In Vulkan, the PSO concept is also crucial. Creating a VkPipeline requires defining all rendering parameters in advance, which helps reduce overhead.

Example of PSO creation in Vulkan:

VkGraphicsPipelineCreateInfo gfxPipelineInfo{};
gfxPipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
gfxPipelineInfo.stageCount = static_cast<uint32_t>(shaderStageCount);
gfxPipelineInfo.pStages = shaderStages;
gfxPipelineInfo.pVertexInputState = &vertexInputConfig;
gfxPipelineInfo.pInputAssemblyState = &inputAssemblyState;
gfxPipelineInfo.pRasterizationState = &rasterizationConfig;
gfxPipelineInfo.pMultisampleState = &multisampleConfig;
gfxPipelineInfo.pDepthStencilState = &depthStencilConfig;
gfxPipelineInfo.pColorBlendState = &colorBlendConfig;
gfxPipelineInfo.pDynamicState = &dynamicConfig;
gfxPipelineInfo.layout = pipelineLayout;
gfxPipelineInfo.renderPass = renderPass;
gfxPipelineInfo.subpass = 0;

VkPipeline pipelineHandle;
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &gfxPipelineInfo, nullptr, &pipelineHandle) != VK_SUCCESS) {
throw std::runtime_error("Failed to create graphics pipeline");
}

Conclusion

PSO serves as a fundamental optimization tool in contemporary graphics APIs such as DirectX 12 and Vulkan. By predefining pipeline configurations, it minimizes computational overhead and enhances rendering efficiency.

Using PSOs requires planning and setup, but in the long run, they provide a substantial efficiency boost, especially in high-performance graphics applications.

If you are developing a game or a graphics engine, effective PSO management will help you achieve maximum rendering performance and flexibility.

Serverspace Knowledge Base

For a deeper understanding of graphics APIs and rendering optimizations, you can explore the ServerSpace Knowledge Base. It offers a wealth of information on PSO, pipeline configurations, and other key technical concepts. You'll also find detailed explanations of rendering techniques, performance tuning, and industry best practices.

FAQ (Frequently Asked Questions)

  • What is a Pipeline State Object (PSO)?
    A PSO is an object that stores all the necessary state information for the graphics pipeline (shaders, blending, rasterization, depth, etc.) and allows the GPU to quickly switch between different configurations during rendering.
  • How is PSO different from older graphics APIs like OpenGL or DirectX 11?
    In older APIs, each state (shader, blend mode, rasterizer, etc.) was set individually, which caused CPU overhead. In DirectX 12 and Vulkan, PSO consolidates all states into one object, making state changes faster and more efficient.
  • What components are typically included in a PSO?
    PSO usually includes shaders, vertex input layouts, rasterizer state, blend state, depth/stencil configuration, primitive topology, and render target formats.
  • Why does PSO improve performance?
    Since all states are predefined, the GPU doesn’t waste time processing multiple API calls for state changes. This reduces CPU overhead and allows the graphics hardware to operate more efficiently.
  • Can PSOs be reused across multiple draw calls?
    Yes. Once created, a PSO can be reused as many times as needed, which simplifies rendering pipelines and improves performance consistency.
  • Is PSO required in Vulkan and DirectX 12?
    Yes, both APIs rely heavily on PSOs. Unlike older APIs, you cannot render efficiently without creating and using pipeline state objects.
Vote:
5 out of 5
Аverage rating : 5
Rated by: 1
1101 CT Amsterdam The Netherlands, Herikerbergweg 292
+31 20 262-58-98
700 300
ITGLOBAL.COM NL
700 300
We use cookies to make your experience on the Serverspace better. By continuing to browse our website, you agree to our
Use of Cookies and Privacy Policy.