From 59827cd601b4e0f1a3c31fba46ecaa1275075461 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 13 Jun 2018 13:16:07 +0200 Subject: [PATCH] - use layout binding qualifiers on uniform buffers when GLSL version >= 4.2 This has no performance benefits but allows checking shader generation correctness without having to implement Vulkan first. --- src/gl/shaders/gl_shaderprogram.cpp | 19 +++++----- src/gl/system/gl_framebuffer.cpp | 3 ++ src/gl/system/gl_framebuffer.h | 1 - src/gl_load/gl_interface.cpp | 1 + src/hwrenderer/data/shaderuniforms.h | 54 +++++++++++++++++++++++++++- src/v_video.h | 2 +- 6 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/gl/shaders/gl_shaderprogram.cpp b/src/gl/shaders/gl_shaderprogram.cpp index fd52a7c38..b767ae51c 100644 --- a/src/gl/shaders/gl_shaderprogram.cpp +++ b/src/gl/shaders/gl_shaderprogram.cpp @@ -145,9 +145,12 @@ void FShaderProgram::Link(const char *name) void FShaderProgram::SetUniformBufferLocation(int index, const char *name) { - GLuint uniformBlockIndex = glGetUniformBlockIndex(mProgram, name); - if (uniformBlockIndex != GL_INVALID_INDEX) - glUniformBlockBinding(mProgram, uniformBlockIndex, index); + if (screen->glslversion < 4.20) + { + GLuint uniformBlockIndex = glGetUniformBlockIndex(mProgram, name); + if (uniformBlockIndex != GL_INVALID_INDEX) + glUniformBlockBinding(mProgram, uniformBlockIndex, index); + } } //========================================================================== @@ -201,6 +204,8 @@ FString FShaderProgram::PatchShader(ShaderType type, const FString &code, const { FString patchedCode; + // If we have 4.2, always use it because it adds important new syntax. + if (maxGlslVersion < 420 && gl.glslversion >= 4.2f) maxGlslVersion = 420; int shaderVersion = MIN((int)round(gl.glslversion * 10) * 10, maxGlslVersion); if (gl.es) patchedCode.AppendFormat("#version %d es\n", shaderVersion); @@ -224,11 +229,3 @@ FString FShaderProgram::PatchShader(ShaderType type, const FString &code, const return patchedCode; } - -//========================================================================== -// -// patch the shader source to work with -// GLSL 1.2 keywords and identifiers -// -//========================================================================== - diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 2411170b3..20caf148e 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -82,8 +82,11 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int mDebug = std::make_shared(); mDebug->Update(); SetGamma(); + + // Move some state to the framebuffer object for easier access. hwcaps = gl.flags; if (gl.legacyMode) hwcaps |= RFL_NO_SHADERS; + glslversion = gl.glslversion; } OpenGLFrameBuffer::~OpenGLFrameBuffer() diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index bd332dfd3..2ae1d2e96 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -45,7 +45,6 @@ public: void SetViewportRects(IntRect *bounds) override; void BlurScene(float amount) override; IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) override; - virtual FString GetUniformLayoutString(int bindingpoint) { return "std140"; } // Retrieves a buffer containing image data for a screenshot. diff --git a/src/gl_load/gl_interface.cpp b/src/gl_load/gl_interface.cpp index 6e07259f5..b543928b2 100644 --- a/src/gl_load/gl_interface.cpp +++ b/src/gl_load/gl_interface.cpp @@ -225,6 +225,7 @@ void gl_LoadExtensions() gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. } #endif + gl.glslversion = 3.31f; // Force GLSL down to 3.3. } else if (gl_version < 4.5f) { diff --git a/src/hwrenderer/data/shaderuniforms.h b/src/hwrenderer/data/shaderuniforms.h index 834122239..b9f34df39 100644 --- a/src/hwrenderer/data/shaderuniforms.h +++ b/src/hwrenderer/data/shaderuniforms.h @@ -57,7 +57,16 @@ public: mFields = fields; FString decl; - decl.Format("layout(%s) uniform %s\n{\n", screen->GetUniformLayoutString(bindingpoint).GetChars(), name); + FString layout; + if (screen->glslversion < 4.20) + { + layout = "std140"; + } + else + { + layout.Format("std140, binding = %d", bindingpoint); + } + decl.Format("layout(%s) uniform %s\n{\n", layout.GetChars(), name); for (const auto &field : fields) { decl.AppendFormat("\t%s %s;\n", GetTypeStr(field.Type), field.Name); @@ -117,3 +126,46 @@ private: std::vector mFields; }; + +enum class SamplerType : int +{ + Sampler1D, + Sampler2D, + Sampler3D, + SamplerCube, + iSampler1D, + iSampler2D, + iSampler3D, + iSamplerCube, + uSampler1D, + uSampler2D, + uSampler3D, + uSamplerCube, +}; + +struct SamplerUniform +{ + const char *GetTypeStr() const + { + switch (mType) + { + default: + case SamplerType::Sampler1D: return "sampler1D"; + case SamplerType::Sampler2D: return "sampler2D"; + case SamplerType::Sampler3D: return "sampler3D"; + case SamplerType::SamplerCube: return "samplerCube"; + case SamplerType::iSampler1D: return "isampler1D"; + case SamplerType::iSampler2D: return "isampler2D"; + case SamplerType::iSampler3D: return "isampler3D"; + case SamplerType::iSamplerCube: return "isamplerCube"; + case SamplerType::uSampler1D: return "usampler1D"; + case SamplerType::uSampler2D: return "usampler2D"; + case SamplerType::uSampler3D: return "usampler3D"; + case SamplerType::uSamplerCube: return "usamplerCube"; + } + } + + int mBinding; + SamplerType mType; + const char *mName; +}; \ No newline at end of file diff --git a/src/v_video.h b/src/v_video.h index 1e985f83a..8e66464af 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -349,6 +349,7 @@ protected: public: int hwcaps = 0; + float glslversion = 0; // This is here so that the differences between old OpenGL and new OpenGL/Vulkan can be handled by platform independent code. int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance. bool enable_quadbuffered = false; @@ -416,7 +417,6 @@ public: // Interface to hardware rendering resources virtual IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) { return nullptr; } - virtual FString GetUniformLayoutString(int bindingpoint) { return ""; } // Begin 2D drawing operations. // Returns true if hardware-accelerated 2D has been entered, false if not.