mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/spirv: Avoid emitting duplicate built-in inputs in spirv_compiler_emit_input().
This works around an issue introduced by commit
66cb2815f0
. SV_PRIMITIVE_ID inputs in
geometry shaders use VKD3DSPR_PRIMID registers, and we create the
corresponding SPIR-V inputs using spirv_compiler_emit_io_register().
Unfortunately we also have an input signature element for the same
input, and simply creating another PrimitiveId input would run into
VUID-StandaloneSpirv-OpEntryPoint-09658.
Before the commit mentioned above, we'd use DCL_INPUT instructions to
emit input declarations, and these would help to distinguish whether
VKD3DSPR_INPUT or VKD3DSPR_PRIMID registers were used for primitive ID
inputs. Note that we can't simply ignore input signature element with
SIGNATURE_TARGET_LOCATION_UNUSED; the DXIL parser emits SV_SAMPLE_INDEX
inputs with that target location, but does require them to use a
VKD3DSPR_INPUT register.
This commit is contained in:
Notes:
Henri Verbeet
2025-08-13 16:27:34 +02:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1677
@@ -5676,6 +5676,48 @@ static unsigned int shader_signature_next_location(const struct shader_signature
|
|||||||
return max_row;
|
return max_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_compiler *compiler,
|
||||||
|
const struct vkd3d_shader_dst_param *dst)
|
||||||
|
{
|
||||||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||||||
|
const struct vkd3d_shader_register *reg = &dst->reg;
|
||||||
|
const struct vkd3d_spirv_builtin *builtin;
|
||||||
|
struct vkd3d_symbol reg_symbol;
|
||||||
|
SpvStorageClass storage_class;
|
||||||
|
uint32_t write_mask, id;
|
||||||
|
struct rb_entry *entry;
|
||||||
|
|
||||||
|
VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr);
|
||||||
|
VKD3D_ASSERT(reg->idx_count < 2);
|
||||||
|
|
||||||
|
if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
|
||||||
|
{
|
||||||
|
builtin = &vkd3d_output_point_size_builtin;
|
||||||
|
storage_class = SpvStorageClassOutput;
|
||||||
|
}
|
||||||
|
else if (!(builtin = get_spirv_builtin_for_register(reg->type, &storage_class)))
|
||||||
|
{
|
||||||
|
FIXME("Unhandled register %#x.\n", reg->type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vPrim may be declared in multiple hull shader phases. */
|
||||||
|
vkd3d_symbol_make_register(®_symbol, reg);
|
||||||
|
if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
|
||||||
|
return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
|
||||||
|
|
||||||
|
id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, 0);
|
||||||
|
spirv_compiler_emit_register_execution_mode(compiler, reg->type);
|
||||||
|
spirv_compiler_emit_register_debug_name(builder, id, reg);
|
||||||
|
|
||||||
|
write_mask = vkd3d_write_mask_from_component_count(builtin->component_count);
|
||||||
|
vkd3d_symbol_set_register_info(®_symbol, id,
|
||||||
|
storage_class, builtin->component_type, write_mask);
|
||||||
|
reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size;
|
||||||
|
|
||||||
|
return spirv_compiler_put_symbol(compiler, ®_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
static void spirv_compiler_emit_input(struct spirv_compiler *compiler,
|
static void spirv_compiler_emit_input(struct spirv_compiler *compiler,
|
||||||
enum vkd3d_shader_register_type reg_type, unsigned int element_idx)
|
enum vkd3d_shader_register_type reg_type, unsigned int element_idx)
|
||||||
{
|
{
|
||||||
@@ -5684,6 +5726,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler,
|
|||||||
const struct signature_element *signature_element;
|
const struct signature_element *signature_element;
|
||||||
const struct shader_signature *shader_signature;
|
const struct shader_signature *shader_signature;
|
||||||
enum vkd3d_shader_component_type component_type;
|
enum vkd3d_shader_component_type component_type;
|
||||||
|
enum vkd3d_shader_register_type sysval_reg_type;
|
||||||
const struct vkd3d_spirv_builtin *builtin;
|
const struct vkd3d_spirv_builtin *builtin;
|
||||||
enum vkd3d_shader_sysval_semantic sysval;
|
enum vkd3d_shader_sysval_semantic sysval;
|
||||||
uint32_t write_mask, reg_write_mask;
|
uint32_t write_mask, reg_write_mask;
|
||||||
@@ -5708,6 +5751,22 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler,
|
|||||||
if (!signature_element->used_mask)
|
if (!signature_element->used_mask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sysval_reg_type = vsir_register_type_from_sysval_input(signature_element->sysval_semantic);
|
||||||
|
if (sysval_reg_type != VKD3DSPR_INPUT)
|
||||||
|
{
|
||||||
|
struct vkd3d_shader_dst_param dst;
|
||||||
|
const struct vkd3d_symbol *symbol;
|
||||||
|
|
||||||
|
vsir_dst_param_init(&dst, sysval_reg_type, VSIR_DATA_F32, 0);
|
||||||
|
symbol = spirv_compiler_emit_io_register(compiler, &dst);
|
||||||
|
|
||||||
|
vkd3d_symbol_make_io(®_symbol, reg_type, element_idx);
|
||||||
|
reg_symbol.id = symbol->id;
|
||||||
|
reg_symbol.info.reg = symbol->info.reg;
|
||||||
|
spirv_compiler_put_symbol(compiler, ®_symbol);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
builtin = get_spirv_builtin_for_sysval(compiler, sysval);
|
builtin = get_spirv_builtin_for_sysval(compiler, sysval);
|
||||||
|
|
||||||
array_sizes[0] = signature_element->register_count;
|
array_sizes[0] = signature_element->register_count;
|
||||||
@@ -5829,47 +5888,6 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spirv_compiler_emit_io_register(struct spirv_compiler *compiler,
|
|
||||||
const struct vkd3d_shader_dst_param *dst)
|
|
||||||
{
|
|
||||||
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
||||||
const struct vkd3d_shader_register *reg = &dst->reg;
|
|
||||||
const struct vkd3d_spirv_builtin *builtin;
|
|
||||||
struct vkd3d_symbol reg_symbol;
|
|
||||||
SpvStorageClass storage_class;
|
|
||||||
uint32_t write_mask, id;
|
|
||||||
struct rb_entry *entry;
|
|
||||||
|
|
||||||
VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr);
|
|
||||||
VKD3D_ASSERT(reg->idx_count < 2);
|
|
||||||
|
|
||||||
if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
|
|
||||||
{
|
|
||||||
builtin = &vkd3d_output_point_size_builtin;
|
|
||||||
storage_class = SpvStorageClassOutput;
|
|
||||||
}
|
|
||||||
else if (!(builtin = get_spirv_builtin_for_register(reg->type, &storage_class)))
|
|
||||||
{
|
|
||||||
FIXME("Unhandled register %#x.\n", reg->type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vPrim may be declared in multiple hull shader phases. */
|
|
||||||
vkd3d_symbol_make_register(®_symbol, reg);
|
|
||||||
if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, 0);
|
|
||||||
|
|
||||||
write_mask = vkd3d_write_mask_from_component_count(builtin->component_count);
|
|
||||||
vkd3d_symbol_set_register_info(®_symbol, id,
|
|
||||||
storage_class, builtin->component_type, write_mask);
|
|
||||||
reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size;
|
|
||||||
spirv_compiler_put_symbol(compiler, ®_symbol);
|
|
||||||
spirv_compiler_emit_register_execution_mode(compiler, reg->type);
|
|
||||||
spirv_compiler_emit_register_debug_name(builder, id, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int get_shader_output_swizzle(const struct spirv_compiler *compiler,
|
static unsigned int get_shader_output_swizzle(const struct spirv_compiler *compiler,
|
||||||
unsigned int register_idx)
|
unsigned int register_idx)
|
||||||
{
|
{
|
||||||
|
@@ -1023,6 +1023,20 @@ static inline bool vsir_register_is_descriptor(const struct vkd3d_shader_registe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline enum vkd3d_shader_register_type vsir_register_type_from_sysval_input(
|
||||||
|
enum vkd3d_shader_sysval_semantic sysval)
|
||||||
|
{
|
||||||
|
switch (sysval)
|
||||||
|
{
|
||||||
|
case VKD3D_SHADER_SV_PRIMITIVE_ID:
|
||||||
|
return VKD3DSPR_PRIMID;
|
||||||
|
case VKD3D_SHADER_SV_COVERAGE:
|
||||||
|
return VKD3DSPR_COVERAGE;
|
||||||
|
default:
|
||||||
|
return VKD3DSPR_INPUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct vkd3d_shader_dst_param
|
struct vkd3d_shader_dst_param
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_register reg;
|
struct vkd3d_shader_register reg;
|
||||||
|
Reference in New Issue
Block a user