Skip to content

Commit e81c3be

Browse files
Render state cache: fixed asynchronous pipelines reloading
1 parent b305ad2 commit e81c3be

File tree

3 files changed

+173
-35
lines changed

3 files changed

+173
-35
lines changed

Graphics/GraphicsTools/include/ReloadablePipelineState.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,18 @@ class ReloadablePipelineState final : public ProxyPipelineState<ObjectBase<IPipe
6161

6262
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
6363

64+
virtual PIPELINE_STATE_STATUS DILIGENT_CALL_TYPE GetStatus(bool WaitForCompletion) override;
65+
6466
static void Create(RenderStateCacheImpl* pStateCache,
6567
IPipelineState* pPipeline,
6668
const PipelineStateCreateInfo& CreateInfo,
6769
IPipelineState** ppReloadablePipeline);
6870

6971
bool Reload(ReloadGraphicsPipelineCallbackType ReloadGraphicsPipeline, void* pUserData);
7072

73+
private:
74+
void CopyStaticResources();
75+
7176
private:
7277
template <typename CreateInfoType>
7378
bool Reload(ReloadGraphicsPipelineCallbackType ReloadGraphicsPipeline, void* pUserData);
@@ -80,6 +85,9 @@ class ReloadablePipelineState final : public ProxyPipelineState<ObjectBase<IPipe
8085
RefCntAutoPtr<RenderStateCacheImpl> m_pStateCache;
8186
std::unique_ptr<CreateInfoWrapperBase> m_pCreateInfo;
8287
const PIPELINE_TYPE m_Type;
88+
89+
// Old pipeline state kept around to copy static resources from
90+
RefCntAutoPtr<IPipelineState> m_pOldPipeline;
8391
};
8492

8593
} // namespace Diligent

Graphics/GraphicsTools/src/ReloadablePipelineState.cpp

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,23 +168,19 @@ bool ReloadablePipelineState::Reload(ReloadGraphicsPipelineCallbackType ReloadGr
168168
{
169169
if (m_pPipeline != pNewPSO)
170170
{
171-
const auto SrcSignCount = m_pPipeline->GetResourceSignatureCount();
172-
const auto DstSignCount = pNewPSO->GetResourceSignatureCount();
173-
if (SrcSignCount == DstSignCount)
171+
// Do not update old pipeline if it is not null.
172+
// If multiple reloads are requested, we need to keep the original pipeline that keeps the original resources.
173+
if (!m_pOldPipeline)
174174
{
175-
for (Uint32 s = 0; s < SrcSignCount; ++s)
176-
{
177-
auto* pSrcSign = m_pPipeline->GetResourceSignature(s);
178-
auto* pDstSign = pNewPSO->GetResourceSignature(s);
179-
if (pSrcSign != pDstSign)
180-
pSrcSign->CopyStaticResources(pDstSign);
181-
}
175+
m_pOldPipeline = m_pPipeline;
182176
}
183-
else
177+
m_pPipeline = pNewPSO;
178+
179+
// If any of the pipelines is not ready, we will copy static resources when both are ready in GetStatus()
180+
if (m_pPipeline->GetStatus() == PIPELINE_STATE_STATUS_READY && m_pOldPipeline->GetStatus() == PIPELINE_STATE_STATUS_READY)
184181
{
185-
UNEXPECTED("The number of resource signatures in old pipeline (", SrcSignCount, ") does not match the number of signatures in new pipeline (", DstSignCount, ")");
182+
CopyStaticResources();
186183
}
187-
m_pPipeline = pNewPSO;
188184
}
189185
}
190186
else
@@ -195,6 +191,58 @@ bool ReloadablePipelineState::Reload(ReloadGraphicsPipelineCallbackType ReloadGr
195191
return !FoundInCache;
196192
}
197193

194+
void ReloadablePipelineState::CopyStaticResources()
195+
{
196+
const Uint32 SrcSignCount = m_pOldPipeline->GetResourceSignatureCount();
197+
const Uint32 DstSignCount = m_pPipeline->GetResourceSignatureCount();
198+
if (SrcSignCount == DstSignCount)
199+
{
200+
for (Uint32 s = 0; s < SrcSignCount; ++s)
201+
{
202+
IPipelineResourceSignature* pSrcSign = m_pOldPipeline->GetResourceSignature(s);
203+
IPipelineResourceSignature* pDstSign = m_pPipeline->GetResourceSignature(s);
204+
if (pSrcSign != pDstSign)
205+
{
206+
pSrcSign->CopyStaticResources(pDstSign);
207+
}
208+
}
209+
}
210+
else
211+
{
212+
UNEXPECTED("The number of resource signatures in old pipeline (", SrcSignCount, ") does not match the number of signatures in new pipeline (", DstSignCount, ")");
213+
}
214+
m_pOldPipeline.Release();
215+
}
216+
217+
218+
PIPELINE_STATE_STATUS ReloadablePipelineState::GetStatus(bool WaitForCompletion)
219+
{
220+
const PIPELINE_STATE_STATUS Status = m_pPipeline ? m_pPipeline->GetStatus(WaitForCompletion) : PIPELINE_STATE_STATUS_FAILED;
221+
if (Status != PIPELINE_STATE_STATUS_READY)
222+
return Status;
223+
224+
if (m_pOldPipeline)
225+
{
226+
const PIPELINE_STATE_STATUS OldPsoStatus = m_pOldPipeline->GetStatus(WaitForCompletion);
227+
if (OldPsoStatus == PIPELINE_STATE_STATUS_READY && Status == PIPELINE_STATE_STATUS_READY)
228+
{
229+
CopyStaticResources();
230+
}
231+
else if (OldPsoStatus == PIPELINE_STATE_STATUS_COMPILING)
232+
{
233+
// Wait until the old pipeline is ready
234+
return PIPELINE_STATE_STATUS_COMPILING;
235+
}
236+
else if (OldPsoStatus == PIPELINE_STATE_STATUS_FAILED)
237+
{
238+
LOG_ERROR_MESSAGE("Failed to copy static resources from the old pipeline after reloading pipeline state '", m_pPipeline->GetDesc().Name,
239+
"'. Old pipeline is in the failed state.");
240+
m_pOldPipeline.Release();
241+
}
242+
}
243+
244+
return Status;
245+
}
198246

199247
bool ReloadablePipelineState::Reload(ReloadGraphicsPipelineCallbackType ReloadGraphicsPipeline, void* pUserData)
200248
{

0 commit comments

Comments
 (0)