-- v3: vkd3d-shader/spirv: Ensure the data register is UINT in spirv_compiler_emit_store_tgsm(). vkd3d-shader/spirv: Bitcast if necessary in spirv_compiler_emit_store_dst_components(). vkd3d-shader/dxil: Support constexpr GEP.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 122 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index b5a61d99d..03c5458b6 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2885,6 +2885,122 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co return VKD3D_OK; }
+static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, const struct dxil_record *record, + struct sm6_value *dst) +{ + const struct sm6_type *elem_type, *pointee_type, *gep_type, *ptr_type; + struct sm6_value *operands[3]; + unsigned int i, j, offset; + uint64_t value; + + i = 0; + pointee_type = (record->operand_count & 1) ? sm6_parser_get_type(sm6, record->operands[i++]) : NULL; + + if (!dxil_record_validate_operand_count(record, i + 6, i + 6, sm6)) + return VKD3D_ERROR_INVALID_SHADER; + + for (j = 0; i < record->operand_count; i += 2, ++j) + { + if (!(elem_type = sm6_parser_get_type(sm6, record->operands[i]))) + return VKD3D_ERROR_INVALID_SHADER; + + if ((value = record->operands[i + 1]) >= sm6->cur_max_value) + { + WARN("Invalid value index %"PRIu64".\n", value); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid value index %"PRIu64".", value); + return VKD3D_ERROR_INVALID_SHADER; + } + else if (value == sm6->value_count) + { + WARN("Invalid value self-reference at %"PRIu64".\n", value); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid value self-reference for a constexpr GEP."); + return VKD3D_ERROR_INVALID_SHADER; + } + + operands[j] = &sm6->values[value]; + if (value > sm6->value_count) + { + operands[j]->type = elem_type; + } + else if (operands[j]->type != elem_type) + { + WARN("Type mismatch.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Type mismatch in constexpr GEP elements."); + } + } + + if (operands[0]->u.reg.idx_count > 1) + { + WARN("Unsupported stacked GEP.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A GEP instruction on the result of a previous GEP is unsupported."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!sm6_value_is_constant_zero(operands[1])) + { + WARN("Expected constant zero.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "The pointer dereference index for a constexpr GEP instruction is not constant zero."); + return VKD3D_ERROR_INVALID_SHADER; + } + if (!sm6_value_is_constant(operands[2]) || !sm6_type_is_integer(operands[2]->type)) + { + WARN("Element index is not constant int.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A constexpr GEP element index is not a constant integer."); + return VKD3D_ERROR_INVALID_SHADER; + } + + dst->structure_stride = operands[0]->structure_stride; + + ptr_type = operands[0]->type; + if (!sm6_type_is_pointer(ptr_type)) + { + WARN("Constexpr GEP base value is not a pointer.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A constexpr GEP base value is not a pointer."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!pointee_type) + { + pointee_type = ptr_type->u.pointer.type; + } + else if (pointee_type != ptr_type->u.pointer.type) + { + WARN("Explicit pointee type mismatch.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Explicit pointee type for constexpr GEP does not match the element type."); + } + + offset = sm6_value_get_constant_uint(operands[2]); + if (!(gep_type = sm6_type_get_element_type_at_index(pointee_type, offset))) + { + WARN("Failed to get element type.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Failed to get the element type of a constexpr GEP."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!(dst->type = sm6_type_get_pointer_to_type(gep_type, ptr_type->u.pointer.addr_space, sm6))) + { + WARN("Failed to get pointer type for type %u.\n", gep_type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Module does not define a pointer type for a constexpr GEP result."); + return VKD3D_ERROR_INVALID_SHADER; + } + dst->u.reg = operands[0]->u.reg; + dst->u.reg.idx[1].offset = offset; + dst->u.reg.idx[1].is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; + dst->u.reg.idx_count = 2; + + return VKD3D_OK; +} + static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const struct dxil_block *block) { enum vkd3d_shader_register_type reg_type = VKD3DSPR_INVALID; @@ -3005,6 +3121,12 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
break;
+ case CST_CODE_CE_GEP: + case CST_CODE_CE_INBOUNDS_GEP: + if ((ret = sm6_parser_init_constexpr_gep(sm6, record, dst)) < 0) + return ret; + break; + case CST_CODE_UNDEF: dxil_record_validate_operand_max_count(record, 0, sm6); dst->u.reg.type = VKD3DSPR_UNDEF;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 46130244c..611d7695f 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4419,11 +4419,11 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp { unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, val_id; + uint32_t type_id, dst_type_id, val_id;
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); if (component_count > 1) { - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, component_ids, component_count); } @@ -4431,6 +4431,11 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp { val_id = *component_ids; } + + dst_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, component_count); + if (dst_type_id != type_id) + val_id = vkd3d_spirv_build_op_bitcast(builder, dst_type_id, val_id); + spirv_compiler_emit_store_dst(compiler, dst, val_id); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 7 ++++--- tests/hlsl/tgsm.shader_test | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 611d7695f..5ab1fcfd2 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -8900,8 +8900,8 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; uint32_t base_coordinate_id, component_idx; - const struct vkd3d_shader_src_param *data; struct vkd3d_shader_register_info reg_info; + struct vkd3d_shader_src_param data; unsigned int component_count;
if (!spirv_compiler_get_register_info(compiler, &dst->reg, ®_info)) @@ -8913,8 +8913,9 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
- data = &src[instruction->src_count - 1]; - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); + data = src[instruction->src_count - 1]; + data.reg.data_type = VKD3D_DATA_UINT; + val_id = spirv_compiler_emit_load_src(compiler, &data, dst->write_mask);
component_count = vsir_write_mask_component_count(dst->write_mask); for (component_idx = 0; component_idx < component_count; ++component_idx) diff --git a/tests/hlsl/tgsm.shader_test b/tests/hlsl/tgsm.shader_test index e6b1a6858..4e0c7a49e 100644 --- a/tests/hlsl/tgsm.shader_test +++ b/tests/hlsl/tgsm.shader_test @@ -116,7 +116,7 @@ void main(uint local_idx : SV_GroupIndex, uint group_id : SV_GroupID,
[test] uniform 0 uint 1 -todo dispatch 2 1 1 +todo(sm<6) dispatch 2 1 1 probe uav 1 (0) r (0.0) probe uav 1 (1) r (0.0) probe uav 1 (2) r (0.0)