在 Direct3D 12 中管理图形管道状态

本主题描述如何在 Direct3D 12 中设置图形管道状态。

管道状态概述

当几何图形提交到要绘制的图形处理单元 (GPU) 时,有各种硬件设置可用来确定如何解释和呈现输入数据。 这些设置统称为图形管道状态,并包括光栅器状态、混合状态和深度模具状态以及提交的 几何图形的基元拓扑类型和将用于呈现的着色器等常见设置。 在 Microsoft Direct3D 12 中,大多数图形管道状态是使用管道状态对象 (PSO) 设置的。 应用可以创建无限数量的这些对象,由 ID3D12PipelineState 接口表示(通常在初始化时)。 然后,在呈现时,命令列表可以通过调用直接命令列表或捆绑中的 ID3D12GraphicsCommandList::SetPipelineState 来设置活动 PSO,以便快速切换管道状态的多个设置。

在 Direct3D 11 中,图形管道状态已绑定到大型、粗粒度状态对象(如 ID3D11BlendState),可以在呈现时使用类似 ID3D11DeviceContext::OMSetBlendState 的方法在即时上下文中创建和设置这些对象。 这背后的构想是 GPU 可以通过同时设置相关设置(例如,混合状态设置)来提高效率。 但是,在如今的图形硬件中,不同的硬件单元之间存在依赖项。 例如,硬件混合状态可能会存在光栅状态以及混合状态的依赖项。 Direct3D 12 中的 PSO 旨在允许 GPU 在每个管道状态中预处理所有依赖设置(通常在初始化时),以便在呈现时尽可能高效地在状态之间切换。

请注意,虽然大多数管道状态设置是使用 PSO 设置的,但有一些状态设置是使用 ID3D12GraphicsCommandList 提供的 API 单独设置的。 下面详细介绍了这些设置和关联的 API。 此外,由直接命令列表和捆绑继承图形管道状态的方式和从直接命令列表和捆绑继承保留图形管道状态的方式存在差异。 本主题提供有关这两种方式的详细信息。

使用管道状态对象设置的图形管道状态

查看可以使用管道状态对象设置的所有不同管道状态的最简单方法是查看初始化对象时传递给 ID3D12Device::CreateGraphicsPipelineState的D3D12_GRAPHICS_PIPELINE_STATE_DESC的参考主题。 可以设置的状态的快速摘要包括:

  • 所有着色器(包括顶点、像素、域、外壳和几何着色器)的字节码。
  • 输入顶点格式。
  • 基元拓扑类型。 请注意,输入装配器基元拓扑类型 (点、线、三角形、补丁) 是在 PSO 中使用 D3D12_PRIMITIVE_TOPOLOGY_TYPE 枚举设置的。 基元邻近度和排序(线列表、线条带、带邻近度数据的线条带等)是使用 ID3D12GraphicsCommandList::IASetPrimitiveTopology 方法在命令列表中设置的。
  • 混合状态、光栅器状态、深度模具状态。
  • 深度模具和呈现器目标格式,以及呈现器目标计数。
  • 多采样参数。
  • 流式处理输出缓冲区。
  • 根签名。 有关详细信息,请参阅根签名

在管道状态对象之外设置的图形管道状态

大多数图形管道状态是使用 PSO 设置的。 但是,有一组管道状态参数是通过调用命令列表中的 ID3D12GraphicsCommandList 接口的方法设置的。 下表显示了通过此方式和相应的方法设置的状态。

状态 方法
资源绑定 IASetIndexBuffer
IASetVertexBuffers
SOSetTargets
OMSetRenderTargets
SetDescriptorHeaps
所有 SetGraphicsRoot... 方法
所有 SetComputeRoot... 方法
视区 RSSetViewports
剪刀矩形 RSSetScissorRects
混合系数 OMSetBlendFactor
深度模具参考值 OMSetStencilRef
输入汇编程序基元拓扑顺序和相邻类型 IASetPrimitiveTopology

图形管道状态继承

由于直接命令列表通常用于一次使用一个,捆绑用于多次同时使用,因此如何继承以前的命令列表或捆绑设置的图形管道状态有不同的规则。

对于使用 PSO 设置的图形管道状态,直接命令列表或捆绑都不会继承其中任何一种状态。 直接命令列表和捆绑的初始图形管道状态在创建时使用 ID3D12PipelineState 参数设置为 ID3D12Device::CreateCommandList。 如果调用中未指定 PSO,则使用默认初始状态。 可以通过调用 ID3D12GraphicsCommandList::SetPipelineState 更改命令列表中的当前 PSO。

直接命令列表也不会继承使用命令列表方法(例如,RSSetViewports)设置的状态。 有关非 PSO 状态的默认初始值的详细信息,请参阅 ID3D12GraphicsCommandList::ClearState

捆绑继承未使用 PSO(基元拓扑类型除外)设置的所有图形管道状态。 捆绑包开始执行时,基元拓扑始终设置为 D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED 。 在捆绑(PSO 本身、基于非 PSO 的状态和资源绑定)中设置的任何状态都会影响其父直接命令列表的状态。 例如,如果从捆绑包中调用 RSSetViewports ,则指定视区将继续在父直接命令列表中设置,以便在设置视区 的 ExecuteBundle 调用之后进行调用。

保留在命令列表或捆绑中设置的资源绑定。 因此,将仍在后续子捆绑执行中设置在直接命令列表中修改的资源绑定。 将仍为父直接命令列表中的后续调用设置在捆绑中修改的资源绑定。

有关绑定的详细信息,请参阅使用根签名捆绑语义部分。