From 4400315c4b9dd3f8cf3c153b43c4a071564f26fa Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Tue, 16 Jul 2024 19:48:48 -0500 Subject: [PATCH] vkd3d-shader: Allow controlling clip planes through vkd3d-shader parameters. --- include/vkd3d_shader.h | 78 +++++++- libs/vkd3d-shader/ir.c | 216 ++++++++++++++++++++++- libs/vkd3d-shader/spirv.c | 112 ++++++++---- libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 4 files changed, 366 insertions(+), 42 deletions(-) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 115bb21b..d08ee74a 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -480,8 +480,8 @@ enum vkd3d_shader_parameter_type /** The parameter value is embedded directly in the shader. */ VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT, /** - * The parameter value is provided to the shader via a specialization - * constant. This value is only supported for the SPIR-V target type. + * The parameter value is provided to the shader via specialization + * constants. This value is only supported for the SPIR-V target type. */ VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT, /** @@ -506,6 +506,13 @@ enum vkd3d_shader_parameter_data_type VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32, /** The parameter is provided as a 32-bit float. \since 1.13 */ VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32, + /** + * The parameter is provided as a 4-dimensional vector of 32-bit floats. + * This parameter must be used with struct vkd3d_shader_parameter1; + * it cannot be used with struct vkd3d_shader_parameter. + * \since 1.14 + */ + VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_DATA_TYPE), }; @@ -589,6 +596,58 @@ enum vkd3d_shader_parameter_name * \since 1.13 */ VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION, + /** + * A mask of enabled clip planes. + * + * When this parameter is provided to a vertex shader, for each nonzero bit + * of this mask, a user clip distance will be generated from vertex position + * in clip space, and the clip plane defined by the indexed vector, taken + * from the VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_# parameter. + * + * Regardless of the specific clip planes which are enabled, the clip + * distances which are output are a contiguous array starting from clip + * distance 0. This affects the interface of OpenGL. For example, if only + * clip planes 1 and 3 are enabled (and so the value of the mask is 0xa), + * the user should enable only GL_CLIP_DISTANCE0 and GL_CLIP_DISTANCE1. + * + * The default value is zero, i.e. do not enable any clip planes. + * + * The data type for this parameter must be + * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32. + * + * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this + * version of vkd3d-shader. + * + * If the source shader writes clip distances and this parameter is nonzero, + * compilation fails. + * + * \since 1.14 + */ + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK, + /** + * Clip plane values. + * See VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK for documentation of + * clip planes. + * + * These enum values are contiguous and arithmetic may safely be performed + * on them. That is, VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_[n] is + * VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 plus n. + * + * The data type for each parameter must be + * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. + * + * The default value for each plane is a (0, 0, 0, 0) vector. + * + * \since 1.14 + */ + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_1, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_2, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_3, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_4, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_5, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_6, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_7, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), }; @@ -636,6 +695,13 @@ struct vkd3d_shader_parameter_immediate_constant1 * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. */ float f32; + /** + * A pointer to the value if the parameter's data type is + * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. + * + * \since 1.14 + */ + float f32_vec4[4]; void *_pointer_pad; uint32_t _pad[4]; } u; @@ -647,7 +713,13 @@ struct vkd3d_shader_parameter_immediate_constant1 */ struct vkd3d_shader_parameter_specialization_constant { - /** The ID of the specialization constant. */ + /** + * The ID of the specialization constant. + * If the type comprises more than one constant, such as + * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, then a contiguous + * array of specialization constants should be used, one for each component, + * and this ID should point to the first component. + */ uint32_t id; }; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b6a0450b..4d02184a 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -215,6 +215,14 @@ static void src_param_init_temp_float(struct vkd3d_shader_src_param *src, unsign src->reg.idx[0].offset = idx; } +static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsigned int idx) +{ + vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + src->reg.dimension = VSIR_DIMENSION_VEC4; + src->swizzle = VKD3D_SHADER_NO_SWIZZLE; + src->reg.idx[0].offset = idx; +} + static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx) { vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); @@ -5539,9 +5547,11 @@ static bool find_colour_signature_idx(const struct shader_signature *signature, static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *program, const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func, - const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, uint32_t colour_temp, size_t *ret_pos) + const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, + uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context) { struct vkd3d_shader_instruction_array *instructions = &program->instructions; + static const struct vkd3d_shader_location no_loc; size_t pos = ret - instructions->elements; struct vkd3d_shader_instruction *ins; @@ -5596,6 +5606,11 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VKD3D_DATA_UINT); break; + case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER, + "Alpha test reference data type must be a single component."); + return VKD3D_ERROR_INVALID_ARGUMENT; + default: FIXME("Unhandled parameter data type %#x.\n", ref->data_type); return VKD3D_ERROR_NOT_IMPLEMENTED; @@ -5682,7 +5697,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro if (ins->opcode == VKD3DSIH_RET) { if ((ret = insert_alpha_test_before_ret(program, ins, compare_func, - ref, colour_signature_idx, colour_temp, &new_pos)) < 0) + ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0) return ret; i = new_pos; continue; @@ -5709,6 +5724,202 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro return VKD3D_OK; } +static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *program, + const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx, + uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos) +{ + struct vkd3d_shader_instruction_array *instructions = &program->instructions; + size_t pos = ret - instructions->elements; + struct vkd3d_shader_instruction *ins; + unsigned int output_idx = 0; + + if (!shader_instruction_array_insert_at(&program->instructions, pos, vkd3d_popcount(mask) + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ins = &program->instructions.elements[pos]; + + for (unsigned int i = 0; i < 8; ++i) + { + if (!(mask & (1u << i))) + continue; + + vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_DP4, 1, 2); + src_param_init_temp_float4(&ins->src[0], position_temp); + src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VKD3D_DATA_FLOAT); + ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + + vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); + if (output_idx < 4) + ins->dst[0].reg.idx[0].offset = low_signature_idx; + else + ins->dst[0].reg.idx[0].offset = high_signature_idx; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = (1u << (output_idx % 4)); + ++output_idx; + + ++ins; + } + + vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1); + vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); + ins->dst[0].reg.idx[0].offset = position_signature_idx; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = program->output_signature.elements[position_signature_idx].mask; + src_param_init_temp_float(&ins->src[0], position_temp); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + + *ret_pos = pos + vkd3d_popcount(mask) + 1; + return VKD3D_OK; +} + +static bool find_position_signature_idx(const struct shader_signature *signature, uint32_t *idx) +{ + for (unsigned int i = 0; i < signature->element_count; ++i) + { + if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_POSITION) + { + *idx = i; + return true; + } + } + + return false; +} + +static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *program, + struct vsir_transformation_context *ctx) +{ + struct shader_signature *signature = &program->output_signature; + unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; + const struct vkd3d_shader_parameter1 *mask_parameter = NULL; + struct signature_element *new_elements, *clip_element; + uint32_t position_signature_idx, position_temp, mask; + static const struct vkd3d_shader_location no_loc; + struct vkd3d_shader_instruction *ins; + unsigned int plane_count; + size_t new_pos; + int ret; + + if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX) + return VKD3D_OK; + + for (unsigned int i = 0; i < program->parameter_count; ++i) + { + const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i]; + + if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK) + mask_parameter = parameter; + } + + if (!mask_parameter) + return VKD3D_OK; + + if (mask_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) + { + vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "Unsupported clip plane mask parameter type %#x.", mask_parameter->type); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + if (mask_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) + { + vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid clip plane mask parameter data type %#x.", mask_parameter->data_type); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + mask = mask_parameter->u.immediate_constant.u.u32; + + if (!mask) + return VKD3D_OK; + + for (unsigned int i = 0; i < signature->element_count; ++i) + { + if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE) + { + vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER, + "Clip planes cannot be used if the shader writes clip distance."); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + } + + if (!find_position_signature_idx(signature, &position_signature_idx)) + { + vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, + "Shader does not write position."); + return VKD3D_ERROR_INVALID_SHADER; + } + + /* Append the clip plane signature indices. */ + + plane_count = vkd3d_popcount(mask); + + if (!(new_elements = vkd3d_realloc(signature->elements, + (signature->element_count + 2) * sizeof(*signature->elements)))) + return VKD3D_ERROR_OUT_OF_MEMORY; + signature->elements = new_elements; + + low_signature_idx = signature->element_count; + clip_element = &signature->elements[signature->element_count++]; + memset(clip_element, 0, sizeof(*clip_element)); + clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; + clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; + clip_element->register_count = 1; + clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4)); + clip_element->used_mask = clip_element->mask; + clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; + + if (plane_count > 4) + { + high_signature_idx = signature->element_count; + clip_element = &signature->elements[signature->element_count++]; + memset(clip_element, 0, sizeof(*clip_element)); + clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; + clip_element->semantic_index = 1; + clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; + clip_element->register_count = 1; + clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4); + clip_element->used_mask = clip_element->mask; + clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; + } + + /* We're going to be reading from the output position, so we need to go + * through the whole shader and convert it to a temp. */ + + position_temp = program->temp_count++; + + for (size_t i = 0; i < program->instructions.count; ++i) + { + ins = &program->instructions.elements[i]; + + if (vsir_instruction_is_dcl(ins)) + continue; + + if (ins->opcode == VKD3DSIH_RET) + { + if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx, + position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0) + return ret; + i = new_pos; + continue; + } + + for (size_t j = 0; j < ins->dst_count; ++j) + { + struct vkd3d_shader_dst_param *dst = &ins->dst[j]; + + /* Note we run after I/O normalization. */ + if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == position_signature_idx) + { + dst->reg.type = VKD3DSPR_TEMP; + dst->reg.idx[0].offset = position_temp; + } + } + } + + return VKD3D_OK; +} + struct validation_context { struct vkd3d_shader_message_context *message_context; @@ -6842,6 +7053,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t } vsir_transform(&ctx, vsir_program_insert_alpha_test); + vsir_transform(&ctx, vsir_program_insert_clip_planes); if (TRACE_ON()) vkd3d_shader_trace(program); diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 248b7aad..37415597 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1228,6 +1228,13 @@ static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_build SpvOpConstantComposite, result_type, constituents, constituent_count); } +static uint32_t vkd3d_spirv_build_op_spec_constant_composite(struct vkd3d_spirv_builder *builder, + uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) +{ + return vkd3d_spirv_build_op_trv(builder, &builder->global_stream, + SpvOpSpecConstantComposite, result_type, constituents, constituent_count); +} + static uint32_t vkd3d_spirv_get_op_constant_composite(struct vkd3d_spirv_builder *builder, uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) { @@ -3324,8 +3331,10 @@ static const struct vkd3d_spec_constant_info *get_spec_constant_info(enum vkd3d_ return NULL; } -static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler) +static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler, unsigned int count) { + uint32_t ret; + if (!compiler->current_spec_constant_id) { unsigned int i, id = 0; @@ -3335,28 +3344,52 @@ static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *com const struct vkd3d_shader_parameter1 *current = &compiler->program->parameters[i]; if (current->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) - id = max(current->u.specialization_constant.id + 1, id); + { + switch (current->data_type) + { + case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: + id = max(current->u.specialization_constant.id + 4, id); + break; + + default: + id = max(current->u.specialization_constant.id + 1, id); + break; + } + } } compiler->current_spec_constant_id = id; } - return compiler->current_spec_constant_id++; + ret = compiler->current_spec_constant_id; + compiler->current_spec_constant_id += count; + return ret; } static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compiler, - enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type) + enum vkd3d_shader_parameter_name name, uint32_t spec_id, + enum vkd3d_data_type type, unsigned int component_count) { + uint32_t scalar_type_id, vector_type_id, id, default_value, components[4]; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_spec_constant_info *info; - uint32_t type_id, id, default_value; info = get_spec_constant_info(name); default_value = info ? info->default_value : 0; - type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); - id = vkd3d_spirv_build_op_spec_constant(builder, type_id, default_value); - vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationSpecId, spec_id); + scalar_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); + vector_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count); + + for (unsigned int i = 0; i < component_count; ++i) + { + components[i] = vkd3d_spirv_build_op_spec_constant(builder, scalar_type_id, default_value); + vkd3d_spirv_build_op_decorate1(builder, components[i], SpvDecorationSpecId, spec_id + i); + } + + if (component_count == 1) + id = components[0]; + else + id = vkd3d_spirv_build_op_spec_constant_composite(builder, vector_type_id, components, component_count); if (info) vkd3d_spirv_build_op_name(builder, id, "%s", info->debug_name); @@ -3373,7 +3406,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile } static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler, - enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type) + enum vkd3d_shader_parameter_name name, uint32_t spec_id, + enum vkd3d_data_type type, unsigned int component_count) { unsigned int i; @@ -3383,17 +3417,17 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler return compiler->spec_constants[i].id; } - return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type); + return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type, component_count); } static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compiler, - const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type) + const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type, unsigned int component_count) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int index = parameter - compiler->program->parameters; uint32_t type_id, ptr_id, ptr_type_id; - type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); + type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, compiler->spirv_parameter_info[index].buffer_id, @@ -3401,48 +3435,49 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi return vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); } +static const struct +{ + enum vkd3d_data_type type; + unsigned int component_count; +} +parameter_data_type_map[] = +{ + [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT, 1}, + [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT, 1}, + [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VKD3D_DATA_FLOAT, 4}, +}; + static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *compiler, - enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type) + enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type, unsigned int component_count) { const struct vkd3d_shader_parameter1 *parameter; - static const struct - { - enum vkd3d_data_type type; - } - type_map[] = - { - [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT}, - [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT}, - }; - if (!(parameter = vsir_program_get_parameter(compiler->program, name))) { WARN("Unresolved shader parameter %#x.\n", name); goto default_parameter; } - if (type_map[parameter->data_type].type != type) - ERR("Expected data type %#x for parameter %#x, got %#x.\n", type, name, parameter->data_type); + if (parameter_data_type_map[parameter->data_type].type != type + || parameter_data_type_map[parameter->data_type].component_count != component_count) + ERR("Expected type %#x, count %u for parameter %#x, got %#x.\n", + type, component_count, name, parameter->data_type); if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) - { - if (parameter->data_type == VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) - return spirv_compiler_get_constant_float(compiler, parameter->u.immediate_constant.u.f32); - else - return spirv_compiler_get_constant_uint(compiler, parameter->u.immediate_constant.u.u32); - } + return spirv_compiler_get_constant(compiler, vkd3d_component_type_from_data_type(type), + component_count, (const uint32_t *)¶meter->u.immediate_constant); if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) - return spirv_compiler_get_spec_constant(compiler, name, parameter->u.specialization_constant.id, type); + return spirv_compiler_get_spec_constant(compiler, name, + parameter->u.specialization_constant.id, type, component_count); if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_BUFFER) - return spirv_compiler_get_buffer_parameter(compiler, parameter, type); + return spirv_compiler_get_buffer_parameter(compiler, parameter, type, component_count); FIXME("Unhandled parameter type %#x.\n", parameter->type); default_parameter: return spirv_compiler_get_spec_constant(compiler, - name, spirv_compiler_alloc_spec_constant_id(compiler), type); + name, spirv_compiler_alloc_spec_constant_id(compiler, component_count), type, component_count); } static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *compiler, @@ -4218,7 +4253,8 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, else if (reg->type == VKD3DSPR_UNDEF) return spirv_compiler_emit_load_undef(compiler, reg, write_mask); else if (reg->type == VKD3DSPR_PARAMETER) - return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, reg->data_type); + return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, + reg->data_type, reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1); component_count = vsir_write_mask_component_count(write_mask); component_type = vkd3d_component_type_from_data_type(reg->data_type); @@ -9563,7 +9599,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co if (src->reg.type == VKD3DSPR_RASTERIZER) { val_id = spirv_compiler_emit_shader_parameter(compiler, - VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT); + VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT, 1); } else { @@ -10611,7 +10647,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct { uint32_t type_id, struct_id, ptr_type_id, var_id; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); + type_id = vkd3d_spirv_get_type_id(builder, + vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type), + parameter_data_type_map[parameter->data_type].component_count); struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1); vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index cec0f356..8c53be49 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -241,6 +241,8 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION = 9018, VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019, + VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER = 9020, + VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC = 9021, VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300,