vkd3d/tests/hlsl/cbuffer.shader_test
Giovanni Mascellani 624eccbab1 ci: Update the DXC version used on the CI to 1.8.2407.
Unfortuantely different versions of DXC accept or fail differently
in some cases. We don't care too much about validating the DXC
behavior itself, but it's useful that all the CI jobs use the
same version so that we don't have to complicate the shader runner
language.

The macOS version is currently bound to be pretty recent because
otherwise libdxil.dylib is not provided. So I'm updating the
Linux and Windows version as well.

I don't expect it should be particularly hard for other maintainers
to keep up with the DXC updates, since it just amounts to
downloading a ZIP file and extracting two libraries.
2024-10-28 17:36:17 +01:00

982 lines
13 KiB
Plaintext

% Uppercase register set names
[pixel shader]
cbuffer Constants : register(B1)
{
};
Texture2D tex : register(T1);
float4 foo : register(C0);
float4 main() : sv_target
{
return foo;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail(sm>=6)]
// Annotations
cbuffer cb : register(b1) < int i = 1; >
{
float4 m1;
};
cbuffer cb < int i = 2; >
{
float4 m2;
};
float4 main() : sv_target
{
return m1 + m2;
}
[pixel shader]
// Test empty constant buffer.
cbuffer Constants : register(b1)
{
};
float4 foo;
float4 main() : sv_target
{
return foo;
}
[pixel shader fail(sm>=6)]
// The 'single' modifier is not a keyword. It's meaningful only for fx_5_0.
single cbuffer cb
{
float4 single;
};
float4 main() : sv_target
{
return single;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail(sm>=6)]
// 'single' modifier is usable when there is a variable with the same name
cbuffer cb
{
float4 single;
};
single cbuffer cb2
{
float4 var;
};
float4 main() : sv_target
{
return single;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader]
typedef float4 single;
single var;
float4 main() : sv_target
{
return var;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail]
typedef float4 single;
single cbuffer cb
{
float4 var;
};
float4 main() : sv_target
{
return var;
}
% SM1 buffer offset allocation follows different rules than SM4.
% Those would have to be tested separately.
[require]
shader model >= 4.0
[pixel shader fail]
cbuffer buffer
{
float4 a : packoffset(c1invalid_extra_chars);
}
float4 main() : sv_target
{
return 0;
}
% Respect register boundaries
[pixel shader]
cbuffer buffer
{
float2 a;
float2 b;
float2 c;
float3 d;
}
float4 main() : sv_target
{
return float4(a.x, b.x, c.x, d.x);
}
[test]
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
draw quad
probe (0, 0) rgba (0.0, 2.0, 4.0, 8.0)
[pixel shader]
cbuffer buffer
{
float a;
float b[2];
float c;
}
float4 main() : sv_target
{
return float4(a, b[0], b[1], c);
}
[test]
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
draw quad
probe (0, 0) rgba (0.0, 4.0, 8.0, 9.0)
[pixel shader]
cbuffer buffer
{
float a;
struct
{
float b;
float c;
} p;
float d;
}
float4 main() : sv_target
{
return float4(a, p.b, p.c, d);
}
[test]
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
draw quad
probe (0, 0) rgba (0.0, 4.0, 5.0, 6.0)
[pixel shader fail]
// Elements cannot overlap if buffer is used.
cbuffer buffer
{
float c : packoffset(c0);
float4 a[2] : packoffset(c1);
float4 b[2] : packoffset(c2);
}
float4 main() : sv_target
{
return float4(c, a[1].x, b[0].x, b[1].x);
}
[pixel shader fail(sm>=6)]
// Elements can overlap if buffer is not used.
cbuffer buffer
{
float4 a[2] : packoffset(c1);
float4 b[2] : packoffset(c2);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader]
cbuffer buffer
{
float4 a : packoffset(c1);
float4 b : packoffset(C2);
}
float4 main() : sv_target
{
return 100 * a + b;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
uniform 4 float4 5.0 6.0 7.0 8.0
uniform 8 float4 9.0 10.0 11.0 12.0
draw quad
probe (0, 0) rgba (509, 610, 711, 812)
[pixel shader]
struct apple
{
float2 a;
float b;
float4 c;
};
cbuffer buffer
{
float4 foo : packoffset(c3);
struct apple bar : packoffset(c1);
}
float4 main() : sv_target
{
return 1000 * foo + 100 * float4(bar.a, 0, 0) + 10 * float4(bar.b, 0, 0, 0) + bar.c;
}
[test]
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
draw quad
probe (0, 0) rgba (12468.0, 13509.0, 14010.0, 15011.0)
[pixel shader]
cbuffer buffer
{
float2 c : packoffset(c0.y);
}
float4 main() : sv_target
{
return float4(c, c);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (2.0, 3.0, 2.0, 3.0)
[pixel shader fail]
// Elements must respect register boundaries.
cbuffer buffer
{
float4 c : packoffset(c0.z);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
// Matrices must be aligned.
cbuffer buffer
{
float1x1 m : packoffset(c0.y);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
// Arrays must be aligned.
cbuffer buffer
{
float a[1] : packoffset(c0.y);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
// Structs must be aligned.
struct apple
{
float p;
};
cbuffer buffer
{
struct apple a : packoffset(c0.y);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
// Invalid offset on unused buffer.
cbuffer buffer
{
float3 a : packoffset(c0.z);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
// Invalid offset on unused variable.
cbuffer buffer
{
float a : packoffset(c0);
float3 b : packoffset(c0.z);
}
float4 main() : sv_target
{
return a;
}
[pixel shader]
cbuffer buffer
{
float4 a : packoffset(c1);
float1 b : packoffset(c0);
float1 c : packoffset(c0.y);
}
float4 main() : sv_target
{
return 100 * a + 10 * b + c;
}
[test]
uniform 0 float 1.0
uniform 1 float 2.0
uniform 4 float4 5.0 6.0 7.0 8.0
draw quad
probe (0, 0) rgba (512.0, 612.0, 712.0, 812.0)
[pixel shader fail(sm<6)]
// packoffset cannot be used unless all elements use it.
cbuffer buffer
{
float4 a : packoffset(c0);
float4 b;
}
float4 main() : sv_target
{
return a + b;
}
[pixel shader]
cbuffer buffer
{
float2 c : packoffset(c0.b);
}
float4 main() : sv_target
{
return float4(c, c);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (3.0, 4.0, 3.0, 4.0)
[pixel shader fail]
cbuffer buffer
{
float2 c : packoffset(c0.xy);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
cbuffer buffer
{
float4x4 mat : packoffset(c0._m00);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
cbuffer buffer
{
float4 a : packoffset(c0._m00);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
cbuffer buffer
{
float2 c : packoffset(c0.xz);
}
float4 main() : sv_target
{
return 0;
}
% packoffset cannot be used outside a constant buffer.
[pixel shader fail]
float4 a : packoffset(c0);
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
float4 foo(float4 a : packoffset(c0))
{
return a;
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
float4 foo(float4 a) : packoffset(c0)
{
return a;
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
struct apple
{
float4 a : packoffset(c0);
};
cbuffer buffer
{
struct apple a;
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
cbuffer buffer
{
struct
{
float4 a : packoffset(c0);
} s;
}
float4 main() : sv_target
{
return 0;
}
[srv 0]
size (2d, 1, 1)
0.0 0.0 0.0 4.0
[sampler 0]
filter linear linear linear
address clamp clamp clamp
[pixel shader]
// Resources are allowed inside constant buffers but they behave as regular resources.
cbuffer buffer
{
float4 a;
Texture2D tex;
sampler sam;
float4 b;
}
float4 main() : sv_target
{
return a + b + tex.Sample(sam, float2(0, 0));
}
[test]
uniform 0 float4 1.0 0.0 0.0 0.0
uniform 4 float4 0.0 2.0 0.0 0.0
uniform 8 float4 0.0 0.0 3.0 0.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 0.0, 4.0)
% packoffset() cannot be used to specify other types of registers
[pixel shader fail]
cbuffer buffer
{
sampler sam : packoffset(s0);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail]
cbuffer buffer
{
Texture2D tex : packoffset(t0);
}
float4 main() : sv_target
{
return 0;
}
[srv 0]
size (2d, 1, 1)
1.0 1.0 1.0 1.0
[srv 1]
size (2d, 1, 1)
2.0 2.0 2.0 2.0
[pixel shader]
// packoffset() can be used in Textures, doesn't change the allocated t register.
cbuffer buffer
{
Texture2D tex : packoffset(c1);
}
float4 main() : sv_target
{
return tex.Load(int3(0, 0, 0));
}
[test]
draw quad
probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0)
% Samplers cannot have packoffset(), unless register() is also specified, or they are not used.
% Note: In SM1 the rules are different: packoffset() is allowed for samplers, but they cannot be
% used together with other numeric fields, which seems like a bug.
[pixel shader fail(sm<6) todo]
Texture2D tex;
cbuffer buffer
{
sampler sam : packoffset(c1);
}
float4 main() : sv_target
{
return tex.Sample(sam, float2(0, 0));
}
[pixel shader todo]
Texture2D tex;
cbuffer buffer
{
sampler sam : packoffset(c1) : register(s0);
}
float4 main() : sv_target
{
return tex.Sample(sam, float2(0, 0));
}
[pixel shader]
cbuffer buffer
{
sampler sam : packoffset(c1);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader]
cbuffer buffer
{
sampler sam : packoffset(c1);
float4 a : packoffset(c0);
}
float4 main() : sv_target
{
return a;
}
% When packoffset is used in one field, resources are also expected to have a reservation.
[pixel shader fail(sm<6)]
cbuffer buffer
{
float4 foo : packoffset(c0);
Texture2D tex;
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail(sm<6)]
cbuffer buffer
{
float4 foo : packoffset(c0);
sampler sam;
}
float4 main() : sv_target
{
return 0;
}
% register() can be used instead of packoffset().
[pixel shader]
cbuffer buffer
{
float4 foo : packoffset(c0);
Texture2D tex : register(T1);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader]
cbuffer buffer
{
float4 foo : packoffset(c0);
sampler sam : register(s1);
}
float4 main() : sv_target
{
return 0;
}
% Using register() alone is considered manual packing for resources, so the other fields expect packoffset().
[pixel shader fail(sm<6)]
cbuffer buffer
{
float4 foo;
Texture2D tex : register(t1);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail(sm<6)]
cbuffer buffer
{
float4 foo;
sampler sam : register(s1);
}
float4 main() : sv_target
{
return 0;
}
% register(c#) is ignored and does not count as manual packing.
[pixel shader]
cbuffer buffer
{
float4 foo : register(c1);
Texture2D tex;
}
float4 main() : sv_target
{
return foo;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
uniform 4 float4 0.0 0.0 0.0 0.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail(sm<6)]
cbuffer buffer
{
float4 foo : register(c1);
Texture2D tex : register(t1);
}
float4 main() : sv_target
{
return foo;
}
% However, valid register reservations count as manual packing even if they
% don't make sense for the given variable.
% sm6 just rejects incorrect reservations.
[pixel shader fail(sm>=6)]
cbuffer buffer
{
float4 bar : register(t1);
}
float4 main() : sv_target
{
return 0;
}
[pixel shader fail(sm>=6)]
cbuffer buffer
{
float4 foo : packoffset(c0);
float4 bar : register(t1);
Texture2D tex : register(s2);
}
float4 main() : sv_target
{
return foo + bar;
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
uniform 4 float4 0.1 0.2 0.3 0.4
draw quad
probe (0, 0) rgba (1.1, 2.2, 3.3, 4.4)
[require]
shader model >= 5.0
[srv 0]
size (2d, 1, 1)
0.0 0.0 0.0 0.5
[pixel shader]
struct apple
{
float2 a;
Texture2D tex;
float b;
};
cbuffer buffer
{
float4 foo : packoffset(c3);
struct apple bar : packoffset(c1);
struct apple baz : register(u3);
}
float4 main() : sv_target
{
return 10 * foo + float4(bar.a, 0, 0) + float4(0, 0, bar.b, 0) + bar.tex.Load(int3(0, 0, 0));
}
[test]
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
uniform 16 float4 16.0 17.0 18.0 19.0
draw quad
probe (0, 0) rgba (124.0, 135.0, 146.0, 150.5)
[require]
shader model >= 5.1
[pixel shader fail]
float4 ConstantBuffer;
float4 main() : sv_target
{
return ConstantBuffer;
}
[pixel shader fail]
struct s
{
float4 m;
};
float4 cb;
ConstantBuffer<s> cb;
float4 main() : sv_target
{
return 0;
}
[pixel shader fail(sm>=6)]
struct s
{
float4 m;
};
float4 main() : sv_target
{
// Local variable do not create resource definitions,
// acting like a constant
ConstantBuffer<s> cb = (s)1;
float4 var = 0.1f;
var += cb.m;
return var;
}
[test]
draw quad
probe (0, 0) rgba (1.1, 1.1, 1.1, 1.1)
[pixel shader]
struct s
{
float4 m;
};
ConstantBuffer<s> cb;
float4 func(s arg)
{
return arg.m;
}
float4 main() : sv_target
{
return func(cb);
}
[test]
uniform 0 float4 1.0 2.0 3.0 4.0
draw quad
probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail todo]
struct s
{
float4 m;
};
float4 main() : sv_target
{
ConstantBuffer<s> cb = (s)0;
cb.m = 1.0f;
return cb.m;
}
[pixel shader]
struct s
{
float4 m;
};
float4 var;
ConstantBuffer<s> cb[2][3] : register(b1);
cbuffer cb
{
float4 m2;
};
float4 main() : sv_target
{
return 0;
}
[pixel shader fail todo]
struct s
{
float4 m;
};
ConstantBuffer<s> func(s arg)
{
return arg;
}
float4 main() : sv_target
{
return 0;
}
[require]
shader model >= 2.0
shader model < 5.1
[pixel shader]
float4 ConstantBuffer;
float4 main() : sv_target
{
return ConstantBuffer;
}