[Bf-blender-cvs] [d8d00713671] temp-gpu-push-constants: GPU: Added push constants to shader interface

Jeroen Bakker noreply at git.blender.org
Fri Jul 2 14:02:15 CEST 2021


Commit: d8d007136719c67e02092b2511bb88f869616f84
Author: Jeroen Bakker
Date:   Fri Jul 2 13:43:01 2021 +0200
Branches: temp-gpu-push-constants
https://developer.blender.org/rBd8d007136719c67e02092b2511bb88f869616f84

GPU: Added push constants to shader interface

===================================================================

M	source/blender/gpu/opengl/gl_shader.cc
M	source/blender/gpu/opengl/gl_shader.hh
M	source/blender/gpu/opengl/gl_shader_interface.cc
M	source/blender/gpu/opengl/gl_shader_interface.hh
M	source/blender/gpu/opengl/gl_shader_patcher.cc
M	source/blender/gpu/opengl/gl_shader_patcher.hh

===================================================================

diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 9ad9ffebd00..b89f59f9557 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -148,8 +148,8 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *>
 
   /* Patch the shader code using the first source slot. */
   sources[0] = glsl_patch_get(gl_stage);
-  converter_.patch(sources);
-  if (converter_.has_errors()) {
+  patch_vulkan_to_opengl(patcher_context_, sources);
+  if (patcher_context_.has_errors()) {
     compilation_failed_ = true;
     return 0;
   }
@@ -231,11 +231,12 @@ bool GLShader::finalize()
     return false;
   }
 
-  interface = new GLShaderInterface(shader_program_);
+  interface = new GLShaderInterface(patcher_context_, shader_program_);
 
-  /* Only patched sources are only freed when shader compilation and linking succeeds for
-   * debugging. */
-  converter_.free();
+  /* Patched sources are only freed when shader compilation and linking successful completed. In
+   * other cases they are kept for debugging purposes and will be GC'd when the GPUShader is freed.
+   */
+  patcher_context_.free_patched_sources();
 
   return true;
 }
diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh
index 63dcbcbabae..dfc44119e50 100644
--- a/source/blender/gpu/opengl/gl_shader.hh
+++ b/source/blender/gpu/opengl/gl_shader.hh
@@ -50,7 +50,8 @@ class GLShader : public Shader {
   bool compilation_failed_ = false;
 
   eGPUShaderTFBType transform_feedback_type_ = GPU_SHADER_TFB_NONE;
-  GLShaderPatcher converter_;
+
+  GLShaderPatcherContext patcher_context_;
 
  public:
   GLShader(const char *name);
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc
index 9cf072b2e8a..b2842020b25 100644
--- a/source/blender/gpu/opengl/gl_shader_interface.cc
+++ b/source/blender/gpu/opengl/gl_shader_interface.cc
@@ -145,7 +145,7 @@ static inline int ssbo_binding(int32_t program, uint32_t ssbo_index)
 /** \name Creation / Destruction
  * \{ */
 
-GLShaderInterface::GLShaderInterface(GLuint program)
+GLShaderInterface::GLShaderInterface(GLShaderPatcherContext &context, GLuint program)
 {
   /* Necessary to make #glUniform works. */
   glUseProgram(program);
@@ -321,6 +321,13 @@ GLShaderInterface::GLShaderInterface(GLuint program)
   // this->debug_print();
 
   this->sort_inputs();
+
+  /* Push Constant Blocks */
+  /* Push constants are converted by GLShaderPatcher to regular uniform buffers. Here we retrieve
+   * the reference to its binding.  */
+  if (context.push_constants.name) {
+    push_constant_input_ = ubo_get(context.push_constants.name->c_str());
+  }
 }
 
 GLShaderInterface::~GLShaderInterface()
diff --git a/source/blender/gpu/opengl/gl_shader_interface.hh b/source/blender/gpu/opengl/gl_shader_interface.hh
index 89a5b631047..059fedd83c6 100644
--- a/source/blender/gpu/opengl/gl_shader_interface.hh
+++ b/source/blender/gpu/opengl/gl_shader_interface.hh
@@ -34,6 +34,8 @@
 
 #include "glew-mx.h"
 
+#include "gl_shader_patcher.hh"
+
 #include "gpu_shader_interface.hh"
 
 namespace blender::gpu {
@@ -48,13 +50,21 @@ class GLShaderInterface : public ShaderInterface {
   /** Reference to VaoCaches using this interface */
   Vector<GLVaoCache *> refs_;
 
+  /* Reference to the ubo binding that is used for push constants. */
+  const ShaderInput *push_constant_input_ = nullptr;
+
  public:
-  GLShaderInterface(GLuint program);
+  GLShaderInterface(GLShaderPatcherContext &context, GLuint program);
   ~GLShaderInterface();
 
   void ref_add(GLVaoCache *ref);
   void ref_remove(GLVaoCache *ref);
 
+  inline const ShaderInput *push_constant_get()
+  {
+    return push_constant_input_;
+  }
+
   MEM_CXX_CLASS_ALLOC_FUNCS("GLShaderInterface");
 };
 
diff --git a/source/blender/gpu/opengl/gl_shader_patcher.cc b/source/blender/gpu/opengl/gl_shader_patcher.cc
index 5d6a766fc6b..15ab4222ae9 100644
--- a/source/blender/gpu/opengl/gl_shader_patcher.cc
+++ b/source/blender/gpu/opengl/gl_shader_patcher.cc
@@ -68,7 +68,7 @@ class GLSLPatch {
       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01232456789_";
 
  public:
-  virtual GLSLPatchResult patch(GLShaderPatchState &context, StringRef source) = 0;
+  virtual GLSLPatchResult patch(GLShaderPatcherContext &context, StringRef source) = 0;
 
  protected:
   static StringRef skip_whitespace(StringRef ref)
@@ -94,7 +94,7 @@ class PatchPushConstants : public GLSLPatch {
   static constexpr StringRef LAYOUT_STD140 = "layout(std140)";
 
  public:
-  GLSLPatchResult patch(GLShaderPatchState &context, StringRef source) override
+  GLSLPatchResult patch(GLShaderPatcherContext &context, StringRef source) override
   {
     GLSLPatchResult result;
 
@@ -115,14 +115,14 @@ class PatchPushConstants : public GLSLPatch {
     name = skip_whitespace(name);
     name = extract_name(name);
 
-    if (context.push_constants.name.empty()) {
+    if (!context.push_constants.name) {
       context.push_constants.name = name;
     }
     else if (context.push_constants.name != name) {
       CLOG_ERROR(&LOG,
                  "Detected different push_constants binding names ('%s' and '%s'). push_constants "
                  "binding names must be identical across all stages.",
-                 context.push_constants.name.c_str(),
+                 context.push_constants.name->c_str(),
                  std::string(name).c_str());
       result.state = GLShaderPatcherState::MismatchedPushConstantNames;
       return result;
@@ -138,7 +138,7 @@ class PatchPushConstants : public GLSLPatch {
 
 class GLSLPatcher : public GLSLPatch {
  private:
-  static void patch(GLShaderPatchState &context,
+  static void patch(GLShaderPatcherContext &context,
                     GLSLPatch &patch,
                     StringRef source,
                     GLSLPatchResult &r_result)
@@ -153,7 +153,7 @@ class GLSLPatcher : public GLSLPatch {
   }
 
  public:
-  GLSLPatchResult patch(GLShaderPatchState &context, StringRef source) override
+  GLSLPatchResult patch(GLShaderPatcherContext &context, StringRef source) override
   {
     GLSLPatchResult result;
     PatchPushConstants push_constants;
@@ -162,7 +162,7 @@ class GLSLPatcher : public GLSLPatch {
   }
 };
 
-void GLShaderPatcher::patch(MutableSpan<const char *> sources)
+void patch_vulkan_to_opengl(GLShaderPatcherContext &context, MutableSpan<const char *> sources)
 {
   for (int i = 0; i < sources.size(); i++) {
     GLSLPatcher patcher;
@@ -174,8 +174,8 @@ void GLShaderPatcher::patch(MutableSpan<const char *> sources)
 
       case GLShaderPatcherState::OkChanged:
         BLI_assert(patch_result.patched_glsl);
-        patched_sources_.append(*patch_result.patched_glsl);
-        sources[i] = patched_sources_.last().c_str();
+        context.patched_sources.append(*patch_result.patched_glsl);
+        sources[i] = context.patched_sources.last().c_str();
 
         /* Keep any errors from previous stages. */
         if (context.state == GLShaderPatcherState::OkUnchanged) {
@@ -191,14 +191,14 @@ void GLShaderPatcher::patch(MutableSpan<const char *> sources)
   }
 }
 
-bool GLShaderPatcher::has_errors() const
+void GLShaderPatcherContext::free_patched_sources()
 {
-  return is_error_state(context.state);
+  patched_sources.clear();
 }
 
-void GLShaderPatcher::free()
+bool GLShaderPatcherContext::has_errors() const
 {
-  patched_sources_.clear();
+  return is_error_state(state);
 }
 
 }  // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_shader_patcher.hh b/source/blender/gpu/opengl/gl_shader_patcher.hh
index 854de2b9ab2..7578600df53 100644
--- a/source/blender/gpu/opengl/gl_shader_patcher.hh
+++ b/source/blender/gpu/opengl/gl_shader_patcher.hh
@@ -26,6 +26,8 @@
 #include "BLI_string_ref.hh"
 #include "BLI_vector.hh"
 
+#include <optional>
+
 namespace blender::gpu {
 
 enum class GLShaderPatcherState {
@@ -34,26 +36,24 @@ enum class GLShaderPatcherState {
   MismatchedPushConstantNames,
 };
 
-struct GLShaderPatchState {
+/** State to keep over GLSL compilation stages, linkage and shader_interface building. */
+struct GLShaderPatcherContext {
   GLShaderPatcherState state = GLShaderPatcherState::OkUnchanged;
+
+  /**
+   * All patched sources. During compilation stage source code is references as `const
+   * char*` These needs to be owned by a `std::string`.
+   */
+  Vector<std::string> patched_sources;
   struct {
-    std::string name;
+    std::optional<std::string> name;
   } push_constants;
-};
 
-class GLShaderPatcher {
- public:
-  GLShaderPatchState context;
-
- private:
-  Vector<std::string> patched_sources_;
-
- public:
-  void patch(MutableSpan<const char *> sources);
   bool has_errors() const;
-  void free();
 
-  MEM_CXX_CLASS_ALLOC_FUNCS("GLShaderPatcher");
+  void free_patched_sources();
 };
 
+void patch_vulkan_to_opengl(GLShaderPatcherContext &context, MutableSpan<const char *> sources);
+
 }  // namespace blender::gpu



More information about the Bf-blender-cvs mailing list