Direct3D 12 尝鲜(三): Pipeline State Object
(转载请注明出处)首先得修正一个错误,前一节说到了Fence中用到帧编号,这个帧编号应该(?)要大于0,所以初始化为1就好了,否则(这一节中)第二次渲染会出一点小错误.(╯‵□′)╯︵┴─┴ 在第一节有提到资源绑定,一般的descriptor,还有就是一个特殊的Root Signatures,微软提到
就是说这个Root Signature是被绑定到图像渲染管线上的资源,我们可以利用D3D12SerializeRootSignature先序列化一个Root Signature,将创建的ID3DBlob(其实就是ID3D10Blob的马甲) 传给ID3D12Device::CreateRootSignature用来创建RootSignature. 在D3D12中,通过将这些糅合成一个不可再变的PSO,不过有提到:
不过就认为不可变也不为过,有点类似于以前的固定管线,不过这个可以多创建几个PSO,常见的几种组合够用了: 可以使用ID3D12Device::CreateGraphicsPipelineState来创建一个PSO,最后两个参数REFIID,void**什么的就不说了,说一下第一个参数D3D12_GRAPHICS_PIPELINE_STATE_DESC,(╯‵□′)╯︵┴─┴,这个东西好大,在x86下,都有500+字节: 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_INDEX_BUFFER_PROPERTIES IndexBufferProperties;
D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
UINT NumRenderTargets;
DXGI_FORMAT RTVFormats[8];
DXGI_FORMAT DSVFormat;
DXGI_SAMPLE_DESC SampleDesc;
UINT NodeMask;
D3D12_CACHED_PIPELINE_STATE CachedPSO;
} D3D12_GRAPHICS_PIPELINE_STATE_DESC;
我们这里创建一个简单的PSO即可,就是VS-PS组合,可以说是最简单的了. 在屏幕上画一个渐变的矩形(全窗口) pRootSignature
VS
PS
DS HS GS
StreamOutput
BlendState
SampleMask
RasterizerState
DepthStencilState
InputLayout
IndexBufferProperties
PrimitiveTopologyType
NumRenderTargets
RTVFormats
DSVFormat
SampleDesc
NodeMask
CachedPSO
说到着色器,那就要编译了,我在D2D特效中一节说到了编译方式,这个算是”离线编译”了,还有就是利用函数即时编译,这里使用的是D3DCompileFromFile函数,还有为了方便,将PS和VS写在了一起 struct VSOut {
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD;
};
VSOut VSMain(uint vertexID : SV_VERTEXID) {
VSOut output;
output.texcoord = float2((vertexID << 1) & 2,vertexID & 2);
output.pos = float4(output.texcoord * float2(2,-2) + float2(-1,1),0,1);
return output;
}
float4 PSMain(VSOut vsOut) : SV_TARGET {
return float4(0,vsOut.texcoord.y,vsOut.texcoord.x,vsOut.texcoord.y * 0.5);
}
这就是我的创建代码: ID3DBlob *sig = nullptr,*info = nullptr;
ID3DBlob *ps = nullptr,*vs = nullptr;
D3D12_ROOT_SIGNATURE rootSigDesc = D3D12_ROOT_SIGNATURE();
// 先序列化RootSignature
if (SUCCEEDED(hr = ::D3D12SerializeRootSignature(&rootSigDesc,D3D_ROOT_SIGNATURE_V1,&sig,&info))) {
// 再创建RootSignature
hr = m_pd3dDevice->CreateRootSignature(
0,sig->GetBufferPointer(),sig->GetBufferSize(),IID_ID3D12RootSignature,reinterpret_cast<void**>(&m_prsPipeline)
);
}
UINT flag = 0;
#if _DEBUG
flag |= D3DCOMPILE_DEBUG;
#endif
// 编译VS
if (SUCCEEDED(hr)) {
::SafeRelease(info);
hr = ::D3DCompileFromFile(
L"shader2in1.hlsl",nullptr,"VSMain","vs_5_0",flag,&vs,&info
);
}
// 编译PS
if (SUCCEEDED(hr)) {
::SafeRelease(info);
hr = ::D3DCompileFromFile(
L"shader2in1.hlsl","PSMain","ps_5_0",&ps,&info
);
}
// 创建PSO
if (SUCCEEDED(hr)) {
// 配置PSO
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {
// Root Signature
m_prsPipeline,// VS
{ vs->GetBufferPointer(),vs->GetBufferSize() },// PS
{ ps->GetBufferPointer(),ps->GetBufferSize() },// DS
{ nullptr,0 },// HS
{ nullptr,// GS
{ nullptr,// SO
{ nullptr,// 合成
CD3D12_BLEND_DESC(D3D12_DEFAULT),// 采样掩码
UINT32_MAX,// 光栅化
CD3D12_RASTERIZER_DESC(D3D12_DEFAULT),// 深度/模板
{ 0 },// 输入布局
{ nullptr,// 索引缓存
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED,// 拓扑类型设置为三角
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,// 1个RTV
1,// RGBA
{ DXGI_FORMAT_R8G8B8A8_UNORM,DXGI_FORMAT_UNKNOWN },// DSV
DXGI_FORMAT_UNKNOWN,// 采样
{ 1,// 节点掩码
0,// 缓存管线
{ nullptr,0 }
};
// 创建PSO
hr = m_pd3dDevice->CreateGraphicsPipelineState(
&desc,IID_ID3D12PipelineState,reinterpret_cast<void**>(&m_pPipelineState)
);
}
::SafeRelease(sig);
::SafeRelease(info);
::SafeRelease(ps);
::SafeRelease(vs);
好了,为了演示命令列表,这次特地创建了2个,一个负责清除,一个负责刻画,前面的命令就不说了,说一下后面的: 因为我们在输入布局(inputlayout)中没有设置,所以直接使用ID3D12GraphicsCommandList::DrawInstanced渲染,不过还得绑定裁剪矩形,还得设定RTV,现在又能最多输出到8个RT,设置PSO,所以代码长这个样子: // 创建刻画命令
if(SUCCEEDED(hr)) {
this->SetResourceBarrier(m_pCmdDraw,m_pTargetBuffer,D3D12_RESOURCE_USAGE_PRESENT,D3D12_RESOURCE_USAGE_RENDER_TARGET);
auto rtv = m_pRTVDescriptor->GetCPUDescriptorHandleForHeapStart();
m_pCmdDraw->RSSetViewports(1,&view);
m_pCmdDraw->SetRenderTargets(&rtv,true,1,nullptr);
m_pCmdDraw->SetGraphicsRootSignature(m_prsPipeline);
m_pCmdDraw->SetPipelineState(m_pPipelineState);
m_pCmdDraw->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D12_RECT scissor = { 0,(LONG)m_uBufferWidth,(LONG)m_uBufferHeight };
m_pCmdDraw->RSSetScissorRects(1,&scissor);
m_pCmdDraw->DrawInstanced(4,0);
this->SetResourceBarrier(m_pCmdDraw,D3D12_RESOURCE_USAGE_RENDER_TARGET,D3D12_RESOURCE_USAGE_PRESENT);
hr = m_pCmdDraw->Close();
}
好了,开启DirectComposition的话,超过哦哦就像这个样子: 不过目前还有问题,就是”闪狗眼”,不知道是不是本机原因,还是D3D12未完善,还是其他什么原因: 代码下载地址:点击这里 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |