Add support for multiview with quad overdraw overlay. Closes #3424

* We multiply the internal array image up by the number of views and read from
  viewindex to write and resolve from different sets of slices
This commit is contained in:
baldurk
2024-09-09 14:43:17 +01:00
parent c7b0c240e2
commit 3c6520d250
7 changed files with 99 additions and 13 deletions
+10 -1
View File
@@ -26,6 +26,10 @@
#extension GL_ARB_shader_image_load_store : require
#endif
#if defined(VULKAN) && defined(USE_MULTIVIEW)
#extension GL_EXT_multiview : require
#endif
#include "glsl_globals.h"
////////////////////////////////////////////////////////////////////////////////////////////
@@ -47,9 +51,14 @@ void main()
{
ivec2 quad = ivec2(gl_FragCoord.xy * 0.5f);
uint view_offset = 0u;
#if defined(VULKAN) && defined(USE_MULTIVIEW)
view_offset += 4 * gl_ViewIndex;
#endif
uint overdraw = 0u;
for(uint i = 0u; i < 4u; i++)
overdraw += imageLoad(overdrawImage, ivec3(quad, i)).x / (i + 1u);
overdraw += imageLoad(overdrawImage, ivec3(quad, i + view_offset)).x / (i + 1u);
color_out = vec4(overdraw);
}
+10 -1
View File
@@ -31,6 +31,10 @@
#extension GL_ARB_gpu_shader5 : require
#endif
#if defined(VULKAN) && defined(USE_MULTIVIEW)
#extension GL_EXT_multiview : require
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Below shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
@@ -71,7 +75,12 @@ void main()
// Count the live pixels, minus 1 (zero indexing)
uint pixelCount = c0 + c1 + c2 + c3 - 1u;
ivec3 quad = ivec3(gl_FragCoord.xy * 0.5, pixelCount);
uint arrayIndex = pixelCount;
#if defined(VULKAN) && defined(USE_MULTIVIEW)
arrayIndex += 4 * gl_ViewIndex;
#endif
ivec3 quad = ivec3(gl_FragCoord.xy * 0.5, arrayIndex);
imageAtomicAdd(overdrawImage, quad, 1);
}
+28
View File
@@ -4330,6 +4330,34 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
driver->vkDestroyRenderPass(driver->GetDev(), SRGBA8MSRP, NULL);
}
VkPipeline VulkanReplay::OverlayRendering::CreateTempMultiviewQuadResolvePipe(WrappedVulkan *driver)
{
VulkanShaderCache *shaderCache = driver->GetShaderCache();
ConciseGraphicsPipeline pipeInfo = {
NoDepthRP,
m_QuadResolvePipeLayout,
shaderCache->GetBuiltinModule(BuiltinShader::BlitVS),
shaderCache->GetBuiltinModule(BuiltinShader::QuadResolveMultiviewFS),
{VK_DYNAMIC_STATE_VIEWPORT},
Samples,
false, // sampleRateShading
false, // depthEnable
false, // stencilEnable
StencilMode::KEEP,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_SRC_ALPHA,
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
0xf, // writeMask
};
VkPipeline ret;
CREATE_OBJECT(ret, pipeInfo);
return ret;
}
void VulkanReplay::OverlayRendering::Destroy(WrappedVulkan *driver)
{
if(ImageMem == VK_NULL_HANDLE)
+36 -10
View File
@@ -45,8 +45,13 @@ RDOC_EXTERN_CONFIG(bool, Vulkan_Debug_SingleSubmitFlushing);
struct VulkanQuadOverdrawCallback : public VulkanActionCallback
{
VulkanQuadOverdrawCallback(WrappedVulkan *vk, VkDescriptorSetLayout descSetLayout,
VkDescriptorSet descSet, const rdcarray<uint32_t> &events)
: m_pDriver(vk), m_DescSetLayout(descSetLayout), m_DescSet(descSet), m_Events(events)
VkDescriptorSet descSet, const rdcarray<uint32_t> &events,
bool multiview)
: m_pDriver(vk),
m_DescSetLayout(descSetLayout),
m_DescSet(descSet),
m_Events(events),
m_Multiview(multiview)
{
m_pDriver->SetActionCB(this);
}
@@ -173,8 +178,8 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback
rs->rasterizerDiscardEnable = false;
}
rdcarray<uint32_t> spirv =
*m_pDriver->GetShaderCache()->GetBuiltinBlob(BuiltinShader::QuadWriteFS);
rdcarray<uint32_t> spirv = *m_pDriver->GetShaderCache()->GetBuiltinBlob(
m_Multiview ? BuiltinShader::QuadWriteMultiviewFS : BuiltinShader::QuadWriteFS);
// patch spirv, change descriptor set to descSet value
size_t it = 5;
@@ -375,6 +380,7 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback
VkDescriptorSetLayout m_DescSetLayout;
VkDescriptorSet m_DescSet;
const rdcarray<uint32_t> &m_Events;
bool m_Multiview;
// cache modified pipelines
struct CachedPipeline
@@ -823,6 +829,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
subRange,
};
if(subRange.layerCount > 1)
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
vkr = m_pDriver->vkCreateImageView(m_Device, &viewInfo, NULL, &m_Overlay.ImageView);
CHECK_VKR(m_pDriver, vkr);
@@ -839,6 +848,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
sub.numSlices,
};
if(multiviewMask > 0)
fbinfo.layers = 1;
vkr = m_pDriver->vkCreateFramebuffer(m_Device, &fbinfo, NULL, &m_Overlay.NoDepthFB);
CHECK_VKR(m_pDriver, vkr);
@@ -2822,10 +2834,19 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
events.erase(0);
}
VkPipeline quadResolveMultiviewPipe = VK_NULL_HANDLE;
VkImage quadImg;
VkDeviceMemory quadImgMem;
VkImageView quadImgView;
uint32_t quadImgArraySlices = 4;
if(multiviewMask > 0)
{
quadImgArraySlices *= Bits::CountOnes(multiviewMask);
quadResolveMultiviewPipe = m_Overlay.CreateTempMultiviewQuadResolvePipe(m_pDriver);
}
VkImageCreateInfo imInfo = {
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
NULL,
@@ -2834,7 +2855,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
VK_FORMAT_R32_UINT,
{RDCMAX(1U, m_Overlay.ImageDim.width >> 1), RDCMAX(1U, m_Overlay.ImageDim.height >> 1), 1},
1,
4,
quadImgArraySlices,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
@@ -2878,7 +2899,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
VK_FORMAT_R32_UINT,
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 4},
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, quadImgArraySlices},
};
vkr = m_pDriver->vkCreateImageView(m_Device, &viewinfo, NULL, &quadImgView);
@@ -2912,7 +2933,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(quadImg),
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 4},
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, quadImgArraySlices},
};
// clear all to black
@@ -2949,7 +2970,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
{
// declare callback struct here
VulkanQuadOverdrawCallback cb(m_pDriver, m_Overlay.m_QuadDescSetLayout,
m_Overlay.m_QuadDescSet, events);
m_Overlay.m_QuadDescSet, events, multiviewMask > 0);
m_pDriver->ReplayLog(events.front(), events.back(), eReplay_Full);
@@ -2983,8 +3004,12 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(m_Overlay.m_QuadResolvePipeline[SampleIndex(iminfo.samples)]));
if(multiviewMask > 0)
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(quadResolveMultiviewPipe));
else
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(m_Overlay.m_QuadResolvePipeline[SampleIndex(iminfo.samples)]));
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(m_Overlay.m_QuadResolvePipeLayout), 0, 1,
UnwrapPtr(m_Overlay.m_QuadDescSet), 0, NULL);
@@ -3007,6 +3032,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->vkDestroyImageView(m_Device, quadImgView, NULL);
m_pDriver->vkDestroyImage(m_Device, quadImg, NULL);
m_pDriver->vkFreeMemory(m_Device, quadImgMem, NULL);
m_pDriver->vkDestroyPipeline(m_Device, quadResolveMultiviewPipe, NULL);
}
// restore back to normal
+2
View File
@@ -667,6 +667,8 @@ private:
void Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool);
void Destroy(WrappedVulkan *driver);
VkPipeline CreateTempMultiviewQuadResolvePipe(WrappedVulkan *driver);
VkDeviceMemory ImageMem = VK_NULL_HANDLE;
VkDeviceSize ImageMemSize = 0;
VkImage Image = VK_NULL_HANDLE;
+11 -1
View File
@@ -44,6 +44,7 @@ enum class BuiltinShaderFlags
None = 0x0,
BaseTypeParameterised = 0x1,
TextureTypeParameterised = 0x2,
Multiview = 0x4,
};
BITMASK_OPERATORS(BuiltinShaderFlags);
@@ -86,9 +87,15 @@ static const BuiltinShaderConfig builtinShaders[] = {
rdcspv::ShaderStage::Compute),
BuiltinShaderConfig(BuiltinShader::QuadResolveFS, EmbeddedResource(glsl_quadresolve_frag),
rdcspv::ShaderStage::Fragment, FeatureCheck::FragmentStores),
BuiltinShaderConfig(BuiltinShader::QuadResolveMultiviewFS,
EmbeddedResource(glsl_quadresolve_frag), rdcspv::ShaderStage::Fragment,
FeatureCheck::FragmentStores, BuiltinShaderFlags::Multiview),
BuiltinShaderConfig(BuiltinShader::QuadWriteFS, EmbeddedResource(glsl_quadwrite_frag),
rdcspv::ShaderStage::Fragment),
BuiltinShaderConfig(BuiltinShader::QuadWriteMultiviewFS, EmbeddedResource(glsl_quadwrite_frag),
rdcspv::ShaderStage::Fragment,
FeatureCheck::FragmentStores | FeatureCheck::NonMetalBackend),
FeatureCheck::FragmentStores | FeatureCheck::NonMetalBackend,
BuiltinShaderFlags::Multiview),
BuiltinShaderConfig(BuiltinShader::TrisizeGS, EmbeddedResource(glsl_trisize_geom),
rdcspv::ShaderStage::Geometry),
BuiltinShaderConfig(BuiltinShader::TrisizeFS, EmbeddedResource(glsl_trisize_frag),
@@ -282,6 +289,9 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver)
defines += rdcstr("#define SHADER_RESTYPE ") + ToStr(textureType) + "\n";
defines += rdcstr("#define SHADER_BASETYPE ") + ToStr(baseType) + "\n";
if(config.flags & BuiltinShaderFlags::Multiview)
defines += rdcstr("#define USE_MULTIVIEW 1\n");
SPIRVBlob &blob = m_BuiltinShaderBlobs[i][baseType][textureType];
rdcstr source = GetDynamicEmbeddedResource(config.resource);
@@ -44,7 +44,9 @@ enum class BuiltinShader
MeshFS,
MeshCS,
QuadResolveFS,
QuadResolveMultiviewFS,
QuadWriteFS,
QuadWriteMultiviewFS,
TrisizeGS,
TrisizeFS,
TexRemap,