From 8530da827474bce8f11a2b9575f56ddd46d27e9c Mon Sep 17 00:00:00 2001 From: Vladislav Korytsko Date: Sat, 29 Nov 2025 18:44:05 +0200 Subject: [PATCH] Fix dataSize calculation in WriteToSubresource Corrects width, height, and depth calculation in WriteToSubresource for the specified subresource when storing provided source data blob. Using base resource dimensions could have led to source-data read access violation. Also updates corresponding test to validate subresource modification. --- renderdoc/driver/d3d12/d3d12_device.cpp | 8 ++-- .../demos/d3d12/d3d12_write_subresource.cpp | 48 +++++++++++++++---- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 97c605fb8..25f45c7c9 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -2338,10 +2338,12 @@ bool WrappedID3D12Device::Serialise_WriteToSubresource(SerialiserType &ser, ID3D } else { - UINT width = UINT(desc.Width); - UINT height = desc.Height; + UINT width = RDCMAX(1U, UINT(desc.Width) >> Subresource); + UINT height = RDCMAX(1U, desc.Height >> Subresource); // only 3D textures have a depth, array slices are separate subresources. - UINT depth = (desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? desc.DepthOrArraySize : 1); + UINT depth = (desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D + ? RDCMAX(1U, UINT(desc.DepthOrArraySize) >> Subresource) + : 1); // if we have a box, use its dimensions if(pDstBox) diff --git a/util/test/demos/d3d12/d3d12_write_subresource.cpp b/util/test/demos/d3d12/d3d12_write_subresource.cpp index 3469de91a..51e48b1c6 100644 --- a/util/test/demos/d3d12/d3d12_write_subresource.cpp +++ b/util/test/demos/d3d12/d3d12_write_subresource.cpp @@ -69,6 +69,9 @@ float4 main(v2f IN) : SV_Target0 D3D12_STATIC_SAMPLER_DESC staticSamp = {}; staticSamp.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; staticSamp.AddressU = staticSamp.AddressV = staticSamp.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + // LOD is clamped to 0 since input SRV has multiple mips for subresource-modification + // validation, but only the first one is considered as output result. + staticSamp.MinLOD = staticSamp.MaxLOD = 0; staticSamp.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; ID3D12RootSignaturePtr sig = MakeSig( @@ -86,11 +89,15 @@ float4 main(v2f IN) : SV_Target0 heap.MemoryPoolPreference = D3D12_MEMORY_POOL_L0; heap.Type = D3D12_HEAP_TYPE_CUSTOM; - uint32_t *texData = new uint32_t[2048 * 2084]; + const size_t width = 2048, height = 2048; + const UINT subresourceIdx = 8; - ID3D12ResourcePtr tex = MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM, 2048, 2048) + uint32_t *baseData = new uint32_t[width * height]; + uint32_t *subresourceData = new uint32_t[(width * height) >> (2 * subresourceIdx)]; + + ID3D12ResourcePtr tex = MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM, width, height) .CustomHeap(heap) - .Mips(1) + .Mips(12) .InitialState(D3D12_RESOURCE_STATE_COMMON); D3D12_GPU_DESCRIPTOR_HANDLE view = @@ -102,15 +109,36 @@ float4 main(v2f IN) : SV_Target0 GPUSync(); - tex->Map(0, NULL, NULL); + { + const size_t rowPitch = width * sizeof(uint32_t), depthPitch = rowPitch * height; - memset(texData, 0, 2048 * 2048 * sizeof(uint32_t)); - tex->WriteToSubresource(0, NULL, texData, 1024 * 4, 1024 * 1024); - D3D12_BOX box = {400, 400, 0, 1600, 1600, 1}; - memset(texData, 0xff, 2048 * 2048 * sizeof(uint32_t)); - tex->WriteToSubresource(0, &box, texData, 1024 * 4, 1024 * 1024); + tex->Map(0, NULL, NULL); - tex->Unmap(0, NULL); + memset(baseData, 0x00, depthPitch); + tex->WriteToSubresource(0, NULL, baseData, rowPitch, depthPitch); + + D3D12_BOX box = {400, 400, 0, 1600, 1600, 1}; + memset(baseData, 0xff, depthPitch); + tex->WriteToSubresource(0, &box, baseData, rowPitch, depthPitch); + + tex->Unmap(0, NULL); + } + + { + const size_t rowPitch = (width >> subresourceIdx) * sizeof(uint32_t), + depthPitch = rowPitch * (height >> subresourceIdx); + + tex->Map(subresourceIdx, NULL, NULL); + + memset(subresourceData, 0x00, depthPitch); + tex->WriteToSubresource(subresourceIdx, NULL, subresourceData, rowPitch, depthPitch); + + D3D12_BOX box = {1, 1, 0, 7, 7, 1}; + memset(subresourceData, 0xff, depthPitch); + tex->WriteToSubresource(subresourceIdx, &box, subresourceData, rowPitch, depthPitch); + + tex->Unmap(subresourceIdx, NULL); + } GPUSync();