From dae88bab52c542262af4ca4f848396261495d244 Mon Sep 17 00:00:00 2001 From: Shaun Ren Date: Tue, 3 Sep 2024 15:30:40 -0400 Subject: [PATCH] vkd3d-shader/hlsl: Parse the outputcontrolpoints attribute. --- libs/vkd3d-shader/hlsl.c | 1 + libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl_codegen.c | 46 +++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + tests/hlsl/hull-shader-attributes.shader_test | 2 +- 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index a38fe1cd..17294fd6 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -4275,6 +4275,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil } ctx->domain = VKD3D_TESSELLATOR_DOMAIN_INVALID; + ctx->output_control_point_count = UINT_MAX; return true; } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 02232608..31059f7e 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1074,6 +1074,7 @@ struct hlsl_ctx uint32_t thread_count[3]; enum vkd3d_tessellator_domain domain; + unsigned int output_control_point_count; /* In some cases we generate opcodes by parsing an HLSL function and then * invoking it. If not NULL, this field is the name of the function that we diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index fc9a882a..58943d26 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -5892,6 +5892,50 @@ static void parse_domain_attribute(struct hlsl_ctx *ctx, const struct hlsl_attri value); } +static void parse_outputcontrolpoints_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr) +{ + const struct hlsl_ir_node *instr; + const struct hlsl_type *type; + const struct hlsl_ir_constant *constant; + + if (attr->args_count != 1) + { + hlsl_error(ctx, &attr->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Expected 1 parameter for [outputcontrolpoints] attribute, but got %u.", attr->args_count); + return; + } + + instr = attr->args[0].node; + type = instr->data_type; + + if (type->class != HLSL_CLASS_SCALAR + || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT)) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, type))) + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Wrong type for argument 0 of [outputcontrolpoints]: expected int or uint, but got %s.", + string->buffer); + hlsl_release_string_buffer(ctx, string); + return; + } + + if (instr->type != HLSL_IR_CONSTANT) + { + hlsl_fixme(ctx, &instr->loc, "Non-constant expression in [outputcontrolpoints] initializer."); + return; + } + constant = hlsl_ir_constant(instr); + + if ((type->e.numeric.type == HLSL_TYPE_INT && constant->value.u[0].i < 0) + || constant->value.u[0].u > 32) + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + "Output control point count must be between 0 and 32."); + + ctx->output_control_point_count = constant->value.u[0].u; +} + static void parse_entry_function_attributes(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *entry_func) { const struct hlsl_profile_info *profile = ctx->profile; @@ -5906,6 +5950,8 @@ static void parse_entry_function_attributes(struct hlsl_ctx *ctx, const struct h else if (!strcmp(attr->name, "domain") && (profile->type == VKD3D_SHADER_TYPE_HULL || profile->type == VKD3D_SHADER_TYPE_DOMAIN)) parse_domain_attribute(ctx, attr); + else if (!strcmp(attr->name, "outputcontrolpoints") && profile->type == VKD3D_SHADER_TYPE_HULL) + parse_outputcontrolpoints_attribute(ctx, attr); else hlsl_warning(ctx, &entry_func->attrs[i]->loc, VKD3D_SHADER_WARNING_HLSL_UNKNOWN_ATTRIBUTE, "Ignoring unknown attribute \"%s\".", entry_func->attrs[i]->name); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d439dbc5..27c570a9 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -155,6 +155,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE = 5033, VKD3D_SHADER_ERROR_HLSL_MISPLACED_COMPILE = 5034, VKD3D_SHADER_ERROR_HLSL_INVALID_DOMAIN = 5035, + VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT = 5036, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, diff --git a/tests/hlsl/hull-shader-attributes.shader_test b/tests/hlsl/hull-shader-attributes.shader_test index 406acc97..b722f11c 100644 --- a/tests/hlsl/hull-shader-attributes.shader_test +++ b/tests/hlsl/hull-shader-attributes.shader_test @@ -437,7 +437,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor;