First, we have to distinguish between the "bind count" and the "allocation size" of variables.
The "allocation size" affects the starting register id for the resource to be allocated next, while the "bind count" is determined by the last field actually used. The former may be larger than the latter.
Currently we are calling `hlsl_reg.bind_count` to what should be `hlsl_reg.allocation_size`. So it is renamed in 2/4.
The proper "bind count" (now computed when needed in 3/4) is important because it is what should appear in the RDEF table and some resource allocation rules depend on it
For instance, for this shader:
``` texture2D texs[3]; texture2D tex;
float4 main() : sv_target { return texs[0].Load(int3(0, 0, 0)) + tex.Load(int3(0, 0, 0)); } ```
the variable "texs" should show a "bind count" of 1, even though its "allocation size" is 3:
``` // Resource Bindings: // // Name Type Format Dim HLSL Bind Count // ------------------------------ ---------- ------- ----------- -------------- ------ // texs texture float4 2d t0 1 // tex texture float4 2d t3 1 ```
In particular, as shown in the tests in 1/4, textures go in this order:
1. Textures created from SM1-style samples. Those whose "bind count" is larger than 1, in the order of the tex1D/tex2D/tex3D/texCube instructions that create them. 2. Textures created from SM1-style samples. Those whose "bind count" is equal to 1, in the order of the tex1D/tex2D/tex3D/texCube instructions that create them. 3. Regular textures in order of declaration.
Note that the difference between 1 and 2 is not given by the "allocation size" but the "bind count". This order is enforced in 4/4.
From: Francisco Casas fcasas@codeweavers.com
--- Makefile.am | 1 + tests/hlsl/texture-ordering.shader_test | 274 ++++++++++++++++++++++++ tests/shader_runner_d3d12.c | 4 +- 3 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 tests/hlsl/texture-ordering.shader_test
diff --git a/Makefile.am b/Makefile.am index ecb7c7e2..a4f46b85 100644 --- a/Makefile.am +++ b/Makefile.am @@ -168,6 +168,7 @@ vkd3d_shader_tests = \ tests/hlsl/texture-load-offset.shader_test \ tests/hlsl/texture-load-typed.shader_test \ tests/hlsl/texture-load.shader_test \ + tests/hlsl/texture-ordering.shader_test \ tests/hlsl/transpose.shader_test \ tests/hlsl/trigonometry.shader_test \ tests/hlsl/trunc.shader_test \ diff --git a/tests/hlsl/texture-ordering.shader_test b/tests/hlsl/texture-ordering.shader_test new file mode 100644 index 00000000..16feb9e1 --- /dev/null +++ b/tests/hlsl/texture-ordering.shader_test @@ -0,0 +1,274 @@ +[require] +shader model >= 4.0 + +[sampler 0] +filter linear linear linear +address clamp clamp clamp + +[sampler 1] +filter linear linear linear +address clamp clamp clamp + +[sampler 2] +filter linear linear linear +address clamp clamp clamp + +[sampler 3] +filter linear linear linear +address clamp clamp clamp + +[sampler 4] +filter linear linear linear +address clamp clamp clamp + +[sampler 5] +filter linear linear linear +address clamp clamp clamp + +[sampler 6] +filter linear linear linear +address clamp clamp clamp + +[texture 0] +size (1, 1) +0.0 0.0 0.0 1.0 + +[texture 1] +size (1, 1) +1.0 1.0 1.0 1.0 + +[texture 2] +size (1, 1) +2.0 2.0 2.0 1.0 + +[texture 3] +size (1, 1) +3.0 3.0 3.0 1.0 + +[texture 4] +size (1, 1) +4.0 4.0 4.0 1.0 + +[texture 5] +size (1, 1) +5.0 5.0 5.0 1.0 + +[texture 6] +size (1, 1) +6.0 6.0 6.0 1.0 + +[texture 7] +size (1, 1) +7.0 7.0 7.0 1.0 + +[texture 8] +size (1, 1) +8.0 8.0 8.0 1.0 + +[texture 9] +size (1, 1) +9.0 9.0 9.0 1.0 + + +% Regarding resource allocation ordering in SM4, textures go in this order: +% 1. Textures created from SM1-style samples. Those whose "bind count" is larger than 1, +% in the order of the tex1D/tex2D/tex3D/texCube instructions that create them. +% 2. Textures created from SM1-style samples. Those whose "bind count" is equal to 1, +% in the order of the tex1D/tex2D/tex3D/texCube instructions that create them. +% 3. Regular textures in order of declaration. +% +% Note that the "bind count" should not be confused with the "allocation size". +% +% The "bind count" appears in the RDEF table ("Count" row), and is determined by the last field +% actually used. +% The "allocation size" for textures affects the starting register id for the next resource in the +% table, and may be larger than the "bind count". + +[pixel shader] +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sam_arr_10 sampler NA NA s0 1 +// sam_arr_01 sampler NA NA s1 2 +// sam_arr_11 sampler NA NA s3 2 +// samA sampler NA NA s5 1 +// samB sampler NA NA s6 1 +// sam_arr_11 texture float4 2d t0 2 +// sam_arr_01 texture float4 2d t2 2 +// samB texture float4 2d t4 1 +// sam_arr_10 texture float4 2d t5 1 +// samA texture float4 2d t6 1 +// tex texture float4 2d t7 1 +// texs texture float4 2d t8 2 + +Texture2D tex; +Texture2D texs[2]; +sampler samA; +sampler samB; +sampler sam_arr_10[2]; +sampler sam_arr_01[2]; +sampler sam_arr_11[2]; + +float4 main() : sv_target +{ + float4 f = 0, g = 0, h = 0, res; + + f += 100 * tex2D(samB, float2(0, 0)); + f += 10 * tex2D(sam_arr_10[0], float2(0, 0)); + f += 1 * tex2D(sam_arr_11[0], float2(0, 0)); + g += 100 * tex2D(sam_arr_11[1], float2(0, 0)); + g += 10 * tex2D(sam_arr_01[1], float2(0, 0)); + g += 1 * texs[1].Load(int3(0, 0, 0)); + h += 100 * texs[0].Load(int3(0, 0, 0)); + h += 10 * tex.Load(int3(0, 0, 0)); + h += 1 * tex2D(samA, float2(0, 0)); + + res.x = f.x; + res.y = g.x; + res.z = h.x; + res.w = f.w + g.w + h.w; + + return res; +} + +[test] +draw quad +todo probe all rgba (450, 139, 876, 333) + + +% Same as the first test, but inverting the declaration order. +% Regarding textures, only the allocation of those that are not created from samplers is affected. +[pixel shader] +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sam_arr_11 sampler NA NA s0 2 +// sam_arr_01 sampler NA NA s2 2 +// sam_arr_10 sampler NA NA s4 1 +// samB sampler NA NA s5 1 +// samA sampler NA NA s6 1 +// sam_arr_11 texture float4 2d t0 2 +// sam_arr_01 texture float4 2d t2 2 +// samB texture float4 2d t4 1 +// sam_arr_10 texture float4 2d t5 1 +// samA texture float4 2d t6 1 +// texs texture float4 2d t7 2 +// tex texture float4 2d t9 1 + +sampler sam_arr_11[2]; +sampler sam_arr_01[2]; +sampler sam_arr_10[2]; +sampler samB; +sampler samA; +Texture2D texs[2]; +Texture2D tex; + +float4 main() : sv_target +{ + float4 f = 0, g = 0, h = 0, res; + + f += 100 * tex2D(samB, float2(0, 0)); + f += 10 * tex2D(sam_arr_10[0], float2(0, 0)); + f += 1 * tex2D(sam_arr_11[0], float2(0, 0)); + g += 100 * tex2D(sam_arr_11[1], float2(0, 0)); + g += 10 * tex2D(sam_arr_01[1], float2(0, 0)); + g += 1 * texs[1].Load(int3(0, 0, 0)); + h += 100 * texs[0].Load(int3(0, 0, 0)); + h += 10 * tex.Load(int3(0, 0, 0)); + h += 1 * tex2D(samA, float2(0, 0)); + + res.x = f.x; + res.y = g.x; + res.z = h.x; + res.w = f.w + g.w + h.w; + + return res; +} + +[test] +draw quad +todo probe all rgba (450, 138, 796, 333) + + +% Same as the first test, but inverting the resource loads order. +% Regarding textures, only the allocation of those that are created from samplers is affected. +[pixel shader] +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sam_arr_10 sampler NA NA s0 1 +// sam_arr_01 sampler NA NA s1 2 +// sam_arr_11 sampler NA NA s3 2 +// samA sampler NA NA s5 1 +// samB sampler NA NA s6 1 +// sam_arr_01 texture float4 2d t0 2 +// sam_arr_11 texture float4 2d t2 2 +// samA texture float4 2d t4 1 +// sam_arr_10 texture float4 2d t5 1 +// samB texture float4 2d t6 1 +// tex texture float4 2d t7 1 +// texs texture float4 2d t8 2 + +Texture2D tex; +Texture2D texs[2]; +sampler samA; +sampler samB; +sampler sam_arr_10[2]; +sampler sam_arr_01[2]; +sampler sam_arr_11[2]; + +float4 main() : sv_target +{ + float4 f = 0, g = 0, h = 0, res; + + f += 100 * tex2D(samA, float2(0, 0)); + f += 10 * tex.Load(int3(0, 0, 0)); + f += 1 * texs[0].Load(int3(0, 0, 0)); + g += 100 * texs[1].Load(int3(0, 0, 0)); + g += 10 * tex2D(sam_arr_01[1], float2(0, 0)); + g += 1 * tex2D(sam_arr_11[1], float2(0, 0)); + h += 100 * tex2D(sam_arr_11[0], float2(0, 0)); + h += 10 * tex2D(sam_arr_10[0], float2(0, 0)); + h += 1 * tex2D(samB, float2(0, 0)); + + res.x = f.x; + res.y = g.x; + res.z = h.x; + res.w = f.w + g.w + h.w; + + return res; +} + +[test] +draw quad +todo probe all rgba (478, 913, 256, 333) + + +% We can conclude that for declared texture arrays, if they are used, the "allocation size" is the +% whole array. +% On the other hand, for textures generated from samplers. the "allocation size" is the "bind count". +[pixel shader] +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sam_arr sampler NA NA s0 2 +// sam sampler NA NA s2 1 +// sam_arr texture float4 2d t0 2 +// texs texture float4 2d t2 1 +// tex texture float4 2d t5 1 + +sampler sam; + +Texture2D texs[3]; +sampler sam_arr[3]; +Texture2D tex; + +float4 main() : sv_target +{ + float4 res = 0; + + res += 100 * texs[0].Sample(sam, float2(0, 0)); + res += 10 * tex2D(sam_arr[1], float2(0, 0)); + res += 1 * tex.Sample(sam, float2(0, 0)); + return res; +} + +[test] +draw quad +todo probe all rgba (215, 215, 215, 111) diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index daeb11e8..bdd47087 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -206,8 +206,8 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad ID3D12GraphicsCommandList *command_list, unsigned int *uniform_index) { D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; - D3D12_ROOT_PARAMETER root_params[8], *root_param; - D3D12_STATIC_SAMPLER_DESC static_samplers[5]; + D3D12_ROOT_PARAMETER root_params[17], *root_param; + D3D12_STATIC_SAMPLER_DESC static_samplers[7]; ID3D12RootSignature *root_signature; HRESULT hr; size_t i;
From: Francisco Casas fcasas@codeweavers.com
We have to distinguish between the "bind count" and the "allocation size" of variables.
The "allocation size" affects the starting register id for the resource to be allocated next, while the "bind count" is determined by the last field actually used. The former may be larger than the latter.
The "bind count" is important because it is what is shown in the RDEF table and some resource allocation rules depend on it, but it is not what we are currently calling "bind count" (which will be introduced in the following patches).
For instance, for this shader:
texture2D texs[3]; texture2D tex;
float4 main() : sv_target { return texs[0].Load(int3(0, 0, 0)) + tex.Load(int3(0, 0, 0)); }
the variable "texs" has a "bind count" of 1, but an "allocation size" of 3:
// Resource Bindings: // // Name Type Format Dim HLSL Bind Count // ------------------------------ ---------- ------- ----------- -------------- ------ // texs texture float4 2d t0 1 // tex texture float4 2d t3 1 --- libs/vkd3d-shader/d3dbc.c | 4 ++-- libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 20 ++++++++++---------- libs/vkd3d-shader/tpf.c | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index fe739339..fdb71805 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -1680,7 +1680,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe else { put_u32(buffer, vkd3d_make_u32(D3DXRS_SAMPLER, var->regs[r].id)); - put_u32(buffer, var->regs[r].bind_count); + put_u32(buffer, var->regs[r].allocation_size); } put_u32(buffer, 0); /* type */ put_u32(buffer, 0); /* FIXME: default value */ @@ -2027,7 +2027,7 @@ static void write_sm1_sampler_dcls(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b if (!var->regs[HLSL_REGSET_SAMPLERS].allocated) continue;
- count = var->regs[HLSL_REGSET_SAMPLERS].bind_count; + count = var->regs[HLSL_REGSET_SAMPLERS].allocation_size;
for (i = 0; i < count; ++i) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index b1427c1d..fb4bdfa6 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -257,7 +257,7 @@ struct hlsl_reg /* Number of registers to be allocated. * Unlike the variable's type's regsize, it is not expressed in register components, but rather * in whole registers, and may depend on which components are used within the shader. */ - uint32_t bind_count; + uint32_t allocation_size; /* For numeric registers, a writemask can be provided to indicate the reservation of only some * of the 4 components. */ unsigned int writemask; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 4f5a5b02..11ebe275 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2868,7 +2868,7 @@ static void allocate_register_reservations(struct hlsl_ctx *ctx) continue; regset = hlsl_type_get_regset(var->data_type);
- if (var->reg_reservation.reg_type && var->regs[regset].bind_count) + if (var->reg_reservation.reg_type && var->regs[regset].allocation_size) { if (var->reg_reservation.reg_type != get_regset_name(regset)) { @@ -2886,7 +2886,7 @@ static void allocate_register_reservations(struct hlsl_ctx *ctx) var->regs[regset].id = var->reg_reservation.reg_index; TRACE("Allocated reserved %s to %c%u-%c%u.\n", var->name, var->reg_reservation.reg_type, var->reg_reservation.reg_index, var->reg_reservation.reg_type, - var->reg_reservation.reg_index + var->regs[regset].bind_count); + var->reg_reservation.reg_index + var->regs[regset].allocation_size); } } } @@ -3144,7 +3144,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a record_allocation(ctx, allocator, reg_idx, writemask, first_write, last_read);
ret.id = reg_idx; - ret.bind_count = 1; + ret.allocation_size = 1; ret.writemask = hlsl_combine_writemasks(writemask, (1u << component_count) - 1); ret.allocated = true; return ret; @@ -3180,7 +3180,7 @@ static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allo record_allocation(ctx, allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, first_write, last_read);
ret.id = reg_idx; - ret.bind_count = align(reg_size, 4) / 4; + ret.allocation_size = align(reg_size, 4) / 4; ret.allocated = true; return ret; } @@ -3306,7 +3306,7 @@ static void calculate_resource_register_counts(struct hlsl_ctx *ctx) /* Samplers (and textures separated from them) are only allocated until the last * used one. */ if (var->objects_usage[k][i].used) - var->regs[k].bind_count = (k == HLSL_REGSET_SAMPLERS || is_separated) ? i + 1 : type->reg_size[k]; + var->regs[k].allocation_size = (k == HLSL_REGSET_SAMPLERS || is_separated) ? i + 1 : type->reg_size[k]; } } } @@ -3613,7 +3613,7 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var { var->regs[HLSL_REGSET_NUMERIC].allocated = true; var->regs[HLSL_REGSET_NUMERIC].id = (*counter)++; - var->regs[HLSL_REGSET_NUMERIC].bind_count = 1; + var->regs[HLSL_REGSET_NUMERIC].allocation_size = 1; var->regs[HLSL_REGSET_NUMERIC].writemask = (1 << var->data_type->dimx) - 1; TRACE("Allocated %s to %s.\n", var->name, debug_register(output ? 'o' : 'v', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); @@ -3792,7 +3792,7 @@ static void allocate_buffers(struct hlsl_ctx *ctx) }
buffer->reg.id = buffer->reservation.reg_index; - buffer->reg.bind_count = 1; + buffer->reg.allocation_size = 1; buffer->reg.allocated = true; TRACE("Allocated reserved %s to cb%u.\n", buffer->name, index); } @@ -3802,7 +3802,7 @@ static void allocate_buffers(struct hlsl_ctx *ctx) ++index;
buffer->reg.id = index; - buffer->reg.bind_count = 1; + buffer->reg.allocation_size = 1; buffer->reg.allocated = true; TRACE("Allocated %s to cb%u.\n", buffer->name, index); ++index; @@ -3842,7 +3842,7 @@ static const struct hlsl_ir_var *get_allocated_object(struct hlsl_ctx *ctx, enum else if (var->regs[regset].allocated) { start = var->regs[regset].id; - count = var->regs[regset].bind_count; + count = var->regs[regset].allocation_size; } else { @@ -3873,7 +3873,7 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - unsigned int count = var->regs[regset].bind_count; + unsigned int count = var->regs[regset].allocation_size;
if (count == 0) continue; diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 351943e2..b1027428 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3061,7 +3061,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un regset = hlsl_type_get_regset(component_type); regset_offset = hlsl_type_get_component_offset(ctx, var->data_type, regset, k);
- if (regset_offset > var->regs[regset].bind_count) + if (regset_offset > var->regs[regset].allocation_size) continue;
if (var->objects_usage[regset][regset_offset].used) @@ -3134,7 +3134,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un
extern_resources[*count].regset = regset; extern_resources[*count].id = var->regs[regset].id; - extern_resources[*count].bind_count = var->regs[regset].bind_count; + extern_resources[*count].bind_count = var->regs[regset].allocation_size;
++*count; }
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 13 +++++++++++++ libs/vkd3d-shader/hlsl.h | 2 ++ libs/vkd3d-shader/tpf.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 4ed7712b..92037752 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1068,6 +1068,19 @@ struct hlsl_ir_var *hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const cha return var; }
+unsigned int hlsl_var_get_bind_count(const struct hlsl_ir_var *var, enum hlsl_regset regset) +{ + unsigned int i, used_reg_size = 0; + + assert(regset <= HLSL_REGSET_LAST_OBJECT); + for (i = 0; i < var->data_type->reg_size[regset]; ++i) + { + if (var->objects_usage[regset][i].used) + used_reg_size = max(used_reg_size, i + 1); + } + return used_reg_size; +} + static bool type_is_single_reg(const struct hlsl_type *type) { return type->class == HLSL_CLASS_SCALAR || type->class == HLSL_CLASS_VECTOR; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index fb4bdfa6..dd272ade 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1189,6 +1189,8 @@ struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, const struct hlsl_reg_reservation *reg_reservation);
+unsigned int hlsl_var_get_bind_count(const struct hlsl_ir_var *var, enum hlsl_regset regset); + void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5); void hlsl_fixme(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index b1027428..e2302857 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3134,7 +3134,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un
extern_resources[*count].regset = regset; extern_resources[*count].id = var->regs[regset].id; - extern_resources[*count].bind_count = var->regs[regset].allocation_size; + extern_resources[*count].bind_count = hlsl_var_get_bind_count(var, regset);
++*count; }
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 28 ++++++++++++++++++++++++ tests/hlsl/combined-samplers.shader_test | 6 ++--- tests/hlsl/texture-ordering.shader_test | 8 +++---- 3 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 11ebe275..550e18c9 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2191,6 +2191,33 @@ static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in return true; }
+static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) +{ + struct list *insertion_point = &ctx->extern_vars; + struct hlsl_ir_var *var, *next; + unsigned int t; + + for (t = 0; t < 2; ++t) + { + LIST_FOR_EACH_ENTRY_SAFE(var, next, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + if (var->is_separated_resource) + { + unsigned int bind_count = hlsl_var_get_bind_count(var, HLSL_REGSET_TEXTURES); + + if ((t == 0) == (bind_count > 1)) + { + list_remove(&var->extern_entry); + list_add_after(insertion_point, &var->extern_entry); + insertion_point = &var->extern_entry; + } + } + } + } + + return false; +} + /* Lower DIV to RCP + MUL. */ static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { @@ -4316,6 +4343,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry if (profile->major_version >= 4) hlsl_transform_ir(ctx, lower_combined_samples, body, NULL); hlsl_transform_ir(ctx, track_object_components_usage, body, NULL); + sort_synthetic_separated_samplers_first(ctx);
if (profile->major_version < 4) { diff --git a/tests/hlsl/combined-samplers.shader_test b/tests/hlsl/combined-samplers.shader_test index 16b5438e..16db3129 100644 --- a/tests/hlsl/combined-samplers.shader_test +++ b/tests/hlsl/combined-samplers.shader_test @@ -60,7 +60,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (10, 10, 10, 11) +probe all rgba (10, 10, 10, 11)
[pixel shader] @@ -74,7 +74,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (21, 21, 21, 11) +probe all rgba (21, 21, 21, 11)
[pixel shader] @@ -105,7 +105,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (104, 104, 104, 111) +probe all rgba (104, 104, 104, 111)
% Sampler arrays with components that have different usage dimensions are only forbidden in SM4 upwards. diff --git a/tests/hlsl/texture-ordering.shader_test b/tests/hlsl/texture-ordering.shader_test index 16feb9e1..1d1329dc 100644 --- a/tests/hlsl/texture-ordering.shader_test +++ b/tests/hlsl/texture-ordering.shader_test @@ -132,7 +132,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (450, 139, 876, 333) +probe all rgba (450, 139, 876, 333)
% Same as the first test, but inverting the declaration order. @@ -185,7 +185,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (450, 138, 796, 333) +probe all rgba (450, 138, 796, 333)
% Same as the first test, but inverting the resource loads order. @@ -238,7 +238,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (478, 913, 256, 333) +probe all rgba (478, 913, 256, 333)
% We can conclude that for declared texture arrays, if they are used, the "allocation size" is the @@ -271,4 +271,4 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (215, 215, 215, 111) +probe all rgba (215, 215, 215, 111)
Do we know that the rule in 4/4 is correct? Could it be, instead, that variables are sorted in descending order of bind count? IIRC the latter has some form of precedent; I think that's how numeric variables are sorted for sm1.
Also, from patch 4/4:
``` + list_remove(&var->extern_entry); + list_add_after(insertion_point, &var->extern_entry); + insertion_point = &var->extern_entry; ```
This works, but I think it might be slightly clearer to build a local list, append to its tail, and then list_move_head() to ctx->extern_vars.
Do we know that the rule in 4/4 is correct? Could it be, instead, that variables are sorted in descending order of bind count? IIRC the latter has some form of precedent; I think that's how numeric variables are sorted for sm1.
After even more testing I see you are right. I will update the series.
This works, but I think it might be slightly clearer to build a local list, append to its tail, and then list_move_head() to ctx->extern_vars.
Okay.