객체들을 실제로 사용하기 위해 렌더링 파이프라인에 묶는 방법은 아직 나오지 않았다. 렌더링 파이프라인의 상태를 제어하는 대부분의 객체는 파이프라인 상태 객체(pipeline state object, PSO)라고 부르는 집합체(aggregate)를 통해서 지정된다. ID3D12PipelineState 인터페이스를 대표적으로 사용한다. PSO를 생성하기 위해 D3D12_GRAPHICS_PIPELINE_STATE_DESC 구조체를 채워야 한다.
void BoxApp::BuildPSO()
{
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
ZeroMemory(&psoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
psoDesc.pRootSignature = mRootSignature.Get();
psoDesc.VS =
{
reinterpret_cast<BYTE*>(mvsByteCode->GetBufferPointer()),
mvsByteCode->GetBufferSize()
};
psoDesc.PS =
{
reinterpret_cast<BYTE*>(mvsByteCode->GetBufferPointer()),
mvsByteCode->GetBufferSize()
};
psoDesc.InputLayout =
{
mInputLayout.data(), (UINT)mInputLayout.size()
};
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;
ThrowIfFailed(mDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(mPSO.GetAddressOf())));
}
이 모든 객체를 하나의 집합체로서 지정하는 이유는 성능 때문이다. 이 덕분에 D3D는 모든 상태가 호환되는지 미리 검증할 수 있으며, 드라이버는 하드웨어 상태의 프로그래밍을 위한 모든 코드를 미리 생성할 수 있다. PSO 검증과 생성에는 시간이 많이 걸릴 수 있으므로 초기화 시점에서 생성해야 한다.
하지만 PSO가 모든 렌더 상태를 포함하는 것은 아니다. 뷰포트, 가위 직사각형 같은 상태는 따로 지정한다. D3D는 하나의 상태 기계(state machine)이다. D3D에는 명시적으로 변경하지 않는 한 그대로 남아 있는 것들이 많다.
다른 말로 하면 어떤 PSO를 명령 목록에 묶었다면, 다른 PSO가 묶이기까지는 그 PSO가 계속 적용된다.
'DirectX' 카테고리의 다른 글
7.1 프레임 자원 (0) | 2022.01.05 |
---|---|
6.10 기하구조 보조 구조체 (0) | 2022.01.03 |
6.8 래스터화기 상태 (0) | 2022.01.03 |
6.7 셰이더의 컴파일 (0) | 2021.12.31 |
6.6 루트 서명과 서술자 테이블 (0) | 2021.12.31 |