diff options
author | Jeroen Bakker <jbakker> | 2022-01-17 16:32:03 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2022-01-17 16:32:28 +0300 |
commit | 8fb2ff458ba579dba08bfdf57d043ad158b5db07 (patch) | |
tree | e6324c08c69de3e8ed34c1f85d0b2982fa1d38ed /source/blender/gpu/opengl/gl_shader_interface.cc | |
parent | 08822801acf648d23791fa308ec8c1c26f86963e (diff) |
GPUShaderCreateInfo for interface abstraction
This is a first part of the Shader Create Info system could be.
A shader create info provides a way to define shader structure, resources
and interfaces. This makes for a quick way to provide backend agnostic
binding informations while also making shader variations easy to declare.
- Clear source input (only one file). Cleans up the GPU api since we can create a
shader from one descriptor
- Resources and interfaces are generated by the backend (much simpler than parsing).
- Bindings are explicit from position in the array.
- GPUShaderInterface becomes a trivial translation of enums and string copy.
- No external dependency to third party lib.
- Cleaner code, less fragmentation of resources in several libs.
- Easy to modify / extend at runtime.
- no parser involve, very easy to code.
- Does not hold any data, can be static and kept on disc.
- Could hold precompiled bytecode for static shaders.
This also includes a new global dependency system.
GLSL shaders can include other sources by using #pragma BLENDER_REQUIRE(...).
This patch already migrated several builtin shaders. Other shaders should be migrated
one at a time, and could be done inside master.
There is a new compile directive `WITH_GPU_SHADER_BUILDER` this is an optional
directive for linting shaders to increase turn around time.
What is remaining:
- pyGPU API {T94975}
- Migration of other shaders. This could be a community effort.
Reviewed By: jbakker
Maniphest Tasks: T94975
Differential Revision: https://developer.blender.org/D13360
Diffstat (limited to 'source/blender/gpu/opengl/gl_shader_interface.cc')
-rw-r--r-- | source/blender/gpu/opengl/gl_shader_interface.cc | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index 9900a4e0766..9dd7b1d57c3 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -25,7 +25,9 @@ #include "BLI_bitmap.h" +#include "gl_backend.hh" #include "gl_batch.hh" +#include "gl_context.hh" #include "gl_shader_interface.hh" @@ -323,6 +325,137 @@ GLShaderInterface::GLShaderInterface(GLuint program) this->sort_inputs(); } +GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateInfo &info) +{ + using namespace blender::gpu::shader; + + attr_len_ = info.vertex_inputs_.size(); + uniform_len_ = info.push_constants_.size(); + ubo_len_ = 0; + ssbo_len_ = 0; + + Vector<ShaderCreateInfo::Resource> all_resources; + all_resources.extend(info.pass_resources_); + all_resources.extend(info.batch_resources_); + + for (ShaderCreateInfo::Resource &res : all_resources) { + switch (res.bind_type) { + case ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER: + ubo_len_++; + break; + case ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER: + ssbo_len_++; + break; + case ShaderCreateInfo::Resource::BindType::SAMPLER: + uniform_len_++; + break; + case ShaderCreateInfo::Resource::BindType::IMAGE: + uniform_len_++; + break; + } + } + + BLI_assert_msg(ubo_len_ <= 16, "enabled_ubo_mask_ is uint16_t"); + + int input_tot_len = attr_len_ + ubo_len_ + uniform_len_ + ssbo_len_; + inputs_ = (ShaderInput *)MEM_callocN(sizeof(ShaderInput) * input_tot_len, __func__); + ShaderInput *input = inputs_; + + name_buffer_ = (char *)MEM_mallocN(info.interface_names_size_, "name_buffer"); + uint32_t name_buffer_offset = 0; + + /* Attributes */ + for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) { + copy_input_name(input, attr.name, name_buffer_, name_buffer_offset); + if (true || !GLContext::explicit_location_support) { + input->location = input->binding = glGetAttribLocation(program, attr.name.c_str()); + } + else { + input->location = input->binding = attr.index; + } + enabled_attr_mask_ |= (1 << input->location); + input++; + } + + /* Uniform Blocks */ + for (const ShaderCreateInfo::Resource &res : all_resources) { + if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) { + copy_input_name(input, res.uniformbuf.name, name_buffer_, name_buffer_offset); + if (true || !GLContext::explicit_location_support) { + input->location = glGetUniformBlockIndex(program, res.uniformbuf.name.c_str()); + glUniformBlockBinding(program, input->location, res.slot); + } + input->binding = res.slot; + enabled_ubo_mask_ |= (1 << input->binding); + input++; + } + } + + /* Uniforms & samplers & images */ + for (const ShaderCreateInfo::Resource &res : all_resources) { + if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) { + copy_input_name(input, res.sampler.name, name_buffer_, name_buffer_offset); + /* Until we make use of explicit uniform location or eliminate all + * sampler manually changing. */ + if (true || !GLContext::explicit_location_support) { + input->location = glGetUniformLocation(program, res.sampler.name.c_str()); + glUniform1i(input->location, res.slot); + } + input->binding = res.slot; + enabled_tex_mask_ |= (1 << input->binding); + input++; + } + else if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) { + copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset); + /* Until we make use of explicit uniform location. */ + if (true || !GLContext::explicit_location_support) { + input->location = glGetUniformLocation(program, res.image.name.c_str()); + glUniform1i(input->location, res.slot); + } + input->binding = res.slot; + enabled_ima_mask_ |= (1 << input->binding); + input++; + } + } + for (const ShaderCreateInfo::PushConst &uni : info.push_constants_) { + copy_input_name(input, uni.name, name_buffer_, name_buffer_offset); + /* Until we make use of explicit uniform location. */ + if (true || !GLContext::explicit_location_support) { + input->location = glGetUniformLocation(program, uni.name.c_str()); + } + input->binding = -1; + input++; + } + + /* SSBOs */ + for (const ShaderCreateInfo::Resource &res : all_resources) { + if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) { + copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset); + input->location = input->binding = res.slot; + enabled_ubo_mask_ |= (1 << input->binding); + input++; + } + } + + /* Builtin Uniforms */ + for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) { + GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int); + const ShaderInput *uni = this->uniform_get(builtin_uniform_name(u)); + builtins_[u] = (uni != nullptr) ? uni->location : -1; + } + + /* Builtin Uniforms Blocks */ + for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORM_BLOCKS; u_int++) { + GPUUniformBlockBuiltin u = static_cast<GPUUniformBlockBuiltin>(u_int); + const ShaderInput *block = this->ubo_get(builtin_uniform_block_name(u)); + builtin_blocks_[u] = (block != nullptr) ? block->binding : -1; + } + + this->sort_inputs(); + + // this->debug_print(); +} + GLShaderInterface::~GLShaderInterface() { for (auto *ref : refs_) { |