diff --git a/src/video_core/host_shaders/vulkan_present.frag b/src/video_core/host_shaders/vulkan_present.frag index 8fb0643a03..41c0916bd9 100644 --- a/src/video_core/host_shaders/vulkan_present.frag +++ b/src/video_core/host_shaders/vulkan_present.frag @@ -20,6 +20,21 @@ layout (push_constant, std140) uniform DrawInfo { layout (set = 0, binding = 0) uniform sampler2D screen_textures[3]; -void main() { - color = texture(screen_textures[screen_id_l], frag_tex_coord); +vec4 GetScreen(int screen_id) { +#ifdef ARRAY_DYNAMIC_INDEX + return texture(screen_textures[screen_id], frag_tex_coord); +#else + switch (screen_id) { + case 0: + return texture(screen_textures[0], frag_tex_coord); + case 1: + return texture(screen_textures[1], frag_tex_coord); + case 2: + return texture(screen_textures[2], frag_tex_coord); + } +#endif +} + +void main() { + color = GetScreen(screen_id_l); } diff --git a/src/video_core/host_shaders/vulkan_present_anaglyph.frag b/src/video_core/host_shaders/vulkan_present_anaglyph.frag index 4d39678e4e..a01ce63f63 100644 --- a/src/video_core/host_shaders/vulkan_present_anaglyph.frag +++ b/src/video_core/host_shaders/vulkan_present_anaglyph.frag @@ -32,8 +32,23 @@ layout (push_constant, std140) uniform DrawInfo { layout (set = 0, binding = 0) uniform sampler2D screen_textures[3]; +vec4 GetScreen(int screen_id) { +#ifdef ARRAY_DYNAMIC_INDEX + return texture(screen_textures[screen_id], frag_tex_coord); +#else + switch (screen_id) { + case 0: + return texture(screen_textures[0], frag_tex_coord); + case 1: + return texture(screen_textures[1], frag_tex_coord); + case 2: + return texture(screen_textures[2], frag_tex_coord); + } +#endif +} + void main() { - vec4 color_tex_l = texture(screen_textures[screen_id_l], frag_tex_coord); - vec4 color_tex_r = texture(screen_textures[screen_id_r], frag_tex_coord); + vec4 color_tex_l = GetScreen(screen_id_l); + vec4 color_tex_r = GetScreen(screen_id_r); color = vec4(color_tex_l.rgb*l+color_tex_r.rgb*r, color_tex_l.a); } diff --git a/src/video_core/host_shaders/vulkan_present_interlaced.frag b/src/video_core/host_shaders/vulkan_present_interlaced.frag index 2f5a18b90b..b033a9dec7 100644 --- a/src/video_core/host_shaders/vulkan_present_interlaced.frag +++ b/src/video_core/host_shaders/vulkan_present_interlaced.frag @@ -20,10 +20,25 @@ layout (push_constant, std140) uniform DrawInfo { layout (set = 0, binding = 0) uniform sampler2D screen_textures[3]; +vec4 GetScreen(int screen_id) { +#ifdef ARRAY_DYNAMIC_INDEX + return texture(screen_textures[screen_id], frag_tex_coord); +#else + switch (screen_id) { + case 0: + return texture(screen_textures[0], frag_tex_coord); + case 1: + return texture(screen_textures[1], frag_tex_coord); + case 2: + return texture(screen_textures[2], frag_tex_coord); + } +#endif +} + void main() { float screen_row = o_resolution.x * frag_tex_coord.x; if (int(screen_row) % 2 == reverse_interlaced) - color = texture(screen_textures[screen_id_l], frag_tex_coord); + color = GetScreen(screen_id_l); else - color = texture(screen_textures[screen_id_r], frag_tex_coord); + color = GetScreen(screen_id_r); } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 5a18b305d1..40cc96f8d3 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -224,15 +224,17 @@ void RendererVulkan::LoadFBToScreenInfo(const Pica::FramebufferConfig& framebuff } void RendererVulkan::CompileShaders() { - vk::Device device = instance.GetDevice(); + const vk::Device device = instance.GetDevice(); + const std::string_view preamble = + instance.IsImageArrayDynamicIndexSupported() ? "#define ARRAY_DYNAMIC_INDEX" : ""; present_vertex_shader = Compile(HostShaders::VULKAN_PRESENT_VERT, vk::ShaderStageFlagBits::eVertex, device); - present_shaders[0] = - Compile(HostShaders::VULKAN_PRESENT_FRAG, vk::ShaderStageFlagBits::eFragment, device); + present_shaders[0] = Compile(HostShaders::VULKAN_PRESENT_FRAG, + vk::ShaderStageFlagBits::eFragment, device, preamble); present_shaders[1] = Compile(HostShaders::VULKAN_PRESENT_ANAGLYPH_FRAG, - vk::ShaderStageFlagBits::eFragment, device); + vk::ShaderStageFlagBits::eFragment, device, preamble); present_shaders[2] = Compile(HostShaders::VULKAN_PRESENT_INTERLACED_FRAG, - vk::ShaderStageFlagBits::eFragment, device); + vk::ShaderStageFlagBits::eFragment, device, preamble); auto properties = instance.GetPhysicalDevice().getProperties(); for (std::size_t i = 0; i < present_samplers.size(); i++) { diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 4bdadb7ca0..031aec73fa 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -248,6 +248,11 @@ public: return triangle_fan_supported; } + /// Returns true if dynamic indices can be used inside shaders. + bool IsImageArrayDynamicIndexSupported() const { + return features.shaderSampledImageArrayDynamicIndexing; + } + /// Returns the minimum vertex stride alignment u32 GetMinVertexStrideAlignment() const { return min_vertex_stride_alignment; diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp index ba5c5f8670..29335c05d5 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp @@ -158,7 +158,8 @@ bool InitializeCompiler() { } } // Anonymous namespace -vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device) { +vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device, + std::string_view premable) { if (!InitializeCompiler()) { return {}; } @@ -176,6 +177,7 @@ vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, v shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_3); shader->setStringsWithLengths(&pass_source_code, &pass_source_code_length, 1); + shader->setPreamble(premable.data()); glslang::TShader::ForbidIncluder includer; if (!shader->parse(&DefaultTBuiltInResource, default_version, profile, false, true, messages, diff --git a/src/video_core/renderer_vulkan/vk_shader_util.h b/src/video_core/renderer_vulkan/vk_shader_util.h index eb932e07dd..cb91aedf85 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.h +++ b/src/video_core/renderer_vulkan/vk_shader_util.h @@ -16,7 +16,8 @@ namespace Vulkan { * @param stage The pipeline stage the shader will be used in. * @param device The vulkan device handle. */ -vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device); +vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, vk::Device device, + std::string_view premable = ""); /** * @brief Creates a vulkan shader module from SPIR-V bytecode.