From: Francisco Casas fcasas@codeweavers.com
It is responsibility of the shader's programmer to ensure that 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 --- v2: - Renamed to 'check_for_non_static_object_references' to 'validate_static_object_references'. - This function always returns false now. - Print different error messages for each case (resource or sampler). - Implemented note_non_static_deref_expressions() to report to the user the location of the expressions that could not be resolved statically.
For instance, the following shader:
--- Texture2D tex[3]; uniform int n;
struct foo { float4 p; Texture2D t; };
float4 main() : sv_target { struct foo s[3];
s[0].t = tex[0]; s[1].t = tex[1]; s[2].t = tex[2]; return s[n].t.Load(0); } ---
gives the following output:
--- test.hlsl:16:22: E5022: Loaded resource from "s" must be determinable at compile time. test.hlsl:16:12: Expression for loaded resource within "s" cannot be resolved statically. Failed to compile shader, ret -4. ---
- The detection of dynamic object type loads that are not used in resouce_loads (which cause an error in native) is left out of this patch to avoid multiple error messages. --- libs/vkd3d-shader/hlsl_codegen.c | 47 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + tests/object-references.shader_test | 4 +- 3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 7f76fce1..6c4a0eec 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -967,6 +967,51 @@ static bool copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *bl return progress; }
+static void note_non_static_deref_expressions(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, + const char *usage) +{ + unsigned int i; + + for (i = 0; i < deref->path_len; ++i) + { + struct hlsl_ir_node *path_node = deref->path[i].node; + + assert(path_node); + if (path_node->type != HLSL_IR_CONSTANT) + hlsl_note(ctx, &path_node->loc, VKD3D_SHADER_LOG_ERROR, + "Expression for %s within "%s" cannot be resolved statically.", + usage, deref->var->name); + } +} + +static bool validate_static_object_references(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + void *context) +{ + unsigned int start, count; + + if (instr->type == HLSL_IR_RESOURCE_LOAD) + { + struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr); + + if (!hlsl_component_index_range_from_deref(ctx, &load->resource, &start, &count)) + { + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF, + "Loaded resource from "%s" must be determinable at compile time.", + load->resource.var->name); + note_non_static_deref_expressions(ctx, &load->resource, "loaded resource"); + } + if (load->sampler.var && !hlsl_component_index_range_from_deref(ctx, &load->sampler, &start, &count)) + { + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF, + "Resource load sampler from "%s" must be determinable at compile time.", + load->sampler.var->name); + note_non_static_deref_expressions(ctx, &load->sampler, "resource load sampler"); + } + } + + return false; +} + 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 +2281,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, validate_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;