diff options
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 3 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.hh | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader.cc | 87 |
3 files changed, 89 insertions, 2 deletions
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 2ced2639c02..2ee7c0503f4 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -249,6 +249,7 @@ static void detect_workarounds() GLContext::fixed_restart_index_support = false; GLContext::geometry_shader_invocations = false; GLContext::layered_rendering_support = false; + GLContext::native_barycentric_support = false; GLContext::multi_bind_support = false; GLContext::multi_draw_indirect_support = false; GLContext::shader_draw_parameters_support = false; @@ -447,6 +448,7 @@ bool GLContext::explicit_location_support = false; bool GLContext::geometry_shader_invocations = false; bool GLContext::fixed_restart_index_support = false; bool GLContext::layered_rendering_support = false; +bool GLContext::native_barycentric_support = false; bool GLContext::multi_bind_support = false; bool GLContext::multi_draw_indirect_support = false; bool GLContext::shader_draw_parameters_support = false; @@ -508,6 +510,7 @@ void GLBackend::capabilities_init() GLContext::geometry_shader_invocations = GLEW_ARB_gpu_shader5; GLContext::fixed_restart_index_support = GLEW_ARB_ES3_compatibility; GLContext::layered_rendering_support = GLEW_AMD_vertex_shader_layer; + GLContext::native_barycentric_support = GLEW_AMD_shader_explicit_vertex_parameter; GLContext::multi_bind_support = GLEW_ARB_multi_bind; GLContext::multi_draw_indirect_support = GLEW_ARB_multi_draw_indirect; GLContext::shader_draw_parameters_support = GLEW_ARB_shader_draw_parameters; diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index 20a7417b358..b7a74863ac4 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -73,6 +73,7 @@ class GLContext : public Context { static bool geometry_shader_invocations; static bool fixed_restart_index_support; static bool layered_rendering_support; + static bool native_barycentric_support; static bool multi_bind_support; static bool multi_draw_indirect_support; static bool shader_draw_parameters_support; diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 4649d32deee..815c488cf8b 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -424,9 +424,28 @@ std::string GLShader::resources_declare(const ShaderCreateInfo &info) const return ss.str(); } +static std::string main_function_wrapper(std::string &pre_main, std::string &post_main) +{ + std::stringstream ss; + /* Prototype for the original main. */ + ss << "\n"; + ss << "void main_function_();\n"; + /* Wrapper to the main function in order to inject code processing on globals. */ + ss << "void main() {\n"; + ss << pre_main; + ss << " main_function_();\n"; + ss << post_main; + ss << "}\n"; + /* Rename the original main. */ + ss << "#define main main_function_\n"; + ss << "\n"; + return ss.str(); +} + std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) const { std::stringstream ss; + std::string post_main = ""; ss << "\n/* Inputs. */\n"; for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) { @@ -442,13 +461,32 @@ std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) con if (!GLContext::layered_rendering_support && bool(info.builtins_ & BuiltinBits::LAYER)) { ss << "out int gpu_Layer;\n"; } + if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) { + if (!GLContext::native_barycentric_support) { + /* Disabled or unsupported. */ + } + else if (GLEW_AMD_shader_explicit_vertex_parameter) { + /* Need this for stable barycentric. */ + ss << "flat out vec4 gpu_pos_flat;\n"; + ss << "out vec4 gpu_pos;\n"; + + post_main += " gpu_pos = gpu_pos_flat = gl_Position;\n"; + } + } ss << "\n"; + + if (post_main.empty() == false) { + std::string pre_main = ""; + ss << main_function_wrapper(pre_main, post_main); + } return ss.str(); } std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) const { std::stringstream ss; + std::string pre_main = ""; + ss << "\n/* Interfaces. */\n"; const Vector<StageInterfaceInfo *> &in_interfaces = (info.geometry_source_.is_empty()) ? info.vertex_out_interfaces_ : @@ -456,6 +494,32 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c for (const StageInterfaceInfo *iface : in_interfaces) { print_interface(ss, "in", *iface); } + if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) { + if (!GLContext::native_barycentric_support) { + ss << "smooth in vec3 gpu_BaryCoord;\n"; + ss << "noperspective in vec3 gpu_BaryCoordNoPersp;\n"; + } + else if (GLEW_AMD_shader_explicit_vertex_parameter) { + /* NOTE(fclem): This won't work with geometry shader. Hopefully, we don't need geometry + * shader workaround if this extension/feature is detected. */ + ss << "\n/* Stable Barycentric Coordinates. */\n"; + ss << "flat in vec4 gpu_pos_flat;\n"; + ss << "__explicitInterpAMD in vec4 gpu_pos;\n"; + /* Globals. */ + ss << "vec3 gpu_BaryCoord;\n"; + ss << "vec3 gpu_BaryCoordNoPersp;\n"; + ss << "\n"; + ss << "vec2 stable_bary_(vec2 in_bary) {\n"; + ss << " vec3 bary = vec3(in_bary, 1.0 - in_bary.x - in_bary.y);\n"; + ss << " if (interpolateAtVertexAMD(gpu_pos, 0) == gpu_pos_flat) { return bary.zxy; }\n"; + ss << " if (interpolateAtVertexAMD(gpu_pos, 2) == gpu_pos_flat) { return bary.yzx; }\n"; + ss << " return bary.xyz;\n"; + ss << "}\n"; + + pre_main += " gpu_BaryCoord = stable_bary_(gl_BaryCoordSmoothAMD);\n"; + pre_main += " gpu_BaryCoordNoPersp = stable_bary_(gl_BaryCoordNoPerspAMD);\n"; + } + } ss << "\n/* Outputs. */\n"; for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) { ss << "layout(location = " << output.index; @@ -473,6 +537,11 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c ss << "out " << to_string(output.type) << " " << output.name << ";\n"; } ss << "\n"; + + if (pre_main.empty() == false) { + std::string post_main = ""; + ss << main_function_wrapper(pre_main, post_main); + } return ss.str(); } @@ -562,7 +631,7 @@ std::string GLShader::workaround_geometry_shader_source_create( const bool do_layer_workaround = !GLContext::layered_rendering_support && bool(info.builtins_ & BuiltinBits::LAYER); - const bool do_barycentric_workaround = !GLContext::native_barycentrics_support && + const bool do_barycentric_workaround = !GLContext::native_barycentric_support && bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD); shader::ShaderCreateInfo info_modified = info; @@ -578,6 +647,10 @@ std::string GLShader::workaround_geometry_shader_source_create( if (do_layer_workaround) { ss << "in int gpu_Layer[];\n"; } + if (do_barycentric_workaround) { + ss << "smooth out vec3 gpu_BaryCoord;\n"; + ss << "noperspective out vec3 gpu_BaryCoordNoPersp;\n"; + } ss << "\n"; ss << "void main()\n"; @@ -592,6 +665,10 @@ std::string GLShader::workaround_geometry_shader_source_create( ss << " = " << iface->instance_name << "_in[" << i << "]." << inout.name << ";\n"; } } + if (do_barycentric_workaround) { + ss << " gpu_BaryCoordNoPersp = gpu_BaryCoord ="; + ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n"; + } ss << " gl_Position = gl_in[" << i << "].gl_Position;\n"; ss << " EmitVertex();\n"; } @@ -602,7 +679,10 @@ std::string GLShader::workaround_geometry_shader_source_create( bool GLShader::do_geometry_shader_injection(const shader::ShaderCreateInfo *info) { BuiltinBits builtins = info->builtins_; - if (!GLContext::native_barycentrics_support && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) { + if (!GLContext::native_barycentric_support && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) { + return true; + } + if (!GLContext::layered_rendering_support && bool(builtins & BuiltinBits::LAYER)) { return true; } return false; @@ -665,6 +745,9 @@ static char *glsl_patch_default_get() STR_CONCAT(patch, slen, "#extension GL_AMD_vertex_shader_layer: enable\n"); STR_CONCAT(patch, slen, "#define gpu_Layer gl_Layer\n"); } + if (GLContext::native_barycentric_support) { + STR_CONCAT(patch, slen, "#extension GL_AMD_shader_explicit_vertex_parameter: enable\n"); + } /* Fallbacks. */ if (!GLContext::shader_draw_parameters_support) { |