From f27fc961454a26d013f598ea3d476ed50faee523 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 13 Mar 2024 15:58:53 +1100 Subject: [PATCH] Updated vkd3d to 9b0d304f8fe4e6f0d065e4561af9e372e1643c2d. --- libs/vkd3d/include/vkd3d_shader.h | 28 +- libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 22 +- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 16 +- libs/vkd3d/libs/vkd3d-shader/dxbc.c | 39 +-- libs/vkd3d/libs/vkd3d-shader/dxil.c | 145 +++++++++-- libs/vkd3d/libs/vkd3d-shader/fx.c | 128 +++++++--- libs/vkd3d/libs/vkd3d-shader/glsl.c | 49 ++-- libs/vkd3d/libs/vkd3d-shader/hlsl.c | 4 + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 24 +- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 8 +- libs/vkd3d/libs/vkd3d-shader/ir.c | 239 ++++++++++++++++-- libs/vkd3d/libs/vkd3d-shader/spirv.c | 166 ++++++++++-- libs/vkd3d/libs/vkd3d-shader/tpf.c | 45 ++-- .../libs/vkd3d-shader/vkd3d_shader_main.c | 22 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 35 ++- libs/vkd3d/libs/vkd3d/device.c | 29 ++- libs/vkd3d/libs/vkd3d/vkd3d_private.h | 3 +- 19 files changed, 781 insertions(+), 224 deletions(-) diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h index 1a62f093d6b..83b90474af4 100644 --- a/libs/vkd3d/include/vkd3d_shader.h +++ b/libs/vkd3d/include/vkd3d_shader.h @@ -218,6 +218,20 @@ enum vkd3d_shader_compile_option_feature_flags VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS), }; +/** + * Flags for vkd3d_shader_parse_dxbc(). + * + * \since 1.12 + */ +enum vkd3d_shader_parse_dxbc_flags +{ + /** Ignore the checksum and continue parsing even if it is + * incorrect. */ + VKD3D_SHADER_PARSE_DXBC_IGNORE_CHECKSUM = 0x00000001, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARSE_DXBC_FLAGS), +}; + enum vkd3d_shader_compile_option_name { /** @@ -285,6 +299,15 @@ enum vkd3d_shader_compile_option_name * \since 1.11 */ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, + /** + * If \a value is non-zero compilation will produce a child effect using + * shared object descriptions, as instructed by the "shared" modifier. + * Child effects are supported with fx_2_0, fx_4_0, and fx_4_1. This option + * and "shared" modifiers are ignored for fx_5_0 profile, and non-fx profiles. + * + * \since 1.12 + */ + VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT = 0x0000000b, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), }; @@ -2385,9 +2408,8 @@ VKD3D_SHADER_API void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc * * \param dxbc A vkd3d_shader_code structure containing the DXBC blob to parse. * - * \param flags A set of flags modifying the behaviour of the function. No - * flags are defined for this version of vkd3d-shader, and this parameter - * should be set to 0. + * \param flags A combination of zero or more elements of enum + * vkd3d_shader_parse_dxbc_flags. * * \param desc A vkd3d_shader_dxbc_desc structure describing the contents of * the DXBC blob. Its vkd3d_shader_dxbc_section_desc structures will contain diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index b8dcfd011b6..fcbb321edd1 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -649,6 +649,8 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum [VKD3D_DATA_UINT8 ] = "uint8", [VKD3D_DATA_UINT64 ] = "uint64", [VKD3D_DATA_BOOL ] = "bool", + [VKD3D_DATA_UINT16 ] = "uint16", + [VKD3D_DATA_HALF ] = "half", }; const char *name; @@ -2196,22 +2198,22 @@ static enum vkd3d_result dump_signature(struct vkd3d_d3d_asm_compiler *compiler, } static enum vkd3d_result dump_signatures(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_desc *shader_desc, enum vkd3d_shader_type shader_type) + const struct vsir_program *program) { enum vkd3d_result ret; if ((ret = dump_signature(compiler, ".input", - shader_type == VKD3D_SHADER_TYPE_DOMAIN ? "vicp" : "v", - &shader_desc->input_signature)) < 0) + program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vicp" : "v", + &program->input_signature)) < 0) return ret; if ((ret = dump_signature(compiler, ".output", "o", - &shader_desc->output_signature)) < 0) + &program->output_signature)) < 0) return ret; if ((ret = dump_signature(compiler, ".patch_constant", - shader_type == VKD3D_SHADER_TYPE_DOMAIN ? "vpc" : "o", - &shader_desc->patch_constant_signature)) < 0) + program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vpc" : "o", + &program->patch_constant_signature)) < 0) return ret; vkd3d_string_buffer_printf(&compiler->buffer, "%s.text%s\n", @@ -2220,8 +2222,8 @@ static enum vkd3d_result dump_signatures(struct vkd3d_d3d_asm_compiler *compiler return VKD3D_OK; } -enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, - const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, +enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, enum vsir_asm_flags flags) { const struct vkd3d_shader_version *shader_version = &program->shader_version; @@ -2297,7 +2299,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, * doesn't even have an explicit concept of signature. */ if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_IO_SIGNATURES && shader_version->major >= 4) { - if ((result = dump_signatures(&compiler, shader_desc, shader_version->type)) < 0) + if ((result = dump_signatures(&compiler, program)) < 0) { vkd3d_string_buffer_cleanup(buffer); return result; @@ -2355,7 +2357,7 @@ void vkd3d_shader_trace(const struct vsir_program *program) const char *p, *q, *end; struct vkd3d_shader_code code; - if (vkd3d_dxbc_binary_to_text(program, NULL, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) + if (d3d_asm_compile(program, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) return; end = (const char *)code.code + code.size; diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index a8cca17faa3..57dd0258aef 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -541,9 +541,9 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp struct signature_element *element; if (output) - signature = &sm1->p.shader_desc.output_signature; + signature = &sm1->p.program.output_signature; else - signature = &sm1->p.shader_desc.input_signature; + signature = &sm1->p.program.input_signature; if ((element = find_signature_element(signature, name, index))) { @@ -581,9 +581,9 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output, struct signature_element *element; if (output) - signature = &sm1->p.shader_desc.output_signature; + signature = &sm1->p.program.output_signature; else - signature = &sm1->p.shader_desc.input_signature; + signature = &sm1->p.program.input_signature; if (!(element = find_signature_element_by_register_index(signature, register_index))) { @@ -886,7 +886,6 @@ static void shader_sm1_destroy(struct vkd3d_shader_parser *parser) struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser); vsir_program_cleanup(&parser->program); - free_shader_desc(&sm1->p.shader_desc); vkd3d_free(sm1); } @@ -1237,7 +1236,6 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, const struct vkd3d_shader_location location = {.source_name = compile_info->source_name}; const uint32_t *code = compile_info->source.code; size_t code_size = compile_info->source.size; - struct vkd3d_shader_desc *shader_desc; struct vkd3d_shader_version version; uint16_t shader_type; size_t token_count; @@ -1290,9 +1288,6 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, if (!vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops, code_size != ~(size_t)0 ? token_count / 4u + 4 : 16)) return VKD3D_ERROR_OUT_OF_MEMORY; - shader_desc = &sm1->p.shader_desc; - shader_desc->byte_code = code; - shader_desc->byte_code_size = code_size; sm1->ptr = sm1->start; return VKD3D_OK; @@ -2067,6 +2062,9 @@ static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b D3DDECLUSAGE usage; bool ret; + if ((!output && !var->last_read) || (output && !var->first_write)) + return; + if (hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, ®.type, ®.reg)) { usage = 0; diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c index 37ebc73c099..8a1012d909b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c @@ -150,7 +150,7 @@ static const char *shader_get_string(const char *data, size_t data_size, size_t } static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context, - const char *source_name, struct vkd3d_shader_dxbc_desc *desc) + const char *source_name, uint32_t flags, struct vkd3d_shader_dxbc_desc *desc) { const struct vkd3d_shader_location location = {.source_name = source_name}; struct vkd3d_shader_dxbc_section_desc *sections, *section; @@ -186,17 +186,20 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_ checksum[1] = read_u32(&ptr); checksum[2] = read_u32(&ptr); checksum[3] = read_u32(&ptr); - vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum); - if (memcmp(checksum, calculated_checksum, sizeof(checksum))) - { - WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match " - "calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n", - checksum[0], checksum[1], checksum[2], checksum[3], - calculated_checksum[0], calculated_checksum[1], - calculated_checksum[2], calculated_checksum[3]); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM, - "Invalid DXBC checksum."); - return VKD3D_ERROR_INVALID_ARGUMENT; + if (!(flags & VKD3D_SHADER_PARSE_DXBC_IGNORE_CHECKSUM)) + { + vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum); + if (memcmp(checksum, calculated_checksum, sizeof(checksum))) + { + WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match " + "calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n", + checksum[0], checksum[1], checksum[2], checksum[3], + calculated_checksum[0], calculated_checksum[1], + calculated_checksum[2], calculated_checksum[3]); + vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM, + "Invalid DXBC checksum."); + return VKD3D_ERROR_INVALID_ARGUMENT; + } } version = read_u32(&ptr); @@ -287,7 +290,7 @@ static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc, unsigned int i; int ret; - if ((ret = parse_dxbc(dxbc, message_context, source_name, &desc)) < 0) + if ((ret = parse_dxbc(dxbc, message_context, source_name, 0, &desc)) < 0) return ret; for (i = 0; i < desc.section_count; ++i) @@ -313,7 +316,7 @@ int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc, *messages = NULL; vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO); - ret = parse_dxbc(dxbc, &message_context, NULL, desc); + ret = parse_dxbc(dxbc, &message_context, NULL, flags, desc); vkd3d_shader_message_context_trace_messages(&message_context); if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0) @@ -485,7 +488,7 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section, struct vkd3d_shader_message_context *message_context, void *context) { - struct vkd3d_shader_desc *desc = context; + struct dxbc_shader_desc *desc = context; int ret; switch (section->tag) @@ -550,7 +553,7 @@ static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section, return VKD3D_OK; } -void free_shader_desc(struct vkd3d_shader_desc *desc) +void free_dxbc_shader_desc(struct dxbc_shader_desc *desc) { shader_signature_cleanup(&desc->input_signature); shader_signature_cleanup(&desc->output_signature); @@ -558,7 +561,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc) } int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, - struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc) + struct vkd3d_shader_message_context *message_context, const char *source_name, struct dxbc_shader_desc *desc) { int ret; @@ -569,7 +572,7 @@ int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, if (ret < 0) { WARN("Failed to parse shader, vkd3d result %d.\n", ret); - free_shader_desc(desc); + free_dxbc_shader_desc(desc); } return ret; diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index a202d208f9d..de51588b513 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -389,6 +389,8 @@ enum dx_intrinsic_opcode DX_BUFFER_LOAD = 68, DX_BUFFER_STORE = 69, DX_GET_DIMENSIONS = 72, + DX_TEXTURE_GATHER = 73, + DX_TEXTURE_GATHER_CMP = 74, DX_ATOMIC_BINOP = 78, DX_ATOMIC_CMP_XCHG = 79, DX_DERIV_COARSEX = 83, @@ -2110,6 +2112,15 @@ static inline bool sm6_value_is_undef(const struct sm6_value *value) return sm6_value_is_register(value) && value->u.reg.type == VKD3DSPR_UNDEF; } +static bool sm6_value_vector_is_constant_or_undef(const struct sm6_value **values, unsigned int count) +{ + unsigned int i; + for (i = 0; i < count; ++i) + if (!sm6_value_is_constant(values[i]) && !sm6_value_is_undef(values[i])) + return false; + return true; +} + static bool sm6_value_is_icb(const struct sm6_value *value) { return value->value_type == VALUE_TYPE_ICB; @@ -2199,6 +2210,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type return VKD3D_DATA_BOOL; case 8: return VKD3D_DATA_UINT8; + case 16: + return VKD3D_DATA_UINT16; case 32: return VKD3D_DATA_UINT; case 64: @@ -2212,6 +2225,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type { switch (type->u.width) { + case 16: + return VKD3D_DATA_HALF; case 32: return VKD3D_DATA_FLOAT; case 64: @@ -2876,7 +2891,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const } if (type->u.width == 16) - FIXME("Half float type is not supported yet.\n"); + dst->u.reg.u.immconst_u32[0] = record->operands[0]; else if (type->u.width == 32) dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]); else if (type->u.width == 64) @@ -4182,7 +4197,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - signature = &sm6->p.shader_desc.input_signature; + signature = &sm6->p.program.input_signature; if (row_index >= signature->element_count) { WARN("Invalid row index %u.\n", row_index); @@ -4572,7 +4587,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr row_index = sm6_value_get_constant_uint(operands[0]); column_index = sm6_value_get_constant_uint(operands[2]); - signature = &sm6->p.shader_desc.output_signature; + signature = &sm6->p.program.output_signature; if (row_index >= signature->element_count) { WARN("Invalid row index %u.\n", row_index); @@ -4612,6 +4627,68 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr src_param_init_from_value(src_param, value); } +static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_register coord, offset; + const struct sm6_value *resource, *sampler; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_instruction *ins; + unsigned int swizzle; + bool extended_offset; + + resource = operands[0]; + sampler = operands[1]; + if (!sm6_value_validate_is_texture_handle(resource, op, sm6) + || !sm6_value_validate_is_sampler_handle(sampler, op, sm6)) + { + return; + } + + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], VKD3D_VEC4_SIZE, NULL, state, &coord)) + return; + + if ((extended_offset = !sm6_value_vector_is_constant_or_undef(&operands[6], 2)) + && !sm6_parser_emit_coordinate_construct(sm6, &operands[6], 2, NULL, state, &offset)) + { + return; + } + + ins = state->ins; + if (op == DX_TEXTURE_GATHER) + { + instruction_init_with_resource(ins, extended_offset ? VKD3DSIH_GATHER4_PO : VKD3DSIH_GATHER4, resource, sm6); + if (!(src_params = instruction_src_params_alloc(ins, 3 + extended_offset, sm6))) + return; + } + else + { + instruction_init_with_resource(ins, extended_offset ? VKD3DSIH_GATHER4_PO_C : VKD3DSIH_GATHER4_C, resource, sm6); + if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6))) + return; + src_param_init_from_value(&src_params[3 + extended_offset], operands[9]); + } + + src_param_init_vector_from_reg(&src_params[0], &coord); + if (extended_offset) + src_param_init_vector_from_reg(&src_params[1], &offset); + else + instruction_set_texel_offset(ins, &operands[6], sm6); + src_param_init_vector_from_reg(&src_params[1 + extended_offset], &resource->u.handle.reg); + src_param_init_vector_from_reg(&src_params[2 + extended_offset], &sampler->u.handle.reg); + /* Swizzle stored in the sampler parameter is the scalar component index to be gathered. */ + swizzle = sm6_value_get_constant_uint(operands[8]); + if (swizzle >= VKD3D_VEC4_SIZE) + { + WARN("Invalid swizzle %#x.\n", swizzle); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Swizzle %#x for a texture gather operation is invalid.", swizzle); + } + src_params[2 + extended_offset].swizzle = swizzle; + + instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); +} + static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4791,6 +4868,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_TEXTURE_GATHER ] = {"o", "HHffffiic", sm6_parser_emit_dx_texture_gather}, + [DX_TEXTURE_GATHER_CMP ] = {"o", "HHffffiicf", sm6_parser_emit_dx_texture_gather}, [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, [DX_TEXTURE_STORE ] = {"v", "Hiiiooooc", sm6_parser_emit_dx_texture_store}, [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, @@ -5055,7 +5134,10 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ break; case CAST_ZEXT: case CAST_SEXT: - /* nop or min precision. TODO: native 16-bit */ + /* nop or min precision. TODO: native 16-bit. + * Extension instructions could be emitted for min precision, but in Windows + * the AMD RX 580 simply drops such instructions, which makes sense as no + * assumptions should be made about any behaviour which depends on bit width. */ if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16)) { op = VKD3DSIH_NOP; @@ -7752,19 +7834,19 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons } if (m->u.node->operand_count && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[0], - &sm6->p.shader_desc.input_signature)) < 0) + &sm6->p.program.input_signature)) < 0) { return ret; } if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[1], - &sm6->p.shader_desc.output_signature)) < 0) + &sm6->p.program.output_signature)) < 0) { return ret; } /* TODO: patch constant signature in operand 2. */ - sm6_parser_init_input_signature(sm6, &sm6->p.shader_desc.input_signature); - sm6_parser_init_output_signature(sm6, &sm6->p.shader_desc.output_signature); + sm6_parser_init_input_signature(sm6, &sm6->p.program.input_signature); + sm6_parser_init_output_signature(sm6, &sm6->p.program.output_signature); return VKD3D_OK; } @@ -8062,7 +8144,6 @@ static void sm6_parser_destroy(struct vkd3d_shader_parser *parser) sm6_parser_metadata_cleanup(sm6); vkd3d_free(sm6->descriptors); vkd3d_free(sm6->values); - free_shader_desc(&parser->shader_desc); vkd3d_free(sm6); } @@ -8080,15 +8161,16 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6 return NULL; } -static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t *byte_code, size_t byte_code_size, - const char *source_name, struct vkd3d_shader_message_context *message_context) +static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *source_name, + struct vkd3d_shader_message_context *message_context, struct dxbc_shader_desc *dxbc_desc) { - const struct shader_signature *output_signature = &sm6->p.shader_desc.output_signature; - const struct shader_signature *input_signature = &sm6->p.shader_desc.input_signature; + const struct shader_signature *output_signature = &sm6->p.program.output_signature; + const struct shader_signature *input_signature = &sm6->p.program.input_signature; + size_t count, length, function_count, byte_code_size = dxbc_desc->byte_code_size; const struct vkd3d_shader_location location = {.source_name = source_name}; uint32_t version_token, dxil_version, token_count, magic; + const uint32_t *byte_code = dxbc_desc->byte_code; unsigned int chunk_offset, chunk_size; - size_t count, length, function_count; enum bitcode_block_abbreviation abbr; struct vkd3d_shader_version version; struct dxil_block *block; @@ -8181,6 +8263,11 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t sm6->ptr = &sm6->start[1]; sm6->bitpos = 2; + sm6->p.program.input_signature = dxbc_desc->input_signature; + sm6->p.program.output_signature = dxbc_desc->output_signature; + sm6->p.program.patch_constant_signature = dxbc_desc->patch_constant_signature; + memset(dxbc_desc, 0, sizeof(*dxbc_desc)); + block = &sm6->root_block; if ((ret = dxil_block_init(block, NULL, sm6)) < 0) { @@ -8351,7 +8438,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser) { - struct vkd3d_shader_desc *shader_desc; + struct dxbc_shader_desc dxbc_desc = {0}; uint32_t *byte_code = NULL; struct sm6_parser *sm6; int ret; @@ -8364,31 +8451,33 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi return VKD3D_ERROR_OUT_OF_MEMORY; } - shader_desc = &sm6->p.shader_desc; - shader_desc->is_dxil = true; + dxbc_desc.is_dxil = true; if ((ret = shader_extract_from_dxbc(&compile_info->source, message_context, compile_info->source_name, - shader_desc)) < 0) + &dxbc_desc)) < 0) { WARN("Failed to extract shader, vkd3d result %d.\n", ret); vkd3d_free(sm6); return ret; } - sm6->p.shader_desc = *shader_desc; - shader_desc = &sm6->p.shader_desc; - - if (((uintptr_t)shader_desc->byte_code & (VKD3D_DXBC_CHUNK_ALIGNMENT - 1))) + if (((uintptr_t)dxbc_desc.byte_code & (VKD3D_DXBC_CHUNK_ALIGNMENT - 1))) { /* LLVM bitcode should be 32-bit aligned, but before dxc v1.7.2207 this was not always the case in the DXBC * container due to missing padding after signature names. Get an aligned copy to prevent unaligned access. */ - if (!(byte_code = vkd3d_malloc(align(shader_desc->byte_code_size, VKD3D_DXBC_CHUNK_ALIGNMENT)))) - ERR("Failed to allocate aligned chunk. Unaligned access will occur.\n"); - else - memcpy(byte_code, shader_desc->byte_code, shader_desc->byte_code_size); + if (!(byte_code = vkd3d_malloc(align(dxbc_desc.byte_code_size, VKD3D_DXBC_CHUNK_ALIGNMENT)))) + { + ERR("Failed to allocate aligned chunk.\n"); + free_dxbc_shader_desc(&dxbc_desc); + vkd3d_free(sm6); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + memcpy(byte_code, dxbc_desc.byte_code, dxbc_desc.byte_code_size); + dxbc_desc.byte_code = byte_code; } - ret = sm6_parser_init(sm6, byte_code ? byte_code : shader_desc->byte_code, shader_desc->byte_code_size, - compile_info->source_name, message_context); + ret = sm6_parser_init(sm6, compile_info->source_name, message_context, &dxbc_desc); + free_dxbc_shader_desc(&dxbc_desc); vkd3d_free(byte_code); if (!sm6->p.failed && ret >= 0) diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index fd5c8443221..fdf132e9ed4 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -64,6 +64,7 @@ struct fx_write_context_ops uint32_t (*write_type)(const struct hlsl_type *type, struct fx_write_context *fx); void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); + bool are_child_effects_supported; }; struct fx_write_context @@ -84,8 +85,12 @@ struct fx_write_context uint32_t buffer_count; uint32_t numeric_variable_count; uint32_t object_variable_count; + uint32_t shared_object_count; + uint32_t shader_variable_count; int status; + bool child_effect; + const struct fx_write_context_ops *ops; }; @@ -174,6 +179,8 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co rb_init(&fx->strings, string_storage_compare); list_init(&fx->types); + + fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect; } static int fx_write_context_cleanup(struct fx_write_context *fx) @@ -320,19 +327,14 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, return value; } -static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) +static const char * get_fx_4_type_name(const struct hlsl_type *type) { - struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; - uint32_t name_offset, offset, size, stride, numeric_desc; - uint32_t elements_count = 0; - const char *name; - static const uint32_t variable_type[] = + static const char * const object_type_names[] = { - [HLSL_CLASS_SCALAR] = 1, - [HLSL_CLASS_VECTOR] = 1, - [HLSL_CLASS_MATRIX] = 1, - [HLSL_CLASS_OBJECT] = 2, - [HLSL_CLASS_STRUCT] = 3, + [HLSL_TYPE_PIXELSHADER] = "PixelShader", + [HLSL_TYPE_VERTEXSHADER] = "VertexShader", + [HLSL_TYPE_RENDERTARGETVIEW] = "RenderTargetView", + [HLSL_TYPE_DEPTHSTENCILVIEW] = "DepthStencilView", }; static const char * const texture_type_names[] = { @@ -357,6 +359,39 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co [HLSL_SAMPLER_DIM_BUFFER] = "RWBuffer", [HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = "RWStructuredBuffer", }; + + if (type->base_type == HLSL_TYPE_TEXTURE) + return texture_type_names[type->sampler_dim]; + + if (type->base_type == HLSL_TYPE_UAV) + return uav_type_names[type->sampler_dim]; + + switch (type->base_type) + { + case HLSL_TYPE_PIXELSHADER: + case HLSL_TYPE_VERTEXSHADER: + case HLSL_TYPE_RENDERTARGETVIEW: + case HLSL_TYPE_DEPTHSTENCILVIEW: + return object_type_names[type->base_type]; + default: + return type->name; + } +} + +static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + uint32_t name_offset, offset, size, stride, numeric_desc; + uint32_t elements_count = 0; + const char *name; + static const uint32_t variable_type[] = + { + [HLSL_CLASS_SCALAR] = 1, + [HLSL_CLASS_VECTOR] = 1, + [HLSL_CLASS_MATRIX] = 1, + [HLSL_CLASS_OBJECT] = 2, + [HLSL_CLASS_STRUCT] = 3, + }; struct hlsl_ctx *ctx = fx->ctx; /* Resolve arrays to element type and number of elements. */ @@ -366,12 +401,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co type = hlsl_get_multiarray_element_type(type); } - if (type->base_type == HLSL_TYPE_TEXTURE) - name = texture_type_names[type->sampler_dim]; - else if (type->base_type == HLSL_TYPE_UAV) - name = uav_type_names[type->sampler_dim]; - else - name = type->name; + name = get_fx_4_type_name(type); name_offset = write_string(name, fx); offset = put_u32_unaligned(buffer, name_offset); @@ -424,6 +454,8 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co { static const uint32_t object_type[] = { + [HLSL_TYPE_PIXELSHADER] = 5, + [HLSL_TYPE_VERTEXSHADER] = 6, [HLSL_TYPE_RENDERTARGETVIEW] = 19, [HLSL_TYPE_DEPTHSTENCILVIEW] = 20, }; @@ -454,7 +486,9 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co switch (type->base_type) { case HLSL_TYPE_DEPTHSTENCILVIEW: + case HLSL_TYPE_PIXELSHADER: case HLSL_TYPE_RENDERTARGETVIEW: + case HLSL_TYPE_VERTEXSHADER: put_u32_unaligned(buffer, object_type[type->base_type]); break; case HLSL_TYPE_TEXTURE: @@ -661,6 +695,7 @@ static const struct fx_write_context_ops fx_4_ops = .write_type = write_fx_4_type, .write_technique = write_fx_4_technique, .write_pass = write_fx_4_pass, + .are_child_effects_supported = true, }; static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) @@ -695,9 +730,12 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) { + const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); + uint32_t elements_count = hlsl_get_multiarray_size(var->data_type); struct vkd3d_bytecode_buffer *buffer = &fx->structured; uint32_t semantic_offset, bind_point = ~0u; - uint32_t name_offset, type_offset; + uint32_t name_offset, type_offset, i; + struct hlsl_ctx *ctx = fx->ctx; if (var->reg_reservation.reg_type) bind_point = var->reg_reservation.reg_index; @@ -712,8 +750,35 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ put_u32(buffer, bind_point); /* Explicit bind point */ + if (fx->child_effect && var->storage_modifiers & HLSL_STORAGE_SHARED) + { + ++fx->shared_object_count; + return; + } + + /* Initializer */ + switch (type->base_type) + { + case HLSL_TYPE_TEXTURE: + case HLSL_TYPE_UAV: + case HLSL_TYPE_RENDERTARGETVIEW: + break; + case HLSL_TYPE_PIXELSHADER: + case HLSL_TYPE_VERTEXSHADER: + /* FIXME: write shader blobs, once parser support works. */ + for (i = 0; i < elements_count; ++i) + put_u32(buffer, 0); + ++fx->shader_variable_count; + break; + default: + hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.\n", + type->base_type); + } + put_u32(buffer, 0); /* Annotations count */ /* FIXME: write annotations */ + + ++fx->object_variable_count; } static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx) @@ -734,7 +799,8 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx bind_point = b->reservation.reg_index; if (b->type == HLSL_BUFFER_TEXTURE) flags |= IS_TBUFFER; - /* FIXME: set 'single' flag for fx_5_0 */ + if (ctx->profile->major_version == 5 && b->modifiers & HLSL_MODIFIER_SINGLE) + flags |= IS_SINGLE; name_offset = write_string(b->name, fx); @@ -806,21 +872,23 @@ static bool is_object_variable(const struct hlsl_ir_var *var) } } -static void write_objects(struct fx_write_context *fx) +static void write_objects(struct fx_write_context *fx, bool shared) { struct hlsl_ir_var *var; - uint32_t count = 0; + + if (shared && !fx->child_effect) + return; LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) { if (!is_object_variable(var)) continue; + if (fx->child_effect && (shared != !!(var->storage_modifiers & HLSL_STORAGE_SHARED))) + continue; + write_fx_4_object_variable(var, fx); - ++count; } - - fx->object_variable_count += count; } static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) @@ -834,9 +902,9 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ write_buffers(&fx); - write_objects(&fx); + write_objects(&fx, false); /* TODO: shared buffers */ - /* TODO: shared objects */ + write_objects(&fx, true); write_techniques(ctx->globals, &fx); @@ -846,7 +914,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, fx.object_variable_count); /* Object variable count. */ put_u32(&buffer, 0); /* Pool buffer count. */ put_u32(&buffer, 0); /* Pool variable count. */ - put_u32(&buffer, 0); /* Pool object count. */ + put_u32(&buffer, fx.shared_object_count); /* Shared object count. */ put_u32(&buffer, fx.technique_count); size_offset = put_u32(&buffer, 0); /* Unstructured size. */ put_u32(&buffer, 0); /* String count. */ @@ -857,7 +925,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, 0); /* Sampler state count. */ put_u32(&buffer, 0); /* Rendertarget view count. */ put_u32(&buffer, 0); /* Depth stencil view count. */ - put_u32(&buffer, 0); /* Shader count. */ + put_u32(&buffer, fx.shader_variable_count); /* Shader count. */ put_u32(&buffer, 0); /* Inline shader count. */ set_u32(&buffer, size_offset, fx.unstructured.size); @@ -893,7 +961,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ write_buffers(&fx); - write_objects(&fx); + write_objects(&fx, false); /* TODO: interface variables */ write_groups(&fx); @@ -915,7 +983,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, 0); /* Sampler state count. */ put_u32(&buffer, 0); /* Rendertarget view count. */ put_u32(&buffer, 0); /* Depth stencil view count. */ - put_u32(&buffer, 0); /* Shader count. */ + put_u32(&buffer, fx.shader_variable_count); /* Shader count. */ put_u32(&buffer, 0); /* Inline shader count. */ put_u32(&buffer, fx.group_count); /* Group count. */ put_u32(&buffer, 0); /* UAV count. */ diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index c234caf8275..7c630d181ef 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -27,22 +27,6 @@ struct vkd3d_glsl_generator bool failed; }; -struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version, - struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location) -{ - struct vkd3d_glsl_generator *generator; - - if (!(generator = vkd3d_malloc(sizeof(*generator)))) - return NULL; - - memset(generator, 0, sizeof(*generator)); - generator->version = *version; - vkd3d_string_buffer_init(&generator->buffer); - generator->location = *location; - generator->message_context = message_context; - return generator; -} - static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( struct vkd3d_glsl_generator *generator, enum vkd3d_shader_error error, const char *fmt, ...) @@ -73,6 +57,8 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator, const struct vkd3d_shader_instruction *instruction) { + generator->location = instruction->location; + switch (instruction->handler_idx) { case VKD3DSIH_DCL_INPUT: @@ -90,7 +76,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator } } -int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, +static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, struct vsir_program *program, struct vkd3d_shader_code *out) { unsigned int i; @@ -101,10 +87,8 @@ int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n"); vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n"); - generator->location.column = 0; for (i = 0; i < program->instructions.count; ++i) { - generator->location.line = i + 1; vkd3d_glsl_handle_instruction(generator, &program->instructions.elements[i]); } @@ -124,8 +108,29 @@ int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, return VKD3D_OK; } -void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator) +static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen) +{ + vkd3d_string_buffer_cleanup(&gen->buffer); +} + +static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_version *version, struct vkd3d_shader_message_context *message_context) { - vkd3d_string_buffer_cleanup(&generator->buffer); - vkd3d_free(generator); + memset(gen, 0, sizeof(*gen)); + gen->version = *version; + vkd3d_string_buffer_init(&gen->buffer); + gen->message_context = message_context; +} + +int glsl_compile(struct vsir_program *program, struct vkd3d_shader_code *out, + struct vkd3d_shader_message_context *message_context) +{ + struct vkd3d_glsl_generator generator; + int ret; + + vkd3d_glsl_generator_init(&generator, &program->shader_version, message_context); + ret = vkd3d_glsl_generator_generate(&generator, program, out); + vkd3d_glsl_generator_cleanup(&generator); + + return ret; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index c315000a6e9..2820b9abf67 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -3597,6 +3597,10 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil { ctx->semantic_compat_mapping = option->value & VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES; } + else if (option->name == VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT) + { + ctx->child_effect = !!option->value; + } } return true; diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 49858869e7d..681f2edce31 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -374,6 +374,7 @@ struct hlsl_attribute #define HLSL_STORAGE_CENTROID 0x00004000 #define HLSL_STORAGE_NOPERSPECTIVE 0x00008000 #define HLSL_STORAGE_LINEAR 0x00010000 +#define HLSL_MODIFIER_SINGLE 0x00020000 #define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \ HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \ @@ -922,6 +923,7 @@ struct hlsl_ctx uint32_t found_numthreads : 1; bool semantic_compat_mapping; + bool child_effect; }; struct hlsl_resource_load_params diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l index 8dcceb94c1c..600e2cf2c6a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l @@ -109,7 +109,6 @@ packoffset {return KW_PACKOFFSET; } pass {return KW_PASS; } PixelShader {return KW_PIXELSHADER; } pixelshader {return KW_PIXELSHADER; } -precise {return KW_PRECISE; } RasterizerOrderedBuffer {return KW_RASTERIZERORDEREDBUFFER; } RasterizerOrderedStructuredBuffer {return KW_RASTERIZERORDEREDSTRUCTUREDBUFFER; } RasterizerOrderedTexture1D {return KW_RASTERIZERORDEREDTEXTURE1D; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index b484a952497..ec8b3d22af2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -5363,7 +5363,6 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %token KW_PACKOFFSET %token KW_PASS %token KW_PIXELSHADER -%token KW_PRECISE %token KW_RASTERIZERORDEREDBUFFER %token KW_RASTERIZERORDEREDSTRUCTUREDBUFFER %token KW_RASTERIZERORDEREDTEXTURE1D @@ -6542,6 +6541,14 @@ type_no_void: { $$ = hlsl_get_type(ctx->cur_scope, "DepthStencilView", true, true); } + | KW_VERTEXSHADER + { + $$ = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true); + } + | KW_PIXELSHADER + { + $$ = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true); + } type: type_no_void @@ -6815,10 +6822,6 @@ var_modifiers: { $$ = add_modifiers(ctx, $2, HLSL_STORAGE_NOPERSPECTIVE, &@1); } - | KW_PRECISE var_modifiers - { - $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_PRECISE, &@1); - } | KW_SHARED var_modifiers { $$ = add_modifiers(ctx, $2, HLSL_STORAGE_SHARED, &@1); @@ -6867,7 +6870,16 @@ var_modifiers: { $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_INLINE, &@1); } - + | var_identifier var_modifiers + { + if (!strcmp($1, "precise")) + $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_PRECISE, &@1); + else if (!strcmp($1, "single")) + $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_SINGLE, &@1); + else + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER, + "Unknown modifier %s.", debugstr_a($1)); + } complex_initializer: initializer_expr diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 8434a921a62..9eb65dc0170 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -2948,7 +2948,7 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru } else if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX) { - struct hlsl_ir_node *neg, *slt, *sum, *mul, *cond2; + struct hlsl_ir_node *neg, *slt, *sum, *cond2, *slt_cast, *mul; /* Expression used here is "slt() * (first - second) + second". */ @@ -2980,7 +2980,11 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru return false; hlsl_block_add_instr(block, sum); - if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, slt, sum))) + if (!(slt_cast = hlsl_new_cast(ctx, slt, sum->data_type, &instr->loc))) + return false; + hlsl_block_add_instr(block, slt_cast); + + if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, slt_cast, sum))) return false; hlsl_block_add_instr(block, mul); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 3c862f33ef1..759c89957d6 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -32,6 +32,9 @@ void vsir_program_cleanup(struct vsir_program *program) vkd3d_free((void *)program->block_names[i]); vkd3d_free(program->block_names); shader_instruction_array_destroy(&program->instructions); + shader_signature_cleanup(&program->input_signature); + shader_signature_cleanup(&program->output_signature); + shader_signature_cleanup(&program->patch_constant_signature); } static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shader_register *reg) @@ -230,7 +233,7 @@ static const struct vkd3d_shader_varying_map *find_varying_map( static enum vkd3d_result remap_output_signature(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { - struct shader_signature *signature = &parser->shader_desc.output_signature; + struct shader_signature *signature = &parser->program.output_signature; const struct vkd3d_shader_varying_map_info *varying_map; unsigned int i; @@ -1394,9 +1397,9 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse normaliser.phase = VKD3DSIH_INVALID; normaliser.shader_type = program->shader_version.type; normaliser.major = program->shader_version.major; - normaliser.input_signature = &parser->shader_desc.input_signature; - normaliser.output_signature = &parser->shader_desc.output_signature; - normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature; + normaliser.input_signature = &program->input_signature; + normaliser.output_signature = &program->output_signature; + normaliser.patch_constant_signature = &program->patch_constant_signature; for (i = 0, has_control_point_phase = false; i < program->instructions.count; ++i) { @@ -1439,9 +1442,9 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse } } - if (!shader_signature_merge(&parser->shader_desc.input_signature, normaliser.input_range_map, false) - || !shader_signature_merge(&parser->shader_desc.output_signature, normaliser.output_range_map, false) - || !shader_signature_merge(&parser->shader_desc.patch_constant_signature, normaliser.pc_range_map, true)) + if (!shader_signature_merge(&program->input_signature, normaliser.input_range_map, false) + || !shader_signature_merge(&program->output_signature, normaliser.output_range_map, false) + || !shader_signature_merge(&program->patch_constant_signature, normaliser.pc_range_map, true)) { program->instructions = normaliser.instructions; return VKD3D_ERROR_OUT_OF_MEMORY; @@ -3065,7 +3068,7 @@ static void vsir_block_list_remove_index(struct vsir_block_list *list, size_t id struct vsir_block { - unsigned int label; + unsigned int label, order_pos; /* `begin' points to the instruction immediately following the * LABEL that introduces the block. `end' points to the terminator * instruction (either BRANCH or RET). They can coincide, meaning @@ -3140,6 +3143,37 @@ struct vsir_cfg size_t *loops_by_header; struct vsir_block_list order; + struct cfg_loop_interval + { + /* `begin' is the position of the first block of the loop in + * the topological sort; `end' is the position of the first + * block after the loop. In other words, `begin' is where a + * `continue' instruction would jump and `end' is where a + * `break' instruction would jump. */ + unsigned int begin, end; + /* Each loop interval can be natural or synthetic. Natural + * intervals are added to represent loops given by CFG back + * edges. Synthetic intervals do not correspond to loops in + * the input CFG, but are added to leverage their `break' + * instruction in order to execute forward edges. + * + * For a synthetic loop interval it's not really important + * which one is the `begin' block, since we don't need to + * execute `continue' for them. So we have some leeway for + * moving it provided that these conditions are met: 1. the + * interval must contain all `break' instructions that target + * it, which in practice means that `begin' can be moved + * backward and not forward; 2. intervals must remain properly + * nested (for each pair of intervals, either one contains the + * other or they are disjoint). + * + * Subject to these conditions, we try to reuse the same loop + * as much as possible (if many forward edges target the same + * block), but we still try to keep `begin' as forward as + * possible, to keep the loop scope as small as possible. */ + bool synthetic; + } *loop_intervals; + size_t loop_interval_count, loop_interval_capacity; }; static void vsir_cfg_cleanup(struct vsir_cfg *cfg) @@ -3157,11 +3191,30 @@ static void vsir_cfg_cleanup(struct vsir_cfg *cfg) vkd3d_free(cfg->blocks); vkd3d_free(cfg->loops); vkd3d_free(cfg->loops_by_header); + vkd3d_free(cfg->loop_intervals); if (TRACE_ON()) vkd3d_string_buffer_cleanup(&cfg->debug_buffer); } +static enum vkd3d_result vsir_cfg_add_loop_interval(struct vsir_cfg *cfg, unsigned int begin, + unsigned int end, bool synthetic) +{ + struct cfg_loop_interval *interval; + + if (!vkd3d_array_reserve((void **)&cfg->loop_intervals, &cfg->loop_interval_capacity, + cfg->loop_interval_count + 1, sizeof(*cfg->loop_intervals))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + interval = &cfg->loop_intervals[cfg->loop_interval_count++]; + + interval->begin = begin; + interval->end = end; + interval->synthetic = synthetic; + + return VKD3D_OK; +} + static bool vsir_block_dominates(struct vsir_block *b1, struct vsir_block *b2) { return bitmap_is_set(b1->dominates, b2->label - 1); @@ -3396,14 +3449,14 @@ static void vsir_cfg_compute_dominators(struct vsir_cfg *cfg) * block without passing through the header block) belong to the same * loop. * - * If the input CFG is reducible, each two loops are either disjoint - * or one is a strict subset of the other, provided that each block - * has at most one incoming back edge. If this condition does not - * hold, a synthetic block can be introduced as the only back edge - * block for the given header block, with all the previous back edge - * now being forward edges to the synthetic block. This is not - * currently implemented (but it is rarely found in practice - * anyway). */ + * If the input CFG is reducible its loops are properly nested (i.e., + * each two loops are either disjoint or one is contained in the + * other), provided that each block has at most one incoming back + * edge. If this condition does not hold, a synthetic block can be + * introduced as the only back edge block for the given header block, + * with all the previous back edge now being forward edges to the + * synthetic block. This is not currently implemented (but it is + * rarely found in practice anyway). */ static enum vkd3d_result vsir_cfg_scan_loop(struct vsir_block_list *loop, struct vsir_block *block, struct vsir_block *header) { @@ -3496,6 +3549,7 @@ struct vsir_cfg_node_sorter { struct vsir_block_list *loop; unsigned int seen_count; + unsigned int begin; } *stack; size_t stack_count, stack_capacity; struct vsir_block_list available_blocks; @@ -3522,6 +3576,7 @@ static enum vkd3d_result vsir_cfg_node_sorter_make_node_available(struct vsir_cf item = &sorter->stack[sorter->stack_count++]; item->loop = loop; item->seen_count = 0; + item->begin = sorter->cfg->order.count; return VKD3D_OK; } @@ -3628,6 +3683,7 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) } vsir_block_list_remove_index(&sorter.available_blocks, i); + block->order_pos = cfg->order.count; if ((ret = vsir_block_list_add_checked(&cfg->order, block)) < 0) goto fail; @@ -3646,6 +3702,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) if (inner_stack_item->seen_count != inner_stack_item->loop->count) break; + if ((ret = vsir_cfg_add_loop_interval(cfg, inner_stack_item->begin, + cfg->order.count, false)) < 0) + goto fail; + new_seen_count = inner_stack_item->loop->count; --sorter.stack_count; } @@ -3706,6 +3766,143 @@ fail: return ret; } +/* Sort loop intervals first by ascending begin time and then by + * descending end time, so that inner intervals appear after outer + * ones and disjoint intervals appear in their proper order. */ +static int compare_loop_intervals(const void *ptr1, const void *ptr2) +{ + const struct cfg_loop_interval *interval1 = ptr1; + const struct cfg_loop_interval *interval2 = ptr2; + + if (interval1->begin != interval2->begin) + return vkd3d_u32_compare(interval1->begin, interval2->begin); + + return -vkd3d_u32_compare(interval1->end, interval2->end); +} + +static enum vkd3d_result vsir_cfg_generate_synthetic_loop_intervals(struct vsir_cfg *cfg) +{ + enum vkd3d_result ret; + size_t i, j, k; + + for (i = 0; i < cfg->block_count; ++i) + { + struct vsir_block *block = &cfg->blocks[i]; + + if (block->label == 0) + continue; + + for (j = 0; j < block->successors.count; ++j) + { + struct vsir_block *successor = block->successors.blocks[j]; + struct cfg_loop_interval *extend = NULL; + unsigned int begin; + enum + { + ACTION_DO_NOTHING, + ACTION_CREATE_NEW, + ACTION_EXTEND, + } action = ACTION_CREATE_NEW; + + /* We've already contructed loop intervals for the back + * edges, there's nothing more to do. */ + if (vsir_block_dominates(successor, block)) + continue; + + assert(block->order_pos < successor->order_pos); + + /* Jumping from a block to the following one is always + * possible, so nothing to do. */ + if (block->order_pos + 1 == successor->order_pos) + continue; + + /* Let's look for a loop interval that already breaks at + * `successor' and either contains or can be extended to + * contain `block'. */ + for (k = 0; k < cfg->loop_interval_count; ++k) + { + struct cfg_loop_interval *interval = &cfg->loop_intervals[k]; + + if (interval->end != successor->order_pos) + continue; + + if (interval->begin <= block->order_pos) + { + action = ACTION_DO_NOTHING; + break; + } + + if (interval->synthetic) + { + action = ACTION_EXTEND; + extend = interval; + break; + } + } + + if (action == ACTION_DO_NOTHING) + continue; + + /* Ok, we have to decide where the new or replacing + * interval has to begin. These are the rules: 1. it must + * begin before `block'; 2. intervals must be properly + * nested; 3. the new interval should begin as late as + * possible, to limit control flow depth and extension. */ + begin = block->order_pos; + + /* Our candidate interval is always [begin, + * successor->order_pos), and we move `begin' backward + * until the candidate interval contains all the intervals + * whose endpoint lies in the candidate interval + * itself. */ + for (k = 0; k < cfg->loop_interval_count; ++k) + { + struct cfg_loop_interval *interval = &cfg->loop_intervals[k]; + + if (begin < interval->end && interval->end < successor->order_pos) + begin = min(begin, interval->begin); + } + + /* New we have to care about the intervals whose begin + * point lies in the candidate interval. We cannot move + * the candidate interval endpoint, because it is + * important that the loop break target matches + * `successor'. So we have to move that interval's begin + * point to the begin point of the candidate interval, + * i.e. `begin'. But what if the interval we should extend + * backward is not synthetic? This cannot happen, + * fortunately, because it would mean that there is a jump + * entering a loop via a block which is not the loop + * header, so the CFG would not be reducible. */ + for (k = 0; k < cfg->loop_interval_count; ++k) + { + struct cfg_loop_interval *interval = &cfg->loop_intervals[k]; + + if (interval->begin < successor->order_pos && successor->order_pos < interval->end) + { + if (interval->synthetic) + interval->begin = min(begin, interval->begin); + assert(begin >= interval->begin); + } + } + + if (action == ACTION_EXTEND) + extend->begin = begin; + else if ((ret = vsir_cfg_add_loop_interval(cfg, begin, successor->order_pos, true)) < 0) + return ret; + } + } + + qsort(cfg->loop_intervals, cfg->loop_interval_count, sizeof(*cfg->loop_intervals), compare_loop_intervals); + + if (TRACE_ON()) + for (i = 0; i < cfg->loop_interval_count; ++i) + TRACE("%s loop interval %u - %u\n", cfg->loop_intervals[i].synthetic ? "Synthetic" : "Natural", + cfg->loop_intervals[i].begin, cfg->loop_intervals[i].end); + + return VKD3D_OK; +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -3717,7 +3914,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, if ((result = instruction_array_lower_texkills(parser)) < 0) return result; - if (parser->shader_desc.is_dxil) + if (parser->program.shader_version.major >= 6) { struct vsir_cfg cfg; @@ -3744,6 +3941,12 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, return result; } + if ((result = vsir_cfg_generate_synthetic_loop_intervals(&cfg)) < 0) + { + vsir_cfg_cleanup(&cfg); + return result; + } + if ((result = simple_structurizer_run(parser)) < 0) { vsir_cfg_cleanup(&cfg); @@ -3766,7 +3969,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, return result; if ((result = instruction_array_normalise_hull_shader_control_point_io(instructions, - &parser->shader_desc.input_signature)) < 0) + &parser->program.input_signature)) < 0) return result; } diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 5856f2f04ba..0568407f997 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -223,6 +223,11 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d } } +static bool data_type_is_floating_point(enum vkd3d_data_type data_type) +{ + return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE; +} + #define VKD3D_SPIRV_VERSION 0x00010000 #define VKD3D_SPIRV_GENERATOR_ID 18 #define VKD3D_SPIRV_GENERATOR_VERSION 11 @@ -1838,6 +1843,7 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder { switch (data_type) { + case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */ case VKD3D_DATA_FLOAT: case VKD3D_DATA_SNORM: case VKD3D_DATA_UNORM: @@ -1845,6 +1851,7 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder break; case VKD3D_DATA_INT: case VKD3D_DATA_UINT: + case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */ return vkd3d_spirv_get_op_type_int(builder, 32, data_type == VKD3D_DATA_INT); break; case VKD3D_DATA_DOUBLE: @@ -2444,14 +2451,14 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) vkd3d_free(compiler); } -static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version, - struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, +static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *program, + const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location, uint64_t config_flags) { - const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; - const struct shader_signature *output_signature = &shader_desc->output_signature; + const struct shader_signature *patch_constant_signature = &program->patch_constant_signature; + const struct shader_signature *output_signature = &program->output_signature; const struct vkd3d_shader_interface_info *shader_interface; const struct vkd3d_shader_descriptor_offset_info *offset_info; const struct vkd3d_shader_spirv_target_info *target_info; @@ -2562,7 +2569,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve rb_init(&compiler->symbol_table, vkd3d_symbol_compare); - compiler->shader_type = shader_version->type; + compiler->shader_type = program->shader_version.type; if ((shader_interface = vkd3d_find_struct(compile_info->next, INTERFACE_INFO))) { @@ -3753,6 +3760,70 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } +/* Based on the implementation in the OpenGL Mathematics library. */ +static uint32_t half_to_float(uint16_t value) +{ + uint32_t s = (value & 0x8000u) << 16; + uint32_t e = (value >> 10) & 0x1fu; + uint32_t m = value & 0x3ffu; + + if (!e) + { + if (!m) + { + /* Plus or minus zero */ + return s; + } + else + { + /* Denormalized number -- renormalize it */ + + while (!(m & 0x400u)) + { + m <<= 1; + --e; + } + + ++e; + m &= ~0x400u; + } + } + else if (e == 31u) + { + /* Positive or negative infinity for zero 'm'. + * Nan for non-zero 'm' -- preserve sign and significand bits */ + return s | 0x7f800000u | (m << 13); + } + + /* Normalized number */ + e += 127u - 15u; + m <<= 13; + + /* Assemble s, e and m. */ + return s | (e << 23) | m; +} + +static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value) +{ + int16_t i; + + /* TODO: native 16-bit support. */ + if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF) + return uint_value; + + if (data_type == VKD3D_DATA_HALF) + return half_to_float(uint_value); + + /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or + * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows + * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These + * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not + * extended, and results match SM 5. It seems best to replicate the sign-extension, and if + * execution is 16-bit, the values will be truncated. */ + i = uint_value; + return (int32_t)i; +} + static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { @@ -3765,14 +3836,15 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile if (reg->dimension == VSIR_DIMENSION_SCALAR) { for (i = 0; i < component_count; ++i) - values[i] = *reg->u.immconst_u32; + values[i] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]); } else { for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; + values[j++] = convert_raw_constant32(reg->data_type, + reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]); } } @@ -3916,6 +3988,13 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil switch (icb->data_type) { + case VKD3D_DATA_HALF: + case VKD3D_DATA_UINT16: + /* Scalar only. */ + for (i = 0; i < element_count; ++i) + elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, + convert_raw_constant32(icb->data_type, icb->data[i])); + break; case VKD3D_DATA_FLOAT: case VKD3D_DATA_INT: case VKD3D_DATA_UINT: @@ -4104,7 +4183,7 @@ static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, uint32_t type_id; type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); - if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) + if (data_type_is_floating_point(reg->data_type)) return vkd3d_spirv_build_op_glsl_std450_fabs(builder, type_id, val_id); FIXME("Unhandled data type %#x.\n", reg->data_type); @@ -4118,7 +4197,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, uint32_t type_id; type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); - if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) + if (data_type_is_floating_point(reg->data_type)) return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id); else if (data_type_is_integer(reg->data_type)) return vkd3d_spirv_build_op_snegate(builder, type_id, val_id); @@ -4302,7 +4381,7 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, } type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); - if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) + if (data_type_is_floating_point(reg->data_type)) return vkd3d_spirv_build_op_glsl_std450_nclamp(builder, type_id, val_id, zero_id, one_id); FIXME("Unhandled data type %#x.\n", reg->data_type); @@ -6903,7 +6982,7 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, assert(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL); val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); - if (dst->reg.data_type == VKD3D_DATA_FLOAT) + if (dst->reg.data_type == VKD3D_DATA_HALF || dst->reg.data_type == VKD3D_DATA_FLOAT) { val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); } @@ -6912,7 +6991,7 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); } - else if (dst->reg.data_type == VKD3D_DATA_UINT) + else if (dst->reg.data_type == VKD3D_DATA_UINT16 || dst->reg.data_type == VKD3D_DATA_UINT) { val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); } @@ -7205,8 +7284,15 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); if (src[0].reg.data_type != VKD3D_DATA_BOOL) - condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); + { + if (instruction->handler_idx == VKD3DSIH_CMP) + condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, + vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), condition_id, + spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); + else + condition_id = spirv_compiler_emit_int_to_bool(compiler, + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); + } val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id); spirv_compiler_emit_store_dst(compiler, dst, val_id); @@ -7738,6 +7824,36 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c spirv_compiler_emit_store_dst(compiler, dst, val_id); } +static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t src0_id, src1_id, type_id, result_id; + unsigned int component_count; + SpvOp op; + + switch (instruction->handler_idx) + { + case VKD3DSIH_SLT: op = SpvOpFOrdLessThan; break; + case VKD3DSIH_SGE: op = SpvOpFOrdGreaterThanEqual; break; + default: + vkd3d_unreachable(); + } + + component_count = vsir_write_mask_component_count(dst->write_mask); + + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); + + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); + result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id); + + result_id = spirv_compiler_emit_bool_to_float(compiler, component_count, result_id, false); + spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id); +} + static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction, uint32_t target_block_id) { @@ -9628,6 +9744,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, break; case VKD3DSIH_DMOVC: case VKD3DSIH_MOVC: + case VKD3DSIH_CMP: spirv_compiler_emit_movc(compiler, instruction); break; case VKD3DSIH_SWAPC: @@ -9752,6 +9869,10 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_UNO: spirv_compiler_emit_orderedness_instruction(compiler, instruction); break; + case VKD3DSIH_SLT: + case VKD3DSIH_SGE: + spirv_compiler_emit_float_comparison_instruction(compiler, instruction); + break; case VKD3DSIH_BFI: case VKD3DSIH_IBFE: case VKD3DSIH_UBFE: @@ -9982,7 +10103,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info; const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - struct vkd3d_shader_desc *shader_desc = &parser->shader_desc; struct vkd3d_shader_instruction_array instructions; struct vsir_program *program = &parser->program; enum vkd3d_result result = VKD3D_OK; @@ -10007,12 +10127,12 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, instructions = program->instructions; memset(&program->instructions, 0, sizeof(program->instructions)); - compiler->input_signature = shader_desc->input_signature; - compiler->output_signature = shader_desc->output_signature; - compiler->patch_constant_signature = shader_desc->patch_constant_signature; - memset(&shader_desc->input_signature, 0, sizeof(shader_desc->input_signature)); - memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature)); - memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature)); + compiler->input_signature = program->input_signature; + compiler->output_signature = program->output_signature; + compiler->patch_constant_signature = program->patch_constant_signature; + memset(&program->input_signature, 0, sizeof(program->input_signature)); + memset(&program->output_signature, 0, sizeof(program->output_signature)); + memset(&program->patch_constant_signature, 0, sizeof(program->patch_constant_signature)); compiler->use_vocp = program->use_vocp; compiler->block_names = program->block_names; compiler->block_name_count = program->block_name_count; @@ -10119,8 +10239,8 @@ int spirv_compile(struct vkd3d_shader_parser *parser, struct spirv_compiler *spirv_compiler; int ret; - if (!(spirv_compiler = spirv_compiler_create(&parser->program.shader_version, &parser->shader_desc, - compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags))) + if (!(spirv_compiler = spirv_compiler_create(&parser->program, compile_info, + scan_descriptor_info, message_context, &parser->location, parser->config_flags))) { ERR("Failed to create SPIR-V compiler.\n"); return VKD3D_ERROR; diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 3be4e40ab0c..bd558693b07 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -954,32 +954,32 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins case VKD3DSPR_INCONTROLPOINT: io_masks = priv->input_register_masks; ranges = &priv->input_index_ranges; - signature = &priv->p.shader_desc.input_signature; + signature = &priv->p.program.input_signature; break; case VKD3DSPR_OUTPUT: if (sm4_parser_is_in_fork_or_join_phase(priv)) { io_masks = priv->patch_constant_register_masks; ranges = &priv->patch_constant_index_ranges; - signature = &priv->p.shader_desc.patch_constant_signature; + signature = &priv->p.program.patch_constant_signature; } else { io_masks = priv->output_register_masks; ranges = &priv->output_index_ranges; - signature = &priv->p.shader_desc.output_signature; + signature = &priv->p.program.output_signature; } break; case VKD3DSPR_COLOROUT: case VKD3DSPR_OUTCONTROLPOINT: io_masks = priv->output_register_masks; ranges = &priv->output_index_ranges; - signature = &priv->p.shader_desc.output_signature; + signature = &priv->p.program.output_signature; break; case VKD3DSPR_PATCHCONST: io_masks = priv->patch_constant_register_masks; ranges = &priv->patch_constant_index_ranges; - signature = &priv->p.shader_desc.patch_constant_signature; + signature = &priv->p.program.patch_constant_signature; break; default: @@ -1113,7 +1113,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst)) { struct signature_element *e = vsir_signature_find_element_for_reg( - &priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + &priv->p.program.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); e->interpolation_mode = ins->flags; } @@ -1128,7 +1128,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst)) { struct signature_element *e = vsir_signature_find_element_for_reg( - &priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + &priv->p.program.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); e->interpolation_mode = ins->flags; } @@ -1748,7 +1748,6 @@ static void shader_sm4_destroy(struct vkd3d_shader_parser *parser) struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser); vsir_program_cleanup(&parser->program); - free_shader_desc(&parser->shader_desc); vkd3d_free(sm4); } @@ -2504,7 +2503,7 @@ static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops = }; static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code, - size_t byte_code_size, const char *source_name, const struct shader_signature *output_signature, + size_t byte_code_size, const char *source_name, struct vkd3d_shader_message_context *message_context) { struct vkd3d_shader_version version; @@ -2648,9 +2647,9 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser) { struct vkd3d_shader_instruction_array *instructions; - struct vkd3d_shader_desc *shader_desc; struct vkd3d_shader_instruction *ins; struct vkd3d_shader_sm4_parser *sm4; + struct dxbc_shader_desc dxbc_desc = {0}; int ret; if (!(sm4 = vkd3d_calloc(1, sizeof(*sm4)))) @@ -2659,36 +2658,40 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi return VKD3D_ERROR_OUT_OF_MEMORY; } - shader_desc = &sm4->p.shader_desc; - shader_desc->is_dxil = false; + dxbc_desc.is_dxil = false; if ((ret = shader_extract_from_dxbc(&compile_info->source, - message_context, compile_info->source_name, shader_desc)) < 0) + message_context, compile_info->source_name, &dxbc_desc)) < 0) { WARN("Failed to extract shader, vkd3d result %d.\n", ret); vkd3d_free(sm4); return ret; } - if (!shader_sm4_init(sm4, shader_desc->byte_code, shader_desc->byte_code_size, - compile_info->source_name, &shader_desc->output_signature, message_context)) + if (!shader_sm4_init(sm4, dxbc_desc.byte_code, dxbc_desc.byte_code_size, + compile_info->source_name, message_context)) { WARN("Failed to initialise shader parser.\n"); - free_shader_desc(shader_desc); + free_dxbc_shader_desc(&dxbc_desc); vkd3d_free(sm4); return VKD3D_ERROR_INVALID_ARGUMENT; } + sm4->p.program.input_signature = dxbc_desc.input_signature; + sm4->p.program.output_signature = dxbc_desc.output_signature; + sm4->p.program.patch_constant_signature = dxbc_desc.patch_constant_signature; + memset(&dxbc_desc, 0, sizeof(dxbc_desc)); + /* DXBC stores used masks inverted for output signatures, for some reason. * We return them un-inverted. */ - uninvert_used_masks(&shader_desc->output_signature); + uninvert_used_masks(&sm4->p.program.output_signature); if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL) - uninvert_used_masks(&shader_desc->patch_constant_signature); + uninvert_used_masks(&sm4->p.program.patch_constant_signature); - if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature, + if (!shader_sm4_parser_validate_signature(sm4, &sm4->p.program.input_signature, sm4->input_register_masks, "Input") - || !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature, + || !shader_sm4_parser_validate_signature(sm4, &sm4->p.program.output_signature, sm4->output_register_masks, "Output") - || !shader_sm4_parser_validate_signature(sm4, &shader_desc->patch_constant_signature, + || !shader_sm4_parser_validate_signature(sm4, &sm4->p.program.patch_constant_signature, sm4->patch_constant_register_masks, "Patch constant")) { shader_sm4_destroy(&sm4->p); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index d128d84d6ea..1ac372f163c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1450,11 +1450,11 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info if (!ret && signature_info) { - if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &parser->shader_desc.input_signature) + if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &parser->program.input_signature) || !vkd3d_shader_signature_from_shader_signature(&signature_info->output, - &parser->shader_desc.output_signature) + &parser->program.output_signature) || !vkd3d_shader_signature_from_shader_signature(&signature_info->patch_constant, - &parser->shader_desc.patch_constant_signature)) + &parser->program.patch_constant_signature)) { ret = VKD3D_ERROR_OUT_OF_MEMORY; } @@ -1553,7 +1553,7 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info; - struct vkd3d_glsl_generator *glsl_generator; + struct vsir_program *program = &parser->program; struct vkd3d_shader_compile_info scan_info; int ret; @@ -1562,23 +1562,13 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, switch (compile_info->target_type) { case VKD3D_SHADER_TARGET_D3D_ASM: - ret = vkd3d_dxbc_binary_to_text(&parser->program, &parser->shader_desc, - compile_info, out, VSIR_ASM_FLAG_NONE); + ret = d3d_asm_compile(program, compile_info, out, VSIR_ASM_FLAG_NONE); break; case VKD3D_SHADER_TARGET_GLSL: if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) return ret; - if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->program.shader_version, - message_context, &parser->location))) - { - ERR("Failed to create GLSL generator.\n"); - vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - return VKD3D_ERROR; - } - - ret = vkd3d_glsl_generator_generate(glsl_generator, &parser->program, out); - vkd3d_glsl_generator_destroy(glsl_generator); + ret = glsl_compile(program, out, message_context); vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); break; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index d257d953dd5..98c311b3655 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -149,6 +149,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_NON_FINITE_RESULT = 5027, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE = 5028, VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE = 5029, + VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, @@ -623,14 +624,16 @@ enum vkd3d_data_type VKD3D_DATA_UINT8, VKD3D_DATA_UINT64, VKD3D_DATA_BOOL, + VKD3D_DATA_UINT16, + VKD3D_DATA_HALF, VKD3D_DATA_COUNT, }; static inline bool data_type_is_integer(enum vkd3d_data_type data_type) { - return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT - || data_type == VKD3D_DATA_UINT64; + return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT16 + || data_type == VKD3D_DATA_UINT || data_type == VKD3D_DATA_UINT64; } static inline bool data_type_is_bool(enum vkd3d_data_type data_type) @@ -1028,7 +1031,7 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade unsigned int reg_idx, unsigned int write_mask); void shader_signature_cleanup(struct shader_signature *signature); -struct vkd3d_shader_desc +struct dxbc_shader_desc { const uint32_t *byte_code; size_t byte_code_size; @@ -1036,7 +1039,10 @@ struct vkd3d_shader_desc struct shader_signature input_signature; struct shader_signature output_signature; struct shader_signature patch_constant_signature; +}; +struct vkd3d_shader_desc +{ struct { uint32_t used, external; @@ -1293,6 +1299,10 @@ struct vsir_program struct vkd3d_shader_version shader_version; struct vkd3d_shader_instruction_array instructions; + struct shader_signature input_signature; + struct shader_signature output_signature; + struct shader_signature patch_constant_signature; + unsigned int input_control_point_count, output_control_point_count; unsigned int block_count; unsigned int temp_count; @@ -1394,8 +1404,8 @@ enum vsir_asm_flags VSIR_ASM_FLAG_DUMP_TYPES = 0x1, }; -enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, - const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, +enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, enum vsir_asm_flags flags); void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); @@ -1487,20 +1497,15 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser); -void free_shader_desc(struct vkd3d_shader_desc *desc); +void free_dxbc_shader_desc(struct dxbc_shader_desc *desc); int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, - struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc); + struct vkd3d_shader_message_context *message_context, const char *source_name, struct dxbc_shader_desc *desc); int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context, struct shader_signature *signature); -struct vkd3d_glsl_generator; - -struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version, - struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location); -int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, - struct vsir_program *program, struct vkd3d_shader_code *out); -void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator); +int glsl_compile(struct vsir_program *program, struct vkd3d_shader_code *out, + struct vkd3d_shader_message_context *message_context); #define SPIRV_MAX_SRC_COUNT 6 @@ -1524,10 +1529,12 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty { switch (data_type) { + case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */ case VKD3D_DATA_FLOAT: case VKD3D_DATA_UNORM: case VKD3D_DATA_SNORM: return VKD3D_SHADER_COMPONENT_FLOAT; + case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */ case VKD3D_DATA_UINT: return VKD3D_SHADER_COMPONENT_UINT; case VKD3D_DATA_INT: diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c index da9c1d964d4..7841a811bf7 100644 --- a/libs/vkd3d/libs/vkd3d/device.c +++ b/libs/vkd3d/libs/vkd3d/device.c @@ -94,6 +94,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), + VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock), VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), @@ -789,6 +790,7 @@ struct vkd3d_physical_device_info VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features; VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_features; VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features; + VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_features; VkPhysicalDeviceRobustness2FeaturesEXT robustness2_features; VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT texel_buffer_alignment_features; @@ -808,6 +810,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *vertex_divisor_properties; VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment_properties; VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features; + VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock_features; VkPhysicalDeviceRobustness2FeaturesEXT *robustness2_features; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; @@ -825,6 +828,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i conditional_rendering_features = &info->conditional_rendering_features; depth_clip_features = &info->depth_clip_features; descriptor_indexing_features = &info->descriptor_indexing_features; + fragment_shader_interlock_features = &info->fragment_shader_interlock_features; robustness2_features = &info->robustness2_features; descriptor_indexing_properties = &info->descriptor_indexing_properties; maintenance3_properties = &info->maintenance3_properties; @@ -846,6 +850,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i vk_prepend_struct(&info->features2, depth_clip_features); descriptor_indexing_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; vk_prepend_struct(&info->features2, descriptor_indexing_features); + fragment_shader_interlock_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT; + vk_prepend_struct(&info->features2, fragment_shader_interlock_features); robustness2_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; vk_prepend_struct(&info->features2, robustness2_features); demote_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; @@ -1158,6 +1164,7 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic static void vkd3d_trace_physical_device_features(const struct vkd3d_physical_device_info *info) { + const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock_features; const VkPhysicalDeviceConditionalRenderingFeaturesEXT *conditional_rendering_features; const VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; @@ -1279,6 +1286,15 @@ static void vkd3d_trace_physical_device_features(const struct vkd3d_physical_dev TRACE(" VkPhysicalDeviceDepthClipEnableFeaturesEXT:\n"); TRACE(" depthClipEnable: %#x.\n", depth_clip_features->depthClipEnable); + fragment_shader_interlock_features = &info->fragment_shader_interlock_features; + TRACE(" VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT:\n"); + TRACE(" fragmentShaderSampleInterlock: %#x.\n.", + fragment_shader_interlock_features->fragmentShaderSampleInterlock); + TRACE(" fragmentShaderPixelInterlock: %#x\n.", + fragment_shader_interlock_features->fragmentShaderPixelInterlock); + TRACE(" fragmentShaderShadingRateInterlock: %#x\n.", + fragment_shader_interlock_features->fragmentShaderShadingRateInterlock); + demote_features = &info->demote_features; TRACE(" VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT:\n"); TRACE(" shaderDemoteToHelperInvocation: %#x.\n", demote_features->shaderDemoteToHelperInvocation); @@ -1476,6 +1492,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, uint32_t *device_extension_count, bool **user_extension_supported) { const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs; + VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock; const struct vkd3d_optional_device_extensions_info *optional_extensions; VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing; VkPhysicalDevice physical_device = device->vk_physical_device; @@ -1539,8 +1556,6 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, device->feature_options.TypedUAVLoadAdditionalFormats = features->shaderStorageImageReadWithoutFormat && d3d12_device_supports_typed_uav_load_additional_formats(device); - /* GL_INTEL_fragment_shader_ordering, no Vulkan equivalent. */ - device->feature_options.ROVsSupported = FALSE; /* GL_INTEL_conservative_rasterization, no Vulkan equivalent. */ device->feature_options.ConservativeRasterizationTier = D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED; device->feature_options.MaxGPUVirtualAddressBitsPerResource = 40; /* FIXME */ @@ -1619,6 +1634,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, *user_extension_supported, vulkan_info, "device", device->vkd3d_instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG); + fragment_shader_interlock = &physical_device_info->fragment_shader_interlock_features; + if (!fragment_shader_interlock->fragmentShaderSampleInterlock + || !fragment_shader_interlock->fragmentShaderPixelInterlock) + vulkan_info->EXT_fragment_shader_interlock = false; + device->feature_options.ROVsSupported = vulkan_info->EXT_fragment_shader_interlock; + if (!physical_device_info->conditional_rendering_features.conditionalRendering) vulkan_info->EXT_conditional_rendering = false; if (!physical_device_info->depth_clip_features.depthClipEnable) @@ -1675,6 +1696,10 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING; + if (vulkan_info->EXT_fragment_shader_interlock) + vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] + = VKD3D_SHADER_SPIRV_EXTENSION_EXT_FRAGMENT_SHADER_INTERLOCK; + if (vulkan_info->EXT_shader_stencil_export) vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT; diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h index 1f47ddd5023..34a98c4fc3d 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -55,7 +55,7 @@ #define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u #define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u -#define VKD3D_MAX_SHADER_EXTENSIONS 4u +#define VKD3D_MAX_SHADER_EXTENSIONS 5u #define VKD3D_MAX_SHADER_STAGES 5u #define VKD3D_MAX_VK_SYNC_OBJECTS 4u #define VKD3D_MAX_DEVICE_BLOCKED_QUEUES 16u @@ -133,6 +133,7 @@ struct vkd3d_vulkan_info bool EXT_debug_marker; bool EXT_depth_clip_enable; bool EXT_descriptor_indexing; + bool EXT_fragment_shader_interlock; bool EXT_mutable_descriptor_type; bool EXT_robustness2; bool EXT_shader_demote_to_helper_invocation; -- 2.43.0