vkd3d-shader/dxil: Parse the f32 denormalization mode.

This commit is contained in:
Giovanni Mascellani
2025-10-27 12:12:00 +01:00
committed by Henri Verbeet
parent e99b29d203
commit 1e4764d555
Notes: Henri Verbeet 2025-12-02 14:37:50 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1842
5 changed files with 87 additions and 2 deletions

View File

@@ -1522,6 +1522,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st
code_size != ~(size_t)0 ? token_count / 4u + 4 : 16, VSIR_CF_STRUCTURED, normalisation_level))
return VKD3D_ERROR_OUT_OF_MEMORY;
program->f32_denorm_mode = VSIR_DENORM_FLUSH_TO_ZERO;
vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name);
sm1->program = program;
sm1->ptr = sm1->start;

View File

@@ -3360,8 +3360,7 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi
if (record->operands[4] > UINT_MAX)
WARN("Invalid attributes id %#"PRIx64".\n", record->operands[4]);
/* 1-based index. */
if ((fn->u.function.attribs_id = record->operands[4]))
TRACE("Ignoring function attributes.\n");
fn->u.function.attribs_id = record->operands[4];
/* These always seem to be zero. */
for (i = 5, j = 0; i < min(record->operand_count, max_count); ++i)
@@ -10929,6 +10928,62 @@ static void sm6_parser_cleanup(struct sm6_parser *sm6)
vkd3d_free(sm6->values);
}
static enum vsir_denorm_mode sm6_function_get_denorm_mode(const struct sm6_function *function,
struct sm6_parser *dxil)
{
unsigned int attribs_id = function->declaration->u.function.attribs_id;
const struct dxil_parameter_attribute *parameter_attribute;
size_t i, j, k;
if (!attribs_id)
return VSIR_DENORM_FLUSH_TO_ZERO;
if (attribs_id > dxil->parameter_attribute_count)
{
vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE,
"Invalid attribute id %u.", attribs_id);
return VSIR_DENORM_FLUSH_TO_ZERO;
}
parameter_attribute = &dxil->parameter_attributes[attribs_id - 1];
for (i = 0; i < parameter_attribute->group_count; ++i)
{
for (j = 0; j < dxil->attribute_group_count; ++j)
{
struct dxil_attribute_group *attribute_group = &dxil->attribute_groups[j];
if (attribute_group->group_id != parameter_attribute->groups[i]
|| attribute_group->parameter_idx != ~0u)
continue;
for (k = 0; k < attribute_group->attribute_count; ++k)
{
struct dxil_attribute *attribute = &attribute_group->attributes[k];
if (attribute->kind != ATTRIBUTE_STRING_WITH_STRING_VALUE
|| strcmp(attribute->key.string, "fp32-denorm-mode"))
continue;
if (!strcmp(attribute->value.string, "preserve"))
return VSIR_DENORM_PRESERVE;
if (!strcmp(attribute->value.string, "ftz"))
return VSIR_DENORM_FLUSH_TO_ZERO;
if (!strcmp(attribute->value.string, "any"))
return VSIR_DENORM_ANY;
vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE,
"Invalid value for attribute `fp32-denorm-mode'.");
return VSIR_DENORM_FLUSH_TO_ZERO;
}
}
}
return VSIR_DENORM_FLUSH_TO_ZERO;
}
static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6, const char *name)
{
size_t i;
@@ -11209,8 +11264,12 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro
goto fail;
}
program->f32_denorm_mode = sm6_function_get_denorm_mode(fn, sm6);
if (version.type == VKD3D_SHADER_TYPE_HULL)
{
enum vsir_denorm_mode cp_denorm_mode;
sm6_parser_add_instruction(sm6, VSIR_OP_HS_CONTROL_POINT_PHASE);
if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0)
@@ -11226,6 +11285,15 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro
goto fail;
}
cp_denorm_mode = sm6_function_get_denorm_mode(fn, sm6);
if (sm6->p.status >= 0 && program->f32_denorm_mode != cp_denorm_mode)
{
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE,
"Patch constant denorm mode %u doesn't match control point denorm mode %u.",
program->f32_denorm_mode, cp_denorm_mode);
}
sm6_parser_add_instruction(sm6, VSIR_OP_HS_FORK_PHASE);
if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0)
goto fail;

View File

@@ -5296,6 +5296,8 @@ int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info,
if (!vsir_program_init(program, compile_info, &version, 0, VSIR_CF_STRUCTURED, normalisation_level))
return VKD3D_ERROR_OUT_OF_MEMORY;
program->f32_denorm_mode = VSIR_DENORM_FLUSH_TO_ZERO;
if ((ret = hlsl_ctx_parse(&ctx, &program->source_files, compile_info, profile, message_context)) < 0)
{
vsir_program_cleanup(program);

View File

@@ -2811,6 +2811,9 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro
if (!vsir_program_init(program, compile_info,
&version, token_count / 7u + 20, VSIR_CF_STRUCTURED, VSIR_NORMALISED_SM4))
return false;
program->f32_denorm_mode = VSIR_DENORM_FLUSH_TO_ZERO;
vkd3d_shader_parser_init(&sm4->p, message_context, compile_info->source_name);
sm4->ptr = sm4->start;
sm4->program = program;

View File

@@ -232,6 +232,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK = 8022,
VKD3D_SHADER_ERROR_DXIL_INVALID_STRING = 8023,
VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE_KIND = 8024,
VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE = 8025,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301,
@@ -1609,6 +1610,13 @@ enum vsir_normalisation_level
VSIR_NORMALISED_SM6,
};
enum vsir_denorm_mode
{
VSIR_DENORM_ANY = 0,
VSIR_DENORM_PRESERVE,
VSIR_DENORM_FLUSH_TO_ZERO,
};
struct vkd3d_shader_descriptor_info1
{
enum vkd3d_shader_descriptor_type type;
@@ -1687,6 +1695,8 @@ struct vsir_program
struct vkd3d_shader_param_allocator src_params;
struct vkd3d_shader_param_allocator dst_params;
enum vsir_denorm_mode f32_denorm_mode;
};
enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program,