mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 21:30:53 +00:00
Use dummy image when no stencil is present for MS<->Array. Closes #1230
* We need to fill all descriptors even if the stencil is skipped dynamically in the shader, since we're not using VK_EXT_descriptor_indexing. Attempt to create a dummy UINT MSAA texture.
This commit is contained in:
@@ -460,6 +460,165 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver)
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Depth MS to Array copy (via graphics)
|
||||
|
||||
// need a dummy UINT texture to fill the binding when we don't have a stencil aspect to copy.
|
||||
// unfortunately there's no single guaranteed UINT format that can be sampled as MSAA, so we try a
|
||||
// few since hopefully we'll find one that will work.
|
||||
VkFormat attemptFormats[] = {VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8_UINT,
|
||||
VK_FORMAT_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT};
|
||||
|
||||
for(VkFormat f : attemptFormats)
|
||||
{
|
||||
VkImageAspectFlags viewAspectMask =
|
||||
IsStencilFormat(f) ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
VkImageAspectFlags barrierAspectMask = viewAspectMask;
|
||||
|
||||
if(IsDepthAndStencilFormat(f) && (barrierAspectMask & VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
barrierAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
VkFormatProperties props = {};
|
||||
driver->vkGetPhysicalDeviceFormatProperties(driver->GetPhysDev(), f, &props);
|
||||
|
||||
if(!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
|
||||
continue;
|
||||
|
||||
VkImageCreateInfo imInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
VK_IMAGE_TYPE_2D,
|
||||
f,
|
||||
{1, 1, 1},
|
||||
1,
|
||||
1,
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_SHARING_MODE_EXCLUSIVE,
|
||||
0,
|
||||
NULL,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
|
||||
VkImageFormatProperties imgprops = {};
|
||||
vkr = driver->vkGetPhysicalDeviceImageFormatProperties(driver->GetPhysDev(), f,
|
||||
imInfo.imageType, imInfo.tiling,
|
||||
imInfo.usage, imInfo.flags, &imgprops);
|
||||
|
||||
if(vkr == VK_ERROR_FORMAT_NOT_SUPPORTED)
|
||||
continue;
|
||||
|
||||
// if it doesn't support MSAA, bail out
|
||||
if(imgprops.sampleCounts == VK_SAMPLE_COUNT_1_BIT)
|
||||
continue;
|
||||
|
||||
vkr = driver->vkCreateImage(driver->GetDev(), &imInfo, NULL, &m_DummyStencilImage[0]);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
rm->SetInternalResource(GetResID(m_DummyStencilImage[0]));
|
||||
|
||||
imInfo.samples = VK_SAMPLE_COUNT_2_BIT;
|
||||
|
||||
RDCASSERT(imgprops.sampleCounts & imInfo.samples, imgprops.sampleCounts, imInfo.samples);
|
||||
|
||||
vkr = driver->vkCreateImage(driver->GetDev(), &imInfo, NULL, &m_DummyStencilImage[1]);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
rm->SetInternalResource(GetResID(m_DummyStencilImage[1]));
|
||||
|
||||
VkMemoryRequirements mrq[2] = {0};
|
||||
driver->vkGetImageMemoryRequirements(driver->GetDev(), m_DummyStencilImage[0], &mrq[0]);
|
||||
driver->vkGetImageMemoryRequirements(driver->GetDev(), m_DummyStencilImage[1], &mrq[1]);
|
||||
|
||||
uint32_t memoryTypeBits = (mrq[0].memoryTypeBits & mrq[1].memoryTypeBits);
|
||||
|
||||
// assume we have some memory type available in common
|
||||
RDCASSERT(memoryTypeBits, mrq[0].memoryTypeBits, mrq[1].memoryTypeBits);
|
||||
|
||||
// allocate memory
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL,
|
||||
AlignUp(mrq[0].size, mrq[1].alignment) + mrq[1].size,
|
||||
driver->GetGPULocalMemoryIndex(memoryTypeBits),
|
||||
};
|
||||
|
||||
vkr = driver->vkAllocateMemory(driver->GetDev(), &allocInfo, NULL, &m_DummyStencilMemory);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
rm->SetInternalResource(GetResID(m_DummyStencilMemory));
|
||||
|
||||
vkr =
|
||||
driver->vkBindImageMemory(driver->GetDev(), m_DummyStencilImage[0], m_DummyStencilMemory, 0);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
vkr = driver->vkBindImageMemory(driver->GetDev(), m_DummyStencilImage[1], m_DummyStencilMemory,
|
||||
AlignUp(mrq[0].size, mrq[1].alignment));
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
m_DummyStencilImage[0],
|
||||
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
|
||||
f,
|
||||
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
|
||||
{
|
||||
viewAspectMask, 0, 1, 0, 1,
|
||||
},
|
||||
};
|
||||
|
||||
vkr = driver->vkCreateImageView(driver->GetDev(), &viewInfo, NULL, &m_DummyStencilView[0]);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
rm->SetInternalResource(GetResID(m_DummyStencilView[0]));
|
||||
|
||||
viewInfo.image = m_DummyStencilImage[1];
|
||||
|
||||
vkr = driver->vkCreateImageView(driver->GetDev(), &viewInfo, NULL, &m_DummyStencilView[1]);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
rm->SetInternalResource(GetResID(m_DummyStencilView[1]));
|
||||
|
||||
VkCommandBuffer cmd = driver->GetNextCmd();
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
|
||||
|
||||
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
// need to update image layout into valid state
|
||||
VkImageMemoryBarrier barrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
0,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
Unwrap(m_DummyStencilImage[0]),
|
||||
{barrierAspectMask, 0, 1, 0, 1},
|
||||
};
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
barrier.image = Unwrap(m_DummyStencilImage[1]);
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_DummyStencilImage[0] == VK_NULL_HANDLE)
|
||||
{
|
||||
RDCERR("Couldn't find any integer format we could generate a dummy multisampled image with");
|
||||
}
|
||||
|
||||
CREATE_OBJECT(m_ArrayMSDescSet, m_ArrayMSDescriptorPool, m_ArrayMSDescSetLayout);
|
||||
|
||||
rm->SetInternalResource(GetResID(m_ArrayMSDescSet));
|
||||
@@ -570,6 +729,12 @@ VulkanDebugManager::~VulkanDebugManager()
|
||||
m_pDriver->vkDestroyDescriptorPool(dev, m_ArrayMSDescriptorPool, NULL);
|
||||
m_pDriver->vkDestroySampler(dev, m_ArrayMSSampler, NULL);
|
||||
|
||||
m_pDriver->vkDestroyImageView(dev, m_DummyStencilView[0], NULL);
|
||||
m_pDriver->vkDestroyImageView(dev, m_DummyStencilView[1], NULL);
|
||||
m_pDriver->vkDestroyImage(dev, m_DummyStencilImage[0], NULL);
|
||||
m_pDriver->vkDestroyImage(dev, m_DummyStencilImage[1], NULL);
|
||||
m_pDriver->vkFreeMemory(dev, m_DummyStencilMemory, NULL);
|
||||
|
||||
m_pDriver->vkDestroyDescriptorSetLayout(dev, m_ArrayMSDescSetLayout, NULL);
|
||||
m_pDriver->vkDestroyPipelineLayout(dev, m_ArrayMSPipeLayout, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, m_Array2MSPipe, NULL);
|
||||
|
||||
@@ -97,6 +97,11 @@ private:
|
||||
|
||||
VkSampler m_ArrayMSSampler = VK_NULL_HANDLE;
|
||||
|
||||
// [0] = non-MSAA, [1] = MSAA
|
||||
VkDeviceMemory m_DummyStencilMemory = VK_NULL_HANDLE;
|
||||
VkImage m_DummyStencilImage[2] = {VK_NULL_HANDLE};
|
||||
VkImageView m_DummyStencilView[2] = {VK_NULL_HANDLE};
|
||||
|
||||
// one per depth/stencil output format
|
||||
VkPipeline m_DepthMS2ArrayPipe[6] = {VK_NULL_HANDLE};
|
||||
// one per depth/stencil output format, per sample count
|
||||
|
||||
@@ -232,6 +232,21 @@ void VulkanDebugManager::CopyDepthTex2DMSToArray(VkImage destArray, VkImage srcM
|
||||
srcdesc[1].imageView = srcStencilView;
|
||||
srcdesc[1].sampler = Unwrap(m_ArrayMSSampler); // not used - we use texelFetch
|
||||
|
||||
if((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) == 0)
|
||||
{
|
||||
if(m_DummyStencilView[1] != VK_NULL_HANDLE)
|
||||
{
|
||||
srcdesc[1].imageView = Unwrap(m_DummyStencilView[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// as a last fallback, hope that setting an incompatible view (float not int) will not break
|
||||
// too badly. This only gets hit when the implementation has such poor format support that
|
||||
// there are no uint formats that can be sampled as MSAA.
|
||||
srcdesc[1].imageView = srcDepthView;
|
||||
}
|
||||
}
|
||||
|
||||
VkWriteDescriptorSet writeSet[] = {
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_ArrayMSDescSet), 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &srcdesc[0], NULL, NULL},
|
||||
@@ -239,10 +254,7 @@ void VulkanDebugManager::CopyDepthTex2DMSToArray(VkImage destArray, VkImage srcM
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &srcdesc[1], NULL, NULL},
|
||||
};
|
||||
|
||||
if(aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), 2, writeSet, 0, NULL);
|
||||
else
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), 1, writeSet, 0, NULL);
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), 2, writeSet, 0, NULL);
|
||||
|
||||
// create a bespoke framebuffer and renderpass for rendering
|
||||
VkAttachmentDescription attDesc = {0,
|
||||
@@ -583,6 +595,21 @@ void VulkanDebugManager::CopyDepthArrayToTex2DMS(VkImage destMS, VkImage srcArra
|
||||
srcdesc[1].imageView = srcStencilView;
|
||||
srcdesc[1].sampler = Unwrap(m_ArrayMSSampler); // not used - we use texelFetch
|
||||
|
||||
if((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) == 0)
|
||||
{
|
||||
if(m_DummyStencilView[0] != VK_NULL_HANDLE)
|
||||
{
|
||||
srcdesc[1].imageView = Unwrap(m_DummyStencilView[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// as a last fallback, hope that setting an incompatible view (float not int) will not break
|
||||
// too badly. This only gets hit when the implementation has such poor format support that
|
||||
// there are no uint formats that can be sampled as MSAA.
|
||||
srcdesc[1].imageView = srcDepthView;
|
||||
}
|
||||
}
|
||||
|
||||
VkWriteDescriptorSet writeSet[] = {
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_ArrayMSDescSet), 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &srcdesc[0], NULL, NULL},
|
||||
@@ -590,10 +617,7 @@ void VulkanDebugManager::CopyDepthArrayToTex2DMS(VkImage destMS, VkImage srcArra
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &srcdesc[1], NULL, NULL},
|
||||
};
|
||||
|
||||
if(aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), 2, writeSet, 0, NULL);
|
||||
else
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), 1, writeSet, 0, NULL);
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), 2, writeSet, 0, NULL);
|
||||
|
||||
// create a bespoke framebuffer and renderpass for rendering
|
||||
VkAttachmentDescription attDesc = {0,
|
||||
|
||||
@@ -1471,7 +1471,9 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo *
|
||||
{
|
||||
if(!IsDepthOrStencilFormat(createInfo_adjusted.format))
|
||||
{
|
||||
if(GetDebugManager()->IsMS2ArraySupported())
|
||||
// need to check the debug manager here since we might be creating this internal image from
|
||||
// its constructor
|
||||
if(GetDebugManager() && GetDebugManager()->IsMS2ArraySupported())
|
||||
createInfo_adjusted.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user