From 7df0e8b9492cf74fa73ca908637af9b8327d3afc Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 13 Mar 2023 14:17:56 +0000 Subject: [PATCH] Fix #103605: Metal barycentric coordinate compilation failure. Fix support for Wireframe and parametric nodes by resolving compilation failures surrounding barycentric coordinates. A final missing part of the Metal implementation for barycentric coordinates was missing. Feedback also addressed to move barycentric calculation out of code-gen and into surface_lib. This also resolves #103606. Authored by Apple: Michael Parkin-White Ref #96261 --- .../engines/eevee/shaders/surface_lib.glsl | 12 +++++++ .../blender/gpu/metal/mtl_shader_generator.mm | 31 +++---------------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl index 5ee020358b5..6bd9d222420 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl @@ -101,6 +101,7 @@ SSR_INTERFACE # if defined(USE_BARYCENTRICS) && !defined(HAIR_SHADER) vec3 barycentric_distances_get() { +# if defined(GPU_OPENGL) /* NOTE: No need to undo perspective divide since it is not applied yet. */ vec3 pos0 = (ProjectionMatrixInverse * gpu_position_at_vertex(0)).xyz; vec3 pos1 = (ProjectionMatrixInverse * gpu_position_at_vertex(1)).xyz; @@ -119,6 +120,17 @@ vec3 barycentric_distances_get() d = dot(d10, edge21); dists.z = sqrt(dot(edge21, edge21) - d * d); return dists.xyz; +# elif defined(GPU_METAL) + /* Calculate Barycentric distances from available parameters in Metal. */ + float3 wp_delta = (length(dfdx(worldPosition.xyz)) + length(dfdy(worldPosition.xyz))); + float3 bc_delta = (length(dfdx(gpu_BaryCoord)) + length(dfdy(gpu_BaryCoord))); + float3 rate_of_change = wp_delta / bc_delta; + vec3 dists; + dists.x = length(rate_of_change * (1.0 - gpu_BaryCoord.x)); + dists.y = length(rate_of_change * (1.0 - gpu_BaryCoord.y)); + dists.z = length(rate_of_change * (1.0 - gpu_BaryCoord.z)); + return dists.xyz; +# endif } # endif diff --git a/source/blender/gpu/metal/mtl_shader_generator.mm b/source/blender/gpu/metal/mtl_shader_generator.mm index 5810ed79f33..7be93ce04ce 100644 --- a/source/blender/gpu/metal/mtl_shader_generator.mm +++ b/source/blender/gpu/metal/mtl_shader_generator.mm @@ -1268,6 +1268,11 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info) ss_fragment << "uint gl_PrimitiveID;" << std::endl; } + /* Global barycentrics. */ + if (msl_iface.uses_barycentrics) { + ss_fragment << "vec3 gpu_BaryCoord;\n"; + } + /* Add Texture members. */ for (const MSLTextureSampler &tex : msl_iface.texture_samplers) { if (bool(tex.stage & ShaderStage::FRAGMENT)) { @@ -2036,33 +2041,7 @@ std::string MSLGeneratorInterface::generate_msl_fragment_entry_stub() /* Barycentrics. */ if (this->uses_barycentrics) { - - /* Main barycentrics. */ out << shader_stage_inst_name << ".gpu_BaryCoord = mtl_barycentric_coord.xyz;" << std::endl; - - /* barycentricDist represents the world-space distance from the current world-space position - * to the opposite edge of the vertex. */ - out << "float3 worldPos = " << shader_stage_inst_name << ".worldPosition.xyz;" << std::endl; - out << "float3 wpChange = (length(dfdx(worldPos))+length(dfdy(worldPos)));" << std::endl; - out << "float3 bcChange = " - "(length(dfdx(mtl_barycentric_coord))+length(dfdy(mtl_barycentric_coord)));" - << std::endl; - out << "float3 rateOfChange = wpChange/bcChange;" << std::endl; - - /* Distance to edge using inverse barycentric value, as rather than the length of 0.7 - * contribution, we'd want the distance to the opposite side. */ - out << shader_stage_inst_name - << ".gpu_BarycentricDist.x = length(rateOfChange * " - "(1.0-mtl_barycentric_coord.x));" - << std::endl; - out << shader_stage_inst_name - << ".gpu_BarycentricDist.y = length(rateOfChange * " - "(1.0-mtl_barycentric_coord.y));" - << std::endl; - out << shader_stage_inst_name - << ".gpu_BarycentricDist.z = length(rateOfChange * " - "(1.0-mtl_barycentric_coord.z));" - << std::endl; } /* Populate Uniforms and uniform blocks. */ -- 2.30.2