Index: binaries/data/mods/mod/shaders/program.rng =================================================================== --- binaries/data/mods/mod/shaders/program.rng +++ binaries/data/mods/mod/shaders/program.rng @@ -55,8 +55,6 @@ gl_Vertex gl_Normal gl_Color - gl_SecondaryColor - gl_FogCoord gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 Index: source/renderer/backend/gl/Device.h =================================================================== --- source/renderer/backend/gl/Device.h +++ source/renderer/backend/gl/Device.h @@ -51,6 +51,7 @@ bool S3TC; bool ARBShaders; bool ARBShadersShadow; + bool computeShaders; bool debugLabels; bool debugScopedLabels; bool multisampling; Index: source/renderer/backend/gl/Device.cpp =================================================================== --- source/renderer/backend/gl/Device.cpp +++ source/renderer/backend/gl/Device.cpp @@ -303,6 +303,7 @@ capabilities.ARBShaders = !ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", nullptr); if (capabilities.ARBShaders) capabilities.ARBShadersShadow = ogl_HaveExtension("GL_ARB_fragment_program_shadow"); + capabilities.computeShaders = ogl_HaveVersion(4, 3) || ogl_HaveExtension("GL_ARB_compute_shader"); #if CONFIG2_GLES // Some GLES implementations have GL_EXT_texture_compression_dxt1 // but that only supports DXT1 so we can't use it. Index: source/renderer/backend/gl/ShaderProgram.cpp =================================================================== --- source/renderer/backend/gl/ShaderProgram.cpp +++ source/renderer/backend/gl/ShaderProgram.cpp @@ -100,22 +100,42 @@ return type; } -GLenum ParseAttribSemantics(const CStr& str) +GLenum ParseAttribSemantics(Renderer::Backend::GL::CDevice* device, const CStr& str) { - // Map known semantics onto the attribute locations documented by NVIDIA - if (str == "gl_Vertex") return 0; - if (str == "gl_Normal") return 2; - if (str == "gl_Color") return 3; - if (str == "gl_SecondaryColor") return 4; - if (str == "gl_FogCoord") return 5; - if (str == "gl_MultiTexCoord0") return 8; - if (str == "gl_MultiTexCoord1") return 9; - if (str == "gl_MultiTexCoord2") return 10; - if (str == "gl_MultiTexCoord3") return 11; - if (str == "gl_MultiTexCoord4") return 12; - if (str == "gl_MultiTexCoord5") return 13; - if (str == "gl_MultiTexCoord6") return 14; - if (str == "gl_MultiTexCoord7") return 15; + // Old mapping makes sense only if we have an old/low-end hardware. Else we + // need to use sequential numbering to fix #3054. We use presence of + // compute shaders as a check that the hardware has universal CUs. + if (device->GetCapabilities().computeShaders) + { + if (str == "gl_Vertex") return 0; + if (str == "gl_Normal") return 1; + if (str == "gl_Color") return 2; + if (str == "gl_MultiTexCoord0") return 3; + if (str == "gl_MultiTexCoord1") return 4; + if (str == "gl_MultiTexCoord2") return 5; + if (str == "gl_MultiTexCoord3") return 6; + if (str == "gl_MultiTexCoord4") return 7; + if (str == "gl_MultiTexCoord5") return 8; + if (str == "gl_MultiTexCoord6") return 9; + if (str == "gl_MultiTexCoord7") return 10; + } + else + { + // Map known semantics onto the attribute locations documented by NVIDIA: + // https://download.nvidia.com/developer/Papers/2005/OpenGL_2.0/NVIDIA_OpenGL_2.0_Support.pdf + // https://developer.download.nvidia.com/opengl/glsl/glsl_release_notes.pdf + if (str == "gl_Vertex") return 0; + if (str == "gl_Normal") return 2; + if (str == "gl_Color") return 3; + if (str == "gl_MultiTexCoord0") return 8; + if (str == "gl_MultiTexCoord1") return 9; + if (str == "gl_MultiTexCoord2") return 10; + if (str == "gl_MultiTexCoord3") return 11; + if (str == "gl_MultiTexCoord4") return 12; + if (str == "gl_MultiTexCoord5") return 13; + if (str == "gl_MultiTexCoord6") return 14; + if (str == "gl_MultiTexCoord7") return 15; + } debug_warn("Invalid attribute semantics"); return 0; @@ -902,7 +922,7 @@ } else if (Param.GetNodeName() == el_attrib) { - int attribLoc = ParseAttribSemantics(Attrs.GetNamedItem(at_semantics)); + const int attribLoc = ParseAttribSemantics(device, Attrs.GetNamedItem(at_semantics)); vertexAttribs[CStrIntern(Attrs.GetNamedItem(at_name))] = attribLoc; } }