From: Francisco Casas fcasas@codeweavers.com
It is responsibility of the shader's programmer to ensure that all object references can be solved statically.
Resource arrays for ps_5_1 and vs_5_1 are an exception which is not properly handled yet. They probably deserve a different object type.
Signed-off-by: Francisco Casas fcasas@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 30 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + tests/object-references.shader_test | 4 ++-- 3 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index eb07ae5c..4c843482 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -967,6 +967,34 @@ static bool copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *bl return progress; }
+static bool check_for_non_static_object_references(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + void *context) +{ + unsigned int start, count; + bool invalid = false; + + if (instr->type == HLSL_IR_RESOURCE_LOAD) + { + struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr); + + invalid |= !hlsl_component_index_range_from_deref(ctx, &load->resource, &start, &count); + if (load->sampler.var) + invalid |= !hlsl_component_index_range_from_deref(ctx, &load->sampler, &start, &count); + } + else if (instr->type == HLSL_IR_LOAD && instr->data_type->type == HLSL_CLASS_OBJECT) + { + struct hlsl_ir_load *load = hlsl_ir_load(instr); + + invalid |= !hlsl_component_index_range_from_deref(ctx, &load->src, &start, &count); + } + + if (invalid) + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF, + "All object references must be determinable at compile time."); + + return invalid; +} + static bool is_vec1(const struct hlsl_type *type) { return (type->type == HLSL_CLASS_SCALAR) || (type->type == HLSL_CLASS_VECTOR && type->dimx == 1); @@ -2236,6 +2264,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry if (ctx->profile->major_version < 4) transform_ir(ctx, lower_division, body, NULL);
+ transform_ir(ctx, check_for_non_static_object_references, body, NULL); + /* TODO: move forward, remove when no longer needed */ transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); while (transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL)); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 8bde5523..aca5606b 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -118,6 +118,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS = 5019, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE = 5020, VKD3D_SHADER_ERROR_HLSL_DIVISION_BY_ZERO = 5021, + VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF = 5022,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, diff --git a/tests/object-references.shader_test b/tests/object-references.shader_test index a9fbbc50..bc36777b 100644 --- a/tests/object-references.shader_test +++ b/tests/object-references.shader_test @@ -101,7 +101,7 @@ draw quad probe all rgba (2132, 2132, 2132, 1111)
-[pixel shader fail todo] +[pixel shader fail] Texture2D tex[3]; uniform int n;
@@ -121,7 +121,7 @@ float4 main() : sv_target }
-[pixel shader fail todo] +[pixel shader fail] // Note: Only valid in shader model 5.1 Texture2D tex[3]; uniform int n;