vkd3d-shader/hlsl: Add support for the centroid interpolation mode in SM1.

This commit is contained in:
Shaun Ren
2025-09-29 20:11:38 -04:00
committed by Henri Verbeet
parent 44582a930c
commit d5770cd347
Notes: Henri Verbeet 2025-10-06 19:48:17 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1721
3 changed files with 60 additions and 55 deletions

View File

@@ -659,7 +659,7 @@ static unsigned int make_mask_contiguous(unsigned int mask)
static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output,
const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval,
unsigned int register_index, bool is_dcl, unsigned int mask)
unsigned int register_index, bool is_dcl, unsigned int mask, uint32_t dst_modifiers)
{
struct vsir_program *program = sm1->program;
struct shader_signature *signature;
@@ -695,7 +695,8 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
element->mask = make_mask_contiguous(mask);
element->used_mask = is_dcl ? 0 : mask;
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
element->interpolation_mode = VKD3DSIM_LINEAR;
element->interpolation_mode = (dst_modifiers & VKD3DSPDM_MSAMPCENTROID)
? VKD3DSIM_LINEAR_CENTROID : VKD3DSIM_LINEAR;
return true;
}
@@ -748,7 +749,7 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output,
}
static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *sm1,
const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask)
const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask, uint32_t dst_modifiers)
{
const struct vkd3d_shader_version *version = &sm1->program->shader_version;
unsigned int register_index = reg->idx_count > 0 ? reg->idx[0].offset : 0;
@@ -757,7 +758,8 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
{
case VKD3DSPR_TEMP:
if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 1 && !register_index)
return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_TARGET, 0, is_dcl, mask);
return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_TARGET,
0, is_dcl, mask, dst_modifiers);
return true;
case VKD3DSPR_INPUT:
@@ -769,15 +771,15 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
return true;
}
return add_signature_element(sm1, false, "COLOR", register_index,
VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask);
VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask, dst_modifiers);
case VKD3DSPR_TEXTURE:
return add_signature_element(sm1, false, "TEXCOORD", register_index,
VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask);
VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask, dst_modifiers);
case VKD3DSPR_TEXCRDOUT:
return add_signature_element(sm1, true, "TEXCOORD", register_index,
VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask);
VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask, dst_modifiers);
case VKD3DSPR_OUTPUT:
if (version->type == VKD3D_SHADER_TYPE_VERTEX)
@@ -789,30 +791,30 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
case VKD3DSPR_ATTROUT:
return add_signature_element(sm1, true, "COLOR", register_index,
VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask);
VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask, dst_modifiers);
case VKD3DSPR_COLOROUT:
return add_signature_element(sm1, true, "COLOR", register_index,
VKD3D_SHADER_SV_TARGET, register_index, is_dcl, mask);
VKD3D_SHADER_SV_TARGET, register_index, is_dcl, mask, dst_modifiers);
case VKD3DSPR_DEPTHOUT:
return add_signature_element(sm1, true, "DEPTH", 0,
VKD3D_SHADER_SV_DEPTH, register_index, is_dcl, 0x1);
VKD3D_SHADER_SV_DEPTH, register_index, is_dcl, 0x1, dst_modifiers);
case VKD3DSPR_RASTOUT:
switch (register_index)
{
case 0:
return add_signature_element(sm1, true, "POSITION", 0,
VKD3D_SHADER_SV_POSITION, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask);
return add_signature_element(sm1, true, "POSITION", 0, VKD3D_SHADER_SV_POSITION,
SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask, dst_modifiers);
case 1:
return add_signature_element(sm1, true, "FOG", 0,
VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1);
return add_signature_element(sm1, true, "FOG", 0, VKD3D_SHADER_SV_NONE,
SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1, dst_modifiers);
case 2:
return add_signature_element(sm1, true, "PSIZE", 0,
VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1);
return add_signature_element(sm1, true, "PSIZE", 0, VKD3D_SHADER_SV_NONE,
SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1, dst_modifiers);
default:
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX,
@@ -825,11 +827,11 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
{
case 0:
return add_signature_element(sm1, false, "VPOS", 0,
VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask);
VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask, dst_modifiers);
case 1:
return add_signature_element(sm1, false, "VFACE", 0,
VKD3D_SHADER_SV_IS_FRONT_FACE, register_index, is_dcl, 0x1);
VKD3D_SHADER_SV_IS_FRONT_FACE, register_index, is_dcl, 0x1, dst_modifiers);
default:
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX,
@@ -849,6 +851,7 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
const struct vkd3d_shader_register *reg = &semantic->resource.reg.reg;
enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE;
unsigned int mask = semantic->resource.reg.write_mask;
uint32_t modifiers = semantic->resource.reg.modifiers;
bool output;
static const char sm1_semantic_names[][13] =
@@ -874,11 +877,11 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
else if (reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_TEXTURE)
output = false;
else /* vpos and vface don't have a semantic. */
return add_signature_element_from_register(sm1, reg, true, mask);
return add_signature_element_from_register(sm1, reg, true, mask, modifiers);
/* sm2 pixel shaders use DCL but don't provide a semantic. */
if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 2)
return add_signature_element_from_register(sm1, reg, true, mask);
return add_signature_element_from_register(sm1, reg, true, mask, modifiers);
/* With the exception of vertex POSITION output, none of these are system
* values. Pixel POSITION input is not equivalent to SV_Position; the closer
@@ -887,8 +890,8 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
&& output && semantic->usage == VKD3D_DECL_USAGE_POSITION)
sysval = VKD3D_SHADER_SV_POSITION;
return add_signature_element(sm1, output, sm1_semantic_names[semantic->usage],
semantic->usage_idx, sysval, reg->idx[0].offset, true, mask);
return add_signature_element(sm1, output, sm1_semantic_names[semantic->usage], semantic->usage_idx, sysval,
reg->idx[0].offset, true, mask, modifiers);
}
static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1,
@@ -932,7 +935,7 @@ static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1,
break;
}
add_signature_element_from_register(sm1, reg, false, mask);
add_signature_element_from_register(sm1, reg, false, mask, 0);
}
/* Read a parameter token from the input stream, and possibly a relative
@@ -2100,6 +2103,8 @@ static void d3dbc_write_semantic_dcl(struct d3dbc_compiler *d3dbc,
put_u32(buffer, token);
reg.write_mask = element->mask;
if (element->interpolation_mode == VKD3DSIM_LINEAR_CENTROID)
reg.modifiers |= VKD3DSPDM_MSAMPCENTROID;
write_sm1_dst_register(buffer, &reg);
}

View File

@@ -6756,8 +6756,8 @@ static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_block *bod
allocate_temp_registers_recurse(ctx, body);
}
static enum vkd3d_shader_interpolation_mode sm4_get_interpolation_mode(struct hlsl_type *type,
unsigned int storage_modifiers)
static enum vkd3d_shader_interpolation_mode get_interpolation_mode(const struct vkd3d_shader_version *version,
struct hlsl_type *type, unsigned int storage_modifiers)
{
unsigned int i;
@@ -6779,6 +6779,9 @@ static enum vkd3d_shader_interpolation_mode sm4_get_interpolation_mode(struct hl
VKD3D_ASSERT(hlsl_is_numeric_type(type));
if (version->major < 4)
storage_modifiers &= HLSL_STORAGE_LINEAR | HLSL_STORAGE_CENTROID;
if ((storage_modifiers & HLSL_STORAGE_NOINTERPOLATION)
|| base_type_get_semantic_equivalent(type->e.numeric.type) == HLSL_TYPE_UINT)
return VKD3DSIM_CONSTANT;
@@ -6885,12 +6888,11 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var
{
unsigned int component_count = is_primitive
? var->data_type->e.array.type->e.numeric.dimx : var->data_type->e.numeric.dimx;
int mode = (ctx->profile->major_version < 4)
? 0 : sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
unsigned int reg_size = optimize ? component_count : 4;
int mode = VKD3DSIM_NONE;
if (special_interpolation)
mode = VKD3DSIM_NONE;
if (version.major >= 4 && !special_interpolation)
mode = get_interpolation_mode(&version, var->data_type, var->storage_modifiers);
var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator,
reg_size, component_count, mode, var->force_align, vip_allocation);
@@ -8582,6 +8584,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog
struct shader_signature *signature, bool output, struct hlsl_ir_var *var)
{
enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_VOID;
enum vkd3d_shader_interpolation_mode interpolation_mode = VKD3DSIM_NONE;
bool is_primitive = hlsl_type_is_primitive_array(var->data_type);
enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE;
unsigned int register_index, mask, use_mask;
@@ -8589,6 +8592,9 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog
enum vkd3d_shader_register_type type;
struct signature_element *element;
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
interpolation_mode = get_interpolation_mode(&program->shader_version, var->data_type, var->storage_modifiers);
if (hlsl_version_ge(ctx, 4, 0))
{
struct vkd3d_string_buffer *string;
@@ -8654,12 +8660,6 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog
}
else
{
if (var->storage_modifiers & HLSL_INTERPOLATION_MODIFIERS_MASK)
{
hlsl_fixme(ctx, &var->loc, "SM1 interpolation modifiers.");
return;
}
if ((!output && !var->last_read) || (output && !var->first_write))
return;
@@ -8674,6 +8674,13 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog
|| (type == VKD3DSPR_INPUT && program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL))
register_index += SM1_COLOR_REGISTER_OFFSET;
}
if (interpolation_mode == VKD3DSIM_LINEAR_CENTROID
&& (vkd3d_shader_ver_ge(&program->shader_version, 3, 0) || type != VKD3DSPR_TEXTURE))
{
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
"The centroid interpolation mode is not supported by the '%s' semantic.", var->semantic.name);
}
}
else
{
@@ -8741,13 +8748,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog
element->register_count = 1;
element->mask = mask;
element->used_mask = use_mask;
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
{
if (program->shader_version.major >= 4)
element->interpolation_mode = sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
else
element->interpolation_mode = VKD3DSIM_LINEAR;
}
element->interpolation_mode = interpolation_mode;
switch (var->data_type->e.numeric.type)
{
@@ -10813,7 +10814,7 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs
dst_param->write_mask = write_mask;
if (var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_PIXEL)
ins->flags = sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
ins->flags = get_interpolation_mode(version, var->data_type, var->storage_modifiers);
}
static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_program *program,