Fix #162948: Vulkan: Math work around for SPIR-V compiler bug

Fix #162948.

This is up-stream issue in SpirV-Opt,
 see https://github.com/KhronosGroup/SPIRV-Tools/issues/6794,
 which is fixed but is not, as of now, in a build yet.

The affected ops are Divide and Snap, so
fold these cases before emitting shader code:

- Divide: fold `safe_divide(a, a)` to `1`.
- Snap: fold `floor(safe_divide(a, a)) * a` to `a`.

Pull Request: https://projects.blender.org/blender/blender/pulls/163039
This commit is contained in:
Le Gia Bao 2026-09-28 16:39:07 +02:00 • committed by Clément Foucault
parent 2120b1d203
commit 5ce66a846e
2 changed files with 28 additions and 0 deletions

View file

@ -41,6 +41,14 @@ void vector_math_divide(
outVector = safe_divide(a, b);
}
/* `a / a` folded to 1 (see #162948). */
[[node]]
void vector_math_divide_self(
float3 a, float3 /*b*/, float3 /*c*/, float /*scale*/, float3 &outVector, float & /*outValue*/)
{
outVector = float3(notEqual(a, float3(0.0f)));
}
[[node]]
void vector_math_cross(
float3 a, float3 b, float3 /*c*/, float /*scale*/, float3 &outVector, float & /*outValue*/)
@ -110,6 +118,14 @@ void vector_math_snap(
outVector = floor(safe_divide(a, b)) * b;
}
/* `floor(a / a) * a` folded to `a` (see #162948). */
[[node]]
void vector_math_snap_self(
float3 a, float3 /*b*/, float3 /*c*/, float /*scale*/, float3 &outVector, float & /*outValue*/)
{
outVector = a;
}
[[node]]
void vector_math_floor(
float3 a, float3 /*b*/, float3 /*c*/, float /*scale*/, float3 &outVector, float & /*outValue*/)

View file

@ -253,6 +253,18 @@ static int gpu_shader_vector_math(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
/* Can't emit 'a / a' (see #162948). So we have to fold it. */
if (in[0].link != nullptr && in[0].link == in[1].link) {
switch (node->custom1) {
case NODE_VECTOR_MATH_DIVIDE:
return GPU_stack_link(mat, node, "vector_math_divide_self", in, out);
case NODE_VECTOR_MATH_SNAP:
return GPU_stack_link(mat, node, "vector_math_snap_self", in, out);
default:
break;
}
}
const char *name = gpu_shader_get_name(node->custom1);
if (name != nullptr) {
return GPU_stack_link(mat, node, name, in, out);