Skip to content

Commit 1edf9ce

Browse files
azhirnovTheMostDiligent
authored andcommitted
Added support for user implementation of device memory interface
1 parent 25f20fd commit 1edf9ce

File tree

6 files changed

+38
-15
lines changed

6 files changed

+38
-15
lines changed

Graphics/GraphicsEngine/interface/DeviceContext.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,9 @@ struct SparseBufferMemoryBindRange
17031703
/// all previous bindings are invalidated.
17041704
/// Vulkan & Direct3D12: different resource regions may be bound to different memory objects.
17051705
/// Vulkan: memory object must be compatible with the resource, use IDeviceMemory::IsCompatible() to ensure that.
1706+
///
1707+
/// \note Memory object can be created by the engine using IRenderDevice::CreateDeviceMemory() or can be implemented by the user.
1708+
/// Memory object must implement interface methods for each backend (IDeviceMemoryD3D11, IDeviceMemoryD3D12, IDeviceMemoryVk).
17061709
IDeviceMemory* pMemory DEFAULT_INITIALIZER(nullptr);
17071710

17081711
#if DILIGENT_CPP_INTERFACE
@@ -1781,10 +1784,13 @@ struct SparseTextureMemoryBindRange
17811784
/// \remarks
17821785
/// Direct3D11: the entire texture must use a single memory object; when a resource is bound to a new memory
17831786
/// object, all previous bindings are invalidated.
1784-
/// Vulkan & Direct3D12: different resource regions may be bound to different memory objects.
1787+
/// Vulkan & Direct3D12: different resource regions may be bound to different memory objects.
17851788
/// Metal: must be the same memory object that was used to create the sparse texture,
17861789
/// see IRenderDeviceMtl::CreateSparseTexture().
17871790
/// Vulkan: memory object must be compatible with the resource, use IDeviceMemory::IsCompatible() to ensure that.
1791+
///
1792+
/// \note Memory object can be created by the engine using IRenderDevice::CreateDeviceMemory() or can be implemented by the user.
1793+
/// Memory object must implement interface methods for each backend (IDeviceMemoryD3D11, IDeviceMemoryD3D12, IDeviceMemoryVk).
17881794
IDeviceMemory* pMemory DEFAULT_INITIALIZER(nullptr);
17891795
};
17901796
typedef struct SparseTextureMemoryBindRange SparseTextureMemoryBindRange;

Graphics/GraphicsEngineD3D12/include/DeviceMemoryD3D12Impl.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ class DeviceMemoryD3D12Impl final : public DeviceMemoryBase<EngineD3D12ImplTrait
6161
/// Implementation of IDeviceMemoryD3D12::GetRange().
6262
virtual DeviceMemoryRangeD3D12 DILIGENT_CALL_TYPE GetRange(Uint64 Offset, Uint64 Size) const override final;
6363

64-
bool IsUsingNVApi() const { return m_UseNVApi; }
64+
/// Implementation of IDeviceMemoryD3D12::IsUsingNVApi().
65+
virtual Bool DILIGENT_CALL_TYPE IsUsingNVApi() const override final { return m_UseNVApi; }
6566

6667
private:
6768
D3D12_HEAP_FLAGS m_d3d12HeapFlags = D3D12_HEAP_FLAG_NONE;

Graphics/GraphicsEngineD3D12/interface/DeviceMemoryD3D12.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,18 @@ DILIGENT_BEGIN_INTERFACE(IDeviceMemoryD3D12, IDeviceMemory)
7070
VIRTUAL DeviceMemoryRangeD3D12 METHOD(GetRange)(THIS_
7171
Uint64 Offset,
7272
Uint64 Size) CONST PURE;
73+
74+
/// Returns true if the heap was created using NVApi.
75+
VIRTUAL Bool METHOD(IsUsingNVApi)(THIS) CONST PURE;
7376
};
7477
DILIGENT_END_INTERFACE
7578

7679
#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h"
7780

7881
#if DILIGENT_C_INTERFACE
7982

80-
# define IDeviceMemoryD3D12_GetRange(This, ...) CALL_IFACE_METHOD(DeviceMemoryD3D12, GetRange, This, __VA_ARGS__)
83+
# define IDeviceMemoryD3D12_GetRange(This, ...) CALL_IFACE_METHOD(DeviceMemoryD3D12, GetRange, This, __VA_ARGS__)
84+
# define IDeviceMemoryD3D12_IsUsingNVApi(This) CALL_IFACE_METHOD(DeviceMemoryD3D12, IsUsingNVApi, This)
8185

8286
#endif
8387

Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,9 +3044,11 @@ void DeviceContextD3D12Impl::BindSparseResourceMemory(const BindSparseResourceMe
30443044
for (Uint32 r = 0; r < BuffBind.NumRanges; ++r)
30453045
{
30463046
const auto& BindRange = BuffBind.pRanges[r];
3047-
const auto* pMemD3D12 = ClassPtrCast<const DeviceMemoryD3D12Impl>(BindRange.pMemory);
3048-
const auto MemRange = pMemD3D12 ? pMemD3D12->GetRange(BindRange.MemoryOffset, BindRange.MemorySize) : DeviceMemoryRangeD3D12{};
3047+
const auto pMemD3D12 = RefCntAutoPtr<IDeviceMemoryD3D12>{BindRange.pMemory, IID_DeviceMemoryD3D12};
3048+
DEV_CHECK_ERR((BindRange.pMemory != nullptr) == (pMemD3D12 != nullptr),
3049+
"Failed to query IDeviceMemoryD3D12 interface from non-null memory object");
30493050

3051+
const auto MemRange = pMemD3D12 ? pMemD3D12->GetRange(BindRange.MemoryOffset, BindRange.MemorySize) : DeviceMemoryRangeD3D12{};
30503052
DEV_CHECK_ERR((MemRange.Offset % D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES) == 0,
30513053
"MemoryOffset must be a multiple of sparse block size");
30523054

@@ -3066,9 +3068,13 @@ void DeviceContextD3D12Impl::BindSparseResourceMemory(const BindSparseResourceMe
30663068
for (Uint32 r = 0; r < TexBind.NumRanges; ++r)
30673069
{
30683070
const auto& BindRange = TexBind.pRanges[r];
3069-
const auto* pMemD3D12 = ClassPtrCast<const DeviceMemoryD3D12Impl>(BindRange.pMemory);
3070-
const auto MemRange = pMemD3D12 ? pMemD3D12->GetRange(BindRange.MemoryOffset, BindRange.MemorySize) : DeviceMemoryRangeD3D12{};
3071+
const auto pMemD3D12 = RefCntAutoPtr<IDeviceMemoryD3D12>{BindRange.pMemory, IID_DeviceMemoryD3D12};
3072+
DEV_CHECK_ERR((BindRange.pMemory != nullptr) == (pMemD3D12 != nullptr),
3073+
"Failed to query IDeviceMemoryD3D12 interface from non-null memory object");
30713074

3075+
const auto MemRange = pMemD3D12 ? pMemD3D12->GetRange(BindRange.MemoryOffset, BindRange.MemorySize) : DeviceMemoryRangeD3D12{};
3076+
DEV_CHECK_ERR((MemRange.Offset % D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES) == 0,
3077+
"MemoryOffset must be a multiple of sparse block size");
30723078
VERIFY_EXPR(pMemD3D12 == nullptr || pMemD3D12->IsUsingNVApi() == UseNVApi);
30733079

30743080
auto& DstMapping = TileMappingMap[TileMappingKey{pTexD3D12->GetD3D12Resource(), MemRange.pHandle}];

Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,10 +3800,12 @@ void DeviceContextVkImpl::BindSparseResourceMemory(const BindSparseResourceMemor
38003800

38013801
for (Uint32 r = 0; r < BuffBind.NumRanges; ++r)
38023802
{
3803-
const auto& SrcRange = BuffBind.pRanges[r];
3804-
const auto* pMemVk = ClassPtrCast<const DeviceMemoryVkImpl>(SrcRange.pMemory);
3805-
const auto MemRangeVk = pMemVk ? pMemVk->GetRange(SrcRange.MemoryOffset, SrcRange.MemorySize) : DeviceMemoryRangeVk{};
3803+
const auto& SrcRange = BuffBind.pRanges[r];
3804+
const auto pMemVk = RefCntAutoPtr<IDeviceMemoryVk>{SrcRange.pMemory, IID_DeviceMemoryVk};
3805+
DEV_CHECK_ERR((SrcRange.pMemory != nullptr) == (pMemVk != nullptr),
3806+
"Failed to query IDeviceMemoryVk interface from non-null memory object");
38063807

3808+
const auto MemRangeVk = pMemVk ? pMemVk->GetRange(SrcRange.MemoryOffset, SrcRange.MemorySize) : DeviceMemoryRangeVk{};
38073809
DEV_CHECK_ERR(MemRangeVk.Offset % BuffSparseProps.BlockSize == 0,
38083810
"MemoryOffset must be multiple of the SparseBufferProperties::BlockSize");
38093811

@@ -3837,10 +3839,12 @@ void DeviceContextVkImpl::BindSparseResourceMemory(const BindSparseResourceMemor
38373839
Uint32 NumImageBindsInRange = 0;
38383840
for (Uint32 r = 0; r < TexBind.NumRanges; ++r)
38393841
{
3840-
const auto& SrcRange = TexBind.pRanges[r];
3841-
const auto* pMemVk = ClassPtrCast<const DeviceMemoryVkImpl>(SrcRange.pMemory);
3842-
const auto MemRangeVk = pMemVk ? pMemVk->GetRange(SrcRange.MemoryOffset, SrcRange.MemorySize) : DeviceMemoryRangeVk{};
3842+
const auto& SrcRange = TexBind.pRanges[r];
3843+
const auto pMemVk = RefCntAutoPtr<IDeviceMemoryVk>{SrcRange.pMemory, IID_DeviceMemoryVk};
3844+
DEV_CHECK_ERR((SrcRange.pMemory != nullptr) == (pMemVk != nullptr),
3845+
"Failed to query IDeviceMemoryVk interface from non-null memory object");
38433846

3847+
const auto MemRangeVk = pMemVk ? pMemVk->GetRange(SrcRange.MemoryOffset, SrcRange.MemorySize) : DeviceMemoryRangeVk{};
38443848
DEV_CHECK_ERR((MemRangeVk.Offset % TexSparseProps.BlockSize) == 0,
38453849
"MemoryOffset must be a multiple of the SparseTextureProperties::BlockSize");
38463850

Tests/DiligentCoreAPITest/src/SparseResourcesTest.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,8 +1906,10 @@ TEST_F(SparseResourceTest, SparseTexture3D)
19061906
{
19071907
GTEST_SKIP() << "Sparse texture 3D is not supported by this device";
19081908
}
1909-
if (pDevice->GetDeviceInfo().IsMetalDevice())
1910-
GTEST_SKIP() << "UAV sparse texture is not supported in Metal"; // AZ TODO: query texture bind flags
1909+
if ((pDevice->GetSparseTextureFormatInfo(TEX_FORMAT_RGBA8_UNORM, RESOURCE_DIM_TEX_3D, 1).BindFlags & BIND_UNORDERED_ACCESS) != 0)
1910+
{
1911+
GTEST_SKIP() << "Sparse texture UAV is not supported by this device";
1912+
}
19111913

19121914
TestingEnvironment::ScopedReset EnvironmentAutoReset;
19131915

0 commit comments

Comments
 (0)