From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 19 +++++++ libs/vkd3d-shader/hlsl.h | 3 ++ libs/vkd3d-shader/tpf.c | 103 ++++++++++++++++++++++++++++++++++++++ tests/cbuffer.shader_test | 6 +-- 4 files changed, 128 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 617aef30..ce007f14 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -430,6 +430,25 @@ struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl return type; }
+void hlsl_write_component_name(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, + const struct hlsl_ir_var *var, unsigned int index) +{ + struct hlsl_type *type = var->data_type, *current_type; + unsigned int element_index; + + vkd3d_string_buffer_printf(buffer, "%s", var->name); + + while (!type_is_single_component(type)) + { + current_type = type; + element_index = traverse_path_from_component_index(ctx, &type, &index); + if (current_type->class == HLSL_CLASS_STRUCT) + vkd3d_string_buffer_printf(buffer, ".%s", current_type->e.record.fields[element_index].name); + else + vkd3d_string_buffer_printf(buffer, "[%u]", element_index); + } +} + static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int path_len) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 6a4e314d..7ed6428a 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1202,6 +1202,9 @@ bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref);
+void hlsl_write_component_name(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, + const struct hlsl_ir_var *var, unsigned int index); + bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index eadad3b9..a807a166 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2515,6 +2515,106 @@ static bool type_is_integer(const struct hlsl_type *type) } }
+/* Create a new extern variable for each object component within each extern variable. */ +static void promote_object_components_to_variables(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) +{ + struct hlsl_ir_var *var; + unsigned int k, i; + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + unsigned int component_count = hlsl_type_component_count(var->data_type); + unsigned int offsets[HLSL_REGSET_LAST_OBJECT + 1]; + struct vkd3d_string_buffer *name; + const char *new_var_name; + + if (var->data_type->class == HLSL_CLASS_OBJECT) + continue; + + for (k = 0; k <= HLSL_REGSET_LAST_OBJECT; ++k) + offsets[k] = 0; + + for (i = 0; i < component_count; ++i) + { + struct hlsl_type *component_type = hlsl_type_get_component_type(ctx, var->data_type, i); + struct hlsl_ir_var *new_var; + struct hlsl_ir_node *instr; + enum hlsl_regset regset; + + if (!hlsl_type_is_resource(component_type)) + continue; + + regset = hlsl_type_get_regset(component_type); + + if (offsets[regset] > var->regs[regset].bind_count) + continue; + + if (var->objects_usage[regset][offsets[regset]].used) + { + if (!(name = hlsl_get_string_buffer(ctx))) + return; + hlsl_write_component_name(ctx, name, var, i); + new_var_name = hlsl_strdup(ctx, name->buffer); + hlsl_release_string_buffer(ctx, name); + + TRACE("Promoting %s as a stand-alone variable.\n", debugstr_a(new_var_name)); + + if (!(new_var = hlsl_new_var(ctx, new_var_name, component_type, &var->loc, NULL, + var->data_type->modifiers, NULL))) + return; + new_var->is_uniform = 1; + list_add_before(&var->scope_entry, &new_var->scope_entry); + list_add_before(&var->extern_entry, &new_var->extern_entry); + + new_var->regs[regset].id = var->regs[regset].id + offsets[regset]; + new_var->regs[regset].allocated = true; + new_var->regs[regset].bind_count = 1; + + new_var->objects_usage[regset][0] = var->objects_usage[regset][offsets[regset]]; + + /* Make all derefs pointing to the component to point to the new variable instead. */ + LIST_FOR_EACH_ENTRY(instr, &entry_func->body.instrs, struct hlsl_ir_node, entry) + { + if (instr->type == HLSL_IR_RESOURCE_LOAD) + { + struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr); + + if (load->resource.var == var && load->resource.offset_regset == regset + && hlsl_offset_from_deref_safe(ctx, &load->resource) == offsets[regset]) + { + load->resource.var = new_var; + hlsl_src_remove(&load->resource.offset); + } + + if (load->sampler.var == var && load->sampler.offset_regset == regset + && hlsl_offset_from_deref_safe(ctx, &load->sampler) == offsets[regset]) + { + load->sampler.var = new_var; + hlsl_src_remove(&load->sampler.offset); + } + } + else if (instr->type == HLSL_IR_RESOURCE_STORE) + { + struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr); + + if (store->resource.var == var && store->resource.offset_regset == regset + && hlsl_offset_from_deref_safe(ctx, &store->resource) == offsets[regset]) + { + store->resource.var = new_var; + hlsl_src_remove(&store->resource.offset); + } + } + } + } + + ++offsets[regset]; + } + + for (i = 0; i <= HLSL_REGSET_LAST_OBJECT; ++i) + var->regs[i].allocated = false; + } +} + bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, bool output, unsigned int *type, enum vkd3d_sm4_swizzle_type *swizzle_type, bool *has_idx) { @@ -5120,6 +5220,9 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun size_t i; int ret;
+ if (ctx->profile->major_version >= 5) + promote_object_components_to_variables(ctx, entry_func); + dxbc_writer_init(&dxbc);
write_sm4_signature(ctx, &dxbc, false); diff --git a/tests/cbuffer.shader_test b/tests/cbuffer.shader_test index 7e2a91dc..83397c18 100644 --- a/tests/cbuffer.shader_test +++ b/tests/cbuffer.shader_test @@ -694,7 +694,7 @@ shader model >= 5.0 size (1, 1) 0.0 0.0 0.0 0.5
-[pixel shader todo] +[pixel shader] struct apple { float2 a; @@ -718,5 +718,5 @@ uniform 0 float4 0.0 1.0 2.0 3.0 uniform 4 float4 4.0 5.0 6.0 7.0 uniform 8 float4 8.0 9.0 10.0 11.0 uniform 12 float4 12.0 13.0 14.0 15.0 -todo draw quad -todo probe all rgba (124.0, 135.0, 146.0, 150.5) +draw quad +probe all rgba (124.0, 135.0, 146.0, 150.5)