From 8ff67b51d17288fcd13e1e86ae7027d2bd43ef08 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 7 Jul 2021 16:49:04 +0200 Subject: Added uniform builtin struct to shader. --- source/blender/gpu/intern/gpu_shader.cc | 6 ++- source/blender/gpu/intern/gpu_shader_private.hh | 12 +++++ .../gpu/intern/gpu_uniform_buffer_private.hh | 3 ++ source/blender/gpu/opengl/gl_shader.cc | 18 +++++++- source/blender/gpu/opengl/gl_shader_interface.cc | 37 ++++++++++++++- source/blender/gpu/opengl/gl_shader_interface.hh | 3 +- .../gpu/tests/gpu_uniform_buffer_struct_test.cc | 53 +++++++++++++++++++++- 7 files changed, 125 insertions(+), 7 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index b71f46fb3fc..048f4582f43 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -59,6 +59,7 @@ Shader::Shader(const char *sh_name) Shader::~Shader() { delete interface; + delete m_shader_struct; } static void standard_defines(Vector &sources) @@ -110,6 +111,9 @@ GPUShader *GPU_shader_create_ex(const char *vertcode, (computecode != nullptr))); Shader *shader = GPUBackend::get()->shader_alloc(shname); + if (uniform_struct_type != GPU_UNIFORM_STRUCT_NONE) { + shader->set_shader_struct(uniform_struct_type); + } if (vertcode) { Vector sources; @@ -211,7 +215,7 @@ void GPU_shader_free(GPUShader *shader) /* -------------------------------------------------------------------- */ /** \name Creation utils * \{ */ - + GPUShader *GPU_shader_create(const char *vertcode, const char *fragcode, const char *geomcode, diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index 65720e457d8..06e0b99b276 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -24,9 +24,13 @@ #include "BLI_string_ref.hh" #include "GPU_shader.h" +#include "GPU_uniform_buffer_types.h" #include "gpu_shader_interface.hh" +#include "gpu_uniform_buffer_private.hh" #include "gpu_vertex_buffer_private.hh" +#include + namespace blender { namespace gpu { @@ -45,6 +49,8 @@ class Shader { /** For debugging purpose. */ char name[64]; + std::optional shader_struct; + public: Shader(const char *name); virtual ~Shader(); @@ -76,6 +82,12 @@ class Shader { return name; }; + UniformBuiltinStruct *m_shader_struct; + void set_shader_struct(GPUUniformBuiltinStructType struct_type) + { + m_shader_struct = new UniformBuiltinStruct(struct_type); + } + protected: void print_log(Span sources, char *log, diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh index 8de5bfdcf93..adeede8f03a 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh @@ -125,6 +125,9 @@ class UniformBuiltinStruct { }; UniformBuiltinStruct(const GPUUniformBuiltinStructType type); + UniformBuiltinStruct(const UniformBuiltinStruct &other) = default; + UniformBuiltinStruct(UniformBuiltinStruct &&other) = default; + ~UniformBuiltinStruct(); void *data() const diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 66a1bd5ceb7..63ba0ab0a34 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -225,8 +225,10 @@ bool GLShader::finalize() this->print_log(sources, log, "Linking", true, &parser); return false; } - - interface = new GLShaderInterface(shader_program_); + const UniformBuiltinStructType *type_info = m_shader_struct != nullptr ? + &m_shader_struct->type_info() : + nullptr; + interface = new GLShaderInterface(type_info, shader_program_); return true; } @@ -308,6 +310,12 @@ void GLShader::transform_feedback_disable() void GLShader::uniform_float(int location, int comp_len, int array_size, const float *data) { + if (m_shader_struct) { + if (m_shader_struct->uniform_float(location, comp_len, array_size, data)) { + return; + } + } + switch (comp_len) { case 1: glUniform1fv(location, array_size, data); @@ -335,6 +343,12 @@ void GLShader::uniform_float(int location, int comp_len, int array_size, const f void GLShader::uniform_int(int location, int comp_len, int array_size, const int *data) { + if (m_shader_struct) { + if (m_shader_struct->uniform_int(location, comp_len, array_size, data)) { + return; + } + } + switch (comp_len) { case 1: glUniform1iv(location, array_size, data); diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index 9cf072b2e8a..d9291cd642a 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(const UniformBuiltinStructType *type_info, GLuint program) { /* Necessary to make #glUniform works. */ glUseProgram(program); @@ -187,6 +187,20 @@ GLShaderInterface::GLShaderInterface(GLuint program) max_ssbo_name_len = 256; } + /* Perform uniform builtin structs after work around to make sure the work around is passed. */ + if (type_info) { + for (int i = 0; i < GPU_NUM_UNIFORMS; i++) { + const GPUUniformBuiltin builtin_uniform = static_cast(i); + const UniformBuiltinStructType::AttributeBinding &binding = type_info->attribute_binding( + builtin_uniform); + if (binding.has_binding()) { + uniform_len++; + max_uniform_name_len = max_ii(max_uniform_name_len, + strlen(builtin_uniform_name(builtin_uniform))); + } + } + } + /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before * allocating the uniform array. */ GLint max_ubo_uni_len = 0; @@ -281,6 +295,24 @@ GLShaderInterface::GLShaderInterface(GLuint program) enabled_ima_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu; } } + if (type_info) { + for (int i = 0; i < GPU_NUM_UNIFORMS; i++) { + const GPUUniformBuiltin builtin_uniform = static_cast(i); + const UniformBuiltinStructType::AttributeBinding &binding = type_info->attribute_binding( + builtin_uniform); + if (binding.has_binding()) { + ShaderInput *input = &inputs_[attr_len_ + ubo_len_ + uniform_len_++]; + input->location = binding.binding; + input->binding = -1; + + char *name = name_buffer_ + name_buffer_offset; + const char *uniform_name = builtin_uniform_name(builtin_uniform); + size_t name_len = strlen(uniform_name); + strcpy(name, uniform_name); + name_buffer_offset += this->set_input_name(input, name, name_len); + } + } + } /* SSBOs */ for (int i = 0; i < ssbo_len; i++) { @@ -301,7 +333,8 @@ GLShaderInterface::GLShaderInterface(GLuint program) /* Builtin Uniforms */ for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) { GPUUniformBuiltin u = static_cast(u_int); - builtins_[u] = glGetUniformLocation(program, builtin_uniform_name(u)); + const ShaderInput *block = this->uniform_get(builtin_uniform_name(u)); + builtins_[u] = (block != nullptr) ? block->binding : -1; } /* Builtin Uniforms Blocks */ diff --git a/source/blender/gpu/opengl/gl_shader_interface.hh b/source/blender/gpu/opengl/gl_shader_interface.hh index 89a5b631047..5125c885cc5 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.hh +++ b/source/blender/gpu/opengl/gl_shader_interface.hh @@ -35,6 +35,7 @@ #include "glew-mx.h" #include "gpu_shader_interface.hh" +#include "gpu_uniform_buffer_private.hh" namespace blender::gpu { @@ -49,7 +50,7 @@ class GLShaderInterface : public ShaderInterface { Vector refs_; public: - GLShaderInterface(GLuint program); + GLShaderInterface(const UniformBuiltinStructType *type_info, GLuint program); ~GLShaderInterface(); void ref_add(GLVaoCache *ref); diff --git a/source/blender/gpu/tests/gpu_uniform_buffer_struct_test.cc b/source/blender/gpu/tests/gpu_uniform_buffer_struct_test.cc index 8468bb1c66a..c03e1438509 100644 --- a/source/blender/gpu/tests/gpu_uniform_buffer_struct_test.cc +++ b/source/blender/gpu/tests/gpu_uniform_buffer_struct_test.cc @@ -1,5 +1,8 @@ -#include "testing/testing.h" +#include "gpu_testing.hh" +#include "GPU_capabilities.h" +#include "GPU_compute.h" +#include "GPU_shader.h" #include "GPU_uniform_buffer_types.h" #include "gpu_uniform_buffer_private.hh" @@ -94,4 +97,52 @@ TEST(GPUUniformStruct, struct1) } } +static void test_custom_shader_with_uniform_builtin_struct() +{ + if (!GPU_compute_shader_support()) { + /* We can't test as a the platform does not support compute shaders. */ + std::cout << "Skipping compute shader test: platform not supported"; + return; + } + + /* Build compute shader. */ + const char *compute_glsl = R"( + +layout(local_size_x = 1, local_size_y = 1) in; +layout(rgba32f, binding = 0) uniform image2D img_output; + +layout(std140) uniform shaderBlock { + mat4 ModelMatrix; + mat4 ModelViewProjectionMatrix; + vec4 color; + vec4 WorldClipPlanes[6]; + bool SrgbTransform; +}; + +void main() { +} + +)"; + + GPUShader *shader = GPU_shader_create_ex(nullptr, + nullptr, + nullptr, + compute_glsl, + nullptr, + nullptr, + GPU_SHADER_TFB_NONE, + nullptr, + 0, + GPU_UNIFORM_STRUCT_1, + __func__); + EXPECT_NE(shader, nullptr); + + float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; + GPU_shader_uniform_4fv(shader, "color", color); + + GPU_shader_free(shader); +} + +GPU_TEST(custom_shader_with_uniform_builtin_struct) + } // namespace blender::gpu::tests \ No newline at end of file -- cgit v1.2.3