vkd3d-shader/hlsl: Process the patch constant function in hlsl_emit_bytecode().

Also, support patch constant function semantics in sm4_sysval_semantic_from_semantic_name().
This commit is contained in:
Shaun Ren 2024-10-15 16:33:21 -04:00 committed by Henri Verbeet
parent aee00ea55a
commit 147f8898ca
Notes: Henri Verbeet 2024-10-16 21:47:54 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1187
4 changed files with 106 additions and 15 deletions

View File

@ -5168,7 +5168,8 @@ uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_d
return allocator.reg_count; return allocator.reg_count;
} }
static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, unsigned int *counter, bool output) static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var,
unsigned int *counter, bool output, bool is_patch_constant_func)
{ {
static const char *const shader_names[] = static const char *const shader_names[] =
{ {
@ -5217,8 +5218,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
enum vkd3d_shader_sysval_semantic semantic; enum vkd3d_shader_sysval_semantic semantic;
bool has_idx; bool has_idx;
if (!sm4_sysval_semantic_from_semantic_name(&semantic, &version, if (!sm4_sysval_semantic_from_semantic_name(&semantic, &version, ctx->semantic_compat_mapping,
ctx->semantic_compat_mapping, var->semantic.name, output)) ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func))
{ {
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC,
"Invalid semantic '%s'.", var->semantic.name); "Invalid semantic '%s'.", var->semantic.name);
@ -5247,15 +5248,16 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
{ {
bool is_patch_constant_func = entry_func == ctx->patch_constant_func;
unsigned int input_counter = 0, output_counter = 0; unsigned int input_counter = 0, output_counter = 0;
struct hlsl_ir_var *var; struct hlsl_ir_var *var;
LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry)
{ {
if (var->is_input_semantic) if (var->is_input_semantic)
allocate_semantic_register(ctx, var, &input_counter, false); allocate_semantic_register(ctx, var, &input_counter, false, is_patch_constant_func);
if (var->is_output_semantic) if (var->is_output_semantic)
allocate_semantic_register(ctx, var, &output_counter, true); allocate_semantic_register(ctx, var, &output_counter, true, is_patch_constant_func);
} }
} }
@ -6301,7 +6303,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx,
bool has_idx, ret; bool has_idx, ret;
ret = sm4_sysval_semantic_from_semantic_name(&sysval, &program->shader_version, ret = sm4_sysval_semantic_from_semantic_name(&sysval, &program->shader_version,
ctx->semantic_compat_mapping, var->semantic.name, output); ctx->semantic_compat_mapping, ctx->domain, var->semantic.name, var->semantic.index, output, false);
VKD3D_ASSERT(ret); VKD3D_ASSERT(ret);
if (sysval == ~0u) if (sysval == ~0u)
return; return;
@ -7749,10 +7751,18 @@ static void process_entry_function(struct hlsl_ctx *ctx,
{ {
var = entry_func->parameters.vars[i]; var = entry_func->parameters.vars[i];
if (hlsl_type_is_resource(var->data_type) || (var->storage_modifiers & HLSL_STORAGE_UNIFORM)) if (hlsl_type_is_resource(var->data_type))
{ {
prepend_uniform_copy(ctx, body, var); prepend_uniform_copy(ctx, body, var);
} }
else if ((var->storage_modifiers & HLSL_STORAGE_UNIFORM))
{
if (ctx->profile->type == VKD3D_SHADER_TYPE_HULL && entry_func == ctx->patch_constant_func)
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
"Patch constant function parameter \"%s\" cannot be uniform.", var->name);
else
prepend_uniform_copy(ctx, body, var);
}
else else
{ {
if (hlsl_get_multiarray_element_type(var->data_type)->class != HLSL_CLASS_STRUCT if (hlsl_get_multiarray_element_type(var->data_type)->class != HLSL_CLASS_STRUCT
@ -7891,6 +7901,13 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
if (ctx->result) if (ctx->result)
return ctx->result; return ctx->result;
if (profile->type == VKD3D_SHADER_TYPE_HULL)
{
process_entry_function(ctx, &global_uniform_block, ctx->patch_constant_func);
if (ctx->result)
return ctx->result;
}
hlsl_block_cleanup(&global_uniform_block); hlsl_block_cleanup(&global_uniform_block);
if (profile->major_version < 4) if (profile->major_version < 4)

View File

@ -3047,9 +3047,57 @@ bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version,
return false; return false;
} }
static bool get_tessfactor_sysval_semantic(enum vkd3d_shader_sysval_semantic *semantic,
enum vkd3d_tessellator_domain domain, uint32_t index)
{
switch (domain)
{
case VKD3D_TESSELLATOR_DOMAIN_LINE:
if (index == 0)
*semantic = VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN;
else if (index == 1)
*semantic = VKD3D_SHADER_SV_TESS_FACTOR_LINEDET;
else
return false;
return true;
case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE:
*semantic = VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE;
return index < 3;
case VKD3D_TESSELLATOR_DOMAIN_QUAD:
*semantic = VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE;
return index < 4;
default:
vkd3d_unreachable();
}
}
static bool get_insidetessfactor_sysval_semantic(enum vkd3d_shader_sysval_semantic *semantic,
enum vkd3d_tessellator_domain domain, uint32_t index)
{
switch (domain)
{
case VKD3D_TESSELLATOR_DOMAIN_LINE:
return false;
case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE:
*semantic = VKD3D_SHADER_SV_TESS_FACTOR_TRIINT;
return index == 0;
case VKD3D_TESSELLATOR_DOMAIN_QUAD:
*semantic = VKD3D_SHADER_SV_TESS_FACTOR_QUADINT;
return index < 2;
default:
vkd3d_unreachable();
}
}
bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic, bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_version *version, bool semantic_compat_mapping, enum vkd3d_tessellator_domain domain,
bool semantic_compat_mapping, const char *semantic_name, bool output) const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func)
{ {
unsigned int i; unsigned int i;
@ -3105,6 +3153,32 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s
}; };
bool needs_compat_mapping = ascii_strncasecmp(semantic_name, "sv_", 3); bool needs_compat_mapping = ascii_strncasecmp(semantic_name, "sv_", 3);
if (is_patch_constant_func)
{
if (output)
{
if (!ascii_strcasecmp(semantic_name, "sv_tessfactor"))
return get_tessfactor_sysval_semantic(sysval_semantic, domain, semantic_idx);
if (!ascii_strcasecmp(semantic_name, "sv_insidetessfactor"))
return get_insidetessfactor_sysval_semantic(sysval_semantic, domain, semantic_idx);
if (!ascii_strcasecmp(semantic_name, "sv_position"))
{
*sysval_semantic = VKD3D_SHADER_SV_NONE;
return true;
}
}
else
{
if (!ascii_strcasecmp(semantic_name, "sv_primitiveid")
|| !ascii_strcasecmp(semantic_name, "sv_position"))
{
*sysval_semantic = ~0u;
return true;
}
return false;
}
}
for (i = 0; i < ARRAY_SIZE(semantics); ++i) for (i = 0; i < ARRAY_SIZE(semantics); ++i)
{ {
if (!ascii_strcasecmp(semantic_name, semantics[i].name) if (!ascii_strcasecmp(semantic_name, semantics[i].name)
@ -4757,8 +4831,8 @@ static void write_sm4_dcl_semantic(const struct tpf_compiler *tpf, const struct
if (shader_sm4_is_scalar_register(&instr.dsts[0].reg)) if (shader_sm4_is_scalar_register(&instr.dsts[0].reg))
instr.dsts[0].reg.dimension = VSIR_DIMENSION_SCALAR; instr.dsts[0].reg.dimension = VSIR_DIMENSION_SCALAR;
sm4_sysval_semantic_from_semantic_name(&semantic, version, sm4_sysval_semantic_from_semantic_name(&semantic, version, tpf->ctx->semantic_compat_mapping,
tpf->ctx->semantic_compat_mapping, var->semantic.name, output); tpf->ctx->domain, var->semantic.name, var->semantic.index, output, false);
if (semantic == ~0u) if (semantic == ~0u)
semantic = VKD3D_SHADER_SV_NONE; semantic = VKD3D_SHADER_SV_NONE;

View File

@ -1609,8 +1609,8 @@ bool sm1_usage_from_semantic_name(const char *semantic_name,
bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version, bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version,
const char *semantic_name, bool output, enum vkd3d_shader_register_type *type, bool *has_idx); const char *semantic_name, bool output, enum vkd3d_shader_register_type *type, bool *has_idx);
bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic, bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_version *version, bool semantic_compat_mapping, enum vkd3d_tessellator_domain domain,
bool semantic_compat_mapping, const char *semantic_name, bool output); const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func);
int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags, int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program); struct vkd3d_shader_message_context *message_context, struct vsir_program *program);

View File

@ -84,7 +84,7 @@ float4 main() : POSITION
return 0; return 0;
} }
[hull shader fail todo] [hull shader fail]
struct patch_constant_data struct patch_constant_data
{ {
float edges[2] : SV_TessFactor; float edges[2] : SV_TessFactor;
@ -140,7 +140,7 @@ float4 main(uniform float4 b) : POSITION
} }
% Patch constant function can't have uniform parameters. % Patch constant function can't have uniform parameters.
[hull shader fail todo] [hull shader fail]
struct patch_constant_data struct patch_constant_data
{ {
float edges[2] : SV_TessFactor; float edges[2] : SV_TessFactor;