From d72ad3b3f4517352dfb3c991f6818ccae4dc9819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 29 Nov 2022 15:29:31 +0100 Subject: [PATCH] Fragment shader generator: Move the framebuffer fetch bit to the shader ID. Will resolve a future issue in the multisampling PR, where the GPU_USE_FRAMEBUFFER_FETCH flag changes at runtime if you switch between no AA and MSAA. Just figured I'd get it in separately for safety. --- GPU/Common/FragmentShaderGenerator.cpp | 9 +++++++-- GPU/Common/ShaderId.cpp | 9 +++++++++ GPU/Common/ShaderId.h | 1 + GPU/Vulkan/ShaderManagerVulkan.cpp | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index dee1dfb431..eba7b966da 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -169,8 +169,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu bool needFramebufferRead = replaceBlend == REPLACE_BLEND_READ_FRAMEBUFFER || colorWriteMask || replaceLogicOp; - bool fetchFramebuffer = needFramebufferRead && gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH); - bool readFramebufferTex = needFramebufferRead && !gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH); + bool fetchFramebuffer = needFramebufferRead && id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH); + bool readFramebufferTex = needFramebufferRead && !id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH); + + if (fetchFramebuffer && (compat.shaderLanguage != GLSL_VULKAN || compat.shaderLanguage != GLSL_3xx)) { + *errorString = "framebuffer fetch requires GLSL: vulkan or 3xx"; + return false; + } bool needFragCoord = readFramebufferTex || gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT); bool writeDepth = gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT); diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 705ce77cb9..e572f721de 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -259,6 +259,7 @@ std::string FragmentShaderDesc(const FShaderID &id) { if ((id.Bits(FS_BIT_REPLACE_LOGIC_OP, 4) != GE_LOGIC_COPY) && !id.Bit(FS_BIT_CLEARMODE)) desc << "ReplaceLogic "; if (id.Bit(FS_BIT_SAMPLE_ARRAY_TEXTURE)) desc << "TexArray "; if (id.Bit(FS_BIT_STEREO)) desc << "Stereo "; + if (id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH)) desc << "(fetch)"; return desc.str(); } @@ -384,6 +385,14 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, stencilWithoutDepth); } } + + // In case the USE flag changes (for example, in multisampling we might disable input attachments), + // we don't want to accidentally use the wrong cached shader here. So moved it to a bit. + if (FragmentIdNeedsFramebufferRead(id)) { + if (gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH)) { + id.SetBit(FS_BIT_USE_FRAMEBUFFER_FETCH); + } + } } *id_out = id; diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 06b252d87d..6c3a886669 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -100,6 +100,7 @@ enum FShaderBit : uint8_t { FS_BIT_SHADER_DEPAL_MODE = 55, // 2 bits (ShaderDepalMode) FS_BIT_SAMPLE_ARRAY_TEXTURE = 57, // For multiview, framebuffers are array textures and we need to sample the two layers correctly. FS_BIT_STEREO = 58, + FS_BIT_USE_FRAMEBUFFER_FETCH = 59, }; static inline FShaderBit operator +(FShaderBit bit, int i) { diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 076d317442..e895e21af6 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -484,7 +484,7 @@ VulkanGeometryShader *ShaderManagerVulkan::GetGeometryShaderFromModule(VkShaderM // instantaneous. #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 30 +#define CACHE_VERSION 31 struct VulkanCacheHeader { uint32_t magic; uint32_t version;