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

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov 2023-09-07 02:09:36 +02:00 committed by Alexandre Julliard
parent 8087cc01f7
commit b5c0c9c22f
Notes: Alexandre Julliard 2023-10-05 22:36:39 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Zebediah Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/330
3 changed files with 55 additions and 0 deletions

View File

@ -93,6 +93,7 @@ vkd3d_shader_tests = \
tests/hlsl/function-overload.shader_test \
tests/hlsl/function-return.shader_test \
tests/hlsl/function.shader_test \
tests/hlsl/fwidth.shader_test \
tests/hlsl/gather-offset.shader_test \
tests/hlsl/gather.shader_test \
tests/hlsl/getdimensions.shader_test \

View File

@ -2961,6 +2961,33 @@ static bool intrinsic_frac(struct hlsl_ctx *ctx,
return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FRACT, arg, loc);
}
static bool intrinsic_fwidth(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_function_decl *func;
struct hlsl_type *type;
char *body;
static const char template[] =
"%s fwidth(%s x)\n"
"{\n"
" return abs(ddx(x)) + abs(ddy(x));\n"
"}";
if (!elementwise_intrinsic_float_convert_args(ctx, params, loc))
return false;
type = params->args[0]->data_type;
if (!(body = hlsl_sprintf_alloc(ctx, template, type->name, type->name)))
return false;
func = hlsl_compile_internal_function(ctx, "fwidth", body);
vkd3d_free(body);
if (!func)
return false;
return add_user_call(ctx, func, params, loc);
}
static bool intrinsic_ldexp(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
@ -3690,6 +3717,7 @@ intrinsic_functions[] =
{"floor", 1, true, intrinsic_floor},
{"fmod", 2, true, intrinsic_fmod},
{"frac", 1, true, intrinsic_frac},
{"fwidth", 1, true, intrinsic_fwidth},
{"ldexp", 2, true, intrinsic_ldexp},
{"length", 1, true, intrinsic_length},
{"lerp", 3, true, intrinsic_lerp},

View File

@ -0,0 +1,26 @@
[require]
shader model >= 3.0
[pixel shader]
float4 main(float4 pos : sv_position) : sv_target
{
// Shader models < 4 don't add 0.5 to sv_position, so this adjustment is required to get the
// same outputs.
pos.x = floor(pos.x) + 0.5;
pos.y = floor(pos.y) + 0.5;
pos /= 10.0;
float nonlinear = pos.x * pos.y - pos.x * (pos.x + 0.5);
float4 res = fwidth(nonlinear);
// Each device may use either the coarse or the fine derivate, so use quantization.
return round(30 * res);
}
[test]
draw quad
probe (10, 10) rgba (8.0, 8.0, 8.0, 8.0)
probe (11, 10) rgba (8.0, 8.0, 8.0, 8.0)
probe (12, 10) rgba (10.0, 10.0, 10.0, 10.0)
probe (16, 16) rgba (12.0, 12.0, 12.0, 12.0)
probe (150, 150) rgba (92.0, 92.0, 92.0, 92.0)