From 7e359ee4ab9d704173c79bdd8954a1c841a52dae Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 19 Jan 2024 17:19:08 +0000 Subject: [PATCH] Implement D3D12 descriptor fetching contents directly from heaps --- renderdoc/api/replay/d3d12_pipestate.h | 6 + renderdoc/driver/d3d12/d3d12_common.cpp | 20 ++ renderdoc/driver/d3d12/d3d12_common.h | 2 + renderdoc/driver/d3d12/d3d12_device_wrap.cpp | 4 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 337 +++++++++++++++++++ renderdoc/driver/d3d12/d3d12_replay.h | 2 + renderdoc/driver/d3d12/d3d12_resources.cpp | 74 +++- renderdoc/driver/d3d12/d3d12_resources.h | 11 +- renderdoc/replay/renderdoc_serialise.inl | 3 +- 9 files changed, 452 insertions(+), 7 deletions(-) diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index 949f7267c..986b464fe 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -932,6 +932,12 @@ struct State DOCUMENT("The :class:`ResourceId` of the root signature object."); ResourceId rootSignatureResourceId; + DOCUMENT(R"(The descriptor heaps currently bound. + +:type: List[ResourceId] +)"); + rdcarray descriptorHeaps; + DOCUMENT(R"(The root signature, as a range per element. :type: List[D3D12RootSignatureRange] diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index 24a7715a4..0b6c4fb16 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -680,6 +680,26 @@ D3DBufferViewFlags MakeBufferFlags(D3D12_BUFFER_UAV_FLAGS flags) return ret; } +DescriptorFlags MakeDescriptorFlags(D3D12_BUFFER_SRV_FLAGS flags) +{ + DescriptorFlags ret = DescriptorFlags::NoFlags; + + if(flags & D3D12_BUFFER_SRV_FLAG_RAW) + ret |= DescriptorFlags::RawBuffer; + + return ret; +} + +DescriptorFlags MakeDescriptorFlags(D3D12_BUFFER_UAV_FLAGS flags) +{ + DescriptorFlags ret = DescriptorFlags::NoFlags; + + if(flags & D3D12_BUFFER_UAV_FLAG_RAW) + ret |= DescriptorFlags::RawBuffer; + + return ret; +} + LogicOperation MakeLogicOp(D3D12_LOGIC_OP op) { switch(op) diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index 1f5599406..8ff7d1960 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -120,6 +120,8 @@ CompareFunction MakeCompareFunc(D3D12_COMPARISON_FUNC func); TextureFilter MakeFilter(D3D12_FILTER filter); D3DBufferViewFlags MakeBufferFlags(D3D12_BUFFER_SRV_FLAGS flags); D3DBufferViewFlags MakeBufferFlags(D3D12_BUFFER_UAV_FLAGS flags); +DescriptorFlags MakeDescriptorFlags(D3D12_BUFFER_SRV_FLAGS flags); +DescriptorFlags MakeDescriptorFlags(D3D12_BUFFER_UAV_FLAGS flags); LogicOperation MakeLogicOp(D3D12_LOGIC_OP op); BlendMultiplier MakeBlendMultiplier(D3D12_BLEND blend, bool alpha); BlendOperation MakeBlendOp(D3D12_BLEND_OP op); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index ab3d77fbe..35a7f83b8 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -1209,7 +1209,7 @@ bool WrappedID3D12Device::Serialise_DynamicDescriptorWrite(SerialiserType &ser, // be undefined RDCASSERT(desc.GetType() != D3D12DescriptorType::Undefined); desc.Create(D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES, this, *handle); - handle->GetHeap()->MarkMutableView(handle->GetHeapIndex()); + handle->GetHeap()->MarkMutableIndex(handle->GetHeapIndex()); } } @@ -1939,7 +1939,7 @@ bool WrappedID3D12Device::Serialise_DynamicDescriptorCopies( for(const DynamicDescriptorCopy © : DescriptorCopies) { CopyDescriptorsSimple(1, *copy.dst, *copy.src, copy.type); - copy.dst->GetHeap()->MarkMutableView(copy.dst->GetHeapIndex()); + copy.dst->GetHeap()->MarkMutableIndex(copy.dst->GetHeapIndex()); } } diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 53c0fc0bc..23f9d977e 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1029,6 +1029,264 @@ void D3D12Replay::FillSampler(D3D12Pipe::Sampler &samp, const D3D12_SAMPLER_DESC samp.mipLODBias = sampDesc.MipLODBias; } +void D3D12Replay::FillDescriptor(Descriptor &dst, const D3D12Descriptor *src) +{ + D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); + + if(src->GetType() == D3D12DescriptorType::Sampler || src->GetType() == D3D12DescriptorType::CBV) + { + return; + } + + if(src->GetHeap()->HasValidDescriptorCache(src->GetHeapIndex())) + { + src->GetHeap()->GetFromDescriptorCache(src->GetHeapIndex(), dst); + return; + } + + dst.resource = rm->GetOriginalID(src->GetResResourceId()); + + if(dst.resource == ResourceId()) + { + src->GetHeap()->GetFromDescriptorCache(src->GetHeapIndex(), dst); + return; + } + + D3D12_RESOURCE_DESC res; + + { + ID3D12Resource *r = rm->GetCurrentAs(src->GetResResourceId()); + res = r->GetDesc(); + } + + { + DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN; + + uint64_t firstElement = UINT64_MAX; + uint32_t numElements = UINT32_MAX; + + if(src->GetType() == D3D12DescriptorType::SRV) + { + D3D12_SHADER_RESOURCE_VIEW_DESC srv = src->GetSRV(); + + if(srv.ViewDimension == D3D12_SRV_DIMENSION_UNKNOWN) + srv = MakeSRVDesc(res); + + if(srv.ViewDimension == D3D12_SRV_DIMENSION_BUFFER) + dst.type = DescriptorType::TypedBuffer; + else + dst.type = DescriptorType::Image; + + fmt = srv.Format; + + dst.textureType = MakeTextureDim(srv.ViewDimension); + + dst.swizzle.red = + (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(0, srv.Shader4ComponentMapping); + dst.swizzle.green = + (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(1, srv.Shader4ComponentMapping); + dst.swizzle.blue = + (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(2, srv.Shader4ComponentMapping); + dst.swizzle.alpha = + (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(3, srv.Shader4ComponentMapping); + + if(srv.ViewDimension == D3D12_SRV_DIMENSION_BUFFER) + { + firstElement = srv.Buffer.FirstElement; + numElements = srv.Buffer.NumElements; + + dst.flags = MakeDescriptorFlags(srv.Buffer.Flags); + if(srv.Buffer.StructureByteStride > 0) + { + dst.elementByteSize = srv.Buffer.StructureByteStride; + dst.type = DescriptorType::Buffer; + } + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE1D) + { + dst.firstMip = srv.Texture1D.MostDetailedMip & 0xff; + dst.numMips = srv.Texture1D.MipLevels & 0xff; + dst.minLODClamp = srv.Texture1D.ResourceMinLODClamp; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE1DARRAY) + { + dst.numSlices = srv.Texture1DArray.ArraySize & 0xffff; + dst.firstSlice = srv.Texture1DArray.FirstArraySlice & 0xffff; + dst.firstMip = srv.Texture1DArray.MostDetailedMip & 0xff; + dst.numMips = srv.Texture1DArray.MipLevels & 0xff; + dst.minLODClamp = srv.Texture1DArray.ResourceMinLODClamp; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D) + { + dst.firstMip = srv.Texture2D.MostDetailedMip & 0xff; + dst.numMips = srv.Texture2D.MipLevels & 0xff; + dst.minLODClamp = srv.Texture2D.ResourceMinLODClamp; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY) + { + dst.numSlices = srv.Texture2DArray.ArraySize & 0xffff; + dst.firstSlice = srv.Texture2DArray.FirstArraySlice & 0xffff; + dst.firstMip = srv.Texture2DArray.MostDetailedMip & 0xff; + dst.numMips = srv.Texture2DArray.MipLevels & 0xff; + dst.minLODClamp = srv.Texture2DArray.ResourceMinLODClamp; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS) + { + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY) + { + dst.numSlices = srv.Texture2DMSArray.ArraySize & 0xffff; + dst.firstSlice = srv.Texture2DMSArray.FirstArraySlice & 0xffff; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE3D) + { + dst.firstMip = srv.Texture3D.MostDetailedMip & 0xff; + dst.numMips = srv.Texture3D.MipLevels & 0xff; + dst.minLODClamp = srv.Texture3D.ResourceMinLODClamp; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE) + { + dst.numSlices = 6; + dst.firstMip = srv.TextureCube.MostDetailedMip & 0xff; + dst.numMips = srv.TextureCube.MipLevels & 0xff; + dst.minLODClamp = srv.TextureCube.ResourceMinLODClamp; + } + else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) + { + dst.numSlices = (srv.TextureCubeArray.NumCubes * 6) & 0xffff; + dst.firstSlice = srv.TextureCubeArray.First2DArrayFace & 0xffff; + dst.firstMip = srv.TextureCubeArray.MostDetailedMip & 0xff; + dst.numMips = srv.TextureCubeArray.MipLevels & 0xff; + dst.minLODClamp = srv.TextureCube.ResourceMinLODClamp; + } + } + else if(src->GetType() == D3D12DescriptorType::UAV) + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uav = src->GetUAV(); + + if(uav.ViewDimension == D3D12_UAV_DIMENSION_UNKNOWN) + uav = MakeUAVDesc(res); + + if(uav.ViewDimension == D3D12_UAV_DIMENSION_BUFFER) + dst.type = uav.Format != DXGI_FORMAT_UNKNOWN ? DescriptorType::ReadWriteTypedBuffer + : DescriptorType::ReadWriteBuffer; + else + dst.type = DescriptorType::ReadWriteImage; + + fmt = uav.Format; + + dst.secondary = rm->GetOriginalID(src->GetCounterResourceId()); + + dst.textureType = MakeTextureDim(uav.ViewDimension); + + if(uav.ViewDimension == D3D12_UAV_DIMENSION_BUFFER) + { + firstElement = uav.Buffer.FirstElement; + numElements = uav.Buffer.NumElements; + + dst.flags = MakeDescriptorFlags(uav.Buffer.Flags); + if(uav.Buffer.StructureByteStride > 0) + dst.elementByteSize = uav.Buffer.StructureByteStride; + + dst.counterByteOffset = uav.Buffer.CounterOffsetInBytes & 0xffffffff; + RDCASSERT(uav.Buffer.CounterOffsetInBytes < 0xffffffff); + + if(dst.secondary != ResourceId()) + { + bytebuf counterVal; + GetDebugManager()->GetBufferData( + rm->GetCurrentAs(src->GetCounterResourceId()), + uav.Buffer.CounterOffsetInBytes, 4, counterVal); + uint32_t *val = (uint32_t *)&counterVal[0]; + dst.bufferStructCount = *val; + } + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE1D) + { + dst.firstMip = uav.Texture1D.MipSlice & 0xff; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE1DARRAY) + { + dst.numSlices = uav.Texture1DArray.ArraySize & 0xffff; + dst.firstSlice = uav.Texture1DArray.FirstArraySlice & 0xffff; + dst.firstMip = uav.Texture1DArray.MipSlice & 0xff; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2D) + { + dst.firstMip = uav.Texture2D.MipSlice & 0xff; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY) + { + dst.numSlices = uav.Texture2DArray.ArraySize & 0xffff; + dst.firstSlice = uav.Texture2DArray.FirstArraySlice & 0xffff; + dst.firstMip = uav.Texture2DArray.MipSlice & 0xff; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DMS) + { + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY) + { + dst.numSlices = uav.Texture2DMSArray.ArraySize & 0xffff; + dst.firstSlice = uav.Texture2DMSArray.FirstArraySlice & 0xffff; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE3D) + { + dst.numSlices = uav.Texture3D.WSize & 0xffff; + dst.firstSlice = uav.Texture3D.FirstWSlice & 0xffff; + dst.firstMip = uav.Texture3D.MipSlice & 0xff; + } + } + + if(fmt == DXGI_FORMAT_UNKNOWN) + fmt = res.Format; + + if(dst.elementByteSize == 0) + dst.elementByteSize = fmt == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, fmt, 0); + + // decode elements into byte offsets + if(firstElement != UINT64_MAX) + { + dst.byteOffset = firstElement * dst.elementByteSize; + dst.byteSize = numElements * dst.elementByteSize; + } + + if(res.MipLevels == 0 && res.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) + res.MipLevels = (uint16_t)CalcNumMips( + (uint32_t)res.Width, res.Height, + res.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? res.DepthOrArraySize : 1); + dst.numMips = RDCMIN(dst.numMips, uint8_t(res.MipLevels & 0xff)); + dst.numSlices = RDCMIN(dst.numSlices, res.DepthOrArraySize); + + dst.format = MakeResourceFormat(fmt); + } + + src->GetHeap()->SetToDescriptorCache(src->GetHeapIndex(), dst); +} + +void D3D12Replay::FillSamplerDescriptor(SamplerDescriptor &dst, const D3D12_SAMPLER_DESC2 &src) +{ + dst.type = DescriptorType::Sampler; + + dst.addressU = MakeAddressMode(src.AddressU); + dst.addressV = MakeAddressMode(src.AddressV); + dst.addressW = MakeAddressMode(src.AddressW); + + dst.borderColorValue.uintValue = src.UintBorderColor; + dst.borderColorType = + ((src.Flags & D3D12_SAMPLER_FLAG_UINT_BORDER_COLOR) != 0 ? CompType::UInt : CompType::Float); + + dst.unnormalized = (src.Flags & D3D12_SAMPLER_FLAG_NON_NORMALIZED_COORDINATES) != 0; + + dst.compareFunction = MakeCompareFunc(src.ComparisonFunc); + dst.filter = MakeFilter(src.Filter); + dst.maxAnisotropy = 0; + if(dst.filter.minify == FilterMode::Anisotropic) + dst.maxAnisotropy = (float)src.MaxAnisotropy; + dst.maxLOD = src.MaxLOD; + dst.minLOD = src.MinLOD; + dst.mipBias = src.MipLODBias; +} + ShaderStageMask ToShaderStageMask(D3D12_SHADER_VISIBILITY vis) { switch(vis) @@ -1818,6 +2076,10 @@ void D3D12Replay::SavePipelineState(uint32_t eventId) } } + state.descriptorHeaps.clear(); + for(ResourceId id : rs.heaps) + state.descriptorHeaps.push_back(rm->GetOriginalID(id)); + if(pipe && pipe->IsGraphics()) { ///////////////////////////////////////////////// @@ -2071,22 +2333,97 @@ void D3D12Replay::SavePipelineState(uint32_t eventId) rdcarray D3D12Replay::GetDescriptors(ResourceId descriptorStore, const rdcarray &ranges) { + if(descriptorStore == ResourceId()) + return {}; + size_t count = 0; for(const DescriptorRange &r : ranges) count += r.count; rdcarray ret; ret.resize(count); + + D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); + + WrappedID3D12DescriptorHeap *heap = + (WrappedID3D12DescriptorHeap *)rm->GetCurrentAs(descriptorStore); + + size_t dst = 0; + for(const DescriptorRange &r : ranges) + { + D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; + D3D12Descriptor *end = desc + heap->GetNumDescriptors(); + + desc += r.offset; + + for(uint32_t i = 0; i < r.count; i++) + { + if(desc >= end) + { + // silently drop out of bounds descriptor reads + } + else if(desc->GetType() == D3D12DescriptorType::CBV) + { + const D3D12_CONSTANT_BUFFER_VIEW_DESC &cbv = desc->GetCBV(); + WrappedID3D12Resource::GetResIDFromAddr(cbv.BufferLocation, ret[dst].resource, + ret[dst].byteOffset); + + ret[dst].resource = rm->GetOriginalID(ret[dst].resource); + ret[dst].byteSize = cbv.SizeInBytes; + } + else if(desc->GetType() != D3D12DescriptorType::Sampler) + { + D3D12Pipe::View view; + FillDescriptor(ret[dst], desc); + } + dst++; + desc++; + } + } + return ret; } rdcarray D3D12Replay::GetSamplerDescriptors(ResourceId descriptorStore, const rdcarray &ranges) { + if(descriptorStore == ResourceId()) + return {}; + size_t count = 0; for(const DescriptorRange &r : ranges) count += r.count; rdcarray ret; ret.resize(count); + + D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); + + WrappedID3D12DescriptorHeap *heap = + (WrappedID3D12DescriptorHeap *)rm->GetCurrentAs(descriptorStore); + + size_t dst = 0; + for(const DescriptorRange &r : ranges) + { + D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; + D3D12Descriptor *end = desc + heap->GetNumDescriptors(); + + desc += r.offset; + + for(uint32_t i = 0; i < r.count; i++) + { + if(desc >= end) + { + // silently drop out of bounds descriptor reads + } + else if(desc->GetType() == D3D12DescriptorType::Sampler) + { + const D3D12_SAMPLER_DESC2 &sampDesc = desc->GetSampler(); + FillSamplerDescriptor(ret[dst], sampDesc); + } + dst++; + desc++; + } + } + return ret; } diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 8c609ca71..256802f8b 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -270,6 +270,8 @@ private: rdcarray &rootElements); void FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor *desc); void FillSampler(D3D12Pipe::Sampler &view, const D3D12_SAMPLER_DESC2 &desc); + void FillDescriptor(Descriptor &dst, const D3D12Descriptor *src); + void FillSamplerDescriptor(SamplerDescriptor &dst, const D3D12_SAMPLER_DESC2 &src); bool CreateSOBuffers(); void ClearPostVSCache(); diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 37c484a1d..7fe435aa8 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -499,13 +499,15 @@ bool WrappedID3D12DescriptorHeap::HasValidViewCache(uint32_t index) if((mutableViewBitmask[index / 64] & (1ULL << (index % 64))) != 0) return false; + EnsureViewCache(); + // anything that's not mutable is valid once it's been set at least once. Since we // zero-initialise, we use bind as a flag (it isn't retrieved from the cache since it depends on // the binding) return cachedViews[index].bind == 1; } -void WrappedID3D12DescriptorHeap::MarkMutableView(uint32_t index) +void WrappedID3D12DescriptorHeap::MarkMutableIndex(uint32_t index) { if(!mutableViewBitmask) return; @@ -518,6 +520,8 @@ void WrappedID3D12DescriptorHeap::GetFromViewCache(uint32_t index, D3D12Pipe::Vi if(!mutableViewBitmask) return; + EnsureViewCache(); + bool dynamicallyUsed = view.dynamicallyUsed; uint32_t bind = view.bind; uint32_t tableIndex = view.tableIndex; @@ -532,11 +536,73 @@ void WrappedID3D12DescriptorHeap::SetToViewCache(uint32_t index, const D3D12Pipe if(!mutableViewBitmask) return; + EnsureViewCache(); + cachedViews[index] = view; // we re-use bind as the indicator that this view is valid cachedViews[index].bind = 1; } +void WrappedID3D12DescriptorHeap::EnsureViewCache() +{ + if(!cachedViews) + { + D3D12_DESCRIPTOR_HEAP_DESC desc = GetDesc(); + cachedViews = new D3D12Pipe::View[desc.NumDescriptors]; + RDCEraseMem(cachedViews, sizeof(D3D12Pipe::View) * desc.NumDescriptors); + } +} + +bool WrappedID3D12DescriptorHeap::HasValidDescriptorCache(uint32_t index) +{ + if(!mutableViewBitmask) + return false; + + // don't cache mutable views. In theory we could but we'd need to know which ones were modified + // mid-frame, to mark the cache as stale when initial contents are re-applied. This optimisation + // is aimed at the assumption of a huge number of descriptors that don't change so we just don't + // cache ones that change mid-frame + if((mutableViewBitmask[index / 64] & (1ULL << (index % 64))) != 0) + return false; + + EnsureDescriptorCache(); + + // anything that's not mutable is valid once it's been set at least once. Since we + // zero-initialise, we use bind as a flag (it isn't retrieved from the cache since it depends on + // the binding) + return cachedDescriptors[index].type != DescriptorType::Unknown; +} + +void WrappedID3D12DescriptorHeap::GetFromDescriptorCache(uint32_t index, Descriptor &view) +{ + if(!mutableViewBitmask) + return; + + EnsureDescriptorCache(); + + view = cachedDescriptors[index]; +} + +void WrappedID3D12DescriptorHeap::EnsureDescriptorCache() +{ + if(!cachedDescriptors) + { + D3D12_DESCRIPTOR_HEAP_DESC desc = GetDesc(); + cachedDescriptors = new Descriptor[desc.NumDescriptors]; + RDCEraseMem(cachedDescriptors, sizeof(Descriptor) * desc.NumDescriptors); + } +} + +void WrappedID3D12DescriptorHeap::SetToDescriptorCache(uint32_t index, const Descriptor &view) +{ + if(!mutableViewBitmask) + return; + + EnsureDescriptorCache(); + + cachedDescriptors[index] = view; +} + WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *real, WrappedID3D12Device *device, const D3D12_DESCRIPTOR_HEAP_DESC &desc, @@ -562,8 +628,8 @@ WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *r { size_t bitmaskSize = AlignUp(desc.NumDescriptors, 64U) / 64; - cachedViews = new D3D12Pipe::View[desc.NumDescriptors]; - RDCEraseMem(cachedViews, sizeof(D3D12Pipe::View) * desc.NumDescriptors); + cachedViews = NULL; + cachedDescriptors = NULL; mutableViewBitmask = new uint64_t[bitmaskSize]; RDCEraseMem(mutableViewBitmask, sizeof(uint64_t) * bitmaskSize); @@ -571,6 +637,7 @@ WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *r else { cachedViews = NULL; + cachedDescriptors = NULL; mutableViewBitmask = NULL; } } @@ -580,6 +647,7 @@ WrappedID3D12DescriptorHeap::~WrappedID3D12DescriptorHeap() Shutdown(); SAFE_DELETE_ARRAY(descriptors); SAFE_DELETE_ARRAY(cachedViews); + SAFE_DELETE_ARRAY(cachedDescriptors); SAFE_DELETE_ARRAY(mutableViewBitmask); } diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index b383c3333..74f01e5d6 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -396,6 +396,7 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12