D3D12에선 온갖 렌더링 스테이트를 묶어서 ID3D12PipelineState객체 하나로 만들어둠. 렌더링하면서 렌더 스테이트를 중간에 바꿀수 있는 API가 아예 존재하지 않음. 오직 ID3D12PipelineState객체만 바꿔가면서 렌더링 할 수 있음.
이게 쉐이더 폭발보다 더 무서움.
[ 알파블랜딩 경우의 수 x 쉐이더 조합의 경우의 수 x 기타(양면 렌더링 여부, Depth Enable, Depth Write여부 등등) ]
변수가 더 있을텐데 이 정도만 해도 대체 몇개의 PipelineState가 나오는건가.
지금도 Shading방식, 그림자여부, 감쇄 라이트 여부 등등에 따라 bit flag로 조합해서 ID3D12PipelineState을 만들어 쓰고 있다. 알파블렌딩 여부는 고려 안했는데 이걸 넣으려니 알파블렌딩 끄고 켜는 경우만 따져도 ID3D12PipelineState개수가 2배로 늘어남. 미치겠네.–;
결국 알파블렌딩 상태 전환을 위해 PipelineState를 이런식으로 만들었다.
ID3D12PipelineState* m_pPipelineState[BLEND_TYPES][VL_SHADER_TYPES][SHADER_PARAMETER_COMBOS];
그리고 이런식으로 루프 돌며 생성
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; SetDefaultPipelineStateDesc(&psoDesc); SetDefaultPipeLineStateRenderTargets(&psoDesc); D3D12_BLEND_DESC blendDesc[BLEND_TYPE_NUM]; for (DWORD i=0; i<BLEND_TYPE_NUM; i++) { SetBlendDesc(blendDesc+i,(BLEND_TYPE)i); } psoDesc.pRootSignature = m_pRootSignature; for (DWORD blend_index=0; blend_index<BLEND_TYPES; blend_index++) { psoDesc.BlendState = blendDesc[blend_index]; for (DWORD i=0; i<VL_SHADER_TYPES; i++) { for (DWORD j=0; j<SHADER_PARAMETER_COMBOS; j++) { if (IsPhysique(j)) { psoDesc.InputLayout = { layoutVL_Physique, _countof(layoutVL_Physique) }; } else { psoDesc.InputLayout = { layoutVL, _countof(layoutVL) }; } psoDesc.VS = CD3DX12_SHADER_BYTECODE(m_pVS[i][j]->pCodeBuffer,m_pVS[i][j]->dwCodeSize); psoDesc.PS = CD3DX12_SHADER_BYTECODE(m_pPS[i][j]->pCodeBuffer,m_pPS[i][j]->dwCodeSize); if (FAILED(pResourceManager->CreateGraphicsPipelineState(&psoDesc, &m_pPipelineState[blend_index][i][j]))) __debugbreak(); } } }
라이트상태,그림자상태 등등에 따라서 Parameter Combo가 16가지.
ShadyerType이 3개,
Blend Type이 현재 3개
해서 144개인데 최종적으론 한 500개까진 늘어나지 않을까.