3434#include < unordered_set>
3535#include < string>
3636
37+ #include " Archiver.h"
38+ #include " Dearchiver.h"
39+ #include " ArchiverFactory.h"
40+ #include " ArchiverFactoryLoader.h"
41+
3742#include " ObjectBase.hpp"
3843#include " ShaderBase.hpp"
3944#include " RefCntAutoPtr.hpp"
4045#include " SerializationDevice.h"
4146#include " SerializedShader.h"
42- #include " Archiver.h"
43- #include " Dearchiver.h"
44- #include " ArchiverFactory.h"
45- #include " ArchiverFactoryLoader.h"
4647#include " XXH128Hasher.hpp"
4748#include " CallbackWrapper.hpp"
4849#include " GraphicsUtilities.h"
@@ -94,6 +95,9 @@ namespace Diligent
9495
9596class RenderStateCacheImpl ;
9697
98+
99+ // / Reloadable shader implements the IShader interface and delegates all
100+ // / calls to the internal shader object, which can be replaced at run-time.
97101class ReloadableShader final : public ObjectBase<IShader>
98102{
99103public:
@@ -120,10 +124,14 @@ class ReloadableShader final : public ObjectBase<IShader>
120124 }
121125 else
122126 {
127+ // This will handle implementation-specific interfaces such as ShaderD3D11Impl::IID_InternalImpl,
128+ // ShaderD3D12Impl::IID_InternalImpl, etc. requested by e.g. pipeline state implementations
129+ // (PipelineStateD3D11Impl, PipelineStateD3D12Impl, etc.)
123130 m_pShader->QueryInterface (IID, ppInterface);
124131 }
125132 }
126133
134+ // Delegate all calls to the internal shader object
127135 PROXY_CONST_METHOD (m_pShader, const ShaderDesc&, GetDesc)
128136 PROXY_CONST_METHOD (m_pShader, Int32, GetUniqueID)
129137 PROXY_METHOD1 (m_pShader, void , SetUserData, IObject*, pUserData)
@@ -144,7 +152,7 @@ class ReloadableShader final : public ObjectBase<IShader>
144152 }
145153 catch (...)
146154 {
147- LOG_ERROR (" Failed to create reloadable shader" );
155+ LOG_ERROR (" Failed to create reloadable shader ' " , (CreateInfo. Desc . Name ? CreateInfo. Desc . Name : " <unnamed> " ), " '. " );
148156 }
149157 }
150158
@@ -158,6 +166,9 @@ class ReloadableShader final : public ObjectBase<IShader>
158166
159167constexpr INTERFACE_ID ReloadableShader::IID_InternalImpl;
160168
169+
170+ // / Reloadable pipeline state implements the IPipelineState interface and delegates all
171+ // / calls to the internal pipeline object, which can be replaced at run-time.
161172class ReloadablePipelineState final : public ObjectBase<IPipelineState>
162173{
163174public:
@@ -184,10 +195,14 @@ class ReloadablePipelineState final : public ObjectBase<IPipelineState>
184195 }
185196 else
186197 {
198+ // This will handle implementation-specific interfaces such as PipelineStateD3D11Impl::IID_InternalImpl,
199+ // PipelineStateD3D12Impl::IID_InternalImpl, etc. requested by e.g. device context implementations
200+ // (DeviceContextD3D11Impl::SetPipelineState, DeviceContextD3D12Impl::SetPipelineState, etc.)
187201 m_pPipeline->QueryInterface (IID, ppInterface);
188202 }
189203 }
190204
205+ // Delegate all calls to the internal pipeline object
191206 PROXY_CONST_METHOD (m_pPipeline, const PipelineStateDesc&, GetDesc)
192207 PROXY_CONST_METHOD (m_pPipeline, Int32, GetUniqueID)
193208 PROXY_METHOD1 (m_pPipeline, void , SetUserData, IObject*, pUserData)
@@ -218,7 +233,7 @@ class ReloadablePipelineState final : public ObjectBase<IPipelineState>
218233 }
219234 catch (...)
220235 {
221- LOG_ERROR (" Failed to create reloadable shader " );
236+ LOG_ERROR (" Failed to create reloadable pipeline state ' " , (CreateInfo. PSODesc . Name ? CreateInfo. PSODesc . Name : " <unnamed> " ), " '. " );
222237 }
223238 }
224239
@@ -311,7 +326,7 @@ class RenderStateCacheImpl final : public ObjectBase<IRenderStateCache>
311326
312327 if (!m_pDearchiver->LoadArchive (pNewData))
313328 {
314- LOG_ERROR_MESSAGE (" Failed to load new render state data" );
329+ LOG_ERROR_MESSAGE (" Failed to add new render state data to existing archive " );
315330 return false ;
316331 }
317332
@@ -338,7 +353,9 @@ class RenderStateCacheImpl final : public ObjectBase<IRenderStateCache>
338353 m_pDearchiver->Reset ();
339354 m_pArchiver->Reset ();
340355 m_Shaders.clear ();
356+ m_ReloadableShaders.clear ();
341357 m_Pipelines.clear ();
358+ m_ReloadablePipelines.clear ();
342359 }
343360
344361 virtual Uint32 DILIGENT_CALL_TYPE Reload (ReloadGraphicsPipelineCallbackType ReloadGraphicsPipeline, void * pUserData) override final ;
@@ -520,6 +537,7 @@ bool RenderStateCacheImpl::CreateShader(const ShaderCreateInfo& ShaderCI,
520537
521538 if (m_CI.EnableHotReload )
522539 {
540+ // Wrap shader in a reloadable shader object
523541 {
524542 std::lock_guard<std::mutex> Guard{m_ReloadableShadersMtx};
525543
@@ -541,7 +559,7 @@ bool RenderStateCacheImpl::CreateShader(const ShaderCreateInfo& ShaderCI,
541559 ReloadableShader::Create (this , pShader, _ShaderCI, ppShader);
542560
543561 std::lock_guard<std::mutex> Guard{m_ReloadableShadersMtx};
544- m_ReloadableShaders.emplace (pShader, RefCntWeakPtr<IShader>( *ppShader) );
562+ m_ReloadableShaders.emplace (pShader, RefCntWeakPtr<IShader>{ *ppShader} );
545563 }
546564 }
547565 else
@@ -569,7 +587,8 @@ bool RenderStateCacheImpl::CreateShaderInternal(const ShaderCreateInfo& ShaderCI
569587 // First, try to check if the shader has already been requested
570588 {
571589 std::lock_guard<std::mutex> Guard{m_ShadersMtx};
572- auto it = m_Shaders.find (Hash);
590+
591+ auto it = m_Shaders.find (Hash);
573592 if (it != m_Shaders.end ())
574593 {
575594 if (auto pShader = it->second .Lock ())
@@ -639,14 +658,14 @@ bool RenderStateCacheImpl::CreateShaderInternal(const ShaderCreateInfo& ShaderCI
639658 {
640659 LOG_ERROR_MESSAGE (" Description of shader '" , (ShaderCI.Desc .Name != nullptr ? ShaderCI.Desc .Name : " <unnamed>" ),
641660 " ' does not match the description of the shader unpacked from the cache. This may be the result of a "
642- " hash conflict, but the probability of this should be virtually zero." );
661+ " hash conflict, though the probability of this should be virtually zero." );
643662 }
644663 }
645664 }
646665
647666 // Next, try to find the shader in the archiver
648667 RefCntAutoPtr<IShader> pArchivedShader{m_pArchiver->GetShader (HashStr.c_str ())};
649- const auto FoundInArchive = pArchivedShader != nullptr ;
668+ const auto FoundInArchive = ( pArchivedShader != nullptr ) ;
650669 if (!pArchivedShader)
651670 {
652671 auto ArchiveShaderCI = ShaderCI;
@@ -680,7 +699,7 @@ bool RenderStateCacheImpl::CreateShaderInternal(const ShaderCreateInfo& ShaderCI
680699 {
681700 LOG_ERROR_MESSAGE (" Description of shader '" , (ShaderCI.Desc .Name != nullptr ? ShaderCI.Desc .Name : " <unnamed>" ),
682701 " ' does not match the description of the shader recently added to the cache. This may be the result of a "
683- " hash conflict, but the probability of this should be virtually zero." );
702+ " hash conflict, though the probability of this should be virtually zero." );
684703 }
685704 }
686705 else
@@ -932,7 +951,7 @@ void CreateRenderStateCache(const RenderStateCacheCreateInfo& CreateInfo,
932951 }
933952 catch (...)
934953 {
935- LOG_ERROR (" Failed to create the bytecode cache" );
954+ LOG_ERROR (" Failed to create the render state cache" );
936955 }
937956}
938957
@@ -1045,7 +1064,7 @@ bool RenderStateCacheImpl::CreatePipelineStateInternal(const CreateInfoType& PSO
10451064 {
10461065 LOG_ERROR_MESSAGE (" Description of pipeline state '" , (PSOCreateInfo.PSODesc .Name != nullptr ? PSOCreateInfo.PSODesc .Name : " <unnamed>" ),
10471066 " ' does not match the description of the pipeline unpacked from the cache. This may be the result of a "
1048- " hash conflict, but the probability of this should be virtually zero." );
1067+ " hash conflict, though the probability of this should be virtually zero." );
10491068 }
10501069 }
10511070 }
@@ -1107,6 +1126,7 @@ Uint32 RenderStateCacheImpl::Reload(ReloadGraphicsPipelineCallbackType ReloadGra
11071126
11081127 Uint32 NumStatesReloaded = 0 ;
11091128
1129+ // Reload all shaders first
11101130 {
11111131 std::lock_guard<std::mutex> Guard{m_ReloadableShadersMtx};
11121132 for (auto shader_it : m_ReloadableShaders)
@@ -1127,6 +1147,9 @@ Uint32 RenderStateCacheImpl::Reload(ReloadGraphicsPipelineCallbackType ReloadGra
11271147 }
11281148 }
11291149
1150+ // Reload pipelines.
1151+ // Note that create info structs reference reloadable shaders, so that when pipelines
1152+ // are re-created, they will automatically use reloaded shaders.
11301153 {
11311154 std::lock_guard<std::mutex> Guard{m_ReloadablePipelinesMtx};
11321155 for (auto pso_it : m_ReloadablePipelines)
@@ -1141,7 +1164,7 @@ Uint32 RenderStateCacheImpl::Reload(ReloadGraphicsPipelineCallbackType ReloadGra
11411164 }
11421165 else
11431166 {
1144- UNEXPECTED (" Shader object is not a ReloadableShader " );
1167+ UNEXPECTED (" Pipeline state object is not a ReloadablePipelineState " );
11451168 }
11461169 }
11471170 }
@@ -1160,7 +1183,8 @@ struct ReloadablePipelineState::CreateInfoWrapperBase : DynamicHeapObjectBase
11601183 m_ImtblSamplers{CI.PSODesc .ResourceLayout .ImmutableSamplers , CI.PSODesc .ResourceLayout .ImmutableSamplers + CI.PSODesc .ResourceLayout .NumImmutableSamplers },
11611184 m_ppSignatures{CI.ppResourceSignatures , CI.ppResourceSignatures + CI.ResourceSignaturesCount }
11621185 {
1163- m_CI.PSODesc .Name = m_Strings.emplace (CI.PSODesc .Name ? CI.PSODesc .Name : " <unnamed>" ).first ->c_str ();
1186+ if (CI.PSODesc .Name != nullptr )
1187+ m_CI.PSODesc .Name = m_Strings.emplace (CI.PSODesc .Name ).first ->c_str ();
11641188
11651189 for (auto & Var : m_Variables)
11661190 Var.Name = m_Strings.emplace (Var.Name ).first ->c_str ();
@@ -1380,6 +1404,7 @@ bool ReloadablePipelineState::Reload(ReloadGraphicsPipelineCallbackType ReloadGr
13801404
13811405 RefCntAutoPtr<IPipelineState> pNewPSO;
13821406
1407+ // Note that the create info struct references reloadable shaders, so that the pipeline will use the updated shaders
13831408 const auto FoundInCache = m_pStateCache->CreatePipelineStateInternal (static_cast <const CreateInfoType&>(CreateInfo), &pNewPSO);
13841409
13851410 if (pNewPSO)
0 commit comments