From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/ir.c | 44 +++++++++++++++++++----- libs/vkd3d-shader/spirv.c | 7 +++- libs/vkd3d-shader/vkd3d_shader_private.h | 3 +- 3 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 179838354..c5262d351 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1336,14 +1336,14 @@ struct clip_cull_normaliser static void shader_signature_transform_clip_cull(struct clip_cull_normaliser_signature *signature, enum vkd3d_shader_sysval_semantic target_sysval, struct clip_cull_normaliser *normaliser) { + unsigned int i, j, base, array_size, reg_mask, count, arrayed_count; struct vkd3d_shader_parser *parser = normaliser->parser; - unsigned int i, j, base, array_size, reg_mask; struct shader_signature *s = signature->s; struct signature_element *e;
/* Up to two vec4 clip/cull elements are allowed. Merge these into an array, * and track the location and array offset of the second one. */ - for (i = 0, array_size = 0, reg_mask = 0, base = 0; i < s->element_count; ++i) + for (i = 0, array_size = 0, reg_mask = 0, base = 0, count = 0, arrayed_count = 0; i < s->element_count; ++i) { e = &s->elements[i];
@@ -1359,10 +1359,25 @@ static void shader_signature_transform_clip_cull(struct clip_cull_normaliser_sig
signature->offsets[i] = array_size; array_size += vsir_write_mask_component_count(e->mask); + ++count; + arrayed_count += e->register_count > 1; }
if (!array_size) return; + /* DXIL supports clip/cull arrays of size 2, and a single array requires no modification. Larger + * arrays exceed the semantic index limit (and cause dxcompiler version 1.7.0.4006 to crash). */ + if (arrayed_count == 1 && count == 1) + return; + /* TODO: combining an array with another clip/cull element should be rare, and requires special handling. */ + if (arrayed_count) + { + WARN("Unsupported multiple elements with at least one array.\n"); + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "Multiple clip or cull signature elements are not supported if at least one is an array."); + normaliser->result = VKD3D_ERROR_INVALID_SHADER; + return; + }
if (array_size > D3D12_CLIP_OR_CULL_DISTANCE_COUNT) { @@ -1525,7 +1540,8 @@ static void shader_src_param_clip_cull_normalise(struct vkd3d_shader_src_param * normaliser->result = VKD3D_ERROR_INVALID_SHADER; return; } - /* Dynamic array addressing of clip/cull inputs is not supported. */ + /* Dynamic array addressing of clip/cull inputs is not supported, except for DXIL arrayed inputs, + * which are filtered out above by 'need_normalisation'. */ if (reg->idx_count >= ARRAY_SIZE(reg->idx)) { WARN("Unexpected index count %u.\n", reg->idx_count); @@ -1640,7 +1656,8 @@ static void shader_dst_param_clip_cull_normalise(struct vkd3d_shader_dst_param *
write_mask = dst_param->write_mask;
- /* Dynamic array addressing of clip/cull outputs is not supported. */ + /* Dynamic array addressing of clip/cull outputs is not supported, except for DXIL arrayed outputs, + * which are filtered out above by 'need_normalisation'. */ if (reg->idx_count >= ARRAY_SIZE(reg->idx)) { WARN("Unexpected index count %u.\n", reg->idx_count); @@ -2755,15 +2772,12 @@ static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_par return result; }
-enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, +enum vkd3d_result vkd3d_shader_normalise_sm4(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { struct vkd3d_shader_instruction_array *instructions = &parser->instructions; enum vkd3d_result result;
- if (parser->shader_desc.is_dxil) - return VKD3D_OK; - if (parser->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) { if ((result = remap_output_signature(parser, compile_info)) < 0) @@ -2809,6 +2823,20 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, return result; }
+enum vkd3d_result vkd3d_shader_normalise_sm6(struct vkd3d_shader_parser *parser) +{ + struct vkd3d_shader_instruction_array *instructions = &parser->instructions; + enum vkd3d_result result; + + if ((result = normalise_clip_cull(parser)) < 0) + return result; + + if (TRACE_ON()) + vkd3d_shader_trace(instructions, &parser->shader_version); + + return vsir_validate(parser); +} + struct validation_context { struct vkd3d_shader_parser *parser; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index b4ebc35e6..c731091f3 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -9541,7 +9541,12 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, enum vkd3d_result result = VKD3D_OK; unsigned int i;
- if ((result = vkd3d_shader_normalise(parser, compile_info)) < 0) + if (parser->shader_desc.is_dxil) + result = vkd3d_shader_normalise_sm6(parser); + else + result = vkd3d_shader_normalise_sm4(parser, compile_info); + + if (result < 0) return result;
if (parser->shader_desc.temp_count) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index e611494ba..891f6202d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1658,7 +1658,8 @@ void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void void dxbc_writer_init(struct dxbc_writer *dxbc); int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *code);
-enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, +enum vkd3d_result vkd3d_shader_normalise_sm4(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info); +enum vkd3d_result vkd3d_shader_normalise_sm6(struct vkd3d_shader_parser *parser);
#endif /* __VKD3D_SHADER_PRIVATE_H */