From 50e1fdcf167b4e3a8284fe5ac5c797cc780adb73 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 21 Sep 2024 09:40:50 +1000 Subject: [PATCH] Updated vkd3d to 2ac7f650a196e47a18ea1957eac5953255cf424d. --- libs/vkd3d/libs/vkd3d-shader/glsl.c | 79 +++++++++++-- libs/vkd3d/libs/vkd3d-shader/ir.c | 32 +++-- libs/vkd3d/libs/vkd3d-shader/spirv.c | 30 ++--- libs/vkd3d/libs/vkd3d-shader/tpf.c | 110 ++++++++++++------ .../libs/vkd3d-shader/vkd3d_shader_private.h | 1 + libs/vkd3d/libs/vkd3d/utils.c | 3 +- 6 files changed, 182 insertions(+), 73 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index ac101d44214..dd1c121d5a8 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -144,6 +144,12 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, vkd3d_string_buffer_printf(buffer, "%#xu", reg->u.immconst_u32[0]); break; + case VSIR_DIMENSION_VEC4: + vkd3d_string_buffer_printf(buffer, "uvec4(%#xu, %#xu, %#xu, %#xu)", + reg->u.immconst_u32[0], reg->u.immconst_u32[1], + reg->u.immconst_u32[2], reg->u.immconst_u32[3]); + break; + default: vkd3d_string_buffer_printf(buffer, "", reg->dimension); vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -211,7 +217,7 @@ static void glsl_src_cleanup(struct glsl_src *src, struct vkd3d_string_buffer_ca } static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vkd3d_glsl_generator *gen, - const char *src, enum vkd3d_data_type dst_data_type, enum vkd3d_data_type src_data_type) + const char *src, enum vkd3d_data_type dst_data_type, enum vkd3d_data_type src_data_type, unsigned int size) { if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) dst_data_type = VKD3D_DATA_FLOAT; @@ -224,16 +230,37 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk return; } - if (src_data_type == VKD3D_DATA_FLOAT && dst_data_type == VKD3D_DATA_UINT) + if (src_data_type == VKD3D_DATA_FLOAT) { - vkd3d_string_buffer_printf(dst, "floatBitsToUint(%s)", src); - return; + switch (dst_data_type) + { + case VKD3D_DATA_INT: + vkd3d_string_buffer_printf(dst, "floatBitsToInt(%s)", src); + return; + case VKD3D_DATA_UINT: + vkd3d_string_buffer_printf(dst, "floatBitsToUint(%s)", src); + return; + default: + break; + } } - if (src_data_type == VKD3D_DATA_UINT && dst_data_type == VKD3D_DATA_FLOAT) + if (src_data_type == VKD3D_DATA_UINT) { - vkd3d_string_buffer_printf(dst, "uintBitsToFloat(%s)", src); - return; + switch (dst_data_type) + { + case VKD3D_DATA_FLOAT: + vkd3d_string_buffer_printf(dst, "uintBitsToFloat(%s)", src); + return; + case VKD3D_DATA_INT: + if (size == 1) + vkd3d_string_buffer_printf(dst, "int(%s)", src); + else + vkd3d_string_buffer_printf(dst, "ivec%u(%s)", size, src); + return; + default: + break; + } } vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -248,6 +275,7 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator const struct vkd3d_shader_register *reg = &vsir_src->reg; struct vkd3d_string_buffer *register_name, *str; enum vkd3d_data_type src_data_type; + unsigned int size; glsl_src->str = vkd3d_string_buffer_get(&gen->string_buffers); register_name = vkd3d_string_buffer_get(&gen->string_buffers); @@ -268,7 +296,8 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator else str = vkd3d_string_buffer_get(&gen->string_buffers); - shader_glsl_print_bitcast(str, gen, register_name->buffer, reg->data_type, src_data_type); + size = reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1; + shader_glsl_print_bitcast(str, gen, register_name->buffer, reg->data_type, src_data_type, size); if (reg->dimension == VSIR_DIMENSION_VEC4) shader_glsl_print_swizzle(str, vsir_src->swizzle, mask); @@ -385,6 +414,30 @@ static void shader_glsl_binop(struct vkd3d_glsl_generator *gen, glsl_dst_cleanup(&dst, &gen->string_buffers); } +static void shader_glsl_relop(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, const char *scalar_op, const char *vector_op) +{ + unsigned int mask_size; + struct glsl_src src[2]; + struct glsl_dst dst; + uint32_t mask; + + mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); + glsl_src_init(&src[0], gen, &ins->src[0], mask); + glsl_src_init(&src[1], gen, &ins->src[1], mask); + + if ((mask_size = vsir_write_mask_component_count(mask)) > 1) + shader_glsl_print_assignment(gen, &dst, "uvec%u(%s(%s, %s)) * 0xffffffffu", + mask_size, vector_op, src[0].str->buffer, src[1].str->buffer); + else + shader_glsl_print_assignment(gen, &dst, "%s %s %s ? 0xffffffffu : 0u", + src[0].str->buffer, scalar_op, src[1].str->buffer); + + glsl_src_cleanup(&src[1], &gen->string_buffers); + glsl_src_cleanup(&src[0], &gen->string_buffers); + glsl_dst_cleanup(&dst, &gen->string_buffers); +} + static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { struct glsl_src src; @@ -555,9 +608,19 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_NOP: break; + case VKD3DSIH_INE: + case VKD3DSIH_NEU: + shader_glsl_relop(gen, ins, "!=", "notEqual"); + break; case VKD3DSIH_MOV: shader_glsl_mov(gen, ins); break; + case VKD3DSIH_MUL: + shader_glsl_binop(gen, ins, "*"); + break; + case VKD3DSIH_OR: + shader_glsl_binop(gen, ins, "|"); + break; case VKD3DSIH_RET: shader_glsl_ret(gen, ins); break; diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 9e06b94e2eb..db9992d9715 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -1208,8 +1208,8 @@ static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser * return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; } -static unsigned int shader_signature_find_element_for_reg(const struct shader_signature *signature, - unsigned int reg_idx, unsigned int write_mask) +static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, + unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx) { unsigned int i, base_write_mask; @@ -1219,7 +1219,8 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si if (e->register_index <= reg_idx && e->register_index + e->register_count > reg_idx && (e->mask & write_mask) == write_mask) { - return i; + *element_idx = i; + return true; } } @@ -1229,15 +1230,20 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si reg_idx, write_mask); base_write_mask = 1u << vsir_write_mask_get_component_idx(write_mask); if (base_write_mask != write_mask) - return shader_signature_find_element_for_reg(signature, reg_idx, base_write_mask); + return shader_signature_find_element_for_reg(signature, reg_idx, base_write_mask, element_idx); - vkd3d_unreachable(); + return false; } struct signature_element *vsir_signature_find_element_for_reg(const struct shader_signature *signature, unsigned int reg_idx, unsigned int write_mask) { - return &signature->elements[shader_signature_find_element_for_reg(signature, reg_idx, write_mask)]; + unsigned int element_idx; + + if (shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx)) + return &signature->elements[element_idx]; + + return NULL; } static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], @@ -1291,9 +1297,10 @@ static void io_normaliser_add_index_range(struct io_normaliser *normaliser, { const struct vkd3d_shader_index_range *range = &ins->declaration.index_range; const struct vkd3d_shader_register *reg = &range->dst.reg; - unsigned int reg_idx, write_mask, element_idx; const struct shader_signature *signature; uint8_t (*range_map)[VKD3D_VEC4_SIZE]; + struct signature_element *element; + unsigned int reg_idx, write_mask; switch (reg->type) { @@ -1325,9 +1332,8 @@ static void io_normaliser_add_index_range(struct io_normaliser *normaliser, reg_idx = reg->idx[reg->idx_count - 1].offset; write_mask = range->dst.write_mask; - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - range_map_set_register_range(range_map, reg_idx, range->register_count, - signature->elements[element_idx].mask, true); + element = vsir_signature_find_element_for_reg(signature, reg_idx, write_mask); + range_map_set_register_range(range_map, reg_idx, range->register_count, element->mask, true); } static int signature_element_mask_compare(const void *a, const void *b) @@ -1648,7 +1654,8 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par id_idx = reg->idx_count - 1; write_mask = dst_param->write_mask; - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); + if (!shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx)) + vkd3d_unreachable(); e = &signature->elements[element_idx]; dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); @@ -1771,7 +1778,8 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par id_idx = reg->idx_count - 1; write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); + if (!shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx)) + vkd3d_unreachable(); e = &signature->elements[element_idx]; if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index a3e121f8687..7f1e0fea2c3 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -299,6 +299,16 @@ static void vkd3d_spirv_stream_free(struct vkd3d_spirv_stream *stream) vkd3d_spirv_stream_clear(stream); } +static void vkd3d_shader_code_from_spirv_stream(struct vkd3d_shader_code *code, struct vkd3d_spirv_stream *stream) +{ + code->code = stream->words; + code->size = stream->word_count * sizeof(*stream->words); + + stream->words = NULL; + stream->capacity = 0; + stream->word_count = 0; +} + static size_t vkd3d_spirv_stream_current_location(struct vkd3d_spirv_stream *stream) { return stream->word_count; @@ -2018,9 +2028,7 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, { uint64_t capability_mask = builder->capability_mask; struct vkd3d_spirv_stream stream; - uint32_t *code; unsigned int i; - size_t size; vkd3d_spirv_stream_init(&stream); @@ -2075,26 +2083,20 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, if (builder->invocation_count) vkd3d_spirv_build_op_execution_mode(&builder->execution_mode_stream, builder->main_function_id, SpvExecutionModeInvocations, &builder->invocation_count, 1); - vkd3d_spirv_stream_append(&stream, &builder->execution_mode_stream); - - vkd3d_spirv_stream_append(&stream, &builder->debug_stream); - vkd3d_spirv_stream_append(&stream, &builder->annotation_stream); - vkd3d_spirv_stream_append(&stream, &builder->global_stream); - vkd3d_spirv_stream_append(&stream, &builder->function_stream); - if (!(code = vkd3d_calloc(stream.word_count, sizeof(*code)))) + if (!vkd3d_spirv_stream_append(&stream, &builder->execution_mode_stream) + || !vkd3d_spirv_stream_append(&stream, &builder->debug_stream) + || !vkd3d_spirv_stream_append(&stream, &builder->annotation_stream) + || !vkd3d_spirv_stream_append(&stream, &builder->global_stream) + || !vkd3d_spirv_stream_append(&stream, &builder->function_stream)) { vkd3d_spirv_stream_free(&stream); return false; } - size = stream.word_count * sizeof(*code); - memcpy(code, stream.words, size); + vkd3d_shader_code_from_spirv_stream(spirv, &stream); vkd3d_spirv_stream_free(&stream); - spirv->code = code; - spirv->size = size; - return true; } diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index cbf28f5ec50..884a2998d5b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -648,6 +648,7 @@ enum vkd3d_sm4_stat_field VKD3D_STAT_BARRIER, VKD3D_STAT_LOD, VKD3D_STAT_GATHER, + VKD3D_STAT_TEMPS, VKD3D_STAT_COUNT, }; @@ -1157,7 +1158,18 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u struct signature_element *e = vsir_signature_find_element_for_reg( &priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); - e->interpolation_mode = ins->flags; + if (!e) + { + WARN("No matching signature element for input register %u with mask %#x.\n", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, + "No matching signature element for input register %u with mask %#x.\n", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + } + else + { + e->interpolation_mode = ins->flags; + } } } @@ -1172,7 +1184,18 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in struct signature_element *e = vsir_signature_find_element_for_reg( &priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); - e->interpolation_mode = ins->flags; + if (!e) + { + WARN("No matching signature element for input register %u with mask %#x.\n", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, + "No matching signature element for input register %u with mask %#x.\n", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + } + else + { + e->interpolation_mode = ins->flags; + } } ins->declaration.register_semantic.sysval_semantic = *tokens; } @@ -1861,6 +1884,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) {VKD3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT, VKD3D_STAT_TESS_CONTROL_POINT_COUNT}, {VKD3D_SM5_OP_SYNC, VKD3D_STAT_BARRIER}, + + {VKD3D_SM4_OP_DCL_TEMPS, VKD3D_STAT_TEMPS}, }; memset(lookup, 0, sizeof(*lookup)); @@ -4403,44 +4428,11 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk } } -static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4_instruction *instr) +static void sm4_update_stat_counters(const struct tpf_writer *tpf, const struct sm4_instruction *instr) { enum vkd3d_shader_type shader_type = tpf->ctx->profile->type; - uint32_t token = instr->opcode | instr->extra_bits, opcode; - struct vkd3d_bytecode_buffer *buffer = tpf->buffer; enum vkd3d_sm4_stat_field stat_field; - unsigned int size, i, j; - size_t token_position; - - if (instr->modifier_count > 0) - token |= VKD3D_SM4_INSTRUCTION_MODIFIER; - - token_position = put_u32(buffer, 0); - - for (i = 0; i < instr->modifier_count; ++i) - { - uint32_t modifier_token = sm4_encode_instruction_modifier(&instr->modifiers[i]); - - if (instr->modifier_count > i + 1) - modifier_token |= VKD3D_SM4_INSTRUCTION_MODIFIER; - put_u32(buffer, modifier_token); - } - - for (i = 0; i < instr->dst_count; ++i) - sm4_write_dst_register(tpf, &instr->dsts[i]); - - for (i = 0; i < instr->src_count; ++i) - sm4_write_src_register(tpf, &instr->srcs[i]); - - if (instr->byte_stride) - put_u32(buffer, instr->byte_stride); - - for (j = 0; j < instr->idx_count; ++j) - put_u32(buffer, instr->idx[j]); - - size = (bytecode_get_size(buffer) - token_position) / sizeof(uint32_t); - token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT); - set_u32(buffer, token_position, token); + uint32_t opcode; ++tpf->stat->fields[VKD3D_STAT_INSTR_COUNT]; @@ -4449,6 +4441,9 @@ static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4 switch (opcode) { + case VKD3D_SM4_OP_DCL_TEMPS: + tpf->stat->fields[stat_field] = max(tpf->stat->fields[stat_field], instr->idx[0]); + break; case VKD3D_SM4_OP_DCL_OUTPUT_TOPOLOGY: case VKD3D_SM4_OP_DCL_INPUT_PRIMITIVE: tpf->stat->fields[stat_field] = (instr->opcode & VKD3D_SM4_PRIMITIVE_TYPE_MASK) @@ -4476,7 +4471,46 @@ static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4 default: ++tpf->stat->fields[stat_field]; } +} + +static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4_instruction *instr) +{ + uint32_t token = instr->opcode | instr->extra_bits; + struct vkd3d_bytecode_buffer *buffer = tpf->buffer; + unsigned int size, i, j; + size_t token_position; + + if (instr->modifier_count > 0) + token |= VKD3D_SM4_INSTRUCTION_MODIFIER; + + token_position = put_u32(buffer, 0); + + for (i = 0; i < instr->modifier_count; ++i) + { + uint32_t modifier_token = sm4_encode_instruction_modifier(&instr->modifiers[i]); + + if (instr->modifier_count > i + 1) + modifier_token |= VKD3D_SM4_INSTRUCTION_MODIFIER; + put_u32(buffer, modifier_token); + } + + for (i = 0; i < instr->dst_count; ++i) + sm4_write_dst_register(tpf, &instr->dsts[i]); + + for (i = 0; i < instr->src_count; ++i) + sm4_write_src_register(tpf, &instr->srcs[i]); + + if (instr->byte_stride) + put_u32(buffer, instr->byte_stride); + + for (j = 0; j < instr->idx_count; ++j) + put_u32(buffer, instr->idx[j]); + + size = (bytecode_get_size(buffer) - token_position) / sizeof(uint32_t); + token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT); + set_u32(buffer, token_position, token); + sm4_update_stat_counters(tpf, instr); } static bool encode_texel_offset_as_aoffimmi(struct sm4_instruction *instr, @@ -6412,7 +6446,7 @@ static void write_sm4_stat(struct hlsl_ctx *ctx, const struct sm4_stat *stat, st struct vkd3d_bytecode_buffer buffer = {0}; put_u32(&buffer, stat->fields[VKD3D_STAT_INSTR_COUNT]); - put_u32(&buffer, 0); /* Temp count */ + put_u32(&buffer, stat->fields[VKD3D_STAT_TEMPS]); put_u32(&buffer, 0); /* Def count */ put_u32(&buffer, 0); /* DCL count */ put_u32(&buffer, stat->fields[VKD3D_STAT_FLOAT]); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index a5d869172d3..447210449da 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -80,6 +80,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_TPF_INVALID_CASE_VALUE = 1007, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DIMENSION = 1008, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_SWIZZLE = 1009, + VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL = 1010, VKD3D_SHADER_WARNING_TPF_MASK_NOT_CONTIGUOUS = 1300, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK = 1301, diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c index 831dc07af56..839bb173854 100644 --- a/libs/vkd3d/libs/vkd3d/utils.c +++ b/libs/vkd3d/libs/vkd3d/utils.c @@ -703,7 +703,7 @@ const char *debug_vk_extent_3d(VkExtent3D extent) const char *debug_vk_queue_flags(VkQueueFlags flags) { - char buffer[159]; + char buffer[191]; buffer[0] = '\0'; #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } @@ -715,6 +715,7 @@ const char *debug_vk_queue_flags(VkQueueFlags flags) #undef FLAG_TO_STR #define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } FLAG_TO_STR(0x20, VK_QUEUE_VIDEO_DECODE_BIT_KHR) + FLAG_TO_STR(0x40, VK_QUEUE_VIDEO_ENCODE_BIT_KHR) #undef FLAG_TO_STR if (flags) FIXME("Unrecognized flag(s) %#x.\n", flags); -- 2.45.2