From 6e15664bffca10be933869bd9cfa4cf5db7c0a61 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Tue, 14 Jan 2025 22:45:57 +0100 Subject: [PATCH] vkd3d-shader/fx: Implement shader assignment. --- libs/vkd3d-shader/fx.c | 134 ++++++++++++++++++++++- libs/vkd3d-shader/hlsl.c | 2 +- libs/vkd3d-shader/hlsl.h | 4 +- libs/vkd3d-shader/hlsl_codegen.c | 21 ++-- libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- libs/vkd3d-shader/vkd3d_shader_private.h | 3 + tests/hlsl/effect-compile.shader_test | 5 +- 7 files changed, 154 insertions(+), 17 deletions(-) diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 61e0e0344..c8ccab686 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -107,6 +107,14 @@ struct fx_5_shader uint32_t iface_bindings; }; +enum fx_shader_type +{ + FX_SHADER_NONE, + FX4_SHADER, + FX4_SHADER_SO, + FX5_SHADER +}; + struct string_entry { struct rb_entry entry; @@ -293,6 +301,7 @@ struct fx_write_context uint32_t rasterizer_state_count; uint32_t blend_state_count; uint32_t string_count; + uint32_t inline_shader_count; int status; bool child_effect; @@ -2285,6 +2294,107 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s return offset; } +static uint32_t write_shader_blob(const struct hlsl_ir_compile *compile, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + struct vkd3d_shader_code source = {0}, rdef = {0}; + const struct hlsl_profile_info *profile; + struct vkd3d_shader_version version; + struct hlsl_ctx *ctx = fx->ctx; + struct vsir_program program; + uint32_t offset; + int ret = 0; + + static const struct vkd3d_shader_compile_option version_option = + { + .name = VKD3D_SHADER_COMPILE_OPTION_API_VERSION, + .value = VKD3D_SHADER_API_VERSION_CURRENT, + }; + static const struct vkd3d_shader_compile_info compile_info = + { + .type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO, + .target_type = VKD3D_SHADER_TARGET_DXBC_TPF, + .options = &version_option, + .option_count = 1, + }; + + version = (struct vkd3d_shader_version) + { + .type = compile->profile->type, + .major = compile->profile->major_version, + .minor = compile->profile->minor_version, + }; + + if (!vsir_program_init(&program, &compile_info, &version, 0, VSIR_CF_STRUCTURED, VSIR_NORMALISED_SM4)) + return 0; + + profile = ctx->profile; + ctx->profile = compile->profile; + ret = hlsl_emit_vsir(ctx, &compile_info, compile->decl, &compile->initializers, &program, &rdef); + ctx->profile = profile; + if (ret < 0) + return 0; + + ret = vsir_program_compile(&program, &rdef, vkd3d_shader_init_config_flags(), + &compile_info, &source, ctx->message_context); + + vkd3d_shader_free_shader_code(&rdef); + vsir_program_cleanup(&program); + if (ret < 0) + return 0; + + offset = put_u32(buffer, source.size); + bytecode_put_bytes_unaligned(buffer, source.code, source.size); + + vkd3d_shader_free_shader_code(&source); + + return offset; +} + +static uint32_t write_fx_shader(enum fx_shader_type type, + const struct hlsl_ir_compile *compile, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + struct fx_5_shader shader = {0}; + uint32_t ret; + + shader = (struct fx_5_shader) + { + .offset = write_shader_blob(compile, fx), + .sodecl_count = compile->output.count > 1 ? 4 : 0, + .rast_stream = compile->output.stream, + }; + + for (size_t i = 0; i < compile->output.count; ++i) + { + shader.sodecl[i] = write_string(compile->output.decls[i], fx); + } + + switch (type) + { + case FX4_SHADER: + ret = put_u32(buffer, shader.offset); + break; + + case FX4_SHADER_SO: + ret = put_u32(buffer, shader.offset); + put_u32(buffer, shader.sodecl[0]); + break; + + case FX5_SHADER: + ret = bytecode_put_bytes(buffer, &shader, sizeof(shader)); + break; + + default: + ret = 0; + break; + } + + ++fx->inline_shader_count; + + return ret; +} + static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, struct fx_write_context *fx) { @@ -2379,6 +2489,24 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl } break; } + case HLSL_IR_COMPILE: + { + enum fx_shader_type shader_type; + + if (hlsl_version_lt(ctx, 5, 0)) + { + assignment_type = FX_4_ASSIGNMENT_INLINE_SHADER; + shader_type = FX4_SHADER_SO; + } + else + { + assignment_type = FX_5_ASSIGNMENT_INLINE_SHADER; + shader_type = FX5_SHADER; + } + + value_offset = write_fx_shader(shader_type, hlsl_ir_compile(value), fx); + break; + } default: hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name); } @@ -2928,6 +3056,8 @@ static void resolve_fx_state_block_values(struct hlsl_ir_var *var, break; } + case HLSL_IR_COMPILE: + break; default: hlsl_fixme(ctx, &ctx->location, "Unhandled node type for object-typed field."); } @@ -3480,7 +3610,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, fx.rtv_count); put_u32(&buffer, fx.dsv_count); put_u32(&buffer, fx.shader_count); - put_u32(&buffer, 0); /* Inline shader count. */ + put_u32(&buffer, fx.inline_shader_count); set_u32(&buffer, size_offset, fx.unstructured.size); @@ -3538,7 +3668,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, fx.rtv_count); put_u32(&buffer, fx.dsv_count); put_u32(&buffer, fx.shader_count); - put_u32(&buffer, 0); /* Inline shader count. */ + put_u32(&buffer, fx.inline_shader_count); put_u32(&buffer, fx.group_count); /* Group count. */ put_u32(&buffer, fx.uav_count); put_u32(&buffer, 0); /* Interface variables count. */ diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 1f1cf4a8c..d7bd4febd 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -5333,7 +5333,7 @@ int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info, return VKD3D_ERROR_INVALID_SHADER; } - ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, program, reflection_data); + ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, NULL, program, reflection_data); hlsl_ctx_cleanup(&ctx); if (ret < 0) vsir_program_cleanup(program); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 78631531c..643b72798 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1652,8 +1652,8 @@ void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body); void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body); int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out); int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, - struct hlsl_ir_function_decl *entry_func, struct vsir_program *program, - struct vkd3d_shader_code *reflection_data); + struct hlsl_ir_function_decl *entry_func, const struct hlsl_block *initializers, + struct vsir_program *program, struct vkd3d_shader_code *reflection_data); bool hlsl_init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int path_len); bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index d02ef1665..1b2cc1c63 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -15311,12 +15311,12 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v } int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, - struct hlsl_ir_function_decl *entry_func, struct vsir_program *program, - struct vkd3d_shader_code *reflection_data) + struct hlsl_ir_function_decl *entry_func, const struct hlsl_block *initializers, + struct vsir_program *program, struct vkd3d_shader_code *reflection_data) { - struct hlsl_block global_uniform_block, body, patch_body; uint32_t config_flags = vkd3d_shader_init_config_flags(); const struct hlsl_profile_info *profile = ctx->profile; + struct hlsl_block initializer_block, body, patch_body; struct list semantic_vars, patch_semantic_vars; struct hlsl_ir_var *var; @@ -15339,13 +15339,17 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info list_init(&ctx->extern_vars); list_init(&semantic_vars); list_init(&patch_semantic_vars); - hlsl_block_init(&global_uniform_block); + + if (!initializers) + hlsl_block_init(&initializer_block); + else if (!hlsl_clone_block(ctx, &initializer_block, initializers)) + return ctx->result; LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) { if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) { - prepend_uniform_copy(ctx, &global_uniform_block, var); + prepend_uniform_copy(ctx, &initializer_block, var); } else if (var->storage_modifiers & HLSL_STORAGE_GROUPSHARED) { @@ -15354,18 +15358,19 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info } } - process_entry_function(ctx, &semantic_vars, &body, &global_uniform_block, entry_func); + process_entry_function(ctx, &semantic_vars, &body, &initializer_block, entry_func); + if (ctx->result) return ctx->result; if (profile->type == VKD3D_SHADER_TYPE_HULL) { - process_entry_function(ctx, &patch_semantic_vars, &patch_body, &global_uniform_block, ctx->patch_constant_func); + process_entry_function(ctx, &patch_semantic_vars, &patch_body, &initializer_block, ctx->patch_constant_func); if (ctx->result) return ctx->result; } - hlsl_block_cleanup(&global_uniform_block); + hlsl_block_cleanup(&initializer_block); if (profile->major_version < 4) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 68285be0a..44459a635 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1776,7 +1776,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char return ret; } -static int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, +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) { diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 57aea864b..262945941 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1716,6 +1716,9 @@ const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( 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); +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); 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_optimize(struct vsir_program *program, uint64_t config_flags, diff --git a/tests/hlsl/effect-compile.shader_test b/tests/hlsl/effect-compile.shader_test index e443bff24..4463a65ef 100644 --- a/tests/hlsl/effect-compile.shader_test +++ b/tests/hlsl/effect-compile.shader_test @@ -270,8 +270,7 @@ technique10 T0 } } - -[effect todo] +[effect] float4 fun(uniform float4 a, float4 b : FOO) : sv_target { return 10 * a + b; @@ -285,7 +284,7 @@ technique10 T0 } } -[effect todo] +[effect] float4 vs( float4 Pos : POSITION ) : SV_POSITION { return Pos; } float4 ps( float4 Pos : SV_POSITION ) : SV_Target { return float4( 1.0f, 1.0f, 0.0f, 1.0f ); }