mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-23 23:16:31 +00:00
Expose memory bindings for buffers/textures on Vulkan and D3D12
* This only applies to explicit memory binding APIs - so D3D11 and GL are excluded. On D3D12, committed resources will not have anything listed here.
This commit is contained in:
@@ -975,7 +975,8 @@ struct BufferDescription
|
||||
bool operator==(const BufferDescription &o) const
|
||||
{
|
||||
return resourceId == o.resourceId && creationFlags == o.creationFlags &&
|
||||
gpuAddress == o.gpuAddress && length == o.length;
|
||||
gpuAddress == o.gpuAddress && length == o.length && memory == o.memory &&
|
||||
memoryOffset == o.memoryOffset;
|
||||
}
|
||||
bool operator<(const BufferDescription &o) const
|
||||
{
|
||||
@@ -987,6 +988,10 @@ struct BufferDescription
|
||||
return gpuAddress < o.gpuAddress;
|
||||
if(!(length == o.length))
|
||||
return length < o.length;
|
||||
if(!(memory == o.memory))
|
||||
return memory < o.memory;
|
||||
if(!(memoryOffset == o.memoryOffset))
|
||||
return memoryOffset < o.memoryOffset;
|
||||
return false;
|
||||
}
|
||||
DOCUMENT(R"(The unique :class:`ResourceId` that identifies this buffer.
|
||||
@@ -1012,6 +1017,21 @@ struct BufferDescription
|
||||
:type: int
|
||||
)");
|
||||
uint64_t length = 0;
|
||||
|
||||
DOCUMENT(R"(The unique :class:`ResourceId` that identifies the memory object this
|
||||
buffer has a fixed binding to. For objects that do not have an explicit memory binding
|
||||
or for sparse buffers, this will not be set.
|
||||
|
||||
:type: ResourceId
|
||||
)");
|
||||
ResourceId memory;
|
||||
|
||||
DOCUMENT(R"(The byte offset in :data:`memory` where the buffer is bound. If
|
||||
:data:`memory` is unset, this will be 0.
|
||||
|
||||
:type: int
|
||||
)");
|
||||
uint64_t memoryOffset = 0;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(BufferDescription);
|
||||
@@ -1035,7 +1055,7 @@ struct TextureDescription
|
||||
height == o.height && depth == o.depth && resourceId == o.resourceId &&
|
||||
cubemap == o.cubemap && mips == o.mips && arraysize == o.arraysize &&
|
||||
creationFlags == o.creationFlags && msQual == o.msQual && msSamp == o.msSamp &&
|
||||
byteSize == o.byteSize;
|
||||
byteSize == o.byteSize && memory == o.memory && memoryOffset == o.memoryOffset;
|
||||
}
|
||||
bool operator<(const TextureDescription &o) const
|
||||
{
|
||||
@@ -1067,6 +1087,10 @@ struct TextureDescription
|
||||
return msSamp < o.msSamp;
|
||||
if(!(byteSize == o.byteSize))
|
||||
return byteSize < o.byteSize;
|
||||
if(!(memory == o.memory))
|
||||
return memory < o.memory;
|
||||
if(!(memoryOffset == o.memoryOffset))
|
||||
return memoryOffset < o.memoryOffset;
|
||||
return false;
|
||||
}
|
||||
DOCUMENT(R"(The format of each pixel in the texture.
|
||||
@@ -1152,6 +1176,21 @@ struct TextureDescription
|
||||
:type: int
|
||||
)");
|
||||
uint64_t byteSize;
|
||||
|
||||
DOCUMENT(R"(The unique :class:`ResourceId` that identifies the memory object this
|
||||
texture has a fixed binding to. For objects that do not have an explicit memory binding
|
||||
or for sparse textures, this will not be set.
|
||||
|
||||
:type: ResourceId
|
||||
)");
|
||||
ResourceId memory;
|
||||
|
||||
DOCUMENT(R"(The byte offset in :data:`memory` where the texture is bound. If
|
||||
:data:`memory` is unset, this will be 0.
|
||||
|
||||
:type: int
|
||||
)");
|
||||
uint64_t memoryOffset = 0;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(TextureDescription);
|
||||
|
||||
@@ -432,6 +432,12 @@ BufferDescription D3D12Replay::GetBuffer(ResourceId id)
|
||||
ret.creationFlags = BufferCategory::NoFlags;
|
||||
ret.gpuAddress = it->second->GetOriginalVA();
|
||||
|
||||
if(it->second->GetHeap())
|
||||
{
|
||||
ret.memory = it->second->GetHeap()->GetResourceID();
|
||||
ret.memoryOffset = it->second->GetHeapOffset();
|
||||
}
|
||||
|
||||
const rdcarray<EventUsage> &usage = m_pDevice->GetQueue()->GetUsage(id);
|
||||
|
||||
for(size_t i = 0; i < usage.size(); i++)
|
||||
@@ -479,11 +485,29 @@ TextureDescription D3D12Replay::GetTexture(ResourceId id)
|
||||
ret.mips = desc.MipLevels;
|
||||
ret.msQual = desc.SampleDesc.Quality;
|
||||
ret.msSamp = RDCMAX(1U, desc.SampleDesc.Count);
|
||||
ret.byteSize = 0;
|
||||
for(uint32_t i = 0; i < ret.mips; i++)
|
||||
ret.byteSize += GetByteSize(ret.width, ret.height, ret.depth, desc.Format, i);
|
||||
ret.byteSize *= ret.arraysize;
|
||||
ret.byteSize *= ret.msSamp;
|
||||
|
||||
if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
ret.byteSize = desc.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.byteSize = m_pDevice->GetResourceAllocationInfo(0, 1, &desc).SizeInBytes;
|
||||
}
|
||||
|
||||
if(ret.byteSize == 0)
|
||||
{
|
||||
for(uint32_t i = 0; i < ret.mips; i++)
|
||||
ret.byteSize += GetByteSize(ret.width, ret.height, ret.depth, desc.Format, i);
|
||||
ret.byteSize *= ret.arraysize;
|
||||
ret.byteSize *= ret.msSamp;
|
||||
}
|
||||
|
||||
if(it->second->GetHeap())
|
||||
{
|
||||
ret.memory = it->second->GetHeap()->GetResourceID();
|
||||
ret.memoryOffset = it->second->GetHeapOffset();
|
||||
}
|
||||
|
||||
switch(ret.dimension)
|
||||
{
|
||||
|
||||
@@ -1480,6 +1480,7 @@ class WrappedID3D12Resource
|
||||
size_t DeleteOverlappingAccStructsInRangeAtOffset(D3D12BufferOffset bufferOffset);
|
||||
|
||||
WrappedID3D12Heap *m_Heap = NULL;
|
||||
uint64_t m_HeapOffset = 0;
|
||||
|
||||
Threading::CriticalSection m_accStructResourcesCS;
|
||||
rdcflatmap<D3D12BufferOffset, D3D12AccelerationStructure *> m_accelerationStructMap;
|
||||
@@ -1498,6 +1499,7 @@ public:
|
||||
}
|
||||
|
||||
WrappedID3D12Heap *GetHeap() { return m_Heap; }
|
||||
uint64_t GetHeapOffset() { return m_HeapOffset; }
|
||||
|
||||
ID3D12Pageable *UnwrappedResidencyPageable()
|
||||
{
|
||||
@@ -1575,6 +1577,7 @@ public:
|
||||
device->AddReplayResource(GetResourceID(), this);
|
||||
|
||||
m_Heap = (WrappedID3D12Heap *)heap;
|
||||
m_HeapOffset = HeapOffset;
|
||||
SAFE_ADDREF(m_Heap);
|
||||
|
||||
// assuming only valid for buffers
|
||||
|
||||
@@ -656,6 +656,9 @@ struct VulkanCreationInfo
|
||||
|
||||
VkMemoryRequirements mrq;
|
||||
|
||||
ResourceId boundMemory;
|
||||
uint64_t boundMemoryOffset;
|
||||
|
||||
ResourceId inlineDescriptorId;
|
||||
};
|
||||
std::unordered_map<ResourceId, Buffer> m_Buffer;
|
||||
|
||||
@@ -345,7 +345,16 @@ rdcarray<BufferDescription> VulkanReplay::GetBuffers()
|
||||
|
||||
TextureDescription VulkanReplay::GetTexture(ResourceId id)
|
||||
{
|
||||
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[id];
|
||||
auto imit = m_pDriver->m_CreationInfo.m_Image.find(id);
|
||||
if(imit == m_pDriver->m_CreationInfo.m_Image.end())
|
||||
{
|
||||
RDCERR("Invalid image id");
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanCreationInfo::Image &iminfo = imit->second;
|
||||
|
||||
VkImage liveWrappedImage = GetResourceManager()->GetHandle<VkImage>(id);
|
||||
|
||||
TextureDescription ret = {};
|
||||
ret.resourceId = id;
|
||||
@@ -357,10 +366,27 @@ TextureDescription VulkanReplay::GetTexture(ResourceId id)
|
||||
ret.depth = iminfo.extent.depth;
|
||||
ret.mips = iminfo.mipLevels;
|
||||
|
||||
ret.byteSize = 0;
|
||||
for(uint32_t s = 0; s < ret.mips; s++)
|
||||
ret.byteSize += GetByteSize(ret.width, ret.height, ret.depth, iminfo.format, s);
|
||||
ret.byteSize *= ret.arraysize;
|
||||
VkMemoryRequirements mrq = {0};
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
|
||||
// some entries in m_Images don't have a live handle - e.g. swapchains
|
||||
if(liveWrappedImage != VK_NULL_HANDLE)
|
||||
ObjDisp(dev)->GetImageMemoryRequirements(Unwrap(dev), Unwrap(liveWrappedImage), &mrq);
|
||||
|
||||
ret.byteSize = mrq.size;
|
||||
if(ret.byteSize == 0)
|
||||
{
|
||||
for(uint32_t s = 0; s < ret.mips; s++)
|
||||
ret.byteSize += GetByteSize(ret.width, ret.height, ret.depth, iminfo.format, s);
|
||||
ret.byteSize *= ret.arraysize;
|
||||
}
|
||||
|
||||
LockedConstImageStateRef lockedImage = m_pDriver->FindConstImageState(id);
|
||||
if(lockedImage && lockedImage->isMemoryBound)
|
||||
{
|
||||
ret.memory = lockedImage->boundMemory;
|
||||
ret.memoryOffset = lockedImage->boundMemoryOffset;
|
||||
}
|
||||
|
||||
ret.msQual = 0;
|
||||
ret.msSamp = RDCMAX(1U, (uint32_t)iminfo.samples);
|
||||
@@ -399,7 +425,14 @@ TextureDescription VulkanReplay::GetTexture(ResourceId id)
|
||||
|
||||
BufferDescription VulkanReplay::GetBuffer(ResourceId id)
|
||||
{
|
||||
VulkanCreationInfo::Buffer &bufinfo = m_pDriver->m_CreationInfo.m_Buffer[id];
|
||||
auto bufit = m_pDriver->m_CreationInfo.m_Buffer.find(id);
|
||||
if(bufit == m_pDriver->m_CreationInfo.m_Buffer.end())
|
||||
{
|
||||
RDCERR("Invalid image id");
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanCreationInfo::Buffer &bufinfo = bufit->second;
|
||||
|
||||
BufferDescription ret;
|
||||
ret.resourceId = id;
|
||||
@@ -407,6 +440,9 @@ BufferDescription VulkanReplay::GetBuffer(ResourceId id)
|
||||
ret.creationFlags = BufferCategory::NoFlags;
|
||||
ret.gpuAddress = bufinfo.gpuAddress;
|
||||
|
||||
ret.memory = bufinfo.boundMemory;
|
||||
ret.memoryOffset = bufinfo.boundMemoryOffset;
|
||||
|
||||
if(bufinfo.usage & (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
|
||||
ret.creationFlags |= BufferCategory::ReadWrite;
|
||||
if(bufinfo.usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT))
|
||||
|
||||
@@ -1734,6 +1734,9 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory(SerialiserType &ser, VkDevice d
|
||||
if(bufInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
|
||||
TrackReplayBufferAddress(device, buffer, memory, memoryOffset);
|
||||
|
||||
bufInfo.boundMemory = memId;
|
||||
bufInfo.boundMemoryOffset = memoryOffset;
|
||||
|
||||
m_CreationInfo.m_Memory[GetResID(memory)].BindMemory(memoryOffset, mrq.size,
|
||||
VulkanCreationInfo::Memory::Linear);
|
||||
}
|
||||
@@ -3534,6 +3537,9 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory2(SerialiserType &ser, VkDevice
|
||||
if(bufInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
|
||||
TrackReplayBufferAddress(device, bindInfo.buffer, bindInfo.memory, bindInfo.memoryOffset);
|
||||
|
||||
bufInfo.boundMemory = memId;
|
||||
bufInfo.boundMemoryOffset = bindInfo.memoryOffset;
|
||||
|
||||
// the memory is immediately dirty because we don't use dirty tracking, it's too expensive to
|
||||
// follow all frame refs in the background and it's pointless because memory almost always
|
||||
// immediately becomes dirty anyway. The one case we might care about non-dirty memory is
|
||||
|
||||
@@ -465,8 +465,10 @@ void DoSerialise(SerialiserType &ser, TextureDescription &el)
|
||||
SERIALISE_MEMBER(msQual);
|
||||
SERIALISE_MEMBER(msSamp);
|
||||
SERIALISE_MEMBER(byteSize);
|
||||
SERIALISE_MEMBER(memory);
|
||||
SERIALISE_MEMBER(memoryOffset);
|
||||
|
||||
SIZE_CHECK(72);
|
||||
SIZE_CHECK(88);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
@@ -476,8 +478,10 @@ void DoSerialise(SerialiserType &ser, BufferDescription &el)
|
||||
SERIALISE_MEMBER(creationFlags);
|
||||
SERIALISE_MEMBER(gpuAddress);
|
||||
SERIALISE_MEMBER(length);
|
||||
SERIALISE_MEMBER(memory);
|
||||
SERIALISE_MEMBER(memoryOffset);
|
||||
|
||||
SIZE_CHECK(32);
|
||||
SIZE_CHECK(48);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
|
||||
Reference in New Issue
Block a user