diff --git a/renderdoc/data/glsl/quadresolve.frag b/renderdoc/data/glsl/quadresolve.frag index 47596dff7..fde927739 100644 --- a/renderdoc/data/glsl/quadresolve.frag +++ b/renderdoc/data/glsl/quadresolve.frag @@ -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); } diff --git a/renderdoc/data/glsl/quadwrite.frag b/renderdoc/data/glsl/quadwrite.frag index 6ffde07da..ac91566c6 100644 --- a/renderdoc/data/glsl/quadwrite.frag +++ b/renderdoc/data/glsl/quadwrite.frag @@ -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); } diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index b2a67f3c8..7cd5b425c 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -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) diff --git a/renderdoc/driver/vulkan/vk_overlay.cpp b/renderdoc/driver/vulkan/vk_overlay.cpp index bee8b30e8..c8e8d53d4 100644 --- a/renderdoc/driver/vulkan/vk_overlay.cpp +++ b/renderdoc/driver/vulkan/vk_overlay.cpp @@ -45,8 +45,13 @@ RDOC_EXTERN_CONFIG(bool, Vulkan_Debug_SingleSubmitFlushing); struct VulkanQuadOverdrawCallback : public VulkanActionCallback { VulkanQuadOverdrawCallback(WrappedVulkan *vk, VkDescriptorSetLayout descSetLayout, - VkDescriptorSet descSet, const rdcarray &events) - : m_pDriver(vk), m_DescSetLayout(descSetLayout), m_DescSet(descSet), m_Events(events) + VkDescriptorSet descSet, const rdcarray &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 spirv = - *m_pDriver->GetShaderCache()->GetBuiltinBlob(BuiltinShader::QuadWriteFS); + rdcarray 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 &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 diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index f7f2a755c..1433da516 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -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; diff --git a/renderdoc/driver/vulkan/vk_shader_cache.cpp b/renderdoc/driver/vulkan/vk_shader_cache.cpp index e87bfe3ed..85047d0e0 100644 --- a/renderdoc/driver/vulkan/vk_shader_cache.cpp +++ b/renderdoc/driver/vulkan/vk_shader_cache.cpp @@ -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); diff --git a/renderdoc/driver/vulkan/vk_shader_cache.h b/renderdoc/driver/vulkan/vk_shader_cache.h index 57c5db510..0230eac5c 100644 --- a/renderdoc/driver/vulkan/vk_shader_cache.h +++ b/renderdoc/driver/vulkan/vk_shader_cache.h @@ -44,7 +44,9 @@ enum class BuiltinShader MeshFS, MeshCS, QuadResolveFS, + QuadResolveMultiviewFS, QuadWriteFS, + QuadWriteMultiviewFS, TrisizeGS, TrisizeFS, TexRemap,