From ea368a631e5c98ef4cadf790ab44170e4ac59816 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 10 Nov 2025 15:46:23 +0000 Subject: [PATCH] Allow GPU upload heaps to be enabled in D3D12. Closes #3724 * We attempt to enable the experimental feature since this allows the use of the feature on a much wider set of OS versions, at the time of this commit support seems quite rare/narrow. --- .../driver/d3d12/d3d12_command_queue_wrap.cpp | 1 + renderdoc/driver/d3d12/d3d12_device_wrap.cpp | 14 ----------- renderdoc/driver/d3d12/d3d12_hooks.cpp | 8 +++++-- renderdoc/driver/d3d12/d3d12_replay.cpp | 24 +++++++++++++++++++ util/test/demos/d3d12/d3d12_helpers.cpp | 7 ++++++ util/test/demos/d3d12/d3d12_helpers.h | 1 + 6 files changed, 39 insertions(+), 16 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index 66861df40..aa26df69b 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -1083,6 +1083,7 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists res->GetHeapProperties(&heapProps, NULL); if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD || + heapProps.Type == D3D12_HEAP_TYPE_GPU_UPLOAD || heapProps.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE) { RDCLOG("Doing GPU readback of mapped memory"); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index a32a732ad..92a42a714 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -2421,20 +2421,6 @@ HRESULT WrappedID3D12Device::CheckFeatureSupport(D3D12_FEATURE Feature, void *pF return S_OK; } - else if(Feature == D3D12_FEATURE_D3D12_OPTIONS16) - { - D3D12_FEATURE_DATA_D3D12_OPTIONS16 *opts = - (D3D12_FEATURE_DATA_D3D12_OPTIONS16 *)pFeatureSupportData; - if(FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS16)) - return E_INVALIDARG; - - opts->GPUUploadHeapSupported = FALSE; - - if(dolog) - RDCLOG("Forcing no GPU upload heap support"); - - return S_OK; - } else if(Feature == D3D12_FEATURE_D3D12_OPTIONS18) { D3D12_FEATURE_DATA_D3D12_OPTIONS18 *opts = diff --git a/renderdoc/driver/d3d12/d3d12_hooks.cpp b/renderdoc/driver/d3d12/d3d12_hooks.cpp index 903fa789c..1bc9ce624 100644 --- a/renderdoc/driver/d3d12/d3d12_hooks.cpp +++ b/renderdoc/driver/d3d12/d3d12_hooks.cpp @@ -417,11 +417,13 @@ public: { rdcarray allowedIIDs; - // allow enabling unsigned DXIL. + // allow enabling unsigned DXIL, and GPU upload heaps on most windows versions for(UINT i = 0; i < NumFeatures; i++) { if(pIIDs[i] == D3D12ExperimentalShaderModels) allowedIIDs.push_back(D3D12ExperimentalShaderModels); + else if(pIIDs[i] == D3D12GPUUploadHeapsOnUnsupportedOS) + allowedIIDs.push_back(D3D12GPUUploadHeapsOnUnsupportedOS); } // there's no "partially successful" error code, so we just lie to the application and pretend @@ -913,11 +915,13 @@ private: { rdcarray allowedIIDs; - // allow enabling unsigned DXIL. + // allow enabling unsigned DXIL, and GPU upload heaps on most windows versions for(UINT i = 0; i < NumFeatures; i++) { if(pIIDs[i] == D3D12ExperimentalShaderModels) allowedIIDs.push_back(D3D12ExperimentalShaderModels); + else if(pIIDs[i] == D3D12GPUUploadHeapsOnUnsupportedOS) + allowedIIDs.push_back(D3D12GPUUploadHeapsOnUnsupportedOS); } // there's no "partially successful" error code, so we just lie to the application and pretend diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 0f7970f46..6ad2b8504 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -50,6 +50,9 @@ RDOC_CONFIG(bool, D3D12_HardwareCounters, true, "Enable support for IHV-specific hardware counters on D3D12."); +RDOC_CONFIG(bool, D3D12_AttemptExperimentalGPUUploadEnable, true, + "Try to enable 'experimental' support for GPU upload heaps on D3D12."); + // this is global so we can free it even after D3D12Replay is destroyed static HMODULE D3D12Lib = NULL; @@ -4523,6 +4526,14 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl PFN_D3D12_CREATE_DEVICE createDevicePtr = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(D3D12Lib, "D3D12CreateDevice"); + typedef HRESULT(WINAPI * PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)( + UINT NumFeatures, const IID *pIIDs, void *pConfigurationStructs, + UINT *pConfigurationStructSizes); + + PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES enableExperimentalPtr = + (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)GetProcAddress(D3D12Lib, + "D3D12EnableExperimentalFeatures"); + RealD3D12CreateFunction createDevice = createDevicePtr; HMODULE dxgilib = LoadLibraryA("dxgi.dll"); @@ -4734,6 +4745,19 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl RDCLOG("DRED enabled"); } + if(D3D12_AttemptExperimentalGPUUploadEnable()) + { + if(config) + { + config->devfactory->EnableExperimentalFeatures(1, &D3D12GPUUploadHeapsOnUnsupportedOS, NULL, + NULL); + } + else + { + enableExperimentalPtr(1, &D3D12GPUUploadHeapsOnUnsupportedOS, NULL, NULL); + } + } + ID3D12Device *dev = NULL; if(config) hr = config->devfactory->CreateDevice(adapter, initParams.MinimumFeatureLevel, diff --git a/util/test/demos/d3d12/d3d12_helpers.cpp b/util/test/demos/d3d12/d3d12_helpers.cpp index 676a66bbf..33c1de189 100644 --- a/util/test/demos/d3d12/d3d12_helpers.cpp +++ b/util/test/demos/d3d12/d3d12_helpers.cpp @@ -267,6 +267,13 @@ D3D12BufferCreator &D3D12BufferCreator::ASB() return *this; } +D3D12BufferCreator &D3D12BufferCreator::GPUUpload() +{ + m_HeapDesc.Type = D3D12_HEAP_TYPE_GPU_UPLOAD; + m_InitialState = D3D12_RESOURCE_STATE_COMMON; + return *this; +} + D3D12BufferCreator &D3D12BufferCreator::Upload() { m_HeapDesc.Type = D3D12_HEAP_TYPE_UPLOAD; diff --git a/util/test/demos/d3d12/d3d12_helpers.h b/util/test/demos/d3d12/d3d12_helpers.h index ddd66d66f..22a350464 100644 --- a/util/test/demos/d3d12/d3d12_helpers.h +++ b/util/test/demos/d3d12/d3d12_helpers.h @@ -137,6 +137,7 @@ public: D3D12BufferCreator &UAV(); D3D12BufferCreator &ASB(); + D3D12BufferCreator &GPUUpload(); D3D12BufferCreator &Upload(); D3D12BufferCreator &Readback();