vkd3d-shader/d3dbc: Make signature masks contiguous.

The goal is to make a requirement for VSIR that signature element
masks are always contiguous. The SPIR-V backend already implicitly
makes that assumption, since it just consider the LSB and popcount
of the mask.

For example, consider this HLSL pixel shader:

    float4 main(float4 color : COLOR) : SV_Target
    {
        return float4(color.x, 10.0f, 11.0f, color.w);
    }

Currently the parser describes the input signature element
corresponding to semantic COLOR as having mask .xw, which is
sensible. However, the SPIR-V parser will interpret that as
a mask starting at x and with popcount 2, and assuming it is
contiguous it will implicitly act as if it were .xy. This is
not correct, because the wrong component will be loaded from
the vertex stage.
This commit is contained in:
Giovanni Mascellani 2024-10-13 17:39:41 +02:00 committed by Henri Verbeet
parent 8943999bd2
commit 083b87c712
Notes: Henri Verbeet 2024-10-17 17:39:22 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1183

View File

@ -561,6 +561,21 @@ static struct signature_element *find_signature_element_by_register_index(
return NULL; return NULL;
} }
/* Add missing bits to a mask to make it contiguous. */
static unsigned int make_mask_contiguous(unsigned int mask)
{
static const unsigned int table[] =
{
0x0, 0x1, 0x2, 0x3,
0x4, 0x7, 0x6, 0x7,
0x8, 0xf, 0xe, 0xf,
0xc, 0xf, 0xe, 0xf,
};
VKD3D_ASSERT(mask < ARRAY_SIZE(table));
return table[mask];
}
static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, 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, 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)
@ -576,7 +591,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
if ((element = find_signature_element(signature, name, index))) if ((element = find_signature_element(signature, name, index)))
{ {
element->mask |= mask; element->mask = make_mask_contiguous(element->mask | mask);
if (!is_dcl) if (!is_dcl)
element->used_mask |= mask; element->used_mask |= mask;
return true; return true;
@ -596,7 +611,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
element->register_index = register_index; element->register_index = register_index;
element->target_location = register_index; element->target_location = register_index;
element->register_count = 1; element->register_count = 1;
element->mask = mask; element->mask = make_mask_contiguous(mask);
element->used_mask = is_dcl ? 0 : mask; element->used_mask = is_dcl ? 0 : mask;
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
element->interpolation_mode = VKD3DSIM_LINEAR; element->interpolation_mode = VKD3DSIM_LINEAR;