From 4018e52d3027afbed1a7b4fa2a198b6996439834 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 19 Nov 2024 13:35:09 +0100 Subject: [PATCH] GPU: OpenGL&Vulkan incorrect workarounds GLSL OpenGL & Vulkan has workarounds when gl_Layer/gl_ViewportIndex isn't supported. In this case a geometry shader will is generated. This geometry shader doesn't follow the GLSL standard and doesn't work on some platforms. This has not been an issue as the platforms that don't support gl_Layer/gl_ViewportIndex don't show the issue. According to the specs gl_Layer and gl_ViewportIndex should be set for each call to EmitVertex. A shader should not rely on that EmitVertex reuses the same memory. Ref https://www.khronos.org/opengl/wiki/Geometry_Shader#Layered_rendering ``` Warning: gl_Layer and gl_ViewportIndex are GS output variables. As such, every time you call EmitVertex, their values will become undefined. Therefore, you must set these variables every time you loop over outputs. ``` Issue detected during development of !129062 Pull Request: https://projects.blender.org/blender/blender/pulls/130506 --- source/blender/gpu/opengl/gl_shader.cc | 12 ++++++------ source/blender/gpu/vulkan/vk_shader.cc | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index baf2104003a..73b3a68ea3e 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -957,12 +957,6 @@ std::string GLShader::workaround_geometry_shader_source_create( ss << "void main()\n"; ss << "{\n"; - if (do_layer_workaround) { - ss << " gl_Layer = gpu_Layer[0];\n"; - } - if (do_viewport_workaround) { - ss << " gl_ViewportIndex = gpu_ViewportIndex[0];\n"; - } if (do_barycentric_workaround) { ss << " gpu_pos[0] = gl_in[0].gl_Position;\n"; ss << " gpu_pos[1] = gl_in[1].gl_Position;\n"; @@ -980,6 +974,12 @@ std::string GLShader::workaround_geometry_shader_source_create( ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n"; } ss << " gl_Position = gl_in[" << i << "].gl_Position;\n"; + if (do_layer_workaround) { + ss << " gl_Layer = gpu_Layer[" << i << "];\n"; + } + if (do_viewport_workaround) { + ss << " gl_ViewportIndex = gpu_ViewportIndex[" << i << "];\n"; + } ss << " EmitVertex();\n"; } ss << "}\n"; diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc index abecee872f7..aff98388dce 100644 --- a/source/blender/gpu/vulkan/vk_shader.cc +++ b/source/blender/gpu/vulkan/vk_shader.cc @@ -1168,12 +1168,6 @@ std::string VKShader::workaround_geometry_shader_source_create( ss << "void main()\n"; ss << "{\n"; - if (do_layer_workaround) { - ss << " gl_Layer = gpu_Layer[0];\n"; - } - if (do_viewport_workaround) { - ss << " gl_ViewportIndex = gpu_ViewportIndex[0];\n"; - } for (auto i : IndexRange(3)) { for (StageInterfaceInfo *iface : info_modified.vertex_out_interfaces_) { for (auto &inout : iface->inouts) { @@ -1186,6 +1180,12 @@ std::string VKShader::workaround_geometry_shader_source_create( ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n"; } ss << " gl_Position = gl_in[" << i << "].gl_Position;\n"; + if (do_layer_workaround) { + ss << " gl_Layer = gpu_Layer[" << i << "];\n"; + } + if (do_viewport_workaround) { + ss << " gl_ViewportIndex = gpu_ViewportIndex[" << i << "];\n"; + } ss << " gpu_EmitVertex();\n"; } ss << "}\n";