Skip to content

Commit 1a27656

Browse files
Added IRenderDevice::CreateDeferredContext() method (API256007)
1 parent 70bdd5b commit 1a27656

File tree

21 files changed

+155
-85
lines changed

21 files changed

+155
-85
lines changed

Graphics/Archiver/include/SerializationDeviceImpl.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -72,6 +72,7 @@ class SerializationDeviceImpl final : public RenderDeviceBase<SerializationEngin
7272
UNSUPPORTED_METHOD(void, CreatePipelineResourceSignature, const PipelineResourceSignatureDesc& Desc, IPipelineResourceSignature** ppSignature)
7373
UNSUPPORTED_METHOD(void, CreateDeviceMemory, const DeviceMemoryCreateInfo& CreateInfo, IDeviceMemory** ppMemory)
7474
UNSUPPORTED_METHOD(void, CreatePipelineStateCache, const PipelineStateCacheCreateInfo& CreateInfo, IPipelineStateCache** ppPSOCache)
75+
UNSUPPORTED_METHOD(void, CreateDeferredContext, IDeviceContext** ppContext)
7576
UNSUPPORTED_METHOD(void, IdleGPU)
7677
UNSUPPORTED_METHOD(void, ReleaseStaleResources, bool ForceRelease)
7778
// clang-format on

Graphics/GraphicsEngine/include/RenderDeviceBase.hpp

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <thread>
3535
#include <vector>
3636
#include <unordered_set>
37+
#include <mutex>
3738

3839
#include "RenderDevice.h"
3940
#include "DeviceObjectBase.hpp"
@@ -308,13 +309,6 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
308309
m_wpImmediateContexts[Ctx] = pImmediateContext;
309310
}
310311

311-
/// Set weak reference to the deferred context
312-
void SetDeferredContext(size_t Ctx, DeviceContextImplType* pDeferredCtx)
313-
{
314-
VERIFY(m_wpDeferredContexts[Ctx].Lock() == nullptr, "Deferred context has already been set");
315-
m_wpDeferredContexts[Ctx] = pDeferredCtx;
316-
}
317-
318312
/// Returns the number of immediate contexts
319313
size_t GetNumImmediateContexts() const
320314
{
@@ -324,11 +318,23 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
324318
/// Returns number of deferred contexts
325319
size_t GetNumDeferredContexts() const
326320
{
321+
std::lock_guard<std::mutex> Guard{m_DeferredCtxMtx};
327322
return m_wpDeferredContexts.size();
328323
}
329324

330-
RefCntAutoPtr<DeviceContextImplType> GetImmediateContext(size_t Ctx) { return m_wpImmediateContexts[Ctx].Lock(); }
331-
RefCntAutoPtr<DeviceContextImplType> GetDeferredContext(size_t Ctx) { return m_wpDeferredContexts[Ctx].Lock(); }
325+
RefCntAutoPtr<DeviceContextImplType> GetImmediateContext(size_t Ctx)
326+
{
327+
return Ctx < m_wpImmediateContexts.size() ?
328+
m_wpImmediateContexts[Ctx].Lock() :
329+
RefCntAutoPtr<DeviceContextImplType>{};
330+
}
331+
RefCntAutoPtr<DeviceContextImplType> GetDeferredContext(size_t Ctx)
332+
{
333+
std::lock_guard<std::mutex> Guard{m_DeferredCtxMtx};
334+
return Ctx < m_wpDeferredContexts.size() ?
335+
m_wpDeferredContexts[Ctx].Lock() :
336+
RefCntAutoPtr<DeviceContextImplType>{};
337+
}
332338

333339
FixedBlockMemoryAllocator& GetTexViewObjAllocator() { return m_TexViewObjAllocator; }
334340
FixedBlockMemoryAllocator& GetBuffViewObjAllocator() { return m_BuffViewObjAllocator; }
@@ -454,11 +460,11 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
454460
const std::string ObjectDescString = GetObjectDescString(Desc);
455461
if (!ObjectDescString.empty())
456462
{
457-
LOG_ERROR("Failed to create ", ObjectTypeName, " object '", (Desc.Name ? Desc.Name : ""), "'\n", ObjectDescString);
463+
LOG_ERROR("Failed to create ", ObjectTypeName, " '", (Desc.Name ? Desc.Name : ""), "'\n", ObjectDescString);
458464
}
459465
else
460466
{
461-
LOG_ERROR("Failed to create ", ObjectTypeName, " object '", (Desc.Name ? Desc.Name : ""), "'");
467+
LOG_ERROR("Failed to create ", ObjectTypeName, " '", (Desc.Name ? Desc.Name : ""), "'");
462468
}
463469
}
464470
}
@@ -549,7 +555,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
549555
template <typename... ExtraArgsType>
550556
void CreateRenderPassImpl(IRenderPass** ppRenderPass, const RenderPassDesc& Desc, const ExtraArgsType&... ExtraArgs)
551557
{
552-
CreateDeviceObject("RenderPass", Desc, ppRenderPass,
558+
CreateDeviceObject("Render Pass", Desc, ppRenderPass,
553559
[&]() //
554560
{
555561
RenderPassImplType* pRenderPassImpl = NEW_RC_OBJ(m_RenderPassAllocator, "Render instance", RenderPassImplType)(static_cast<RenderDeviceImplType*>(this), Desc, ExtraArgs...);
@@ -571,7 +577,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
571577
template <typename... ExtraArgsType>
572578
void CreateBLASImpl(IBottomLevelAS** ppBLAS, const BottomLevelASDesc& Desc, const ExtraArgsType&... ExtraArgs)
573579
{
574-
CreateDeviceObject("BottomLevelAS", Desc, ppBLAS,
580+
CreateDeviceObject("Bottom-level AS", Desc, ppBLAS,
575581
[&]() //
576582
{
577583
BottomLevelASImplType* pBottomLevelASImpl = NEW_RC_OBJ(m_BLASAllocator, "BottomLevelAS instance", BottomLevelASImplType)(static_cast<RenderDeviceImplType*>(this), Desc, ExtraArgs...);
@@ -582,7 +588,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
582588
template <typename... ExtraArgsType>
583589
void CreateTLASImpl(ITopLevelAS** ppTLAS, const TopLevelASDesc& Desc, const ExtraArgsType&... ExtraArgs)
584590
{
585-
CreateDeviceObject("TopLevelAS", Desc, ppTLAS,
591+
CreateDeviceObject("Top-level AS", Desc, ppTLAS,
586592
[&]() //
587593
{
588594
TopLevelASImplType* pTopLevelASImpl = NEW_RC_OBJ(m_TLASAllocator, "TopLevelAS instance", TopLevelASImplType)(static_cast<RenderDeviceImplType*>(this), Desc, ExtraArgs...);
@@ -592,7 +598,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
592598

593599
void CreateSBTImpl(IShaderBindingTable** ppSBT, const ShaderBindingTableDesc& Desc)
594600
{
595-
CreateDeviceObject("ShaderBindingTable", Desc, ppSBT,
601+
CreateDeviceObject("Shader Binding Table", Desc, ppSBT,
596602
[&]() //
597603
{
598604
ShaderBindingTableImplType* pSBTImpl = NEW_RC_OBJ(m_SBTAllocator, "ShaderBindingTable instance", ShaderBindingTableImplType)(static_cast<RenderDeviceImplType*>(this), Desc);
@@ -603,7 +609,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
603609
template <typename... ExtraArgsType>
604610
void CreatePipelineResourceSignatureImpl(IPipelineResourceSignature** ppSignature, const PipelineResourceSignatureDesc& Desc, const ExtraArgsType&... ExtraArgs)
605611
{
606-
CreateDeviceObject("PipelineResourceSignature", Desc, ppSignature,
612+
CreateDeviceObject("Pipeline Resource Signature", Desc, ppSignature,
607613
[&]() //
608614
{
609615
PipelineResourceSignatureImplType* pPRSImpl = NEW_RC_OBJ(m_PipeResSignAllocator, "PipelineResourceSignature instance", PipelineResourceSignatureImplType)(static_cast<RenderDeviceImplType*>(this), Desc, ExtraArgs...);
@@ -614,7 +620,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
614620
template <typename... ExtraArgsType>
615621
void CreateDeviceMemoryImpl(IDeviceMemory** ppMemory, const DeviceMemoryCreateInfo& MemCI, const ExtraArgsType&... ExtraArgs)
616622
{
617-
CreateDeviceObject("DeviceMemory", MemCI.Desc, ppMemory,
623+
CreateDeviceObject("Device Memory", MemCI.Desc, ppMemory,
618624
[&]() //
619625
{
620626
DeviceMemoryImplType* pDevMemImpl = NEW_RC_OBJ(m_MemObjAllocator, "DeviceMemory instance", DeviceMemoryImplType)(static_cast<RenderDeviceImplType*>(this), MemCI, ExtraArgs...);
@@ -624,14 +630,54 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
624630

625631
void CreatePipelineStateCacheImpl(IPipelineStateCache** ppCache, const PipelineStateCacheCreateInfo& PSOCacheCI)
626632
{
627-
CreateDeviceObject("PSOCache", PSOCacheCI.Desc, ppCache,
633+
CreateDeviceObject("PSO Cache", PSOCacheCI.Desc, ppCache,
628634
[&]() //
629635
{
630636
PipelineStateCacheImplType* pPSOCacheImpl = NEW_RC_OBJ(m_PSOCacheAllocator, "PSOCache instance", PipelineStateCacheImplType)(static_cast<RenderDeviceImplType*>(this), PSOCacheCI);
631637
pPSOCacheImpl->QueryInterface(IID_PipelineStateCache, reinterpret_cast<IObject**>(ppCache));
632638
});
633639
}
634640

641+
template <typename... ExtraArgsType>
642+
void CreateDeferredContextImpl(IDeviceContext** ppContext, const ExtraArgsType&... ExtraArgs)
643+
{
644+
std::lock_guard<std::mutex> Guard{m_DeferredCtxMtx};
645+
646+
Uint32 CtxIndex = 0;
647+
while (CtxIndex < m_wpDeferredContexts.size() && m_wpDeferredContexts[CtxIndex].IsValid())
648+
++CtxIndex;
649+
650+
const Uint32 ContextId = static_cast<Uint32>(GetNumImmediateContexts()) + CtxIndex;
651+
const std::string CtxName = std::string{"Deferred context "} + std::to_string(CtxIndex) + " (ContextId: " + std::to_string(ContextId) + ")";
652+
DeviceContextDesc Desc{
653+
CtxName.c_str(),
654+
COMMAND_QUEUE_TYPE_UNKNOWN,
655+
true, // IsDeferred
656+
ContextId,
657+
};
658+
659+
CreateDeviceObject("Device context", Desc, ppContext,
660+
[&]() //
661+
{
662+
DeviceContextImplType* pCtxImpl = NEW_RC_OBJ(GetRawAllocator(), "DeviceContext instance", DeviceContextImplType)(
663+
static_cast<RenderDeviceImplType*>(this),
664+
Desc,
665+
ExtraArgs...);
666+
pCtxImpl->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContext));
667+
});
668+
669+
if (*ppContext != nullptr)
670+
{
671+
if (CtxIndex >= m_wpDeferredContexts.size())
672+
{
673+
VERIFY_EXPR(CtxIndex == m_wpDeferredContexts.size());
674+
m_wpDeferredContexts.resize(CtxIndex + 1);
675+
}
676+
677+
m_wpDeferredContexts[CtxIndex] = static_cast<DeviceContextImplType*>(*ppContext);
678+
}
679+
}
680+
635681
protected:
636682
RefCntAutoPtr<IEngineFactory> m_pEngineFactory;
637683

@@ -651,6 +697,7 @@ class RenderDeviceBase : public ObjectBase<typename EngineImplTraits::RenderDevi
651697
std::vector<RefCntWeakPtr<DeviceContextImplType>, STDAllocatorRawMem<RefCntWeakPtr<DeviceContextImplType>>> m_wpImmediateContexts;
652698

653699
/// Weak references to deferred contexts.
700+
mutable std::mutex m_DeferredCtxMtx;
654701
std::vector<RefCntWeakPtr<DeviceContextImplType>, STDAllocatorRawMem<RefCntWeakPtr<DeviceContextImplType>>> m_wpDeferredContexts;
655702

656703
IMemoryAllocator& m_RawMemAllocator; ///< Raw memory allocator

Graphics/GraphicsEngine/interface/APIInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
/// \file
3131
/// Diligent API information
3232

33-
#define DILIGENT_API_VERSION 256006
33+
#define DILIGENT_API_VERSION 256007
3434

3535
#include "../../../Primitives/interface/BasicTypes.h"
3636

Graphics/GraphicsEngine/interface/GraphicsTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3462,6 +3462,8 @@ struct EngineCreateInfo
34623462
/// IEngineFactoryD3D12::CreateDeviceAndContextsD3D12, and IEngineFactoryVk::CreateDeviceAndContextsVk)
34633463
/// starting at position max(1, NumImmediateContexts).
34643464
///
3465+
/// \remarks Additional deferred contexts may be created later by calling IRenderDevice::CreateDeferredContext().
3466+
///
34653467
/// \warning An application must manually call IDeviceContext::FinishFrame for
34663468
/// deferred contexts to let the engine release stale resources.
34673469
Uint32 NumDeferredContexts DEFAULT_INITIALIZER(0);

Graphics/GraphicsEngine/interface/RenderDevice.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -53,6 +53,7 @@
5353
#include "ShaderBindingTable.h"
5454
#include "PipelineResourceSignature.h"
5555
#include "DeviceMemory.h"
56+
#include "DeviceContext.h"
5657

5758
#include "DepthStencilState.h"
5859
#include "RasterizerState.h"
@@ -335,6 +336,15 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject)
335336
IPipelineStateCache** ppPSOCache) PURE;
336337

337338

339+
/// Creates a deferred context.
340+
341+
/// \param [out] ppContext - Address of the memory location where a pointer to the
342+
/// deferred context interface will be written.
343+
///
344+
/// \remarks Deferred contexts are not supported in OpenGL and WebGPU backends.
345+
VIRTUAL void METHOD(CreateDeferredContext)(THIS_
346+
IDeviceContext** ppContext) PURE;
347+
338348
/// Returns the device information, see Diligent::RenderDeviceInfo for details.
339349
VIRTUAL const RenderDeviceInfo REF METHOD(GetDeviceInfo)(THIS) CONST PURE;
340350

@@ -452,6 +462,8 @@ DILIGENT_END_INTERFACE
452462
# define IRenderDevice_CreateSBT(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSBT, This, __VA_ARGS__)
453463
# define IRenderDevice_CreatePipelineResourceSignature(This, ...) CALL_IFACE_METHOD(RenderDevice, CreatePipelineResourceSignature, This, __VA_ARGS__)
454464
# define IRenderDevice_CreateDeviceMemory(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateDeviceMemory, This, __VA_ARGS__)
465+
# define IRenderDevice_CreatePipelineStateCache(This, ...) CALL_IFACE_METHOD(RenderDevice, CreatePipelineStateCache, This, __VA_ARGS__)
466+
# define IRenderDevice_CreateDeferredContext(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateDeferredContext, This, __VA_ARGS__)
455467
# define IRenderDevice_GetAdapterInfo(This) CALL_IFACE_METHOD(RenderDevice, GetAdapterInfo, This)
456468
# define IRenderDevice_GetDeviceInfo(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceInfo, This)
457469
# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__)

Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ class DeviceContextD3D11Impl final : public DeviceContextBase<EngineD3D11ImplTra
5555
using TDeviceContextBase = DeviceContextBase<EngineD3D11ImplTraits>;
5656

5757
DeviceContextD3D11Impl(IReferenceCounters* pRefCounters,
58-
IMemoryAllocator& Allocator,
5958
RenderDeviceD3D11Impl* pDevice,
60-
ID3D11DeviceContext1* pd3d11DeviceContext,
61-
const DeviceContextDesc& Desc);
59+
const DeviceContextDesc& Desc,
60+
ID3D11DeviceContext1* pd3d11DeviceContext);
6261
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
6362

6463
/// Implementation of IDeviceContext::Begin() in Direct3D11 backend.

Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ class RenderDeviceD3D11Impl final : public RenderDeviceD3DBase<EngineD3D11ImplTr
132132
virtual void DILIGENT_CALL_TYPE CreatePipelineStateCache(const PipelineStateCacheCreateInfo& CreateInfo,
133133
IPipelineStateCache** ppPSOCache) override final;
134134

135+
/// Implementation of IRenderDevice::CreateDeferredContext() in Direct3D11 backend.
136+
virtual void DILIGENT_CALL_TYPE CreateDeferredContext(IDeviceContext** ppContext) override final;
137+
135138
/// Implementation of IRenderDeviceD3D11::GetD3D11Device() in Direct3D11 backend.
136139
ID3D11Device* DILIGENT_CALL_TYPE GetD3D11Device() override final { return m_pd3d11Device; }
137140

Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,17 @@ namespace Diligent
4848
{
4949

5050
DeviceContextD3D11Impl::DeviceContextD3D11Impl(IReferenceCounters* pRefCounters,
51-
IMemoryAllocator& Allocator,
5251
RenderDeviceD3D11Impl* pDevice,
53-
ID3D11DeviceContext1* pd3d11DeviceContext,
54-
const DeviceContextDesc& Desc) :
52+
const DeviceContextDesc& Desc,
53+
ID3D11DeviceContext1* pd3d11DeviceContext) :
5554
// clang-format off
5655
TDeviceContextBase
5756
{
5857
pRefCounters,
5958
pDevice,
6059
Desc
6160
},
62-
m_pd3d11DeviceContext {pd3d11DeviceContext },
61+
m_pd3d11DeviceContext {pd3d11DeviceContext},
6362
#ifdef DILIGENT_DEVELOPMENT
6463
m_D3D11ValidationFlags{pDevice->GetProperties().D3D11ValidationFlags},
6564
#endif

Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -389,14 +389,15 @@ void EngineFactoryD3D11Impl::AttachToD3D11Device(void* pd
389389

390390
RefCntAutoPtr<DeviceContextD3D11Impl> pDeviceContextD3D11{
391391
NEW_RC_OBJ(RawAllocator, "DeviceContextD3D11Impl instance", DeviceContextD3D11Impl)(
392-
RawAllocator, pRenderDeviceD3D11, pd3d11ImmediateCtx1,
392+
pRenderDeviceD3D11,
393393
DeviceContextDesc{
394394
EngineCI.pImmediateContextInfo ? EngineCI.pImmediateContextInfo[0].Name : nullptr,
395395
pRenderDeviceD3D11->GetAdapterInfo().Queues[0].QueueType,
396396
False, // IsDefered
397397
0, // Context id
398398
0 // Queue id
399-
} //
399+
},
400+
pd3d11ImmediateCtx1 //
400401
)};
401402
// We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D11 will
402403
// keep a weak reference to the context
@@ -405,29 +406,7 @@ void EngineFactoryD3D11Impl::AttachToD3D11Device(void* pd
405406

406407
for (Uint32 DeferredCtx = 0; DeferredCtx < EngineCI.NumDeferredContexts; ++DeferredCtx)
407408
{
408-
CComPtr<ID3D11DeviceContext> pd3d11DeferredCtx;
409-
410-
HRESULT hr = pd3d11Device->CreateDeferredContext(0, &pd3d11DeferredCtx);
411-
CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D11 deferred context");
412-
413-
CComQIPtr<ID3D11DeviceContext1> pd3d11DeferredCtx1{pd3d11DeferredCtx};
414-
if (!pd3d11DeferredCtx1)
415-
LOG_ERROR_AND_THROW("Failed to get ID3D11DeviceContext1 interface from device context");
416-
417-
RefCntAutoPtr<DeviceContextD3D11Impl> pDeferredCtxD3D11{
418-
NEW_RC_OBJ(RawAllocator, "DeviceContextD3D11Impl instance", DeviceContextD3D11Impl)(
419-
RawAllocator, pRenderDeviceD3D11, pd3d11DeferredCtx1,
420-
DeviceContextDesc{
421-
nullptr,
422-
COMMAND_QUEUE_TYPE_UNKNOWN,
423-
true,
424-
1 + DeferredCtx // Context id
425-
} //
426-
)};
427-
// We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will
428-
// keep a weak reference to the context
429-
pDeferredCtxD3D11->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts + 1 + DeferredCtx));
430-
pRenderDeviceD3D11->SetDeferredContext(DeferredCtx, pDeferredCtxD3D11);
409+
pRenderDeviceD3D11->CreateDeferredContext(ppContexts + 1 + DeferredCtx);
431410
}
432411
}
433412
catch (const std::runtime_error&)

0 commit comments

Comments
 (0)