HLSL: work around FXC failures when dynamically indexing arrays in structs

FXC fails to compile code that assigns to dynamically-indexed fixed-size
arrays in structs on internal shader variables with:

error X3500: array reference cannot be used as an l-value; not natively
addressable

This CL detects this case, and transforms such assignments into copying
out the array to a local variable, assigning to that local, and then
copying the array back.

Also manually regenerate SKIPs for HLSL/FXC after this change, which
fixes 30 tests. Also exposes some "compilation aborted unexpectedly" now
that  "array reference cannot be used as an l-value" has been fixed. For
tests that fail for both DXC and FXC, updating SKIPs to the DXC one to
help distinguish actual FXC bugs from valid errors.

Bug: tint:998
Bug: tint:1206
Change-Id: I09204d8d81ab27d1c257538ad702414ccc386543
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/71620
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Antonio Maiorano
2021-12-13 15:55:11 +00:00
committed by Tint LUCI CQ
parent 5923803f7e
commit d733fdb85c
98 changed files with 2149 additions and 6619 deletions

View File

@@ -1,21 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_ubo : register(b0, space0) {
uint4 ubo[1];
};
struct S {
int data[64];
};
RWByteAddressBuffer result : register(u1, space0);
[numthreads(1, 1, 1)]
void f() {
S s = (S)0;
s.data[asint(ubo[0].x)] = 1;
result.Store(0u, asuint(s.data[3]));
return;
}
C:\src\tint\test\Shader@0x000002C587F87250(14,3-25): error X3500: array reference cannot be used as an l-value; not natively addressable

View File

@@ -1,25 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_ubo : register(b0, space0) {
uint4 ubo[1];
};
struct S {
int data[64];
};
RWByteAddressBuffer result : register(u1, space0);
void x(inout S p) {
p.data[asint(ubo[0].x)] = 1;
}
[numthreads(1, 1, 1)]
void f() {
S s = (S)0;
x(s);
result.Store(0u, asuint(s.data[3]));
return;
}
C:\src\tint\test\Shader@0x000002338E919910(12,3-25): error X3500: array reference cannot be used as an l-value; not natively addressable

View File

@@ -1,21 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_ubo : register(b0, space0) {
uint4 ubo[1];
};
struct S {
int data[64];
};
RWByteAddressBuffer result : register(u1, space0);
static S s = (S)0;
[numthreads(1, 1, 1)]
void f() {
s.data[asint(ubo[0].x)] = 1;
result.Store(0u, asuint(s.data[3]));
return;
}
C:\src\tint\test\Shader@0x000001D94063C630(14,3-25): error X3500: array reference cannot be used as an l-value; not natively addressable

View File

@@ -1,25 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_ubo : register(b0, space0) {
uint4 ubo[1];
};
struct S {
int data[64];
};
RWByteAddressBuffer result : register(u1, space0);
static S s = (S)0;
void x(inout S p) {
p.data[asint(ubo[0].x)] = 1;
}
[numthreads(1, 1, 1)]
void f() {
x(s);
result.Store(0u, asuint(s.data[3]));
return;
}
C:\src\tint\test\Shader@0x0000018B80081AA0(13,3-25): error X3500: array reference cannot be used as an l-value; not natively addressable

View File

@@ -0,0 +1,23 @@
struct Simulation {
i : u32;
};
struct Particle {
position : array<vec3<f32>, 8>;
lifetime : f32;
color : vec4<f32>;
velocity : vec3<f32>;
};
struct Particles {
p : array<Particle>;
};
[[group(1), binding(3)]] var<storage, read> particles : Particles;
[[group(1), binding(4)]] var<uniform> sim : Simulation;
[[stage(compute), workgroup_size(1)]]
fn main() {
var particle = particles.p[0];
particle.position[sim.i] = particle.position[sim.i];
}

View File

@@ -0,0 +1,38 @@
struct Particle {
float3 position[8];
float lifetime;
float4 color;
float3 velocity;
};
ByteAddressBuffer particles : register(t3, space1);
cbuffer cbuffer_sim : register(b4, space1) {
uint4 sim[1];
};
typedef float3 tint_symbol_3_ret[8];
tint_symbol_3_ret tint_symbol_3(ByteAddressBuffer buffer, uint offset) {
float3 arr[8] = (float3[8])0;
{
[loop] for(uint i_1 = 0u; (i_1 < 8u); i_1 = (i_1 + 1u)) {
arr[i_1] = asfloat(buffer.Load3((offset + (i_1 * 16u))));
}
}
return arr;
}
Particle tint_symbol_2(ByteAddressBuffer buffer, uint offset) {
const Particle tint_symbol_8 = {tint_symbol_3(buffer, (offset + 0u)), asfloat(buffer.Load((offset + 128u))), asfloat(buffer.Load4((offset + 144u))), asfloat(buffer.Load3((offset + 160u)))};
return tint_symbol_8;
}
[numthreads(1, 1, 1)]
void main() {
Particle particle = tint_symbol_2(particles, (176u * uint(0)));
{
float3 tint_symbol_1[8] = particle.position;
tint_symbol_1[sim[0].x] = particle.position[sim[0].x];
particle.position = tint_symbol_1;
}
return;
}