Fill shader debug fetch descriptors with dummy contents

* We need to do this to comply with static use, which is considered *before*
  specialization constants have been applied, meaning when we run our gather all
  variants must be valid :(.
This commit is contained in:
baldurk
2020-04-30 12:33:08 +01:00
parent 48451793bb
commit 94be1b8ce8
3 changed files with 180 additions and 36 deletions
+121 -34
View File
@@ -1969,26 +1969,35 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
int index = 0;
VkDeviceSize offsets[ARRAY_COUNT(DummyImages)];
VkDeviceSize curOffset = 0;
// we pick RGBA8 formats to be guaranteed they will be supported
VkFormat formats[] = {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_SINT};
VkImageType types[] = {VK_IMAGE_TYPE_1D, VK_IMAGE_TYPE_2D, VK_IMAGE_TYPE_3D, VK_IMAGE_TYPE_2D};
VkImageViewType viewtypes[] = {VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_2D_ARRAY,
VK_IMAGE_VIEW_TYPE_3D, VK_IMAGE_VIEW_TYPE_2D_ARRAY};
VkImageViewType viewtypes[] = {
VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_VIEW_TYPE_3D,
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
driver->GetDeviceFeatures().imageCubeArray ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
: VK_IMAGE_VIEW_TYPE_CUBE,
};
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");
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyImages) == ARRAY_COUNT(DummyImageViews),
RDCCOMPILE_ASSERT(sizeof(DummyImages) == sizeof(DummyImageViews),
"dummy image arrays mismatched sizes");
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyImages) == ARRAY_COUNT(DummyWrites),
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyImages) == ARRAY_COUNT(formats),
"dummy image arrays mismatched sizes");
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyImages) == ARRAY_COUNT(DummyInfos),
// types + 1 for cube
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyImages[0]) == ARRAY_COUNT(types) + 1,
"dummy image arrays mismatched sizes");
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyImages[0]) == ARRAY_COUNT(viewtypes),
"dummy image arrays mismatched sizes");
RDCCOMPILE_ASSERT(ARRAY_COUNT(DummyWrites) == ARRAY_COUNT(DummyInfos),
"dummy image arrays mismatched sizes");
VkMemoryAllocateInfo allocInfo = {
@@ -2020,11 +2029,18 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
VK_IMAGE_LAYOUT_UNDEFINED,
};
vkr = driver->vkCreateImage(driver->GetDev(), &imInfo, NULL, &DummyImages[index]);
// make the 2D image cube-compatible
if(type == 1)
{
imInfo.arrayLayers = 6;
imInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
vkr = driver->vkCreateImage(driver->GetDev(), &imInfo, NULL, &DummyImages[fmt][type]);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkMemoryRequirements mrq = {0};
driver->vkGetImageMemoryRequirements(driver->GetDev(), DummyImages[index], &mrq);
driver->vkGetImageMemoryRequirements(driver->GetDev(), DummyImages[fmt][type], &mrq);
uint32_t memIndex = driver->GetGPULocalMemoryIndex(mrq.memoryTypeBits);
@@ -2037,7 +2053,7 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
// align to our alignment, then increment curOffset by our size
curOffset = AlignUp(curOffset, mrq.alignment);
offsets[index] = curOffset;
offsets[fmt][type] = curOffset;
curOffset += mrq.size;
// fill out the descriptor set write to the write binding - set will be filled out
@@ -2082,6 +2098,35 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
DummyInfos[index + 1].sampler = Unwrap(DummySampler);
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,
};
vkr = driver->vkCreateBuffer(driver->GetDev(), &bufInfo, NULL, &DummyBuffer);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkMemoryRequirements mrq = {0};
driver->vkGetBufferMemoryRequirements(driver->GetDev(), DummyBuffer, &mrq);
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);
@@ -2090,30 +2135,42 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
RDCASSERTEQUAL(vkr, VK_SUCCESS);
// bind all the image memory
for(index = 0; index < (int)ARRAY_COUNT(DummyImages); index++)
{
// there are a couple of empty images at the end for YUV textures which re-use the 2D image
if(DummyImages[index] == VK_NULL_HANDLE)
continue;
vkr = driver->vkBindImageMemory(driver->GetDev(), DummyImages[index], DummyMemory,
offsets[index]);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
}
// now that the image memory is bound, we can create the image views and fill the descriptor
// set
// writes.
index = 0;
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);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
}
// now that the image memory is bound, we can create the image views and fill the descriptor
// set writes.
index = 0;
for(size_t fmt = 0; fmt < ARRAY_COUNT(formats); fmt++)
{
for(size_t type = 0; type < ARRAY_COUNT(viewtypes); type++)
{
size_t imType = type;
// the cubemap view re-uses the 2D image
if(viewtypes[type] == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
{
imType = 1;
}
VkImageViewCreateInfo viewInfo = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
NULL,
0,
DummyImages[index],
DummyImages[fmt][imType],
viewtypes[type],
formats[fmt],
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
@@ -2123,10 +2180,17 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
},
};
vkr = driver->vkCreateImageView(driver->GetDev(), &viewInfo, NULL, &DummyImageViews[index]);
vkr = driver->vkCreateImageView(driver->GetDev(), &viewInfo, NULL,
&DummyImageViews[fmt][type]);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
DummyInfos[index].imageView = Unwrap(DummyImageViews[index]);
// the cubemap view we don't create an info for it, and the image is already transitioned
if(viewtypes[type] == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
continue;
RDCASSERT((size_t)index < ARRAY_COUNT(DummyInfos), index);
DummyInfos[index].imageView = Unwrap(DummyImageViews[fmt][type]);
// need to update image layout into valid state
VkImageMemoryBarrier barrier = {
@@ -2138,8 +2202,8 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(DummyImages[index]),
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
Unwrap(DummyImages[fmt][imType]),
{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS},
};
DoPipelineBarrier(cmd, 1, &barrier);
@@ -2152,6 +2216,22 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
DummyInfos[index].imageView = DummyInfos[1].imageView;
DummyInfos[index + 1].imageView = DummyInfos[1].imageView;
if(DummyBuffer != VK_NULL_HANDLE)
{
VkFormat bufViewTypes[] = {
VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_SINT,
};
for(size_t i = 0; i < ARRAY_COUNT(bufViewTypes); i++)
{
VkBufferViewCreateInfo viewInfo = {
VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, NULL, 0, DummyBuffer, bufViewTypes[i], 0, 16,
};
vkr = driver->vkCreateBufferView(driver->GetDev(), &viewInfo, NULL, &DummyBufferView[i]);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
}
}
ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
}
}
@@ -2181,12 +2261,19 @@ void VulkanReplay::TextureRendering::Destroy(WrappedVulkan *driver)
driver->vkDestroySampler(driver->GetDev(), PointSampler, NULL);
driver->vkDestroySampler(driver->GetDev(), LinearSampler, NULL);
for(size_t i = 0; i < ARRAY_COUNT(DummyImages); i++)
for(size_t fmt = 0; fmt < ARRAY_COUNT(DummyImages); fmt++)
{
driver->vkDestroyImageView(driver->GetDev(), DummyImageViews[i], NULL);
driver->vkDestroyImage(driver->GetDev(), DummyImages[i], NULL);
for(size_t type = 0; type < ARRAY_COUNT(DummyImages[0]); type++)
{
driver->vkDestroyImageView(driver->GetDev(), DummyImageViews[fmt][type], NULL);
driver->vkDestroyImage(driver->GetDev(), DummyImages[fmt][type], NULL);
}
}
for(size_t fmt = 0; fmt < ARRAY_COUNT(DummyBufferView); fmt++)
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);
+13 -2
View File
@@ -232,6 +232,9 @@ struct ShaderDebugData
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
VkRenderPass RenderPass = VK_NULL_HANDLE;
VkDescriptorImageInfo DummyImageInfos[3][6] = {};
VkWriteDescriptorSet DummyWrites[3][7] = {};
VkShaderModule Module[4] = {};
std::map<uint32_t, VkPipeline> m_Pipelines;
@@ -557,12 +560,20 @@ private:
// descriptors must be valid even if they're skipped dynamically in the shader, so we create
// tiny (but valid) dummy images to fill in the rest of the descriptors
VkImage DummyImages[14] = {VK_NULL_HANDLE};
VkImageView DummyImageViews[14] = {VK_NULL_HANDLE};
// images and views are re-used elsewhere in replay, so index them sensibly
//
// [float/uint/sint][1D/2D/3D/MS/Cube]
//
// the cube image is re-used from the 2D one, so only the view is valid
VkImage DummyImages[3][5] = {};
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] = {};
std::map<ResourceId, TextureDisplayViews> TextureViews;
@@ -1037,6 +1037,16 @@ public:
writeSets[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
}
// reset descriptor sets to dummy state
uint32_t resetIndex = 0;
if(uintTex)
resetIndex = 1;
else if(sintTex)
resetIndex = 2;
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(m_DebugData.DummyWrites[resetIndex]),
m_DebugData.DummyWrites[resetIndex], 0, NULL);
// overwrite with our data
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), sampler != VK_NULL_HANDLE ? 3 : 2, writeSets, 0,
NULL);
@@ -4143,6 +4153,42 @@ rdcarray<ShaderDebugState> VulkanReplay::ContinueDebug(ShaderDebugger *debugger)
VkMarkerRegion region("ContinueDebug Simulation Loop");
for(size_t fmt = 0; fmt < ARRAY_COUNT(m_TexRender.DummyImageViews); fmt++)
{
for(size_t dim = 0; dim < ARRAY_COUNT(m_TexRender.DummyImageViews[0]); dim++)
{
m_ShaderDebugData.DummyImageInfos[fmt][dim].imageLayout =
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
m_ShaderDebugData.DummyImageInfos[fmt][dim].imageView =
Unwrap(m_TexRender.DummyImageViews[fmt][dim]);
m_ShaderDebugData.DummyWrites[fmt][dim].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
m_ShaderDebugData.DummyWrites[fmt][dim].descriptorCount = 1;
m_ShaderDebugData.DummyWrites[fmt][dim].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
m_ShaderDebugData.DummyWrites[fmt][dim].dstBinding = uint32_t(dim + 1);
m_ShaderDebugData.DummyWrites[fmt][dim].dstSet = Unwrap(m_ShaderDebugData.DescSet);
m_ShaderDebugData.DummyWrites[fmt][dim].pImageInfo =
&m_ShaderDebugData.DummyImageInfos[fmt][dim];
}
m_ShaderDebugData.DummyImageInfos[fmt][5].sampler = Unwrap(m_TexRender.DummySampler);
m_ShaderDebugData.DummyWrites[fmt][5].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
m_ShaderDebugData.DummyWrites[fmt][5].descriptorCount = 1;
m_ShaderDebugData.DummyWrites[fmt][5].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
m_ShaderDebugData.DummyWrites[fmt][5].dstBinding = (uint32_t)ShaderDebugBind::Sampler;
m_ShaderDebugData.DummyWrites[fmt][5].dstSet = Unwrap(m_ShaderDebugData.DescSet);
m_ShaderDebugData.DummyWrites[fmt][5].pImageInfo = &m_ShaderDebugData.DummyImageInfos[fmt][5];
m_ShaderDebugData.DummyWrites[fmt][6].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
m_ShaderDebugData.DummyWrites[fmt][6].descriptorCount = 1;
m_ShaderDebugData.DummyWrites[fmt][6].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
m_ShaderDebugData.DummyWrites[fmt][6].dstBinding = (uint32_t)ShaderDebugBind::Buffer;
m_ShaderDebugData.DummyWrites[fmt][6].dstSet = Unwrap(m_ShaderDebugData.DescSet);
m_ShaderDebugData.DummyWrites[fmt][6].pTexelBufferView =
UnwrapPtr(m_TexRender.DummyBufferView[fmt]);
}
rdcarray<ShaderDebugState> ret = spvDebugger->ContinueDebug();
VulkanAPIWrapper *api = (VulkanAPIWrapper *)spvDebugger->GetAPIWrapper();