diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 9866f90c..e470115f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -6055,6 +6055,72 @@ static void parse_entry_function_attributes(struct hlsl_ctx *ctx, const struct h } } +static void validate_hull_shader_attributes(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *entry_func) +{ + if (ctx->domain == VKD3D_TESSELLATOR_DOMAIN_INVALID) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [domain] attribute.", entry_func->func->name); + } + + if (ctx->output_control_point_count == UINT_MAX) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [outputcontrolpoints] attribute.", entry_func->func->name); + } + + if (!ctx->output_primitive) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [outputtopology] attribute.", entry_func->func->name); + } + + if (!ctx->partitioning) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [partitioning] attribute.", entry_func->func->name); + } + + if (!ctx->patch_constant_func) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [patchconstantfunc] attribute.", entry_func->func->name); + } + else if (ctx->patch_constant_func == entry_func) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_RECURSIVE_CALL, + "Patch constant function cannot be the entry point function."); + /* Native returns E_NOTIMPL instead of E_FAIL here. */ + ctx->result = VKD3D_ERROR_NOT_IMPLEMENTED; + return; + } + + switch (ctx->domain) + { + case VKD3D_TESSELLATOR_DOMAIN_LINE: + if (ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW + || ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW) + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE, + "Triangle output topologies are not available for isoline domains."); + break; + + case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE: + if (ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE) + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE, + "Line output topologies are not available for triangle domains."); + break; + + case VKD3D_TESSELLATOR_DOMAIN_QUAD: + if (ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE) + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE, + "Line output topologies are not available for quad domains."); + break; + + default: + break; + } +} + static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body) { struct hlsl_ir_node *instr, *next; @@ -7071,8 +7137,12 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry } parse_entry_function_attributes(ctx, entry_func); + if (ctx->result) + return ctx->result; - if (profile->type == VKD3D_SHADER_TYPE_COMPUTE && !ctx->found_numthreads) + if (profile->type == VKD3D_SHADER_TYPE_HULL) + validate_hull_shader_attributes(ctx, entry_func); + else if (profile->type == VKD3D_SHADER_TYPE_COMPUTE && !ctx->found_numthreads) hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, "Entry point \"%s\" is missing a [numthreads] attribute.", entry_func->func->name); diff --git a/tests/hlsl/hull-shader-attributes.shader_test b/tests/hlsl/hull-shader-attributes.shader_test index b722f11c..0bddf787 100644 --- a/tests/hlsl/hull-shader-attributes.shader_test +++ b/tests/hlsl/hull-shader-attributes.shader_test @@ -24,7 +24,7 @@ float4 main() : POSITION %% Test missing attributes. -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -46,7 +46,7 @@ float4 main() : POSITION } % outputcontrolpoints defaults to 0 for SM >= 6. -[hull shader fail(sm<6) todo] +[hull shader fail(sm<6)] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -67,7 +67,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -88,7 +88,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -109,7 +109,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -174,7 +174,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -195,7 +195,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[2] : SV_TessFactor; @@ -238,7 +238,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[3] : SV_TessFactor; @@ -326,7 +326,7 @@ float4 main() : POSITION return 0; } -[hull shader fail todo] +[hull shader fail] struct patch_constant_data { float edges[4] : SV_TessFactor; @@ -460,7 +460,7 @@ float4 main() : POSITION % patchconstantfunc can't point to the main function. -[hull shader notimpl(sm<6) fail(sm>=6) todo] +[hull shader notimpl(sm<6) fail(sm>=6)] struct patch_constant_data { float edges[2] : SV_TessFactor;