From 6a24d35dec5b1619f2ab470a94e2a9d50e31b040 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 18 Mar 2025 22:33:03 -0300 Subject: [PATCH] Finish D3D12 Support. --- UnleashedRecomp/gpu/rhi/plume_d3d12.cpp | 33 +++++++++++++++++++++---- UnleashedRecomp/gpu/rhi/plume_d3d12.h | 1 + UnleashedRecomp/gpu/video.cpp | 9 +++++-- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp index 1ac7dfc4..97bb942a 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp @@ -2387,7 +2387,7 @@ namespace plume { range.End = readRange->end; } - void *outputData; + void *outputData = nullptr; d3d->Map(subresource, (readRange != nullptr) ? &range : nullptr, &outputData); return outputData; } @@ -2638,7 +2638,15 @@ namespace plume { this->desc = desc; D3D12MA::POOL_DESC poolDesc = {}; - poolDesc.HeapProperties.Type = toD3D12(desc.heapType); + + // When using an UMA architecture without explicit support for GPU Upload heaps, we instead just make a custom heap with the same properties as Upload heaps. + if (desc.heapType == RenderHeapType::GPU_UPLOAD && device->capabilities.uma && !device->capabilities.gpuUploadHeap) { + poolDesc.HeapProperties = device->d3d->GetCustomHeapProperties(0, D3D12_HEAP_TYPE_UPLOAD); + } + else { + poolDesc.HeapProperties.Type = toD3D12(desc.heapType); + } + poolDesc.MinBlockCount = desc.minBlockCount; poolDesc.MaxBlockCount = desc.maxBlockCount; poolDesc.Flags |= desc.useLinearAlgorithm ? D3D12MA::POOL_FLAG_ALGORITHM_LINEAR : D3D12MA::POOL_FLAG_NONE; @@ -3392,7 +3400,7 @@ namespace plume { if (SUCCEEDED(res)) { triangleFanSupportOption = d3d12Options15.TriangleFanSupported; } - + // Check if dynamic depth bias and GPU upload heap are supported. bool dynamicDepthBiasOption = false; bool gpuUploadHeapOption = false; @@ -3435,7 +3443,10 @@ namespace plume { capabilities.triangleFan = triangleFanSupportOption; capabilities.dynamicDepthBias = dynamicDepthBiasOption; capabilities.uma = uma; - capabilities.gpuUploadHeap = gpuUploadHeapOption; + + // Pretend GPU Upload heaps are supported if UMA is supported, as the backend has a workaround using a custom pool for it. + capabilities.gpuUploadHeap = uma || gpuUploadHeapOption; + description.name = deviceName; description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory; description.vendor = RenderDeviceVendor(adapterDesc.VendorId); @@ -3533,6 +3544,13 @@ namespace plume { colorTargetHeapAllocator = std::make_unique(this, TargetDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_RTV); depthTargetHeapAllocator = std::make_unique(this, TargetDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_DSV); + // Create the custom upload pool that will be used as the fallback when using an UMA architecture without explicit support for GPU Upload heaps. + if (capabilities.uma && !capabilities.gpuUploadHeap) { + RenderPoolDesc poolDesc; + poolDesc.heapType = RenderHeapType::GPU_UPLOAD; + customUploadPool = std::make_unique(this, poolDesc); + } + // Create a command queue only for retrieving the timestamp frequency. Delete it immediately afterwards. std::unique_ptr timestampCommandQueue = std::make_unique(this, RenderCommandListType::DIRECT); res = timestampCommandQueue->d3d->GetTimestampFrequency(×tampFrequency); @@ -3582,7 +3600,12 @@ namespace plume { } std::unique_ptr D3D12Device::createBuffer(const RenderBufferDesc &desc) { - return std::make_unique(this, nullptr, desc); + if ((desc.heapType == RenderHeapType::GPU_UPLOAD) && capabilities.uma && !capabilities.gpuUploadHeap) { + return std::make_unique(this, customUploadPool.get(), desc); + } + else { + return std::make_unique(this, nullptr, desc); + } } std::unique_ptr D3D12Device::createTexture(const RenderTextureDesc &desc) { diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.h b/UnleashedRecomp/gpu/rhi/plume_d3d12.h index d4987fbc..87980e56 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.h +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.h @@ -430,6 +430,7 @@ namespace plume { std::unique_ptr samplerHeapAllocator; std::unique_ptr colorTargetHeapAllocator; std::unique_ptr depthTargetHeapAllocator; + std::unique_ptr customUploadPool; RenderDeviceCapabilities capabilities; RenderDeviceDescription description; uint64_t timestampFrequency = 1; diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 4dfa2e7e..28caa169 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -2109,6 +2109,8 @@ static void* LockVertexBuffer(GuestBuffer* buffer, uint32_t, uint32_t, uint32_t return LockBuffer(buffer, flags); } +static std::atomic g_bufferUploadCount = 0; + template static void UnlockBuffer(GuestBuffer* buffer, bool useCopyQueue) { @@ -2124,7 +2126,7 @@ static void UnlockBuffer(GuestBuffer* buffer, bool useCopyQueue) } }; - if (useCopyQueue && (g_capabilities.uma || g_capabilities.gpuUploadHeap)) + if (useCopyQueue && g_capabilities.gpuUploadHeap) { copyBuffer(reinterpret_cast(buffer->buffer->map())); buffer->buffer->unmap(); @@ -2153,6 +2155,8 @@ static void UnlockBuffer(GuestBuffer* buffer, bool useCopyQueue) g_tempBuffers[g_frame].emplace_back(std::move(uploadBuffer)); } } + + g_bufferUploadCount++; } template @@ -2330,10 +2334,11 @@ static void DrawProfiler() std::lock_guard lock(g_userHeap.physicalMutex); physicalDiagnostics = o1heapGetDiagnostics(g_userHeap.physicalHeap); } - + ImGui::Text("Heap Allocated: %d MB", int32_t(diagnostics.allocated / (1024 * 1024))); ImGui::Text("Physical Heap Allocated: %d MB", int32_t(physicalDiagnostics.allocated / (1024 * 1024))); ImGui::Text("GPU Waits: %d", int32_t(g_waitForGPUCount)); + ImGui::Text("Buffer Uploads: %d", int32_t(g_bufferUploadCount)); ImGui::NewLine(); ImGui::Text("Present Wait: %s", g_capabilities.presentWait ? "Supported" : "Unsupported");