diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index 13a003da9..87c368e5a 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -269,6 +269,10 @@ struct View DOCUMENT("The :class:`ResourceId` of the underlying resource the view refers to."); ResourceId resourceId; + DOCUMENT("The :class:`ResourceId` of the resource where the hidden buffer counter is stored."); + ResourceId counterResourceId; + DOCUMENT("The byte offset in :data:`counterResourceId` where the counter is stored."); + uint32_t counterByteOffset = 0; DOCUMENT("The :class:`TextureType` of the view type."); TextureType type; DOCUMENT(R"(The format cast that the view uses. @@ -293,6 +297,14 @@ since single descriptors may only be dynamically skipped by control flow. bool dynamicallyUsed = true; DOCUMENT("The :class:`D3DBufferViewFlags` set for the buffer."); D3DBufferViewFlags bufferFlags = D3DBufferViewFlags::NoFlags; + DOCUMENT("Valid for textures - the highest mip that is available through the view."); + uint8_t firstMip = 0; + DOCUMENT("Valid for textures - the number of mip levels in the view."); + uint8_t numMips = 1; + DOCUMENT("Valid for texture arrays or 3D textures - the first slice available through the view."); + uint16_t firstSlice = 0; + DOCUMENT("Valid for texture arrays or 3D textures - the number of slices in the view."); + uint16_t numSlices = 1; DOCUMENT("If the view has a hidden counter, this stores the current value of the counter."); uint32_t bufferStructCount = 0; DOCUMENT(R"(The byte size of a single element in the view. Either the byte size of @@ -304,21 +316,6 @@ since single descriptors may only be dynamically skipped by control flow. DOCUMENT("Valid for buffers - the number of elements to be used in the view."); uint32_t numElements = 1; - DOCUMENT("The :class:`ResourceId` of the resource where the hidden buffer counter is stored."); - ResourceId counterResourceId; - DOCUMENT("The byte offset in :data:`counterResourceId` where the counter is stored."); - uint64_t counterByteOffset = 0; - - DOCUMENT("Valid for textures - the highest mip that is available through the view."); - uint32_t firstMip = 0; - DOCUMENT("Valid for textures - the number of mip levels in the view."); - uint32_t numMips = 1; - - DOCUMENT("Valid for texture arrays or 3D textures - the first slice available through the view."); - uint32_t firstSlice = 0; - DOCUMENT("Valid for texture arrays or 3D textures - the number of slices in the view."); - uint32_t numSlices = 1; - DOCUMENT("The minimum mip-level clamp applied when sampling this texture."); float minLODClamp = 0.0f; }; diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 25b526bcd..9b49315aa 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -734,7 +734,7 @@ DOCUMENT(R"(The dimensionality of a texture binding. A Cubemap texture array. )"); -enum class TextureType : uint32_t +enum class TextureType : uint16_t { Unknown, First = Unknown, diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index 740392244..2354d9744 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -1176,6 +1176,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()); } } @@ -2552,7 +2553,10 @@ bool WrappedID3D12Device::Serialise_DynamicDescriptorCopies( { // not optimal, but simple for now. Do a wrapped copy so that internal tracking is also updated for(const DynamicDescriptorCopy © : DescriptorCopies) + { CopyDescriptorsSimple(1, *copy.dst, *copy.src, copy.type); + copy.dst->GetHeap()->MarkMutableView(copy.dst->GetHeapIndex()); + } } return true; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 26c5793e2..3158e8df0 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -660,10 +660,19 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor return; } + if(desc->GetHeap()->HasValidViewCache(desc->GetHeapIndex())) + { + desc->GetHeap()->GetFromViewCache(desc->GetHeapIndex(), view); + return; + } + view.resourceId = rm->GetOriginalID(desc->GetResResourceId()); if(view.resourceId == ResourceId()) + { + desc->GetHeap()->SetToViewCache(desc->GetHeapIndex(), view); return; + } D3D12_RESOURCE_DESC res; @@ -690,30 +699,30 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor } else if(rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE1D) { - view.firstMip = rtv.Texture1D.MipSlice; + view.firstMip = rtv.Texture1D.MipSlice & 0xff; view.numMips = 1; view.firstSlice = 0; view.numSlices = 1; } else if(rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE1DARRAY) { - view.firstMip = rtv.Texture1DArray.MipSlice; + view.firstMip = rtv.Texture1DArray.MipSlice & 0xff; view.numMips = 1; - view.numSlices = rtv.Texture1DArray.ArraySize; - view.firstSlice = rtv.Texture1DArray.FirstArraySlice; + view.numSlices = rtv.Texture1DArray.ArraySize & 0xffff; + view.firstSlice = rtv.Texture1DArray.FirstArraySlice & 0xffff; } else if(rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2D) { - view.firstMip = rtv.Texture2D.MipSlice; + view.firstMip = rtv.Texture2D.MipSlice & 0xff; view.numMips = 1; view.firstSlice = 0; view.numSlices = 1; } else if(rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DARRAY) { - view.numSlices = rtv.Texture2DArray.ArraySize; - view.firstSlice = rtv.Texture2DArray.FirstArraySlice; - view.firstMip = rtv.Texture2DArray.MipSlice; + view.numSlices = rtv.Texture2DArray.ArraySize & 0xffff; + view.firstSlice = rtv.Texture2DArray.FirstArraySlice & 0xffff; + view.firstMip = rtv.Texture2DArray.MipSlice & 0xff; view.numMips = 1; } else if(rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DMS) @@ -727,14 +736,14 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor { view.firstMip = 0; view.numMips = 1; - view.numSlices = rtv.Texture2DMSArray.ArraySize; - view.firstSlice = rtv.Texture2DMSArray.FirstArraySlice; + view.numSlices = rtv.Texture2DMSArray.ArraySize & 0xffff; + view.firstSlice = rtv.Texture2DMSArray.FirstArraySlice & 0xffff; } else if(rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE3D) { - view.numSlices = rtv.Texture3D.WSize; - view.firstSlice = rtv.Texture3D.FirstWSlice; - view.firstMip = rtv.Texture3D.MipSlice; + view.numSlices = rtv.Texture3D.WSize & 0xffff; + view.firstSlice = rtv.Texture3D.FirstWSlice & 0xffff; + view.firstMip = rtv.Texture3D.MipSlice & 0xff; view.numMips = 1; } } @@ -748,31 +757,31 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor if(dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE1D) { - view.firstMip = dsv.Texture1D.MipSlice; + view.firstMip = dsv.Texture1D.MipSlice & 0xff; } else if(dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE1DARRAY) { - view.numSlices = dsv.Texture1DArray.ArraySize; - view.firstSlice = dsv.Texture1DArray.FirstArraySlice; - view.firstMip = dsv.Texture1DArray.MipSlice; + view.numSlices = dsv.Texture1DArray.ArraySize & 0xffff; + view.firstSlice = dsv.Texture1DArray.FirstArraySlice & 0xffff; + view.firstMip = dsv.Texture1DArray.MipSlice & 0xff; } else if(dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2D) { - view.firstMip = dsv.Texture2D.MipSlice; + view.firstMip = dsv.Texture2D.MipSlice & 0xff; } else if(dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY) { - view.numSlices = dsv.Texture2DArray.ArraySize; - view.firstSlice = dsv.Texture2DArray.FirstArraySlice; - view.firstMip = dsv.Texture2DArray.MipSlice; + view.numSlices = dsv.Texture2DArray.ArraySize & 0xffff; + view.firstSlice = dsv.Texture2DArray.FirstArraySlice & 0xffff; + view.firstMip = dsv.Texture2DArray.MipSlice & 0xff; } else if(dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DMS) { } else if(dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY) { - view.numSlices = dsv.Texture2DMSArray.ArraySize; - view.firstSlice = dsv.Texture2DMSArray.FirstArraySlice; + view.numSlices = dsv.Texture2DMSArray.ArraySize & 0xffff; + view.firstSlice = dsv.Texture2DMSArray.FirstArraySlice & 0xffff; } } else if(desc->GetType() == D3D12DescriptorType::SRV) @@ -806,30 +815,30 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE1D) { - view.firstMip = srv.Texture1D.MostDetailedMip; - view.numMips = srv.Texture1D.MipLevels; + view.firstMip = srv.Texture1D.MostDetailedMip & 0xff; + view.numMips = srv.Texture1D.MipLevels & 0xff; view.minLODClamp = srv.Texture1D.ResourceMinLODClamp; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE1DARRAY) { - view.numSlices = srv.Texture1DArray.ArraySize; - view.firstSlice = srv.Texture1DArray.FirstArraySlice; - view.firstMip = srv.Texture1DArray.MostDetailedMip; - view.numMips = srv.Texture1DArray.MipLevels; + view.numSlices = srv.Texture1DArray.ArraySize & 0xffff; + view.firstSlice = srv.Texture1DArray.FirstArraySlice & 0xffff; + view.firstMip = srv.Texture1DArray.MostDetailedMip & 0xff; + view.numMips = srv.Texture1DArray.MipLevels & 0xff; view.minLODClamp = srv.Texture1DArray.ResourceMinLODClamp; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D) { - view.firstMip = srv.Texture2D.MostDetailedMip; - view.numMips = srv.Texture2D.MipLevels; + view.firstMip = srv.Texture2D.MostDetailedMip & 0xff; + view.numMips = srv.Texture2D.MipLevels & 0xff; view.minLODClamp = srv.Texture2D.ResourceMinLODClamp; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY) { - view.numSlices = srv.Texture2DArray.ArraySize; - view.firstSlice = srv.Texture2DArray.FirstArraySlice; - view.firstMip = srv.Texture2DArray.MostDetailedMip; - view.numMips = srv.Texture2DArray.MipLevels; + view.numSlices = srv.Texture2DArray.ArraySize & 0xffff; + view.firstSlice = srv.Texture2DArray.FirstArraySlice & 0xffff; + view.firstMip = srv.Texture2DArray.MostDetailedMip & 0xff; + view.numMips = srv.Texture2DArray.MipLevels & 0xff; view.minLODClamp = srv.Texture2DArray.ResourceMinLODClamp; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS) @@ -837,28 +846,28 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY) { - view.numSlices = srv.Texture2DMSArray.ArraySize; - view.firstSlice = srv.Texture2DMSArray.FirstArraySlice; + view.numSlices = srv.Texture2DMSArray.ArraySize & 0xffff; + view.firstSlice = srv.Texture2DMSArray.FirstArraySlice & 0xffff; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE3D) { - view.firstMip = srv.Texture3D.MostDetailedMip; - view.numMips = srv.Texture3D.MipLevels; + view.firstMip = srv.Texture3D.MostDetailedMip & 0xff; + view.numMips = srv.Texture3D.MipLevels & 0xff; view.minLODClamp = srv.Texture3D.ResourceMinLODClamp; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE) { view.numSlices = 6; - view.firstMip = srv.TextureCube.MostDetailedMip; - view.numMips = srv.TextureCube.MipLevels; + view.firstMip = srv.TextureCube.MostDetailedMip & 0xff; + view.numMips = srv.TextureCube.MipLevels & 0xff; view.minLODClamp = srv.TextureCube.ResourceMinLODClamp; } else if(srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) { - view.numSlices = srv.TextureCubeArray.NumCubes * 6; - view.firstSlice = srv.TextureCubeArray.First2DArrayFace; - view.firstMip = srv.TextureCubeArray.MostDetailedMip; - view.numMips = srv.TextureCubeArray.MipLevels; + view.numSlices = (srv.TextureCubeArray.NumCubes * 6) & 0xffff; + view.firstSlice = srv.TextureCubeArray.First2DArrayFace & 0xffff; + view.firstMip = srv.TextureCubeArray.MostDetailedMip & 0xff; + view.numMips = srv.TextureCubeArray.MipLevels & 0xff; view.minLODClamp = srv.TextureCube.ResourceMinLODClamp; } } @@ -884,43 +893,44 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor if(uav.Buffer.StructureByteStride > 0) view.elementByteSize = uav.Buffer.StructureByteStride; - view.counterByteOffset = uav.Buffer.CounterOffsetInBytes; + view.counterByteOffset = uav.Buffer.CounterOffsetInBytes & 0xffffffff; + RDCASSERT(uav.Buffer.CounterOffsetInBytes < 0xffffffff); if(view.counterResourceId != ResourceId()) { bytebuf counterVal; GetDebugManager()->GetBufferData( rm->GetCurrentAs(desc->GetCounterResourceId()), - view.counterByteOffset, 4, counterVal); + uav.Buffer.CounterOffsetInBytes, 4, counterVal); uint32_t *val = (uint32_t *)&counterVal[0]; view.bufferStructCount = *val; } } else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE1D) { - view.firstMip = uav.Texture1D.MipSlice; + view.firstMip = uav.Texture1D.MipSlice & 0xff; } else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE1DARRAY) { - view.numSlices = uav.Texture1DArray.ArraySize; - view.firstSlice = uav.Texture1DArray.FirstArraySlice; - view.firstMip = uav.Texture1DArray.MipSlice; + view.numSlices = uav.Texture1DArray.ArraySize & 0xffff; + view.firstSlice = uav.Texture1DArray.FirstArraySlice & 0xffff; + view.firstMip = uav.Texture1DArray.MipSlice & 0xff; } else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2D) { - view.firstMip = uav.Texture2D.MipSlice; + view.firstMip = uav.Texture2D.MipSlice & 0xff; } else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY) { - view.numSlices = uav.Texture2DArray.ArraySize; - view.firstSlice = uav.Texture2DArray.FirstArraySlice; - view.firstMip = uav.Texture2DArray.MipSlice; + view.numSlices = uav.Texture2DArray.ArraySize & 0xffff; + view.firstSlice = uav.Texture2DArray.FirstArraySlice & 0xffff; + view.firstMip = uav.Texture2DArray.MipSlice & 0xff; } else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE3D) { - view.numSlices = uav.Texture3D.WSize; - view.firstSlice = uav.Texture3D.FirstWSlice; - view.firstMip = uav.Texture3D.MipSlice; + view.numSlices = uav.Texture3D.WSize & 0xffff; + view.firstSlice = uav.Texture3D.FirstWSlice & 0xffff; + view.firstMip = uav.Texture3D.MipSlice & 0xff; } } @@ -932,6 +942,8 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor view.viewFormat = MakeResourceFormat(fmt); } + + desc->GetHeap()->SetToViewCache(desc->GetHeapIndex(), view); } void D3D12Replay::FillSampler(D3D12Pipe::Sampler &samp, const D3D12_SAMPLER_DESC &sampDesc) diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 6b079765e..15b53c6d5 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -350,6 +350,57 @@ rdcarray WrappedID3D12Resource::AddRefBuffersBeforeCapture(D3D return ret; } +bool WrappedID3D12DescriptorHeap::HasValidViewCache(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; + + // 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) +{ + if(!mutableViewBitmask) + return; + + mutableViewBitmask[index / 64] |= (1ULL << (index % 64)); +} + +void WrappedID3D12DescriptorHeap::GetFromViewCache(uint32_t index, D3D12Pipe::View &view) +{ + if(!mutableViewBitmask) + return; + + bool dynamicallyUsed = view.dynamicallyUsed; + uint32_t bind = view.bind; + uint32_t tableIndex = view.tableIndex; + view = cachedViews[index]; + view.dynamicallyUsed = dynamicallyUsed; + view.bind = bind; + view.tableIndex = tableIndex; +} + +void WrappedID3D12DescriptorHeap::SetToViewCache(uint32_t index, const D3D12Pipe::View &view) +{ + if(!mutableViewBitmask) + return; + + cachedViews[index] = view; + // we re-use bind as the indicator that this view is valid + cachedViews[index].bind = 1; + mutableViewBitmask[index / 64] |= (1ULL << (index % 64)); +} + WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *real, WrappedID3D12Device *device, const D3D12_DESCRIPTOR_HEAP_DESC &desc, @@ -368,12 +419,32 @@ WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *r RDCEraseMem(descriptors, sizeof(D3D12Descriptor) * desc.NumDescriptors); for(UINT i = 0; i < desc.NumDescriptors; i++) descriptors[i].Setup(this, i); + + // only cache views for "large" descriptor heaps where we expect few will actually change + // mid-frame + if(IsReplayMode(device->GetState()) && desc.NumDescriptors > 1024) + { + size_t bitmaskSize = AlignUp(desc.NumDescriptors, 64U) / 64; + + cachedViews = new D3D12Pipe::View[desc.NumDescriptors]; + RDCEraseMem(cachedViews, sizeof(D3D12Pipe::View) * desc.NumDescriptors); + + mutableViewBitmask = new uint64_t[bitmaskSize]; + RDCEraseMem(mutableViewBitmask, sizeof(uint64_t) * bitmaskSize); + } + else + { + cachedViews = NULL; + mutableViewBitmask = NULL; + } } WrappedID3D12DescriptorHeap::~WrappedID3D12DescriptorHeap() { Shutdown(); SAFE_DELETE_ARRAY(descriptors); + SAFE_DELETE_ARRAY(cachedViews); + SAFE_DELETE_ARRAY(mutableViewBitmask); } void WrappedID3D12PipelineState::ShaderEntry::BuildReflection() diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 0a7da6db7..756d1f98a 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -396,6 +396,9 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12 @@ -1565,7 +1565,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::OM &el) SERIALISE_MEMBER(multiSampleCount); SERIALISE_MEMBER(multiSampleQuality); - SIZE_CHECK(264); + SIZE_CHECK(240); } template @@ -1609,7 +1609,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::State &el) SERIALISE_MEMBER(resourceStates); - SIZE_CHECK(1424); + SIZE_CHECK(1400); } #pragma endregion D3D12 pipeline state