vkd3d-shader/hlsl: Add determinant() function.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov 2023-09-06 16:18:18 +02:00 committed by Alexandre Julliard
parent 8723b5d266
commit b13d60d805
Notes: Alexandre Julliard 2024-03-08 23:44:48 +01:00
Approved-by: Zebediah Figura (@zfigura)
Approved-by: Francisco Casas (@fcasas)
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/329
3 changed files with 206 additions and 0 deletions

View File

@ -86,6 +86,7 @@ vkd3d_shader_tests = \
tests/hlsl/cross.shader_test \
tests/hlsl/d3dcolor-to-ubyte4.shader_test \
tests/hlsl/ddxddy.shader_test \
tests/hlsl/determinant.shader_test \
tests/hlsl/discard.shader_test \
tests/hlsl/distance.shader_test \
tests/hlsl/dot.shader_test \

View File

@ -3155,6 +3155,94 @@ static bool intrinsic_ddy_fine(struct hlsl_ctx *ctx,
return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSY_FINE, arg, loc);
}
static bool intrinsic_determinant(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
static const char determinant2x2[] =
"%s determinant(%s2x2 m)\n"
"{\n"
" return m._11 * m._22 - m._12 * m._21;\n"
"}";
static const char determinant3x3[] =
"%s determinant(%s3x3 m)\n"
"{\n"
" %s2x2 m1 = { m._22, m._23, m._32, m._33 };\n"
" %s2x2 m2 = { m._21, m._23, m._31, m._33 };\n"
" %s2x2 m3 = { m._21, m._22, m._31, m._32 };\n"
" %s3 v1 = { m._11, -m._12, m._13 };\n"
" %s3 v2 = { determinant(m1), determinant(m2), determinant(m3) };\n"
" return dot(v1, v2);\n"
"}";
static const char determinant4x4[] =
"%s determinant(%s4x4 m)\n"
"{\n"
" %s3x3 m1 = { m._22, m._23, m._24, m._32, m._33, m._34, m._42, m._43, m._44 };\n"
" %s3x3 m2 = { m._21, m._23, m._24, m._31, m._33, m._34, m._41, m._43, m._44 };\n"
" %s3x3 m3 = { m._21, m._22, m._24, m._31, m._32, m._34, m._41, m._42, m._44 };\n"
" %s3x3 m4 = { m._21, m._22, m._23, m._31, m._32, m._33, m._41, m._42, m._43 };\n"
" %s4 v1 = { m._11, -m._12, m._13, -m._14 };\n"
" %s4 v2 = { determinant(m1), determinant(m2), determinant(m3), determinant(m4) };\n"
" return dot(v1, v2);\n"
"}";
static const char *templates[] =
{
[2] = determinant2x2,
[3] = determinant3x3,
[4] = determinant4x4,
};
struct hlsl_ir_node *arg = params->args[0];
const struct hlsl_type *type = arg->data_type;
struct hlsl_ir_function_decl *func;
const char *typename, *template;
unsigned int dim;
char *body;
if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_MATRIX)
{
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Invalid argument type.");
return false;
}
dim = min(type->dimx, type->dimy);
if (dim == 1)
{
if (!(arg = intrinsic_float_convert_arg(ctx, params, arg, loc)))
return false;
return hlsl_add_load_component(ctx, params->instrs, arg, 0, loc);
}
typename = type->base_type == HLSL_TYPE_HALF ? "half" : "float";
template = templates[dim];
switch (dim)
{
case 2:
body = hlsl_sprintf_alloc(ctx, template, typename, typename);
break;
case 3:
body = hlsl_sprintf_alloc(ctx, template, typename, typename, typename,
typename, typename, typename, typename);
break;
case 4:
body = hlsl_sprintf_alloc(ctx, template, typename, typename, typename,
typename, typename, typename, typename, typename);
break;
default:
vkd3d_unreachable();
}
if (!body)
return false;
func = hlsl_compile_internal_function(ctx, "determinant", body);
vkd3d_free(body);
if (!func)
return false;
return add_user_call(ctx, func, params, loc);
}
static bool intrinsic_distance(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
@ -4138,6 +4226,7 @@ intrinsic_functions[] =
{"ddy_coarse", 1, true, intrinsic_ddy_coarse},
{"ddy_fine", 1, true, intrinsic_ddy_fine},
{"degrees", 1, true, intrinsic_degrees},
{"determinant", 1, true, intrinsic_determinant},
{"distance", 2, true, intrinsic_distance},
{"dot", 2, true, intrinsic_dot},
{"exp", 1, true, intrinsic_exp},

View File

@ -0,0 +1,116 @@
[pixel shader]
float s;
float4 main() : sv_target
{
return determinant(s);
}
[test]
uniform 0 float4 9.0 2.0 3.0 4.0
draw quad
probe all rgba (9.0, 9.0, 9.0, 9.0)
[pixel shader]
float1x1 m;
float4 main() : sv_target
{
return determinant(m);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe all rgba (1.0, 1.0, 1.0, 1.0)
[pixel shader]
float2x2 m;
float4 main() : sv_target
{
return determinant(m);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
uniform 4 float4 5.0 6.0 7.0 8.0
draw quad
probe all rgba (-4.0, -4.0, -4.0, -4.0)
[pixel shader]
float2x1 m;
float4 main() : sv_target
{
return determinant(m);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
uniform 4 float4 5.0 6.0 7.0 8.0
draw quad
probe all rgba (1.0, 1.0, 1.0, 1.0)
[pixel shader]
float3x3 m;
float4 main() : sv_target
{
return determinant(m);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
uniform 4 float4 5.0 -6.0 7.0 8.0
uniform 8 float4 9.0 10.0 11.0 12.0
draw quad
probe all rgba (192.0, 192.0, 192.0, 192.0)
[pixel shader]
float4x4 m;
float4 main() : sv_target
{
return determinant(m);
}
[test]
uniform 0 float4 1.0 -2.0 3.0 4.0
uniform 4 float4 5.0 6.0 -7.0 8.0
uniform 8 float4 9.0 10.0 11.0 12.0
uniform 12 float4 13.0 14.0 15.0 16.0
draw quad
probe all rgba (-672.0, -672.0, -672.0, -672.0)
[pixel shader]
float3x4 m;
float4 main() : sv_target
{
return determinant(m);
}
[test]
uniform 0 float4 1.0 2.0 3.0 0.0
uniform 4 float4 5.0 -6.0 7.0 0.0
uniform 8 float4 9.0 10.0 11.0 0.0
uniform 12 float4 0.0 0.0 0.0 0.0
draw quad
probe all rgba (192.0, 192.0, 192.0, 192.0)
[pixel shader fail]
float1 v;
float4 main() : sv_target
{
return determinant(v);
}
[pixel shader fail]
float2 v;
float4 main() : sv_target
{
return determinant(v);
}