Skip to content

Commit b305ad2

Browse files
Render state cache: implemented asynchronous pipeline states (close #606)
1 parent ce4894a commit b305ad2

File tree

15 files changed

+483
-76
lines changed

15 files changed

+483
-76
lines changed

Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,4 +896,38 @@ ProcessPipelineStateCreateInfoShaders(CreateInfoType&& CI, HandlerType&& Handler
896896
}
897897
}
898898

899+
template <typename CreateInfoType>
900+
SHADER_STATUS GetPipelineStateCreateInfoShadersStatus(const CreateInfoType& CI, bool WaitForCompletion = false)
901+
{
902+
SHADER_STATUS OverallStatus = SHADER_STATUS_READY;
903+
ProcessPipelineStateCreateInfoShaders(CI, [&OverallStatus, WaitForCompletion](IShader* pShader) {
904+
if (pShader == nullptr)
905+
return;
906+
907+
SHADER_STATUS ShaderStatus = pShader->GetStatus(WaitForCompletion);
908+
switch (ShaderStatus)
909+
{
910+
case SHADER_STATUS_UNINITIALIZED:
911+
UNEXPECTED("Shader status must not be uninitialized");
912+
break;
913+
914+
case SHADER_STATUS_COMPILING:
915+
OverallStatus = (OverallStatus == SHADER_STATUS_READY) ? SHADER_STATUS_COMPILING : OverallStatus;
916+
break;
917+
918+
case SHADER_STATUS_READY:
919+
// Do nothing
920+
break;
921+
922+
case SHADER_STATUS_FAILED:
923+
OverallStatus = SHADER_STATUS_FAILED;
924+
break;
925+
926+
default:
927+
UNEXPECTED("Unexpected shader status");
928+
}
929+
});
930+
return OverallStatus;
931+
}
932+
899933
} // namespace Diligent

Graphics/GraphicsEngine/include/DeviceObjectBase.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class DeviceObjectBase : public ObjectBase<BaseInterface>
140140

141141
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_DeviceObject, TBase)
142142

143-
virtual const ObjectDescType& DILIGENT_CALL_TYPE GetDesc() const override final
143+
virtual const ObjectDescType& DILIGENT_CALL_TYPE GetDesc() const override
144144
{
145145
return m_Desc;
146146
}

Graphics/GraphicsEngine/include/PipelineStateBase.hpp

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -484,14 +484,22 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
484484

485485
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase)
486486

487+
virtual const PipelineStateDesc& DILIGENT_CALL_TYPE GetDesc() const override final
488+
{
489+
CheckPipelineReady();
490+
return this->m_Desc;
491+
}
492+
487493
Uint32 GetBufferStride(Uint32 BufferSlot) const
488494
{
495+
CheckPipelineReady();
489496
VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline());
490497
return BufferSlot < m_pGraphicsPipelineData->BufferSlotsUsed ? m_pGraphicsPipelineData->pStrides[BufferSlot] : 0;
491498
}
492499

493500
Uint32 GetNumBufferSlotsUsed() const
494501
{
502+
CheckPipelineReady();
495503
VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline());
496504
return m_pGraphicsPipelineData->BufferSlotsUsed;
497505
}
@@ -510,20 +518,23 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
510518

511519
virtual const GraphicsPipelineDesc& DILIGENT_CALL_TYPE GetGraphicsPipelineDesc() const override final
512520
{
521+
CheckPipelineReady();
513522
VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline());
514523
VERIFY_EXPR(m_pGraphicsPipelineData != nullptr);
515524
return m_pGraphicsPipelineData->Desc;
516525
}
517526

518527
virtual const RayTracingPipelineDesc& DILIGENT_CALL_TYPE GetRayTracingPipelineDesc() const override final
519528
{
529+
CheckPipelineReady();
520530
VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline());
521531
VERIFY_EXPR(m_pRayTracingPipelineData != nullptr);
522532
return m_pRayTracingPipelineData->Desc;
523533
}
524534

525535
virtual const TilePipelineDesc& DILIGENT_CALL_TYPE GetTilePipelineDesc() const override final
526536
{
537+
CheckPipelineReady();
527538
VERIFY_EXPR(this->m_Desc.IsTilePipeline());
528539
VERIFY_EXPR(m_pTilePipelineData != nullptr);
529540
return m_pTilePipelineData->Desc;
@@ -557,9 +568,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
557568
virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding,
558569
bool InitStaticResources) override final
559570
{
560-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
561-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
562-
". Use GetStatus() to check the pipeline state status.");
571+
CheckPipelineReady();
563572

564573
*ppShaderResourceBinding = nullptr;
565574

@@ -576,9 +585,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
576585
virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType,
577586
const Char* Name) override final
578587
{
579-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
580-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
581-
". Use GetStatus() to check the pipeline state status.");
588+
CheckPipelineReady();
582589

583590
if (!m_UsingImplicitSignature)
584591
{
@@ -600,9 +607,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
600607
virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType,
601608
Uint32 Index) override final
602609
{
603-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
604-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
605-
". Use GetStatus() to check the pipeline state status.");
610+
CheckPipelineReady();
606611

607612
if (!m_UsingImplicitSignature)
608613
{
@@ -623,9 +628,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
623628

624629
virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final
625630
{
626-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
627-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
628-
". Use GetStatus() to check the pipeline state status.");
631+
CheckPipelineReady();
629632

630633
if (!m_UsingImplicitSignature)
631634
{
@@ -648,9 +651,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
648651
IResourceMapping* pResourceMapping,
649652
BIND_SHADER_RESOURCES_FLAGS Flags) override final
650653
{
651-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
652-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
653-
". Use GetStatus() to check the pipeline state status.");
654+
CheckPipelineReady();
654655

655656
if (!m_UsingImplicitSignature)
656657
{
@@ -664,9 +665,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
664665

665666
virtual void DILIGENT_CALL_TYPE InitializeStaticSRBResources(IShaderResourceBinding* pSRB) const override final
666667
{
667-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
668-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
669-
". Use GetStatus() to check the pipeline state status.");
668+
CheckPipelineReady();
670669

671670
if (!m_UsingImplicitSignature)
672671
{
@@ -680,9 +679,7 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
680679

681680
virtual void DILIGENT_CALL_TYPE CopyStaticResources(IPipelineState* pDstPipeline) const override final
682681
{
683-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
684-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
685-
". Use GetStatus() to check the pipeline state status.");
682+
CheckPipelineReady();
686683

687684
if (pDstPipeline == nullptr)
688685
{
@@ -710,31 +707,22 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
710707
/// Implementation of IPipelineState::GetResourceSignatureCount().
711708
virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final
712709
{
713-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
714-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
715-
". Use GetStatus() to check the pipeline state status.");
716-
710+
CheckPipelineReady();
717711
return m_SignatureCount;
718712
}
719713

720714
/// Implementation of IPipelineState::GetResourceSignature().
721715
virtual PipelineResourceSignatureImplType* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final
722716
{
723-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
724-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
725-
". Use GetStatus() to check the pipeline state status.");
726-
717+
CheckPipelineReady();
727718
VERIFY_EXPR(Index < m_SignatureCount);
728719
return m_Signatures[Index];
729720
}
730721

731722
/// Implementation of IPipelineState::IsCompatibleWith().
732723
virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override // May be overridden
733724
{
734-
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
735-
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
736-
". Use GetStatus() to check the pipeline state status.");
737-
725+
CheckPipelineReady();
738726
DEV_CHECK_ERR(pPSO != nullptr, "pPSO must not be null");
739727

740728
if (pPSO == this)
@@ -1148,6 +1136,14 @@ class PipelineStateBase : public DeviceObjectBase<typename EngineImplTraits::Pip
11481136
}
11491137

11501138
private:
1139+
void CheckPipelineReady() const
1140+
{
1141+
// It is OK to use m_Desc.Name as it is initialized by DeviceObjectBase
1142+
DEV_CHECK_ERR(m_Status.load() == PIPELINE_STATE_STATUS_READY, "Pipeline state '", this->m_Desc.Name,
1143+
"' is expected to be Ready, but its actual status is ", GetPipelineStateStatusString(m_Status.load()),
1144+
". Use GetStatus() to check the pipeline state status.");
1145+
}
1146+
11511147
static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, FixedLinearAllocator& MemPool) noexcept
11521148
{
11531149
if (SrcLayout.Variables != nullptr)

Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo&
172172
if (m_Desc.IsAnyGraphicsPipeline())
173173
{
174174
// In Direct3D11, UAVs use the same register space as render targets
175-
ResCounters[D3D11_RESOURCE_RANGE_UAV][PSInd] = GetGraphicsPipelineDesc().NumRenderTargets;
175+
ResCounters[D3D11_RESOURCE_RANGE_UAV][PSInd] = m_pGraphicsPipelineData->Desc.NumRenderTargets;
176176
}
177177

178178
for (Uint32 sign = 0; sign < m_SignatureCount; ++sign)
@@ -303,8 +303,8 @@ void PipelineStateD3D11Impl::InitializePipeline(const GraphicsPipelineStateCreat
303303
if (GetD3D11VertexShader() == nullptr)
304304
LOG_ERROR_AND_THROW("Vertex shader is null");
305305

306-
const auto& GraphicsPipeline = GetGraphicsPipelineDesc();
307-
auto* const pDeviceD3D11 = m_pDevice->GetD3D11Device();
306+
const GraphicsPipelineDesc& GraphicsPipeline = m_pGraphicsPipelineData->Desc;
307+
ID3D11Device* const pDeviceD3D11 = m_pDevice->GetD3D11Device();
308308

309309
D3D11_BLEND_DESC D3D11BSDesc = {};
310310
BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc);

Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ void PipelineStateD3D12Impl::InitializePipeline(const GraphicsPipelineStateCreat
681681
auto* pd3d12Device = m_pDevice->GetD3D12Device();
682682
if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS)
683683
{
684-
const auto& GraphicsPipeline = GetGraphicsPipelineDesc();
684+
const GraphicsPipelineDesc& GraphicsPipeline = m_pGraphicsPipelineData->Desc;
685685

686686
D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {};
687687

@@ -720,7 +720,7 @@ void PipelineStateD3D12Impl::InitializePipeline(const GraphicsPipelineStateCreat
720720

721721
std::vector<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC>> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D12_INPUT_ELEMENT_DESC>"));
722722

723-
const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout;
723+
const auto& InputLayout = GraphicsPipeline.InputLayout;
724724
if (InputLayout.NumElements > 0)
725725
{
726726
LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements);
@@ -782,7 +782,7 @@ void PipelineStateD3D12Impl::InitializePipeline(const GraphicsPipelineStateCreat
782782
#ifdef D3D12_H_HAS_MESH_SHADER
783783
else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH)
784784
{
785-
const auto& GraphicsPipeline = GetGraphicsPipelineDesc();
785+
const GraphicsPipelineDesc& GraphicsPipeline = m_pGraphicsPipelineData->Desc;
786786

787787
struct MESH_SHADER_PIPELINE_STATE_DESC
788788
{

Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ void PipelineStateVkImpl::InitializePipeline(const GraphicsPipelineStateCreateIn
828828
InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules);
829829

830830
const auto vkSPOCache = CreateInfo.pPSOCache != nullptr ? ClassPtrCast<PipelineStateCacheVkImpl>(CreateInfo.pPSOCache)->GetVkPipelineCache() : VK_NULL_HANDLE;
831-
CreateGraphicsPipeline(m_pDevice, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, GetRenderPassPtr(), vkSPOCache);
831+
CreateGraphicsPipeline(m_pDevice, vkShaderStages, m_PipelineLayout, m_Desc, m_pGraphicsPipelineData->Desc, m_Pipeline, GetRenderPassPtr(), vkSPOCache);
832832
}
833833

834834
void PipelineStateVkImpl::InitializePipeline(const ComputePipelineStateCreateInfo& CreateInfo)
@@ -853,7 +853,7 @@ void PipelineStateVkImpl::InitializePipeline(const RayTracingPipelineStateCreate
853853
const auto vkShaderGroups = BuildRTShaderGroupDescription(CreateInfo, m_pRayTracingPipelineData->NameToGroupIndex, ShaderStages);
854854
const auto vkSPOCache = CreateInfo.pPSOCache != nullptr ? ClassPtrCast<PipelineStateCacheVkImpl>(CreateInfo.pPSOCache)->GetVkPipelineCache() : VK_NULL_HANDLE;
855855

856-
CreateRayTracingPipeline(m_pDevice, vkShaderStages, vkShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline, vkSPOCache);
856+
CreateRayTracingPipeline(m_pDevice, vkShaderStages, vkShaderGroups, m_PipelineLayout, m_Desc, m_pRayTracingPipelineData->Desc, m_Pipeline, vkSPOCache);
857857

858858
VERIFY(m_pRayTracingPipelineData->NameToGroupIndex.size() == vkShaderGroups.size(),
859859
"The size of NameToGroupIndex map does not match the actual number of groups in the pipeline. This is a bug.");

Graphics/GraphicsEngineWebGPU/src/PipelineStateWebGPUImpl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,10 @@ void PipelineStateWebGPUImpl::InitializeWebGPURenderPipeline(const TShaderStages
357357
{
358358
VERIFY(!ShaderStages.empty() && ShaderStages.size() <= 2, "Incorrect shader count for graphics pipeline");
359359

360-
const GraphicsPipelineDesc& GraphicsPipeline = GetGraphicsPipelineDesc();
360+
const GraphicsPipelineDesc& GraphicsPipeline = m_pGraphicsPipelineData->Desc;
361361

362362
WGPURenderPipelineDescriptor wgpuRenderPipelineDesc{};
363-
wgpuRenderPipelineDesc.label = GetDesc().Name;
363+
wgpuRenderPipelineDesc.label = m_Desc.Name;
364364
wgpuRenderPipelineDesc.layout = m_PipelineLayout.GetWebGPUPipelineLayout();
365365

366366
WGPUFragmentState wgpuFragmentState{};
@@ -581,7 +581,7 @@ void PipelineStateWebGPUImpl::InitializeWebGPUComputePipeline(const TShaderStage
581581
wgpuShaderModule.Reset(wgpuDeviceCreateShaderModule(m_pDevice->GetWebGPUDevice(), &wgpuShaderModuleDesc));
582582

583583
WGPUComputePipelineDescriptor wgpuComputePipelineDesc{};
584-
wgpuComputePipelineDesc.label = GetDesc().Name;
584+
wgpuComputePipelineDesc.label = m_Desc.Name;
585585
wgpuComputePipelineDesc.compute.module = wgpuShaderModule.Get();
586586
wgpuComputePipelineDesc.compute.entryPoint = pShaderWebGPU->GetEntryPoint();
587587
wgpuComputePipelineDesc.layout = m_PipelineLayout.GetWebGPUPipelineLayout();

Graphics/GraphicsTools/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ if(ARCHIVER_SUPPORTED)
5454
interface/RenderStateCache.hpp
5555
)
5656
list(APPEND INCLUDE
57+
include/AsyncPipelineState.hpp
5758
include/RenderStateCacheImpl.hpp
5859
include/ReloadableShader.hpp
5960
include/ReloadablePipelineState.hpp
6061
)
6162
list(APPEND SOURCE
63+
src/AsyncPipelineState.cpp
6264
src/RenderStateCacheImpl.cpp
6365
src/ReloadableShader.cpp
6466
src/ReloadablePipelineState.cpp

0 commit comments

Comments
 (0)