mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Use AllocateMemoryForResource for dummy image/buffer memory
* This makes the allocation more reliable e.g. for cases where the image memory can't share with buffer memory.
This commit is contained in:
@@ -353,6 +353,9 @@ enum class MemoryScope : uint8_t
|
||||
{
|
||||
InitialContents,
|
||||
First = InitialContents,
|
||||
// On replay, initial contents memory is never freed, so any immutable replay memory can be
|
||||
// allocated the same way
|
||||
ImmutableReplayDebug = InitialContents,
|
||||
IndirectReadback,
|
||||
Count,
|
||||
};
|
||||
|
||||
@@ -1981,9 +1981,6 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
VkSampleCountFlagBits sampleCounts[] = {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT};
|
||||
|
||||
VkDeviceSize offsets[ARRAY_COUNT(formats)][ARRAY_COUNT(types)];
|
||||
VkDeviceSize curOffset = 0;
|
||||
|
||||
// type max is one higher than the last RESTYPE, and RESTYPES are 1-indexed
|
||||
RDCCOMPILE_ASSERT(RESTYPE_TEXTYPEMAX - 1 == ARRAY_COUNT(types),
|
||||
"RESTYPE values don't match formats for dummy images");
|
||||
@@ -2000,10 +1997,6 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyWrites) == ARRAY_COUNT(DummyInfos),
|
||||
"dummy image arrays mismatched sizes");
|
||||
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL, 0, ~0U,
|
||||
};
|
||||
|
||||
CREATE_OBJECT(DummySampler, VK_FILTER_NEAREST);
|
||||
|
||||
for(size_t fmt = 0; fmt < ARRAY_COUNT(formats); fmt++)
|
||||
@@ -2039,22 +2032,12 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
vkr = driver->vkCreateImage(driver->GetDev(), &imInfo, NULL, &DummyImages[fmt][type]);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkMemoryRequirements mrq = {0};
|
||||
driver->vkGetImageMemoryRequirements(driver->GetDev(), DummyImages[fmt][type], &mrq);
|
||||
MemoryAllocation alloc = driver->AllocateMemoryForResource(
|
||||
DummyImages[fmt][type], MemoryScope::ImmutableReplayDebug, MemoryType::GPULocal);
|
||||
|
||||
uint32_t memIndex = driver->GetGPULocalMemoryIndex(mrq.memoryTypeBits);
|
||||
|
||||
// make sure all images can use the same memory type
|
||||
RDCASSERTMSG("memory type indices don't overlap!",
|
||||
allocInfo.memoryTypeIndex == ~0U || allocInfo.memoryTypeIndex == memIndex,
|
||||
allocInfo.memoryTypeIndex, memIndex, fmt, type);
|
||||
|
||||
allocInfo.memoryTypeIndex = memIndex;
|
||||
|
||||
// align to our alignment, then increment curOffset by our size
|
||||
curOffset = AlignUp(curOffset, mrq.alignment);
|
||||
offsets[fmt][type] = curOffset;
|
||||
curOffset += mrq.size;
|
||||
vkr = driver->vkBindImageMemory(driver->GetDev(), DummyImages[fmt][type], alloc.mem,
|
||||
alloc.offs);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
// fill out the descriptor set write to the write binding - set will be filled out
|
||||
// on demand when we're actually using these writes.
|
||||
@@ -2099,10 +2082,7 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
DummyInfos[index + 1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
// align up for the dummy buffer
|
||||
VkDeviceSize bufferOffset = 0;
|
||||
{
|
||||
curOffset = AlignUp(curOffset, driver->GetDeviceProps().limits.bufferImageGranularity);
|
||||
|
||||
VkBufferCreateInfo bufInfo = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, 0, 16,
|
||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
||||
@@ -2111,43 +2091,10 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
vkr = driver->vkCreateBuffer(driver->GetDev(), &bufInfo, NULL, &DummyBuffer);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkMemoryRequirements mrq = {0};
|
||||
driver->vkGetBufferMemoryRequirements(driver->GetDev(), DummyBuffer, &mrq);
|
||||
MemoryAllocation alloc = driver->AllocateMemoryForResource(
|
||||
DummyBuffer, MemoryScope::ImmutableReplayDebug, MemoryType::GPULocal);
|
||||
|
||||
if(mrq.memoryTypeBits & (1U << allocInfo.memoryTypeIndex))
|
||||
{
|
||||
curOffset = AlignUp(curOffset, mrq.alignment);
|
||||
bufferOffset = curOffset;
|
||||
curOffset += mrq.size;
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Can't use memory type %u for dummy buffer!", allocInfo.memoryTypeIndex);
|
||||
driver->vkDestroyBuffer(driver->GetDev(), DummyBuffer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// align up a bit just to be safe
|
||||
allocInfo.allocationSize = AlignUp(curOffset, (VkDeviceSize)1024ULL);
|
||||
|
||||
// allocate one big block
|
||||
vkr = driver->vkAllocateMemory(driver->GetDev(), &allocInfo, NULL, &DummyMemory);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
// bind all the image memory
|
||||
for(size_t fmt = 0; fmt < ARRAY_COUNT(formats); fmt++)
|
||||
{
|
||||
for(size_t type = 0; type < ARRAY_COUNT(types); type++)
|
||||
{
|
||||
vkr = driver->vkBindImageMemory(driver->GetDev(), DummyImages[fmt][type], DummyMemory,
|
||||
offsets[fmt][type]);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if(DummyBuffer != VK_NULL_HANDLE)
|
||||
{
|
||||
vkr = driver->vkBindBufferMemory(driver->GetDev(), DummyBuffer, DummyMemory, bufferOffset);
|
||||
vkr = driver->vkBindBufferMemory(driver->GetDev(), DummyBuffer, alloc.mem, alloc.offs);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -2280,8 +2227,6 @@ void VulkanReplay::TextureRendering::Destroy(WrappedVulkan *driver)
|
||||
driver->vkDestroyBufferView(driver->GetDev(), DummyBufferView[fmt], NULL);
|
||||
driver->vkDestroyBuffer(driver->GetDev(), DummyBuffer, NULL);
|
||||
|
||||
driver->vkFreeMemory(driver->GetDev(), DummyMemory, NULL);
|
||||
|
||||
driver->vkDestroySampler(driver->GetDev(), DummySampler, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,12 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "core/settings.h"
|
||||
#include "vk_core.h"
|
||||
|
||||
RDOC_DEBUG_CONFIG(bool, Vulkan_Debug_MemoryAllocationLogging, false,
|
||||
"Output verbose debug logging messages when allocating internal memory.");
|
||||
|
||||
void WrappedVulkan::ChooseMemoryIndices()
|
||||
{
|
||||
// we need to do this little dance because Get*MemoryIndex checks to see if the existing
|
||||
@@ -158,9 +162,12 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
// invalidate/flush safely. This is at most 256 bytes which is likely already satisfied.
|
||||
ret.size = AlignUp(ret.size, nonCoherentAtomSize);
|
||||
|
||||
RDCDEBUG("Allocating 0x%llx (0x%llx requested) with alignment 0x%llx in 0x%x for a %s (%s in %s)",
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("Allocating 0x%llx (0x%llx requested) with alignment 0x%llx in 0x%x for a %s (%s in %s)",
|
||||
ret.size, mrq.size, mrq.alignment, mrq.memoryTypeBits, buffer ? "buffer" : "image",
|
||||
ToStr(type).c_str(), ToStr(scope).c_str());
|
||||
}
|
||||
|
||||
rdcarray<MemoryAllocation> &blockList = m_MemoryBlocks[(size_t)scope];
|
||||
|
||||
@@ -168,17 +175,23 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
int i = 0;
|
||||
for(MemoryAllocation &block : blockList)
|
||||
{
|
||||
RDCDEBUG(
|
||||
"Considering block %d: memory type %u and type %s. Total size 0x%llx, current offset "
|
||||
"0x%llx, last alloc was %s",
|
||||
i, block.memoryTypeIndex, ToStr(block.type).c_str(), block.size, block.offs,
|
||||
block.buffer ? "buffer" : "image");
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG(
|
||||
"Considering block %d: memory type %u and type %s. Total size 0x%llx, current offset "
|
||||
"0x%llx, last alloc was %s",
|
||||
i, block.memoryTypeIndex, ToStr(block.type).c_str(), block.size, block.offs,
|
||||
block.buffer ? "buffer" : "image");
|
||||
}
|
||||
i++;
|
||||
|
||||
// skip this block if it's not the memory type we want
|
||||
if(ret.type != block.type || (mrq.memoryTypeBits & (1 << block.memoryTypeIndex)) == 0)
|
||||
{
|
||||
RDCDEBUG("block type %d or memory type %d is incompatible", block.type, block.memoryTypeIndex);
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("block type %d or memory type %d is incompatible", block.type, block.memoryTypeIndex);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -194,15 +207,21 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
|
||||
if(offs > block.size)
|
||||
{
|
||||
RDCDEBUG("Next offset 0x%llx would be off the end of the memory (size 0x%llx).", offs,
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("Next offset 0x%llx would be off the end of the memory (size 0x%llx).", offs,
|
||||
block.size);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
VkDeviceSize avail = block.size - offs;
|
||||
|
||||
RDCDEBUG("At next offset 0x%llx, there's 0x%llx bytes available for 0x%llx bytes requested",
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("At next offset 0x%llx, there's 0x%llx bytes available for 0x%llx bytes requested",
|
||||
offs, avail, ret.size);
|
||||
}
|
||||
|
||||
// if the allocation will fit, we've found our candidate.
|
||||
if(ret.size <= avail)
|
||||
@@ -215,7 +234,10 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
ret.offs = offs;
|
||||
ret.mem = block.mem;
|
||||
|
||||
RDCDEBUG("Allocating using this block: 0x%llx -> 0x%llx", ret.offs, block.offs);
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("Allocating using this block: 0x%llx -> 0x%llx", ret.offs, block.offs);
|
||||
}
|
||||
|
||||
// stop searching
|
||||
break;
|
||||
@@ -224,7 +246,10 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
|
||||
if(ret.mem == VK_NULL_HANDLE)
|
||||
{
|
||||
RDCDEBUG("No available block found - allocating new block");
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("No available block found - allocating new block");
|
||||
}
|
||||
|
||||
VkDeviceSize &allocSize = m_MemoryBlockSize[(size_t)scope];
|
||||
|
||||
@@ -237,7 +262,7 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
case 128:
|
||||
case 256: allocSize = 256; break;
|
||||
default:
|
||||
RDCDEBUG("Unexpected previous allocation size 0x%llx bytes, allocating 256MB", allocSize);
|
||||
RDCWARN("Unexpected previous allocation size 0x%llx bytes, allocating 256MB", allocSize);
|
||||
allocSize = 256;
|
||||
break;
|
||||
}
|
||||
@@ -255,8 +280,11 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
{
|
||||
if(mrq.memoryTypeBits > (1U << m))
|
||||
{
|
||||
RDCDEBUG("Avoiding memory type %u due to small heap size (%llu)", m,
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("Avoiding memory type %u due to small heap size (%llu)", m,
|
||||
m_PhysicalDeviceData.memProps.memoryHeaps[heap].size);
|
||||
}
|
||||
mrq.memoryTypeBits &= ~(1U << m);
|
||||
}
|
||||
}
|
||||
@@ -288,12 +316,18 @@ MemoryAllocation WrappedVulkan::AllocateMemoryForResource(bool buffer, VkMemoryR
|
||||
// if it's still over-sized, just allocate precisely enough and give it a dedicated allocation
|
||||
if(ret.size > info.allocationSize)
|
||||
{
|
||||
RDCDEBUG("Over-sized allocation for 0x%llx bytes", ret.size);
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("Over-sized allocation for 0x%llx bytes", ret.size);
|
||||
}
|
||||
info.allocationSize = ret.size;
|
||||
}
|
||||
}
|
||||
|
||||
RDCDEBUG("Creating new allocation of 0x%llx bytes", info.allocationSize);
|
||||
if(Vulkan_Debug_MemoryAllocationLogging)
|
||||
{
|
||||
RDCLOG("Creating new allocation of 0x%llx bytes", info.allocationSize);
|
||||
}
|
||||
|
||||
MemoryAllocation chunk;
|
||||
chunk.buffer = ret.buffer;
|
||||
|
||||
@@ -570,7 +570,6 @@ private:
|
||||
VkImageView DummyImageViews[3][5] = {};
|
||||
VkWriteDescriptorSet DummyWrites[14] = {};
|
||||
VkDescriptorImageInfo DummyInfos[14] = {};
|
||||
VkDeviceMemory DummyMemory = VK_NULL_HANDLE;
|
||||
VkSampler DummySampler = VK_NULL_HANDLE;
|
||||
VkBuffer DummyBuffer = VK_NULL_HANDLE;
|
||||
VkBufferView DummyBufferView[3] = {};
|
||||
|
||||
Reference in New Issue
Block a user