vkd3d/tests/hlsl/loop.shader_test
Giovanni Mascellani 51f13391e6 vkd3d-shader/ir: Introduce a simple control flow graph structurizer.
The structurizer is implemented along the lines of what is usually called
the "structured program theorem": the control flow is completely
virtualized by mean of an additional TEMP register which stores the
block index which is currently running. The whole program is then
converted to a huge switch construction enclosed in a loop, executing
at each iteration the appropriate block and updating the register
depending on block jump instruction.

The algorithm's generality is also its major weakness: it accepts any
input program, even if its CFG is not reducible, but the output
program lacks any useful convergence information. It satisfies the
letter of the SPIR-V requirements, but it is expected that it will
be very inefficient to run on a GPU (unless a downstream compiler is
able to devirtualize the control flow and do a proper convergence
analysis pass). The algorithm is however very simple, and good enough
to at least pass tests, enabling further development. A better
alternative is expected to be upstreamed incrementally.

Side note: the structured program theorem is often called the
Böhm-Jacopini theorem; Böhm and Jacopini did indeed prove a variation
of it, but their algorithm is different from what is commontly attributed
to them and implemented here, so I opted for not using their name.
2024-02-06 23:07:07 +01:00

248 lines
3.5 KiB
Plaintext

% TODO: dxcompiler emits no loops for any of these test shaders.
[pixel shader todo(sm<4)]
float a;
float4 main() : sv_target
{
float res = 0;
for (int i = 0; i < 10; ++i)
{
res += a;
// The temp copy of 'a' must reserve its registers for the rest of the loop.
// It shall not be overwritten.
}
return res;
}
[test]
uniform 0 float 5.0
todo(sm<4) draw quad
probe all rgba (50.0, 50.0, 50.0, 50.0)
[pixel shader todo(sm<4)]
float a;
float4 main() : sv_target
{
float res = 0;
for (int i = 0; i < 10; ++i)
{
res += a;
// The temp copy of 'a' must reserve its registers for the rest of the loop.
// It shall not be overwritten.
i++;
}
return res;
}
[test]
uniform 0 float 4.0
todo(sm<4) draw quad
probe all rgba (20.0, 20.0, 20.0, 20.0)
[pixel shader todo(sm<4)]
float a;
float4 main() : sv_target
{
int i = 0;
float res = a;
while (i < 10)
{
if (i == 5)
{
res += 0.1f;
break;
}
res += 1.0f;
i++;
if (i == 2) continue;
res += 100.f;
}
return res;
}
[test]
uniform 0 float 4.0
todo(sm<4) draw quad
probe all rgba (409.1, 409.1, 409.1, 409.1)
[pixel shader todo(sm<4)]
float a;
float4 main() : sv_target
{
int i = 0;
float res = a;
do
{
res += 1.0f;
if (i == 5)
{
res += 0.1f;
break;
}
i++;
if (i == 2) continue;
res += 100.f;
}
while (i < 10);
return res;
}
[test]
uniform 0 float 4.0
todo(sm<4) draw quad
probe all rgba (410.1, 410.1, 410.1, 410.1)
% loop attribute by itself
[pixel shader todo(sm<4)]
float4 main() : sv_target
{
float ret = 0.0;
[loop] for (int i = 0; i < 10; ++i)
{
ret += 1.0;
}
return ret;
}
[test]
todo(sm<4) draw quad
probe all rgba (10.0, 10.0, 10.0, 10.0)
[pixel shader todo(sm<4)]
float4 main() : sv_target
{
float ret = 0.0;
int i = 0;
[loop] while (i < 10)
{
ret += 1.0;
i++;
}
return ret;
}
[test]
todo(sm<4) draw quad
probe all rgba (10.0, 10.0, 10.0, 10.0)
[pixel shader todo(sm<4)]
float4 main() : sv_target
{
float ret = 0.0;
int i = 0;
[loop] do
{
i++;
ret += 1.0;
} while (i < 10);
return ret;
}
[test]
todo(sm<4) draw quad
probe all rgba (10.0, 10.0, 10.0, 10.0)
% unroll can't be used with fastopt or loop
[pixel shader fail]
float4 main() : sv_target
{
float ret = 0.0;
[loop] [unroll(1)] for (int i = 0; i < 10; ++i)
{
ret += 1.0;
}
return ret;
}
[pixel shader fail]
float4 main() : sv_target
{
float ret = 0.0;
[fastopt] [unroll(1)] for (int i = 0; i < 10; ++i)
{
ret += 1.0;
}
return ret;
}
[pixel shader fail]
float4 main() : sv_target
{
float ret = 0.0;
int i = 0;
[loop] [unroll(1)] while (i < 10)
{
ret += 1.0;
i++;
}
return ret;
}
[pixel shader fail]
float4 main() : sv_target
{
float ret = 0.0;
int i = 0;
[fastopt] [unroll(1)] while (i < 10)
{
ret += 1.0;
i++;
}
return ret;
}
[pixel shader fail]
float4 main() : sv_target
{
float ret = 0.0;
int i = 0;
[loop] [unroll(1)] do
{
ret += 1.0;
i++;
} while (i < 10)
return ret;
}
[pixel shader fail]
float4 main() : sv_target
{
float ret = 0.0;
int i = 0;
[fastopt] [unroll(1)] do
{
ret += 1.0;
i++;
} while (i < 10)
return ret;
}