vkd3d/tests/hlsl/lerp.shader_test

66 lines
1.1 KiB
Plaintext
Raw Normal View History

[pixel shader]
uniform float4 x;
uniform float4 y;
uniform float4 s;
float4 main() : SV_TARGET
{
return lerp(x, y, s);
}
[test]
uniform 0 float4 2.0 3.0 4.0 5.0
uniform 4 float4 0.0 -10.0 10.0 100.0
uniform 8 float4 0.0 1.0 -1.0 0.75
draw quad
probe all rgba (2.0, -10.0, -2.0, 76.25)
vkd3d-shader/d3dbc: Implement casts from ints to floats as a MOV. For temporary registers, SM1-SM3 integer types are internally represented as floating point, so, in order to perform a cast from ints to floats we need a mere MOV. For constant integer registers "iN" there is no operation for casting from a floating point register to them. For address registers "aN", and the loop counting register "aL", vertex shaders have the "mova" operation but we haven't used these registers in any way yet. We probably would want to introduce these as synthetic variables allocated in a special register set. In that case we have to remember to use MOVA instead of MOV in the store operations, but they shouldn't be src or dst of CAST operations. Regarding constant integer registers, in some shaders, constants are expected to be received formatted as an integer, such as: int m; float4 main() : sv_target { float4 res = {0, 0, 0, 0}; for (int k = 0; k < m; ++k) res += k; return res; } which compiles as: // Registers: // // Name Reg Size // ------------ ----- ---- // m i0 1 // ps_3_0 def c0, 0, 1, 0, 0 mov r0, c0.x mov r1.x, c0.x rep i0 add r0, r0, r1.x add r1.x, r1.x, c0.y endrep mov oC0, r0 but this only happens if the integer constant is used directly in an instruction that needs it, and as I said there is no instruction that allows converting them to a float representation. Notice how a more complex shader, that performs operations with this integer variable "m": int m; float4 main() : sv_target { float4 res = {0, 0, 0, 0}; for (int k = 0; k < m * m; ++k) res += k; return res; } gives the following output: // Registers: // // Name Reg Size // ------------ ----- ---- // m c0 1 // ps_3_0 def c1, 0, 0, 1, 0 defi i0, 255, 0, 0, 0 mul r0.x, c0.x, c0.x mov r1, c1.y mov r0.y, c1.y rep i0 mov r0.z, r0.x break_ge r0.y, r0.z add r1, r0.y, r1 add r0.y, r0.y, c1.z endrep mov oC0, r1 Meaning that the uniform "m" is just stored as a floating point in "c0", the constant integer register "i0" is just set to 255 (hoping it is a high enough value) using "defi", and the "break_ge" involving c0 is used to break from the loop. We could potentially use this approach to implement loops from SM3 without expecting the variables being received as constant integer registers. According to the D3D documentation, for SM1-SM3 constant integer registers are only used by the 'loop' and 'rep' instructions.
2023-10-20 14:38:12 -07:00
[pixel shader]
uniform int4 x;
uniform int4 y;
uniform int4 s;
float4 main() : SV_TARGET
{
return lerp(x, y, s);
}
[test]
if(sm<4) uniform 0 float4 2 3 4 0
if(sm<4) uniform 4 float4 0 -10 10 1000000
if(sm<4) uniform 8 float4 0 1 -1 1000000
if(sm>=4) uniform 0 int4 2 3 4 0
if(sm>=4) uniform 4 int4 0 -10 10 1000000
if(sm>=4) uniform 8 int4 0 1 -1 1000000
vkd3d-shader/d3dbc: Implement casts from ints to floats as a MOV. For temporary registers, SM1-SM3 integer types are internally represented as floating point, so, in order to perform a cast from ints to floats we need a mere MOV. For constant integer registers "iN" there is no operation for casting from a floating point register to them. For address registers "aN", and the loop counting register "aL", vertex shaders have the "mova" operation but we haven't used these registers in any way yet. We probably would want to introduce these as synthetic variables allocated in a special register set. In that case we have to remember to use MOVA instead of MOV in the store operations, but they shouldn't be src or dst of CAST operations. Regarding constant integer registers, in some shaders, constants are expected to be received formatted as an integer, such as: int m; float4 main() : sv_target { float4 res = {0, 0, 0, 0}; for (int k = 0; k < m; ++k) res += k; return res; } which compiles as: // Registers: // // Name Reg Size // ------------ ----- ---- // m i0 1 // ps_3_0 def c0, 0, 1, 0, 0 mov r0, c0.x mov r1.x, c0.x rep i0 add r0, r0, r1.x add r1.x, r1.x, c0.y endrep mov oC0, r0 but this only happens if the integer constant is used directly in an instruction that needs it, and as I said there is no instruction that allows converting them to a float representation. Notice how a more complex shader, that performs operations with this integer variable "m": int m; float4 main() : sv_target { float4 res = {0, 0, 0, 0}; for (int k = 0; k < m * m; ++k) res += k; return res; } gives the following output: // Registers: // // Name Reg Size // ------------ ----- ---- // m c0 1 // ps_3_0 def c1, 0, 0, 1, 0 defi i0, 255, 0, 0, 0 mul r0.x, c0.x, c0.x mov r1, c1.y mov r0.y, c1.y rep i0 mov r0.z, r0.x break_ge r0.y, r0.z add r1, r0.y, r1 add r0.y, r0.y, c1.z endrep mov oC0, r1 Meaning that the uniform "m" is just stored as a floating point in "c0", the constant integer register "i0" is just set to 255 (hoping it is a high enough value) using "defi", and the "break_ge" involving c0 is used to break from the loop. We could potentially use this approach to implement loops from SM3 without expecting the variables being received as constant integer registers. According to the D3D documentation, for SM1-SM3 constant integer registers are only used by the 'loop' and 'rep' instructions.
2023-10-20 14:38:12 -07:00
draw quad
probe all rgba (2.0, -10.0, -2.0, 1e12) 4
[pixel shader]
float4 main() : sv_target
{
float3x2 a = {6, 5, 4, 3, 2, 1};
float2x3 b = {1, 2, 3, 4.2, 5.2, 6.2};
float3x4 c = 2.4;
float2x2 r = lerp(a, b, c);
return float4(r);
}
[test]
draw quad
probe all rgba (-6.0, -2.2, 4.48, 8.28) 1
[pixel shader fail]
float4 main() : sv_target
{
float2x2 a = {0, 1, 2, 3};
float2x2 b = {1, 2, 3, 4};
float4 c = {0.5, 0.5, 0.5, 0.5};
lerp(a, b, c);
return 0;
}