将wordpress网站变成app,广州seo优化,百度网络营销中心,贵州网站建设系统到目前为止展示过编写输入布局描述、创建顶点着色器和像素着色器#xff0c;以及配置光栅器状态组这 3 个步骤。接下来讲如何将这些对象绑定到图形流水线上#xff0c;用以实际绘制图形。大多数控制图形流水线状态的对象被统称为流水线状态对象#xff08;Pipeline State Ob…到目前为止展示过编写输入布局描述、创建顶点着色器和像素着色器以及配置光栅器状态组这 3 个步骤。接下来讲如何将这些对象绑定到图形流水线上用以实际绘制图形。大多数控制图形流水线状态的对象被统称为流水线状态对象Pipeline State ObjectPSO用 ID3D12PipelineState 接口来表示。要创建 PSO我们首先要填写一份描述其细节的 D3D12_GRAPHICS_PIPELINE_STATE_DESC 结构体实例。
typedef struct D3D12_GRAPHICS_PIPELINE_STATE_DESC
{ID3D12RootSignature *pRootSignature;D3D12_SHADER_BYTECODE VS;D3D12_SHADER_BYTECODE PS;D3D12_SHADER_BYTECODE DS;D3D12_SHADER_BYTECODE HS;D3D12_SHADER_BYTECODE GS;D3D12_STREAM_OUTPUT_DESC StreamOutput;D3D12_BLEND_DESC BlendState;UINT SampleMask;D3D12_RASTERIZER_DESC RasterizerState;D3D12_DEPTH_STENCIL_DESC DepthStencilState;D3D12_INPUT_LAYOUT_DESC InputLayout;D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;UINT NumRenderTargets;DXGI_FORMAT RTVFormats[8];DXGI_FORMAT DSVFormat;DXGI_SAMPLE_DESC SampleDesc;
} D3D12_GRAPHICS_PIPELINE_STATE_DESC;
1. pRootSignature指向一个与此 PSO 相绑定的根签名的指针。该根签名一定要与此 PSO 指定的着色器相兼容。
2. VS待绑定的顶点着色器。此成员由结构体 D3D12_SHADER_BYTECODE 表示这个结构体存有指向已编译好的字节码数据的指针以及该字节码数据所占的字节大小。 typedef struct D3D12_SHADER_BYTECODE {const void *pShaderBytecode;SIZE_T BytecodeLength;} D3D12_SHADER_BYTECODE;
3. PS待绑定的像素着色器。
4. DS待绑定的域着色器我们将在后续章节中讲解此类型的着色器。
5. HS待绑定的外壳着色器我们将在后续章节中讲解此类型的着色器。
6. GS待绑定的几何着色器我们将在后续章节中讲解此类型的着色器。
7. StreamOutput用于实现一种称作流输出stream-out的高级技术。目前我们仅将此字段清零。
8. BlendState指定混合blending操作所用的混合状态。我们将在后续章节中讨论此状态组目前仅将此成员指定为默认的 CD3DX12_BLEND_DESC(D3D12_DEFAULT)。
9. SampleMask多重采样最多可采集 32 个样本。借此参数的 32 位整数值即可设置每个采样点的采集情况采集或禁止采集。例如若禁用了第 5 位将第 5 位设置为 0则将不会对第 5 个样本进行采样。当然要禁止采集第 5 个样本的前提是所用的多重采样至少要有 5 个样本。假如一个应用程序仅使用了单采样single sampling那么只能针对该参数的第 1 位进行配置。一般来说使用的都是默认值 0xffffffff即表示对所有的采样点都进行采样。
10. RasterizerState指定用来配置光栅器的光栅化状态。
11. DepthStencilState指定用于配置深度/模板测试的深度/模板状态。我们将在后续章节中对此状态进行讨论目前只把它设为默认的 CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT)。
12. InputLayout输入布局描述此结构体中有两个成员一个由 D3D12_INPUT_ELEMENT_DESC 元素构成的数组以及一个表示此数组中元素数量的无符号整数。 typedef struct D3D12_INPUT_LAYOUT_DESC{const D3D12_INPUT_ELEMENT_DESC *pInputElementDescs;UINT NumElements;} D3D12_INPUT_LAYOUT_DESC;
13. PrimitiveTopologyType指定图元的拓扑类型。
typedef enum D3D12_PRIMITIVE_TOPOLOGY_TYPE { D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED 0,D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT 1,D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE 2,D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE 3,D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH 4} D3D12_PRIMITIVE_TOPOLOGY_TYPE
14. NumRenderTargets同时所用的渲染目标数量即 RTVFormats 数组中渲染目标格式的数量。
15. RTVFormats渲染目标的格式。利用该数组实现向多渲染目标同时进行写操作。使用此 PSO 的渲染目标的格式设定应当与此参数相匹配。
16. DSVFormat深度/模板缓冲区的格式。使用此 PSO 的深度/模板缓冲区的格式设定应当与此参数相匹配。
17. SampleDesc描述多重采样对每个像素采样的数量及其质量级别。此参数应与渲染目标的对应设置相匹配。
在 D3D12_GRAPHICS_PIPELINE_STATE_DESC 实例填写完毕后我们即可用 ID3D12Device::CreateGraphicsPipelineState 方法来创建 ID3D12PipelineState 对象。
// BoxApp.cpp 58行
ComPtr mRootSignature;
std::vector mInputLayout;
ComPtr mvsByteCode;
ComPtr mpsByteCode;
...
// BoxApp.cpp 436行 BuildPSO()
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
ZeroMemory(psoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
psoDesc.InputLayout { mInputLayout.data(), (UINT)mInputLayout.size() };
psoDesc.pRootSignature mRootSignature.Get();
psoDesc.VS
{ reinterpret_cast(mvsByteCode-GetBufferPointer()),mvsByteCode-GetBufferSize()
};
psoDesc.PS
{ reinterpret_cast(mpsByteCode-GetBufferPointer()), mpsByteCode-GetBufferSize()
};
psoDesc.RasterizerState CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.BlendState CD3DX12_BLEND_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
psoDesc.SampleMask UINT_MAX;
psoDesc.PrimitiveTopologyType D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.NumRenderTargets 1;
psoDesc.RTVFormats[0] mBackBufferFormat;
psoDesc.SampleDesc.Count m4xMsaaState ? 4 : 1;
psoDesc.SampleDesc.Quality m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
psoDesc.DSVFormat mDepthStencilFormat;ComPtr mPSO;
md3dDevice-CreateGraphicsPipelineState(psoDesc, IID_PPV_ARGS(mPSO)));
ID3D12PipelineState 对象集合了大量的流水线状态信息。为了保证性能我们将所有这些对象都集总在一起一并送至渲染流水线。通过这样的一个集合Direct3D 便可以确定所有的状态是否彼此兼容而驱动程序则能够据此而提前生成硬件本地指令及其状态。
注意由于 PSO 的验证和创建操作过于耗时所以应在初始化期间就生成 PSO。除非有特别的需求例如在运行时创建 PSO 伊始就要当即对它进行第一次引用的这种情况。随后我们就可将它存于如散列表哈希表这样的集合里以便在后续使用时快速获取。
并非所有的渲染状态都封装于 PSO 内如视口viewport和裁剪矩形scissor rectangle等属性就独立于 PSO。由于将这些状态的设置与其他的流水线状态分隔开来会更有效所以把它们强行集中在 PSO 内也并不会为之增添任何优势。
Direct3D 实质上就是一种状态机state machine里面的事物会保持它们各自的状态直到我们将其改变。如果我们以不同的 PSO 去绘制不同物体则需要像下面那样来组织代码
// 重置命令列表并指定初始 PSO
mCommandList-Reset(mDirectCmdListAlloc.Get(), mPSO1.Get());
/* ……使用 PSO 1绘制物体…… */// 改变 PSO
mCommandList-SetPipelineState(mPSO2.Get());
/* ……使用 PSO 2绘制物体…… */// 改变 PSO
mCommandList-SetPipelineState(mPSO3.Get());
/* ……使用 PSO 3绘制物体…… */
换句话说如果把一个 PSO 与命令列表相绑定那么在我们设置另一个 PSO 或重置命令列表之前会一直沿用当前的 PSO 绘制物体。
考虑到程序的性能问题我们应当尽可能减少改变 PSO 状态的次数。为此若能以一个 PSO 绘制出所有的物体绝不用第二个 PSO。切记不要在每次绘制调用时都修改 PSO。