From baab59667d933fe15af4b456ea994d7aaf489d27 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 15 Aug 2025 07:48:03 +1000 Subject: [PATCH] Updated vkd3d to 44fffee5e1331e1c7e10489d84723c3b9dad7e17. --- libs/vkd3d/include/vkd3d_shader.h | 1 + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 17 +- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 5 +- libs/vkd3d/libs/vkd3d-shader/glsl.c | 3 + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 122 +++-- libs/vkd3d/libs/vkd3d-shader/hlsl.h | 3 +- libs/vkd3d/libs/vkd3d-shader/hlsl.y | 24 +- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 27 +- libs/vkd3d/libs/vkd3d-shader/ir.c | 418 +++++++++++------- libs/vkd3d/libs/vkd3d-shader/spirv.c | 100 +++-- .../libs/vkd3d-shader/vkd3d_shader_main.c | 161 +++++-- .../libs/vkd3d-shader/vkd3d_shader_private.h | 51 ++- 12 files changed, 607 insertions(+), 325 deletions(-) diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h index b50271ce9bb..0fd3c67b7e0 100644 --- a/libs/vkd3d/include/vkd3d_shader.h +++ b/libs/vkd3d/include/vkd3d_shader.h @@ -2966,6 +2966,7 @@ VKD3D_SHADER_API int vkd3d_shader_convert_root_signature(struct vkd3d_shader_ver * - VKD3D_SHADER_SOURCE_DXBC_DXIL * - VKD3D_SHADER_SOURCE_DXBC_TPF * - VKD3D_SHADER_SOURCE_D3D_BYTECODE + * - VKD3D_SHADER_SOURCE_HLSL * * \param compile_info A chained structure containing scan parameters. * \n diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index 2ec9a74249b..6425a8f62d2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -1961,7 +1961,7 @@ static void shader_print_descriptors(struct vkd3d_d3d_asm_compiler *compiler, } enum vkd3d_result d3d_asm_compile(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, enum vsir_asm_flags flags) + struct vkd3d_shader_code *out, enum vsir_asm_flags flags, struct vkd3d_shader_message_context *message_context) { const struct vkd3d_shader_version *shader_version = &program->shader_version; enum vkd3d_shader_compile_option_formatting_flags formatting; @@ -2029,6 +2029,14 @@ enum vkd3d_result d3d_asm_compile(struct vsir_program *program, const struct vkd if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_IO_SIGNATURES && shader_version->major >= 4) compiler.flags |= VSIR_ASM_FLAG_DUMP_SIGNATURES; + if (compiler.flags & VSIR_ASM_FLAG_ALLOCATE_TEMPS) + { + if ((result = vsir_allocate_temp_registers(program, message_context)) < 0) + return result; + if ((result = vsir_update_dcl_temps(program, message_context))) + return result; + } + buffer = &compiler.buffer; vkd3d_string_buffer_init(buffer); @@ -2250,17 +2258,22 @@ void vsir_program_trace(struct vsir_program *program) { const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES | VSIR_ASM_FLAG_DUMP_SIGNATURES | VSIR_ASM_FLAG_DUMP_DESCRIPTORS; + struct vkd3d_shader_message_context message_context; struct vkd3d_shader_code code; const char *p, *q, *end; + vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_NONE); + trace_signature(&program->input_signature, "Input"); trace_signature(&program->output_signature, "Output"); trace_signature(&program->patch_constant_signature, "Patch-constant"); trace_io_declarations(program); - if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) + if (d3d_asm_compile(program, NULL, &code, flags, &message_context) != VKD3D_OK) return; + vkd3d_shader_message_context_cleanup(&message_context); + end = (const char *)code.code + code.size; for (p = code.code; p < end; p = q) { diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index dd13757bf59..751e5578276 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -1513,7 +1513,10 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c return ret; } - return VKD3D_OK; + if (program->normalisation_level >= VSIR_NORMALISED_SM4) + ret = vsir_program_lower_d3dbc(program, config_flags, compile_info, message_context); + + return ret; } bool sm1_register_from_semantic_name(const struct vkd3d_shader_version *version, const char *semantic_name, diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index e57a4aa2731..dfe0a40ddf0 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -2444,6 +2444,9 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0) return ret; + if ((ret = vsir_allocate_temp_registers(program, message_context)) < 0) + return ret; + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); VKD3D_ASSERT(program->has_descriptor_info); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index 3199072275b..62335086e20 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -4897,8 +4897,9 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) hlsl_release_string_buffer(ctx, name); } -static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, - const struct hlsl_profile_info *profile, struct vkd3d_shader_message_context *message_context) +static bool hlsl_ctx_init(struct hlsl_ctx *ctx, struct vkd3d_shader_source_list *source_files, + const struct vkd3d_shader_compile_info *compile_info, const struct hlsl_profile_info *profile, + struct vkd3d_shader_message_context *message_context) { unsigned int i; @@ -4908,15 +4909,12 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil ctx->message_context = message_context; - if (!(ctx->source_files = hlsl_alloc(ctx, sizeof(*ctx->source_files)))) - return false; - if (!(ctx->source_files[0] = hlsl_strdup(ctx, compile_info->source_name ? compile_info->source_name : ""))) - { - vkd3d_free(ctx->source_files); + ctx->source_files = source_files; + if (!vkd3d_shader_source_list_append(source_files, + compile_info->source_name ? compile_info->source_name : "")) return false; - } - ctx->source_files_count = 1; - ctx->location.source_name = ctx->source_files[0]; + + ctx->location.source_name = source_files->sources[0]; ctx->location.line = ctx->location.column = 1; vkd3d_string_buffer_cache_init(&ctx->string_buffers); @@ -4924,8 +4922,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil if (!(ctx->dummy_scope = hlsl_new_scope(ctx, NULL))) { - vkd3d_free((void *)ctx->source_files[0]); - vkd3d_free(ctx->source_files); + vkd3d_string_buffer_cache_cleanup(&ctx->string_buffers); return false; } hlsl_push_scope(ctx); @@ -5010,9 +5007,6 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) struct hlsl_type *type, *next_type; unsigned int i; - for (i = 0; i < ctx->source_files_count; ++i) - vkd3d_free((void *)ctx->source_files[i]); - vkd3d_free(ctx->source_files); vkd3d_string_buffer_cache_cleanup(&ctx->string_buffers); rb_destroy(&ctx->functions, free_function_rb, NULL); @@ -5054,26 +5048,13 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) vkd3d_free(ctx->constant_defs.regs); } -static int hlsl_ctx_parse(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, +static int hlsl_ctx_parse(struct hlsl_ctx *ctx, struct vkd3d_shader_source_list *source_list, + const struct vkd3d_shader_compile_info *compile_info, const struct hlsl_profile_info *profile, struct vkd3d_shader_message_context *message_context) { enum vkd3d_shader_target_type target_type = compile_info->target_type; - const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; - const struct hlsl_profile_info *profile; int ret; - if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO))) - { - ERR("No HLSL source info given.\n"); - return VKD3D_ERROR_INVALID_ARGUMENT; - } - - if (!(profile = hlsl_get_target_info(hlsl_source_info->profile))) - { - FIXME("Unknown compilation target %s.\n", debugstr_a(hlsl_source_info->profile)); - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - if (target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, @@ -5099,7 +5080,7 @@ static int hlsl_ctx_parse(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil return VKD3D_ERROR_INVALID_ARGUMENT; } - if (!hlsl_ctx_init(ctx, compile_info, profile, message_context)) + if (!hlsl_ctx_init(ctx, source_list, compile_info, profile, message_context)) return VKD3D_ERROR_OUT_OF_MEMORY; if ((ret = hlsl_lexer_compile(ctx, &compile_info->source)) == 2) @@ -5128,35 +5109,85 @@ static int hlsl_ctx_parse(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil int hlsl_compile_effect(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_code *out) { + const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; + struct vkd3d_shader_source_list source_list; + const struct hlsl_profile_info *profile; struct hlsl_ctx ctx; int ret; - if ((ret = hlsl_ctx_parse(&ctx, compile_info, message_context)) < 0) + if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO))) + { + WARN("No HLSL source info given.\n"); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + + if (!(profile = hlsl_get_target_info(hlsl_source_info->profile))) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, + "Unknown target profile '%s'.", hlsl_source_info->profile); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + + vkd3d_shader_source_list_init(&source_list); + if ((ret = hlsl_ctx_parse(&ctx, &source_list, compile_info, profile, message_context)) < 0) + { + vkd3d_shader_source_list_cleanup(&source_list); return ret; + } ret = hlsl_emit_effect_binary(&ctx, out); hlsl_ctx_cleanup(&ctx); + vkd3d_shader_source_list_cleanup(&source_list); return ret; } -int hlsl_compile_shader(const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_code *out) +int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, + struct vsir_program *program, struct vkd3d_shader_code *reflection_data) { const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; - uint64_t config_flags = vkd3d_shader_init_config_flags(); struct hlsl_ir_function_decl *decl, *entry_func = NULL; - struct vkd3d_shader_code reflection_data = {0}; + enum vsir_normalisation_level normalisation_level; + const struct hlsl_profile_info *profile; + struct vkd3d_shader_version version; struct hlsl_ir_function *func; - struct vsir_program program; const char *entry_point; struct hlsl_ctx ctx; int ret; - if ((ret = hlsl_ctx_parse(&ctx, compile_info, message_context)) < 0) + if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO))) + { + WARN("No HLSL source info given.\n"); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + + if (!(profile = hlsl_get_target_info(hlsl_source_info->profile))) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, + "Unknown target profile '%s'.", hlsl_source_info->profile); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + + version = (struct vkd3d_shader_version) + { + .type = profile->type, + .major = profile->major_version, + .minor = profile->minor_version, + }; + normalisation_level = VSIR_NORMALISED_SM4; + if (version.major < 4 && (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM + || compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE)) + normalisation_level = VSIR_NORMALISED_SM1; + if (!vsir_program_init(program, compile_info, &version, 0, VSIR_CF_STRUCTURED, normalisation_level)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if ((ret = hlsl_ctx_parse(&ctx, &program->source_files, compile_info, profile, message_context)) < 0) + { + vsir_program_cleanup(program); return ret; + } - hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO); entry_point = hlsl_source_info->entry_point ? hlsl_source_info->entry_point : "main"; if ((func = hlsl_get_function(&ctx, entry_point))) { @@ -5181,17 +5212,16 @@ int hlsl_compile_shader(const struct vkd3d_shader_compile_info *compile_info, hlsl_error(&ctx, &loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Entry point \"%s\" is not defined.", entry_point); hlsl_ctx_cleanup(&ctx); + vsir_program_cleanup(program); return VKD3D_ERROR_INVALID_SHADER; } - if ((ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, &program, &reflection_data)) >= 0) - { - vsir_program_trace(&program); - ret = vsir_program_compile(&program, &reflection_data, config_flags, compile_info, out, message_context); - vkd3d_shader_free_shader_code(&reflection_data); - vsir_program_cleanup(&program); - } + ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, program, reflection_data); hlsl_ctx_cleanup(&ctx); + if (ret < 0) + vsir_program_cleanup(program); + else + vsir_program_trace(program); return ret; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index c3002258aa2..d67f820fe8b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -1093,8 +1093,7 @@ struct hlsl_ctx { const struct hlsl_profile_info *profile; - const char **source_files; - unsigned int source_files_count; + struct vkd3d_shader_source_list *source_files; /* Current location being read in the HLSL source, updated while parsing. */ struct vkd3d_shader_location location; /* Stores the logging messages and logging configuration. */ diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 66582e884fe..024d96c5663 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -7190,23 +7190,19 @@ declaration_statement_list: preproc_directive: PRE_LINE STRING { - const char **new_array = NULL; - - ctx->location.line = $1; if (strcmp($2, ctx->location.source_name)) - new_array = hlsl_realloc(ctx, ctx->source_files, - sizeof(*ctx->source_files) * (ctx->source_files_count + 1)); - - if (new_array) - { - ctx->source_files = new_array; - ctx->source_files[ctx->source_files_count++] = $2; - ctx->location.source_name = $2; - } - else { - vkd3d_free($2); + if (!vkd3d_shader_source_list_append(ctx->source_files, $2)) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + } + else + { + ctx->location.line = $1; + ctx->location.source_name = ctx->source_files->sources[ctx->source_files->count - 1]; + } } + vkd3d_free($2); } struct_declaration_without_vars: diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index dbda72eb30f..0b3dee4d2ce 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -9945,6 +9945,11 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co sm1_generate_vsir_block(ctx, body, program); program->ssa_count = ctx->ssa_count; + + if (ctx->result) + return; + if (program->normalisation_level >= VSIR_NORMALISED_SM4) + ctx->result = vsir_program_lower_d3dbc(program, config_flags, compile_info, ctx->message_context); } D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) @@ -14272,7 +14277,6 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info uint32_t config_flags = vkd3d_shader_init_config_flags(); const struct hlsl_profile_info *profile = ctx->profile; struct list semantic_vars, patch_semantic_vars; - struct vkd3d_shader_version version = {0}; struct hlsl_ir_var *var; parse_entry_function_attributes(ctx, entry_func); @@ -14349,39 +14353,24 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info if (ctx->result) return ctx->result; - version.major = ctx->profile->major_version; - version.minor = ctx->profile->minor_version; - version.type = ctx->profile->type; - if (!vsir_program_init(program, compile_info, &version, 0, VSIR_CF_STRUCTURED, VSIR_NORMALISED_SM4)) - { - ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; - return ctx->result; - } - generate_vsir_signature(ctx, program, entry_func, &semantic_vars); - if (version.type == VKD3D_SHADER_TYPE_HULL) + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL) generate_vsir_signature(ctx, program, ctx->patch_constant_func, &patch_semantic_vars); - if (version.major < 4) + if (program->shader_version.major < 4) sm1_generate_ctab(ctx, reflection_data); else sm4_generate_rdef(ctx, reflection_data); if (ctx->result) - { - vsir_program_cleanup(program); return ctx->result; - } - if (version.major < 4) + if (program->shader_version.major < 4) sm1_generate_vsir(ctx, compile_info, entry_func, &semantic_vars, &body, config_flags, program); else sm4_generate_vsir(ctx, compile_info, entry_func, &semantic_vars, &body, &patch_semantic_vars, &patch_body, config_flags, program); if (ctx->result) - { vkd3d_shader_free_shader_code(reflection_data); - vsir_program_cleanup(program); - } return ctx->result; } diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 9d93936ac9e..23e059a3490 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -451,6 +451,8 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_c return false; } + vkd3d_shader_source_list_init(&program->source_files); + return true; } @@ -463,6 +465,7 @@ void vsir_program_cleanup(struct vsir_program *program) for (i = 0; i < program->block_name_count; ++i) vkd3d_free((void *)program->block_names[i]); vkd3d_free(program->block_names); + vkd3d_shader_source_list_cleanup(&program->source_files); shader_instruction_array_destroy(&program->instructions); shader_signature_cleanup(&program->input_signature); shader_signature_cleanup(&program->output_signature); @@ -1387,6 +1390,53 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog return VKD3D_OK; } +static enum vkd3d_result vsir_program_lower_texcrd(struct vsir_program *program, + struct vkd3d_shader_instruction *ins, struct vkd3d_shader_message_context *message_context) +{ + /* texcrd DST, t# -> mov DST, t# */ + + if (ins->src[0].modifiers) + { + vkd3d_shader_error(message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "Aborting due to not yet implemented feature: texcrd source modifier."); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + + ins->opcode = VSIR_OP_MOV; + + return VKD3D_OK; +} + +static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *program, + struct vkd3d_shader_instruction *ins, struct vkd3d_shader_message_context *message_context) +{ + unsigned int idx = ins->src[0].reg.idx[0].offset; + struct vkd3d_shader_src_param *srcs; + + /* texld DST, t# -> sample DST, t#, resource#, sampler# */ + + if (ins->src[0].modifiers) + { + vkd3d_shader_error(message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "Aborting due to not yet implemented feature: texld source modifier."); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + + if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 3))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + /* Note we run before I/O normalization. */ + srcs[0] = ins->src[0]; + vsir_src_param_init_resource(&srcs[1], idx, idx); + vsir_src_param_init_sampler(&srcs[2], idx, idx); + + ins->opcode = VSIR_OP_SAMPLE; + ins->src = srcs; + ins->src_count = 3; + + return VKD3D_OK; +} + static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, struct vsir_program_iterator *it, unsigned int *tmp_idx) { @@ -1605,6 +1655,45 @@ static enum vkd3d_result vsir_program_lower_dcl_output(struct vsir_program *prog return VKD3D_OK; } +static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_program *program, + struct vsir_transformation_context *ctx) +{ + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + struct vkd3d_shader_message_context *message_context = ctx->message_context; + struct vkd3d_shader_instruction *ins; + unsigned int tmp_idx = ~0u; + + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { + enum vkd3d_result ret; + + switch (ins->opcode) + { + case VSIR_OP_TEXCRD: + ret = vsir_program_lower_texcrd(program, ins, message_context); + break; + + case VSIR_OP_TEXLD: + if (program->shader_version.major == 1) + ret = vsir_program_lower_texld_sm1(program, ins, message_context); + else if (ins->flags == VKD3DSI_TEXLD_PROJECT) + ret = vsir_program_lower_texldp(program, &it, &tmp_idx); + else + ret = vsir_program_lower_texld(program, ins, message_context); + break; + + default: + ret = VKD3D_OK; + break; + } + + if (ret < 0) + return ret; + } + + return VKD3D_OK; +} + static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *program, struct vsir_transformation_context *ctx) { @@ -1688,19 +1777,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr } break; - case VSIR_OP_TEXLD: - if (ins->flags == VKD3DSI_TEXLD_PROJECT) - { - if ((ret = vsir_program_lower_texldp(program, &it, &tmp_idx)) < 0) - return ret; - } - else - { - if ((ret = vsir_program_lower_texld(program, ins, message_context)) < 0) - return ret; - } - break; - case VSIR_OP_TEXLDD: if ((ret = vsir_program_lower_texldd(program, ins)) < 0) return ret; @@ -1714,7 +1790,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VSIR_OP_TEXBEM: case VSIR_OP_TEXBEML: case VSIR_OP_TEXCOORD: - case VSIR_OP_TEXCRD: case VSIR_OP_TEXDEPTH: case VSIR_OP_TEXDP3: case VSIR_OP_TEXDP3TEX: @@ -1762,6 +1837,39 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, return VKD3D_OK; } +/* ps_1_* outputs color in r0. Add an instruction to copy that to oC0. + * We don't need to modify the signature since it already contains COLOR. */ +static enum vkd3d_result vsir_program_normalise_ps1_output(struct vsir_program *program, + struct vsir_transformation_context *ctx) +{ + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_location loc; + + if (!(ins = vsir_program_iterator_tail(&it))) + return VKD3D_OK; + loc = ins->location; + + if (!(ins = vsir_program_append(program))) + return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1)) + { + vsir_instruction_init(ins, &loc, VSIR_OP_NOP); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + src_param_init_temp_float4(&ins->src[0], 0); + ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + /* Note we run before I/O normalization. */ + vsir_dst_param_init(&ins->dst[0], VKD3DSPR_COLOROUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = 0; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; + ins->dst[0].modifiers = VKD3DSPDM_SATURATE; + + return VKD3D_OK; +} + static struct signature_element *add_signature_element(struct shader_signature *signature, const char *semantic_name, uint32_t semantic_index, uint32_t mask, uint32_t register_index, enum vkd3d_shader_interpolation_mode interpolation_mode) @@ -1814,6 +1922,7 @@ static enum vkd3d_result vsir_program_add_diffuse_output(struct vsir_program *pr static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); static const struct vkd3d_shader_location no_loc; struct vkd3d_shader_instruction *ins; unsigned int i; @@ -1825,17 +1934,16 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra /* Write the instruction after all LABEL, DCL, and NOP instructions. * We need to skip NOP instructions because they might result from removed * DCLs, and there could still be DCLs after NOPs. */ - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - ins = &program->instructions.elements[i]; - if (!vsir_instruction_is_dcl(ins) && ins->opcode != VSIR_OP_LABEL && ins->opcode != VSIR_OP_NOP) break; } - if (!shader_instruction_array_insert_at(&program->instructions, i, 1)) + vsir_program_iterator_prev(&it); + if (!vsir_program_iterator_insert_after(&it, 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - ins = &program->instructions.elements[i]; + ins = vsir_program_iterator_next(&it); vsir_instruction_init_with_params(program, ins, &no_loc, VSIR_OP_MOV, 1, 1); vsir_dst_param_init(&ins->dst[0], VKD3DSPR_ATTROUT, VSIR_DATA_F32, 1); @@ -1936,6 +2044,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program struct vsir_transformation_context *ctx) { const struct vkd3d_shader_location location = {.source_name = ctx->compile_info->source_name}; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct vkd3d_shader_message_context *message_context = ctx->message_context; const struct vkd3d_shader_compile_info *compile_info = ctx->compile_info; bool allows_subset_masks = target_allows_subset_masks(compile_info); @@ -1945,6 +2054,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program struct signature_element *new_elements, *e; unsigned int uninit_varying_count = 0; unsigned int subset_varying_count = 0; + struct vkd3d_shader_instruction *ins; unsigned int new_register_count = 0; unsigned int i; @@ -2044,18 +2154,18 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program } /* Write each uninitialized varying before each ret. */ - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; struct vkd3d_shader_location loc; if (ins->opcode != VSIR_OP_RET) continue; loc = ins->location; - if (!shader_instruction_array_insert_at(&program->instructions, i, uninit_varying_count)) + vsir_program_iterator_prev(&it); + if (!vsir_program_iterator_insert_after(&it, uninit_varying_count)) return VKD3D_ERROR_OUT_OF_MEMORY; - ins = &program->instructions.elements[i]; + ins = vsir_program_iterator_next(&it); for (unsigned int j = signature->element_count - uninit_varying_count; j < signature->element_count; ++j) { @@ -2065,10 +2175,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, e->register_index, e->mask); vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; - ++ins; + ins = vsir_program_iterator_next(&it); } - - i += uninit_varying_count; } /* Vulkan (without KHR_maintenance4) disallows any mismatching masks, @@ -2079,10 +2187,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program if (!subset_varying_count || allows_subset_masks) return VKD3D_OK; - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - for (unsigned int j = 0; j < ins->dst_count; ++j) remove_unread_output_components(signature, ins, &ins->dst[j]); } @@ -2121,10 +2227,9 @@ struct shader_phase_location_array unsigned int count; }; -static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normaliser, - unsigned int index, struct shader_phase_location_array *locations) +static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normaliser, unsigned int index, + struct vkd3d_shader_instruction *ins, struct shader_phase_location_array *locations) { - struct vkd3d_shader_instruction *ins = &normaliser->program->instructions.elements[index]; struct shader_phase_location *loc; bool b; @@ -2289,15 +2394,19 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_program *program, struct vsir_transformation_context *ctx) { - struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct shader_phase_location_array locations; struct hull_flattener flattener = {program}; + struct vkd3d_shader_instruction *ins; enum vkd3d_result result = VKD3D_OK; unsigned int i; flattener.phase = VSIR_OP_INVALID; - for (i = 0, locations.count = 0; i < instructions->count; ++i) - flattener_eliminate_phase_related_dcls(&flattener, i, &locations); + locations.count = 0; + for (ins = vsir_program_iterator_head(&it), i = 0; ins; ins = vsir_program_iterator_next(&it), ++i) + { + flattener_eliminate_phase_related_dcls(&flattener, i, ins, &locations); + } bitmap_clear(program->io_dcls, VKD3DSPR_FORKINSTID); bitmap_clear(program->io_dcls, VKD3DSPR_JOININSTID); @@ -2315,10 +2424,9 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro if (flattener.phase != VSIR_OP_INVALID) { - if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) + if (!(ins = vsir_program_append(program))) return VKD3D_ERROR_OUT_OF_MEMORY; - vsir_instruction_init(&instructions->elements[instructions->count++], - &flattener.last_ret_location, VSIR_OP_RET); + vsir_instruction_init(ins, &flattener.last_ret_location, VSIR_OP_RET); } return result; @@ -2436,11 +2544,11 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_io( struct vsir_program *program, struct vsir_transformation_context *ctx) { - struct vkd3d_shader_instruction_array *instructions; struct control_point_normaliser normaliser; unsigned int input_control_point_count; struct vkd3d_shader_location location; struct vkd3d_shader_instruction *ins; + struct vsir_program_iterator it; enum vkd3d_result ret; unsigned int i, j; @@ -2458,13 +2566,11 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i return VKD3D_ERROR_OUT_OF_MEMORY; } normaliser.instructions = program->instructions; - instructions = &normaliser.instructions; + it = vsir_program_iterator(&normaliser.instructions); normaliser.phase = VSIR_OP_INVALID; - for (i = 0; i < normaliser.instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - ins = &instructions->elements[i]; - switch (ins->opcode) { case VSIR_OP_HS_CONTROL_POINT_PHASE: @@ -2484,10 +2590,8 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i normaliser.phase = VSIR_OP_INVALID; input_control_point_count = 1; - for (i = 0; i < instructions->count; ++i) + for (ins = vsir_program_iterator_head(&it), i = 0; ins; ins = vsir_program_iterator_next(&it), ++i) { - ins = &instructions->elements[i]; - switch (ins->opcode) { case VSIR_OP_DCL_INPUT_CONTROL_POINT_COUNT: @@ -2531,7 +2635,6 @@ struct io_normaliser { struct vkd3d_shader_message_context *message_context; enum vkd3d_result result; - struct vkd3d_shader_instruction_array instructions; enum vkd3d_shader_type shader_type; uint8_t major; struct shader_signature *input_signature; @@ -3147,10 +3250,10 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program *program, struct vsir_transformation_context *ctx) { - struct io_normaliser normaliser = {ctx->message_context, VKD3D_OK, program->instructions}; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + struct io_normaliser normaliser = {ctx->message_context, VKD3D_OK}; struct vkd3d_shader_instruction *ins; enum vkd3d_result ret; - unsigned int i; VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_HULL_CONTROL_POINT_IO); @@ -3161,10 +3264,8 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program normaliser.output_signature = &program->output_signature; normaliser.patch_constant_signature = &program->patch_constant_signature; - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - ins = &program->instructions.elements[i]; - switch (ins->opcode) { case VSIR_OP_DCL_OUTPUT_CONTROL_POINT_COUNT: @@ -3190,16 +3291,14 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program normaliser.output_range_map, false)) < 0 || (ret = shader_signature_merge(&normaliser, &program->patch_constant_signature, normaliser.pc_range_map, true)) < 0) - { - program->instructions = normaliser.instructions; return ret; - } normaliser.phase = VSIR_OP_INVALID; - for (i = 0; i < normaliser.instructions.count; ++i) - shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser); + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { + shader_instruction_normalise_io_params(ins, &normaliser); + } - program->instructions = normaliser.instructions; program->use_vocp = normaliser.use_vocp; program->normalisation_level = VSIR_NORMALISED_SM6; return normaliser.result; @@ -3288,13 +3387,13 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct flat_constants_normaliser normaliser = {0}; - unsigned int i, j; + struct vkd3d_shader_instruction *ins; + unsigned int i; - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - if (ins->opcode == VSIR_OP_DEF || ins->opcode == VSIR_OP_DEFI || ins->opcode == VSIR_OP_DEFB) { struct flat_constant_def *def; @@ -3309,15 +3408,19 @@ static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_progr def = &normaliser.defs[normaliser.def_count++]; get_flat_constant_register_type(&ins->dst[0].reg, &def->set, &def->index, NULL); - for (j = 0; j < 4; ++j) - def->value[j] = ins->src[0].reg.u.immconst_u32[j]; + for (i = 0; i < 4; ++i) + { + def->value[i] = ins->src[0].reg.u.immconst_u32[i]; + } vkd3d_shader_instruction_make_nop(ins); } else { - for (j = 0; j < ins->src_count; ++j) - shader_register_normalise_flat_constants(&ins->src[j], &normaliser); + for (i = 0; i < ins->src_count; ++i) + { + shader_register_normalise_flat_constants(&ins->src[i], &normaliser); + } } } @@ -3328,13 +3431,13 @@ static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_progr static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *program, struct vsir_transformation_context *ctx) { - size_t i, depth = 0; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + struct vkd3d_shader_instruction *ins; bool dead = false; + size_t depth = 0; - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - switch (ins->opcode) { case VSIR_OP_IF: @@ -3707,10 +3810,11 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte struct vkd3d_shader_message_context *message_context) { struct vkd3d_shader_instruction_array *instructions; + const struct vkd3d_shader_instruction *instruction; struct vsir_program *program = flattener->program; bool is_hull_shader, after_declarations_section; struct vkd3d_shader_instruction *dst_ins; - size_t i; + struct vsir_program_iterator it; instructions = &program->instructions; is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL; @@ -3719,10 +3823,10 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte if (!cf_flattener_require_space(flattener, instructions->count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - for (i = 0; i < instructions->count; ++i) + it = vsir_program_iterator(instructions); + for (instruction = vsir_program_iterator_head(&it); instruction; instruction = vsir_program_iterator_next(&it)) { unsigned int loop_header_block_id, loop_body_block_id, continue_block_id, merge_block_id, true_block_id; - const struct vkd3d_shader_instruction *instruction = &instructions->elements[i]; const struct vkd3d_shader_src_param *src = instruction->src; struct cf_flattener_info *cf_info; @@ -4321,10 +4425,12 @@ static void ssas_to_temps_block_info_cleanup(struct ssas_to_temps_block_info *bl static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_program *program, struct vsir_transformation_context *ctx) { - size_t ins_capacity = 0, ins_count = 0, phi_count, incoming_count, i; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + size_t ins_capacity = 0, ins_count = 0, phi_count, incoming_count; struct ssas_to_temps_block_info *info, *block_info = NULL; struct vkd3d_shader_instruction *instructions = NULL; struct ssas_to_temps_alloc alloc = {0}; + struct vkd3d_shader_instruction *ins; unsigned int current_label = 0; VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); @@ -4338,9 +4444,10 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ if (!ssas_to_temps_alloc_init(&alloc, program->ssa_count, program->temp_count)) goto fail; - for (i = 0, phi_count = 0, incoming_count = 0; i < program->instructions.count; ++i) + phi_count = 0; + incoming_count = 0; + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; unsigned int j, temp_idx; /* Only phi src/dst SSA values need be converted here. Structurisation may @@ -4383,9 +4490,9 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count + incoming_count - phi_count)) goto fail; - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *mov_ins, *ins = &program->instructions.elements[i]; + struct vkd3d_shader_instruction *mov_ins; size_t j; for (j = 0; j < ins->dst_count; ++j) @@ -6826,14 +6933,12 @@ static enum vkd3d_result vsir_program_apply_flat_interpolation(struct vsir_progr } static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *program, - const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func, + struct vsir_program_iterator *it, enum vkd3d_shader_comparison_func compare_func, const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, - uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context) + uint32_t colour_temp, struct vkd3d_shader_message_context *message_context) { - struct vkd3d_shader_instruction_array *instructions = &program->instructions; - const struct vkd3d_shader_location loc = ret->location; + struct vkd3d_shader_location loc = vsir_program_iterator_current(it)->location; static const struct vkd3d_shader_location no_loc; - size_t pos = ret - instructions->elements; struct vkd3d_shader_instruction *ins; static const struct @@ -6854,23 +6959,23 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr if (compare_func == VKD3D_SHADER_COMPARISON_FUNC_NEVER) { - if (!shader_instruction_array_insert_at(&program->instructions, pos, 1)) + vsir_program_iterator_prev(it); + if (!vsir_program_iterator_insert_after(it, 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - ret = NULL; - ins = &program->instructions.elements[pos]; + ins = vsir_program_iterator_next(it); vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_DISCARD, 0, 1); ins->flags = VKD3D_SHADER_CONDITIONAL_OP_Z; src_param_init_const_uint(&ins->src[0], 0); + vsir_program_iterator_next(it); - *ret_pos = pos + 1; return VKD3D_OK; } - if (!shader_instruction_array_insert_at(&program->instructions, pos, 3)) + vsir_program_iterator_prev(it); + if (!vsir_program_iterator_insert_after(it, 3)) return VKD3D_ERROR_OUT_OF_MEMORY; - ret = NULL; - ins = &program->instructions.elements[pos]; + ins = vsir_program_iterator_next(it); switch (ref->data_type) { @@ -6902,14 +7007,14 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr ins->src[opcodes[compare_func].swap ? 1 : 0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[opcodes[compare_func].swap ? 1 : 0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); - ++ins; + ins = vsir_program_iterator_next(it); vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_DISCARD, 0, 1); ins->flags = VKD3D_SHADER_CONDITIONAL_OP_Z; src_param_init_ssa_bool(&ins->src[0], program->ssa_count); ++program->ssa_count; - ++ins; + ins = vsir_program_iterator_next(it); vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VSIR_DATA_F32, 1); ins->dst[0].reg.idx[0].offset = colour_signature_idx; @@ -6919,20 +7024,21 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; - *ret_pos = pos + 3; + vsir_program_iterator_next(it); + return VKD3D_OK; } static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct vkd3d_shader_message_context *message_context = ctx->message_context; const struct vkd3d_shader_parameter1 *func = NULL, *ref = NULL; uint32_t colour_signature_idx, colour_temp = ~0u; static const struct vkd3d_shader_location no_loc; enum vkd3d_shader_comparison_func compare_func; struct vkd3d_shader_instruction *ins; - size_t new_pos; int ret; if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) @@ -6969,19 +7075,16 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro if (compare_func != VKD3D_SHADER_COMPARISON_FUNC_NEVER) colour_temp = program->temp_count++; - for (size_t i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - ins = &program->instructions.elements[i]; - if (vsir_instruction_is_dcl(ins)) continue; if (ins->opcode == VSIR_OP_RET) { - if ((ret = insert_alpha_test_before_ret(program, ins, compare_func, - ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0) + if ((ret = insert_alpha_test_before_ret(program, &it, compare_func, + ref, colour_signature_idx, colour_temp, message_context)) < 0) return ret; - i = new_pos; continue; } @@ -7007,19 +7110,17 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro } static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *program, - const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx, - uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos) + struct vsir_program_iterator *it, uint32_t mask, uint32_t position_signature_idx, + uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx) { - struct vkd3d_shader_instruction_array *instructions = &program->instructions; - const struct vkd3d_shader_location loc = ret->location; - size_t pos = ret - instructions->elements; + const struct vkd3d_shader_location loc = vsir_program_iterator_current(it)->location; struct vkd3d_shader_instruction *ins; unsigned int output_idx = 0; - if (!shader_instruction_array_insert_at(&program->instructions, pos, vkd3d_popcount(mask) + 1)) + vsir_program_iterator_prev(it); + if (!vsir_program_iterator_insert_after(it, vkd3d_popcount(mask) + 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - ret = NULL; - ins = &program->instructions.elements[pos]; + ins = vsir_program_iterator_next(it); for (unsigned int i = 0; i < 8; ++i) { @@ -7041,7 +7142,7 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog ins->dst[0].write_mask = (1u << (output_idx % 4)); ++output_idx; - ++ins; + ins = vsir_program_iterator_next(it); } vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -7052,14 +7153,15 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog src_param_init_temp_float(&ins->src[0], position_temp); ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ins = vsir_program_iterator_next(it); - *ret_pos = pos + vkd3d_popcount(mask) + 1; return VKD3D_OK; } static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct shader_signature *signature = &program->output_signature; unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; const struct vkd3d_shader_parameter1 *mask_parameter = NULL; @@ -7068,7 +7170,6 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr struct signature_element *clip_element; struct vkd3d_shader_instruction *ins; unsigned int plane_count; - size_t new_pos; int ret; if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX) @@ -7144,19 +7245,16 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr position_temp = program->temp_count++; - for (size_t i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - ins = &program->instructions.elements[i]; - if (vsir_instruction_is_dcl(ins)) continue; if (ins->opcode == VSIR_OP_RET) { - if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx, - position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0) + if ((ret = insert_clip_planes_before_ret(program, &it, mask, position_signature_idx, + position_temp, low_signature_idx, high_signature_idx)) < 0) return ret; - i = new_pos; continue; } @@ -7185,32 +7283,32 @@ static bool is_pre_rasterization_shader(enum vkd3d_shader_type type) } static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *program, - const struct vkd3d_shader_instruction *ret, size_t *ret_pos) + struct vsir_program_iterator *it) { - struct vkd3d_shader_instruction_array *instructions = &program->instructions; - const struct vkd3d_shader_location loc = ret->location; - size_t pos = ret - instructions->elements; + const struct vkd3d_shader_location loc = vsir_program_iterator_current(it)->location; struct vkd3d_shader_instruction *ins; - if (!shader_instruction_array_insert_at(&program->instructions, pos, 1)) + vsir_program_iterator_prev(it); + if (!vsir_program_iterator_insert_after(it, 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - ret = NULL; - ins = &program->instructions.elements[pos]; + ins = vsir_program_iterator_next(it); vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, VSIR_DATA_F32); + ins = vsir_program_iterator_next(it); - *ret_pos = pos + 1; return VKD3D_OK; } static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); const struct vkd3d_shader_parameter1 *size_parameter = NULL; static const struct vkd3d_shader_location no_loc; + struct vkd3d_shader_instruction *ins; if (program->has_point_size) return VKD3D_OK; @@ -7239,18 +7337,14 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro program->has_point_size = true; /* Append a point size write before each ret. */ - for (size_t i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - if (ins->opcode == VSIR_OP_RET) { - size_t new_pos; int ret; - if ((ret = insert_point_size_before_ret(program, ins, &new_pos)) < 0) + if ((ret = insert_point_size_before_ret(program, &it)) < 0) return ret; - i = new_pos; } } @@ -7261,7 +7355,9 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra struct vsir_transformation_context *ctx) { const struct vkd3d_shader_parameter1 *min_parameter = NULL, *max_parameter = NULL; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); static const struct vkd3d_shader_location no_loc; + struct vkd3d_shader_instruction *ins; if (!program->has_point_size) return VKD3D_OK; @@ -7298,9 +7394,8 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra /* Replace writes to the point size by inserting a clamp before each write. */ - for (size_t i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; const struct vkd3d_shader_location *loc; unsigned int ssa_value; bool clamp = false; @@ -7324,11 +7419,11 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra if (!clamp) continue; - if (!shader_instruction_array_insert_at(&program->instructions, i + 1, !!min_parameter + !!max_parameter)) + if (!vsir_program_iterator_insert_after(&it, !!min_parameter + !!max_parameter)) return VKD3D_ERROR_OUT_OF_MEMORY; - ins = &program->instructions.elements[i + 1]; - loc = &program->instructions.elements[i].location; + loc = &vsir_program_iterator_current(&it)->location; + ins = vsir_program_iterator_next(&it); if (min_parameter) { @@ -7345,8 +7440,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; } - ++ins; - ++i; + ins = vsir_program_iterator_next(&it); } if (max_parameter) @@ -7356,8 +7450,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, VSIR_DATA_F32); vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; - - ++i; + ins = vsir_program_iterator_next(&it); } } @@ -7435,12 +7528,13 @@ static bool replace_texcoord_with_point_coord(struct vsir_program *program, static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions), it2; const struct vkd3d_shader_parameter1 *sprite_parameter = NULL; static const struct vkd3d_shader_location no_loc; struct vkd3d_shader_instruction *ins; bool used_texcoord = false; unsigned int coord_temp; - size_t i, insert_pos; + size_t i; if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) return VKD3D_OK; @@ -7481,21 +7575,16 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr /* Construct the new temp after all LABEL, DCL, and NOP instructions. * We need to skip NOP instructions because they might result from removed * DCLs, and there could still be DCLs after NOPs. */ - for (i = 0; i < program->instructions.count; ++i) + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { - ins = &program->instructions.elements[i]; - if (!vsir_instruction_is_dcl(ins) && ins->opcode != VSIR_OP_LABEL && ins->opcode != VSIR_OP_NOP) break; } - insert_pos = i; - + it2 = it; /* Replace each texcoord read with a read from the point coord. */ - for (; i < program->instructions.count; ++i) + for (; ins; ins = vsir_program_iterator_next(&it2)) { - ins = &program->instructions.elements[i]; - if (vsir_instruction_is_dcl(ins)) continue; @@ -7524,9 +7613,10 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr if (used_texcoord) { - if (!shader_instruction_array_insert_at(&program->instructions, insert_pos, 2)) + vsir_program_iterator_prev(&it); + if (!vsir_program_iterator_insert_after(&it, 2)) return VKD3D_ERROR_OUT_OF_MEMORY; - ins = &program->instructions.elements[insert_pos]; + ins = vsir_program_iterator_next(&it); vsir_instruction_init_with_params(program, ins, &no_loc, VSIR_OP_MOV, 1, 1); dst_param_init_temp_float4(&ins->dst[0], coord_temp); @@ -7534,14 +7624,14 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr vsir_src_param_init(&ins->src[0], VKD3DSPR_POINT_COORD, VSIR_DATA_F32, 0); ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; - ++ins; + ins = vsir_program_iterator_next(&it); vsir_instruction_init_with_params(program, ins, &no_loc, VSIR_OP_MOV, 1, 1); dst_param_init_temp_float4(&ins->dst[0], coord_temp); ins->dst[0].write_mask = VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; - ++ins; + vsir_program_iterator_next(&it); program->has_point_coord = true; } @@ -12045,6 +12135,28 @@ enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uin return ctx.result; } +enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) +{ + struct vsir_transformation_context ctx = + { + .result = VKD3D_OK, + .program = program, + .config_flags = config_flags, + .compile_info = compile_info, + .message_context = message_context, + }; + + vsir_transform(&ctx, vsir_program_lower_d3dbc_instructions); + if (program->shader_version.major == 1 && program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL) + vsir_transform(&ctx, vsir_program_normalise_ps1_output); + + if (TRACE_ON()) + vsir_program_trace(program); + + return ctx.result; +} + enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) { diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 4f50eadf714..a4990d982bc 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -5676,6 +5676,48 @@ static unsigned int shader_signature_next_location(const struct shader_signature return max_row; } +static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_register *reg = &dst->reg; + const struct vkd3d_spirv_builtin *builtin; + struct vkd3d_symbol reg_symbol; + SpvStorageClass storage_class; + uint32_t write_mask, id; + struct rb_entry *entry; + + VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr); + VKD3D_ASSERT(reg->idx_count < 2); + + if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) + { + builtin = &vkd3d_output_point_size_builtin; + storage_class = SpvStorageClassOutput; + } + else if (!(builtin = get_spirv_builtin_for_register(reg->type, &storage_class))) + { + FIXME("Unhandled register %#x.\n", reg->type); + return NULL; + } + + /* vPrim may be declared in multiple hull shader phases. */ + vkd3d_symbol_make_register(®_symbol, reg); + if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) + return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); + + id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, 0); + spirv_compiler_emit_register_execution_mode(compiler, reg->type); + spirv_compiler_emit_register_debug_name(builder, id, reg); + + write_mask = vkd3d_write_mask_from_component_count(builtin->component_count); + vkd3d_symbol_set_register_info(®_symbol, id, + storage_class, builtin->component_type, write_mask); + reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; + + return spirv_compiler_put_symbol(compiler, ®_symbol); +} + static void spirv_compiler_emit_input(struct spirv_compiler *compiler, enum vkd3d_shader_register_type reg_type, unsigned int element_idx) { @@ -5684,6 +5726,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, const struct signature_element *signature_element; const struct shader_signature *shader_signature; enum vkd3d_shader_component_type component_type; + enum vkd3d_shader_register_type sysval_reg_type; const struct vkd3d_spirv_builtin *builtin; enum vkd3d_shader_sysval_semantic sysval; uint32_t write_mask, reg_write_mask; @@ -5708,6 +5751,22 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, if (!signature_element->used_mask) return; + sysval_reg_type = vsir_register_type_from_sysval_input(signature_element->sysval_semantic); + if (sysval_reg_type != VKD3DSPR_INPUT) + { + struct vkd3d_shader_dst_param dst; + const struct vkd3d_symbol *symbol; + + vsir_dst_param_init(&dst, sysval_reg_type, VSIR_DATA_F32, 0); + symbol = spirv_compiler_emit_io_register(compiler, &dst); + + vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); + reg_symbol.id = symbol->id; + reg_symbol.info.reg = symbol->info.reg; + spirv_compiler_put_symbol(compiler, ®_symbol); + return; + } + builtin = get_spirv_builtin_for_sysval(compiler, sysval); array_sizes[0] = signature_element->register_count; @@ -5829,47 +5888,6 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, } } -static void spirv_compiler_emit_io_register(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_register *reg = &dst->reg; - const struct vkd3d_spirv_builtin *builtin; - struct vkd3d_symbol reg_symbol; - SpvStorageClass storage_class; - uint32_t write_mask, id; - struct rb_entry *entry; - - VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr); - VKD3D_ASSERT(reg->idx_count < 2); - - if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) - { - builtin = &vkd3d_output_point_size_builtin; - storage_class = SpvStorageClassOutput; - } - else if (!(builtin = get_spirv_builtin_for_register(reg->type, &storage_class))) - { - FIXME("Unhandled register %#x.\n", reg->type); - return; - } - - /* vPrim may be declared in multiple hull shader phases. */ - vkd3d_symbol_make_register(®_symbol, reg); - if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) - return; - - id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, 0); - - write_mask = vkd3d_write_mask_from_component_count(builtin->component_count); - vkd3d_symbol_set_register_info(®_symbol, id, - storage_class, builtin->component_type, write_mask); - reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; - spirv_compiler_put_symbol(compiler, ®_symbol); - spirv_compiler_emit_register_execution_mode(compiler, reg->type); - spirv_compiler_emit_register_debug_name(builder, id, reg); -} - static unsigned int get_shader_output_swizzle(const struct spirv_compiler *compiler, unsigned int register_idx) { diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index 891a33d326f..d1992c9d446 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -57,6 +57,39 @@ uint32_t vkd3d_parse_integer(const char *s) return ret; } +bool vkd3d_shader_source_list_append(struct vkd3d_shader_source_list *l, const char *source) +{ + char *s; + + if (!(s = vkd3d_strdup(source))) + return false; + + if (!vkd3d_array_reserve((void **)&l->sources, &l->capacity, l->count + 1, sizeof(*l->sources))) + { + vkd3d_free(s); + return false; + } + l->sources[l->count++] = s; + + return true; +} + +void vkd3d_shader_source_list_cleanup(struct vkd3d_shader_source_list *l) +{ + size_t i; + + for (i = 0; i < l->count; ++i) + { + vkd3d_free((void *)l->sources[i]); + } + vkd3d_free(l->sources); +} + +void vkd3d_shader_source_list_init(struct vkd3d_shader_source_list *l) +{ + memset(l, 0, sizeof(*l)); +} + void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer) { buffer->buffer_size = 16; @@ -767,12 +800,28 @@ static int vkd3d_shader_validate_compile_info(const struct vkd3d_shader_compile_ } static enum vkd3d_result vsir_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags, - struct vkd3d_shader_message_context *message_context, struct vsir_program *program) + const struct shader_dump_data *dump_data, struct vkd3d_shader_message_context *message_context, + struct vsir_program *program, struct vkd3d_shader_code *reflection_data) { + struct vkd3d_shader_compile_info preprocessed_info; + struct vkd3d_shader_code preprocessed; enum vkd3d_result ret; switch (compile_info->source_type) { + case VKD3D_SHADER_SOURCE_HLSL: + if ((ret = preproc_lexer_parse(compile_info, &preprocessed, message_context)) >= 0) + { + vkd3d_shader_dump_shader(dump_data, preprocessed.code, preprocessed.size, SHADER_DUMP_TYPE_PREPROC); + + preprocessed_info = *compile_info; + preprocessed_info.source = preprocessed; + ret = hlsl_parse(&preprocessed_info, message_context, program, reflection_data); + + vkd3d_shader_free_shader_code(&preprocessed); + } + break; + case VKD3D_SHADER_SOURCE_D3D_BYTECODE: ret = d3dbc_parse(compile_info, config_flags, message_context, program); break; @@ -803,13 +852,19 @@ static enum vkd3d_result vsir_parse(const struct vkd3d_shader_compile_info *comp if (TRACE_ON()) vsir_program_trace(program); - - vsir_program_cleanup(program); - return ret; + goto fail; } - if (compile_info->target_type != VKD3D_SHADER_TARGET_NONE) - ret = vsir_program_transform_early(program, config_flags, compile_info, message_context); + if (compile_info->target_type != VKD3D_SHADER_TARGET_NONE + && (ret = vsir_program_transform_early(program, config_flags, compile_info, message_context)) < 0) + goto fail; + + return ret; + +fail: + vkd3d_shader_free_shader_code(reflection_data); + vsir_program_cleanup(program); + return ret; } @@ -1233,6 +1288,40 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co s->sampler_index = sampler_idx; } +static void vkd3d_shader_scan_sample_instruction(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) +{ + unsigned int resource_idx = resource->idx[0].offset; + unsigned int sampler_idx = sampler->idx[0].offset; + + vkd3d_shader_scan_combined_sampler_usage(context, resource, sampler); + + if (!context->scan_descriptor_info) + return; + + /* Sample instructions lowered from 1.x texture instructions have no + * DCL, so we need to add the resource if it didn't already exist. + * Such descriptors have a fixed count, type, etc. */ + + if (!vkd3d_shader_find_descriptor(context->scan_descriptor_info, + VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_idx)) + { + struct vkd3d_shader_register_range range = {.first = resource_idx, .last = resource_idx}; + + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource, + &range, VKD3D_SHADER_RESOURCE_TEXTURE_2D, VSIR_DATA_F32); + } + + if (!vkd3d_shader_find_descriptor(context->scan_descriptor_info, + VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_idx)) + { + struct vkd3d_shader_register_range range = {.first = sampler_idx, .last = sampler_idx}; + + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, resource, + &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED); + } +} + static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context, const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type, enum vsir_data_type resource_data_type, unsigned int sample_count, @@ -1436,13 +1525,6 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte if (context->cf_info_count) context->cf_info[context->cf_info_count - 1].inside_block = false; break; - case VSIR_OP_TEXLD: - if (context->version->major == 1) - sampler_reg = &instruction->dst[0].reg; - else - sampler_reg = &instruction->src[1].reg; - vkd3d_shader_scan_combined_sampler_usage(context, sampler_reg, sampler_reg); - break; case VSIR_OP_TEX: case VSIR_OP_TEXBEM: case VSIR_OP_TEXBEML: @@ -1459,7 +1541,6 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte break; case VSIR_OP_GATHER4: case VSIR_OP_GATHER4_C: - case VSIR_OP_SAMPLE: case VSIR_OP_SAMPLE_B: case VSIR_OP_SAMPLE_C: case VSIR_OP_SAMPLE_C_LZ: @@ -1467,6 +1548,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte case VSIR_OP_SAMPLE_LOD: vkd3d_shader_scan_combined_sampler_usage(context, &instruction->src[1].reg, &instruction->src[2].reg); break; + case VSIR_OP_SAMPLE: + vkd3d_shader_scan_sample_instruction(context, &instruction->src[1].reg, &instruction->src[2].reg); + break; case VSIR_OP_GATHER4_PO: case VSIR_OP_GATHER4_PO_C: vkd3d_shader_scan_combined_sampler_usage(context, &instruction->src[2].reg, &instruction->src[3].reg); @@ -1691,7 +1775,9 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages) { struct vkd3d_shader_message_context message_context; + struct vkd3d_shader_code reflection_data = {0}; struct shader_dump_data dump_data; + struct vsir_program program; int ret; TRACE("compile_info %p, messages %p.\n", compile_info, messages); @@ -1709,21 +1795,12 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char fill_shader_dump_data(compile_info, &dump_data); vkd3d_shader_dump_shader(&dump_data, compile_info->source.code, compile_info->source.size, SHADER_DUMP_TYPE_SOURCE); - if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL) - { - FIXME("HLSL support not implemented.\n"); - ret = VKD3D_ERROR_NOT_IMPLEMENTED; - } - else + if (!(ret = vsir_parse(compile_info, vkd3d_shader_init_config_flags(), + &dump_data, &message_context, &program, &reflection_data))) { - uint64_t config_flags = vkd3d_shader_init_config_flags(); - struct vsir_program program; - - if (!(ret = vsir_parse(compile_info, config_flags, &message_context, &program))) - { - ret = vsir_program_scan(&program, compile_info, &message_context, false); - vsir_program_cleanup(&program); - } + ret = vsir_program_scan(&program, compile_info, &message_context, false); + vkd3d_shader_free_shader_code(&reflection_data); + vsir_program_cleanup(&program); } vkd3d_shader_message_context_trace_messages(&message_context); @@ -1733,12 +1810,13 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char return ret; } -int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, +static int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { struct vkd3d_shader_scan_combined_resource_sampler_info combined_sampler_info; struct vkd3d_shader_compile_info scan_info; + enum vsir_asm_flags asm_flags; int ret; scan_info = *compile_info; @@ -1748,7 +1826,11 @@ int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader case VKD3D_SHADER_TARGET_D3D_ASM: if ((ret = vsir_program_scan(program, &scan_info, message_context, true)) < 0) return ret; - ret = d3d_asm_compile(program, compile_info, out, VSIR_ASM_FLAG_NONE); + asm_flags = VSIR_ASM_FLAG_NONE; + if (program->shader_version.major < 6 && compile_info->source_type != VKD3D_SHADER_SOURCE_DXBC_TPF + && compile_info->source_type != VKD3D_SHADER_SOURCE_D3D_BYTECODE) + asm_flags |= VSIR_ASM_FLAG_ALLOCATE_TEMPS; + ret = d3d_asm_compile(program, compile_info, out, asm_flags, message_context); break; case VKD3D_SHADER_TARGET_D3D_BYTECODE: @@ -1795,7 +1877,7 @@ int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader return ret; } -static int compile_hlsl(const struct vkd3d_shader_compile_info *compile_info, +static int fx_compile(const struct vkd3d_shader_compile_info *compile_info, const struct shader_dump_data *dump_data, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { @@ -1810,10 +1892,7 @@ static int compile_hlsl(const struct vkd3d_shader_compile_info *compile_info, preprocessed_info = *compile_info; preprocessed_info.source = preprocessed; - if (compile_info->target_type == VKD3D_SHADER_TARGET_FX) - ret = hlsl_compile_effect(&preprocessed_info, message_context, out); - else - ret = hlsl_compile_shader(&preprocessed_info, message_context, out); + ret = hlsl_compile_effect(&preprocessed_info, message_context, out); vkd3d_shader_free_shader_code(&preprocessed); return ret; @@ -1841,9 +1920,10 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, fill_shader_dump_data(compile_info, &dump_data); vkd3d_shader_dump_shader(&dump_data, compile_info->source.code, compile_info->source.size, SHADER_DUMP_TYPE_SOURCE); - if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL) + if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL + && compile_info->target_type == VKD3D_SHADER_TARGET_FX) { - ret = compile_hlsl(compile_info, &dump_data, out, &message_context); + ret = fx_compile(compile_info, &dump_data, out, &message_context); } else if (compile_info->source_type == VKD3D_SHADER_SOURCE_FX) { @@ -1856,11 +1936,14 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, else { uint64_t config_flags = vkd3d_shader_init_config_flags(); + struct vkd3d_shader_code reflection_data = {0}; struct vsir_program program; - if (!(ret = vsir_parse(compile_info, config_flags, &message_context, &program))) + if (!(ret = vsir_parse(compile_info, config_flags, &dump_data, + &message_context, &program, &reflection_data))) { - ret = vsir_program_compile(&program, NULL, config_flags, compile_info, out, &message_context); + ret = vsir_program_compile(&program, &reflection_data, config_flags, compile_info, out, &message_context); + vkd3d_shader_free_shader_code(&reflection_data); vsir_program_cleanup(&program); } } diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index 5bf3728a325..e758c16b3d4 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -937,6 +937,16 @@ enum vkd3d_shader_type struct vkd3d_shader_message_context; +struct vkd3d_shader_source_list +{ + const char **sources; + size_t capacity, count; +}; + +bool vkd3d_shader_source_list_append(struct vkd3d_shader_source_list *l, const char *source); +void vkd3d_shader_source_list_cleanup(struct vkd3d_shader_source_list *l); +void vkd3d_shader_source_list_init(struct vkd3d_shader_source_list *l); + struct vkd3d_shader_version { enum vkd3d_shader_type type; @@ -1013,6 +1023,20 @@ static inline bool vsir_register_is_descriptor(const struct vkd3d_shader_registe } } +static inline enum vkd3d_shader_register_type vsir_register_type_from_sysval_input( + enum vkd3d_shader_sysval_semantic sysval) +{ + switch (sysval) + { + case VKD3D_SHADER_SV_PRIMITIVE_ID: + return VKD3DSPR_PRIMID; + case VKD3D_SHADER_SV_COVERAGE: + return VKD3DSPR_COVERAGE; + default: + return VKD3DSPR_INPUT; + } +} + struct vkd3d_shader_dst_param { struct vkd3d_shader_register reg; @@ -1463,12 +1487,21 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_tail(struct static inline struct vkd3d_shader_instruction *vsir_program_iterator_next( struct vsir_program_iterator *iterator) { - if (iterator->idx < iterator->array->count) + if (iterator->idx < iterator->array->count || iterator->idx == SIZE_MAX) ++iterator->idx; return vsir_program_iterator_current(iterator); } +static inline struct vkd3d_shader_instruction *vsir_program_iterator_prev( + struct vsir_program_iterator *iterator) +{ + if (iterator->idx != SIZE_MAX) + --iterator->idx; + + return vsir_program_iterator_current(iterator); +} + /* When insertion takes place, argument `it' is updated to point to the same * instruction as before the insertion, but all other iterators and pointers * to the same container are invalidated and cannot be used any more. */ @@ -1563,6 +1596,7 @@ struct vsir_program struct vsir_features features; + struct vkd3d_shader_source_list source_files; const char **block_names; size_t block_name_count; }; @@ -1572,14 +1606,13 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, struct vkd3d_shader_message_context *message_context); void vsir_program_cleanup(struct vsir_program *program); -int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, - uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( const struct vsir_program *program, enum vkd3d_shader_parameter_name name); bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type, enum vsir_normalisation_level normalisation_level); +enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uint64_t config_flags, @@ -1652,11 +1685,12 @@ enum vsir_asm_flags VSIR_ASM_FLAG_DUMP_ALL_INDICES = 0x2, VSIR_ASM_FLAG_DUMP_SIGNATURES = 0x4, VSIR_ASM_FLAG_DUMP_DESCRIPTORS = 0x8, + VSIR_ASM_FLAG_ALLOCATE_TEMPS = 0x10, }; enum vkd3d_result d3d_asm_compile(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_compile_info *compile_info, struct vkd3d_shader_code *out, + enum vsir_asm_flags flags, struct vkd3d_shader_message_context *message_context); void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer); @@ -1808,8 +1842,9 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, int hlsl_compile_effect(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_code *out); -int hlsl_compile_shader(const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_code *out); +int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, + struct vsir_program *program, struct vkd3d_shader_code *reflection_data); static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( enum vsir_data_type data_type) { -- 2.50.1