From 33ba298b5db24b002d936e135c3c84aa2300e6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 25 Jan 2022 15:08:11 +0100 Subject: GPUShader: Add optionnal single shader stage interface for in and out This makes optionnal the use of a different interface for the geometry shader stage output. When the vertex and geometry interface instance name matches, a `_in` and `_out` suffix is added to the end of the instance name. This makes it easier to have optional geometry shader stages. # Conflicts: # source/blender/gpu/intern/gpu_shader_create_info.hh --- .../blender/gpu/intern/gpu_shader_create_info.hh | 7 ++++- source/blender/gpu/opengl/gl_shader.cc | 32 ++++++++++++++++++++-- source/blender/gpu/opengl/gl_shader_interface.cc | 8 ++++++ 3 files changed, 43 insertions(+), 4 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh index 02c303fb8fa..6fe6d7676fb 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.hh +++ b/source/blender/gpu/intern/gpu_shader_create_info.hh @@ -380,7 +380,12 @@ struct ShaderCreateInfo { return *(Self *)this; } - /* Only needed if geometry shader is enabled. */ + /** + * Only needed if geometry shader is enabled. + * IMPORTANT: Input and output instance name will have respectively "_in" and "_out" suffix + * appended in the geometry shader IF AND ONLY IF the vertex_out interface instance name matches + * the geometry_out interface instance name. + */ Self &geometry_out(StageInterfaceInfo &interface) { geometry_out_interfaces_.append(&interface); diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index bf18ba09c03..6cfe8e90d3e 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -492,16 +492,34 @@ std::string GLShader::geometry_layout_declare(const ShaderCreateInfo &info) cons return ss.str(); } +static StageInterfaceInfo *find_interface_by_name(const Vector &ifaces, + const StringRefNull &name) +{ + for (auto iface : ifaces) { + if (iface->name == name) { + return iface; + } + } + return nullptr; +} + std::string GLShader::geometry_interface_declare(const ShaderCreateInfo &info) const { + std::stringstream ss; ss << "\n/* Interfaces. */\n"; for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) { - print_interface(ss, "in", *iface, "[]"); + bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_, + iface->instance_name) != nullptr; + const char *suffix = (has_matching_output_iface) ? "_in[]" : "[]"; + print_interface(ss, "in", *iface, suffix); } ss << "\n"; for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) { - print_interface(ss, "out", *iface); + bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_, + iface->instance_name) != nullptr; + const char *suffix = (has_matching_input_iface) ? "_out" : ""; + print_interface(ss, "out", *iface, suffix); } ss << "\n"; return ss.str(); @@ -532,7 +550,7 @@ std::string GLShader::compute_layout_declare(const ShaderCreateInfo &info) const static char *glsl_patch_default_get() { /** Used for shader patching. Init once. */ - static char patch[512] = "\0"; + static char patch[700] = "\0"; if (patch[0] != '\0') { return patch; } @@ -559,6 +577,11 @@ static char *glsl_patch_default_get() if (GLContext::shader_draw_parameters_support) { STR_CONCAT(patch, slen, "#extension GL_ARB_shader_draw_parameters : enable\n"); STR_CONCAT(patch, slen, "#define GPU_ARB_shader_draw_parameters\n"); + STR_CONCAT(patch, slen, "#define gpu_BaseInstance gl_BaseInstanceARB\n"); + } + else { + /* Fallback: Emulate base instance using a uniform. */ + STR_CONCAT(patch, slen, "uniform int gpu_BaseInstance\n"); } if (GLContext::geometry_shader_invocations) { STR_CONCAT(patch, slen, "#extension GL_ARB_gpu_shader5 : enable\n"); @@ -569,6 +592,9 @@ static char *glsl_patch_default_get() STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n"); } + /* Vulkan GLSL compat. */ + STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceID + gpu_BaseInstance)\n"); + /* Derivative sign can change depending on implementation. */ STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]); STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]); diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index 772d0888823..4414ba0464b 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -440,6 +440,14 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI } } + /* Compatibility uniforms. */ + if (!GLContext::shader_draw_parameters_support) { + input->location = glGetUniformLocation(program, "gpu_BaseInstance"); + copy_input_name(input, "gpu_BaseInstance", name_buffer_, name_buffer_offset); + input->binding = -1; + input++; + } + /* Builtin Uniforms */ for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) { GPUUniformBuiltin u = static_cast(u_int); -- cgit v1.2.3