Files
vkd3d/tests/hlsl/clip-cull-distance-1.shader_test

879 lines
23 KiB
Plaintext
Raw Normal View History

[require]
shader model >= 4.0
cull-distance
[input layout]
0 r32g32-float POSITION
% 9 triangles, on a 3x3 arrangement.
[vb 0]
-0.52 -0.52
-0.46 -0.50
-0.50 -0.46
-0.52 -0.02
-0.46 0.00
-0.50 0.04
-0.52 0.48
-0.46 0.50
-0.50 0.54
-0.02 -0.52
0.04 -0.50
0.00 -0.46
-0.02 -0.02
0.04 0.00
0.00 0.04
-0.02 0.48
0.04 0.50
0.00 0.54
0.48 -0.52
0.54 -0.50
0.50 -0.46
0.48 -0.02
0.54 0.00
0.50 0.04
0.48 0.48
0.54 0.50
0.50 0.54
[rtv 0]
format r32g32b32a32-float
size (2d, 640, 480)
[vertex shader todo]
struct vertex
{
float4 position : SV_POSITION;
float cull : SV_CULLDISTANCE;
float clip : SV_CLIPDISTANCE;
};
void main(float4 position : POSITION, out vertex vertex)
{
vertex.position = position;
// All 3 triangles on the left column are removed by culling.
// All 3 triangles on the bottom row are removed by clipping.
// The triangles on the middle row will be partially removed by clipping.
vertex.cull = position.x;
vertex.clip = position.y;
}
[pixel shader]
float4 main(const in float4 position : SV_Position) : SV_Target
{
return float4(1.0f, 1.0f, 1.0f, 1.0f);
}
[test]
clear rtv 0 0.0 0.0 0.0 1.0
todo(sm<6) draw triangle list 27
probe rtv 0 (160, 120) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(1.0, 1.0, 1.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 1.0, 1.0)
probe rtv 0 (480, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 239) f32(1.0, 1.0, 1.0, 1.0)
[require]
shader model >= 4.0
shader model < 4.1
cull-distance
% Same as previous vertex shader, but already compiled with FXC.
[vertex shader dxbc-tpf-hex]
43425844 0ec8a95b 7857d61f 02c08472 6edf4bf9 00000001 00000170 % DXBC header
00000003 0000002c 00000060 000000e4 %
4e475349 0000002c 00000001 00000008 % .input
00000020 00000000 00000000 00000003 00000000 00000f0f % .param POSITION.xyzw, v0.xyzw, float
49534f50 4e4f4954 ababab00 % "POSITION"
4e47534f 0000007c 00000003 00000008 % .output
00000050 00000000 00000001 00000003 00000000 0000000f % .param SV_POSITION.xyzw, o0.xyzw, float, POS
0000005c 00000000 00000003 00000003 00000001 00000e01 % .param SV_CULLDISTANCE.x, o1.x, float, CULLDST
0000006c 00000000 00000002 00000003 00000001 00000d02 % .param SV_CLIPDISTANCE.y, o1.y, float, CLIPDST
505f5653 5449534f 004e4f49 % "SV_POSITION"
435f5653 444c4c55 41545349 0045434e % "SV_CULLDISTANCE"
435f5653 4450494c 41545349 0045434e % "SV_CLIPDISTANCE"
52444853 00000084 00010040 00000021 % .text vs_4_0
0300005f 001010f2 00000000 % dcl_input v0.xyzw
04000067 001020f2 00000000 00000001 % dcl_output_siv o0.xyzw, position
04000067 00102012 00000001 00000003 % dcl_output_siv o1.x, cull_distance
04000067 00102022 00000001 00000002 % dcl_output_siv o1.y, clip_distance
05000036 001020f2 00000000 00101e46 00000000 % mov o0.xyzw, v0.xyzw
05000036 00102012 00000001 0010100a 00000000 % mov o1.x, v0.x
05000036 00102022 00000001 0010101a 00000000 % mov o1.y, v0.y
0100003e % ret
[pixel shader]
float4 main(const in float4 position : SV_Position) : SV_Target
{
return float4(1.0f, 1.0f, 1.0f, 1.0f);
}
[test]
clear rtv 0 0.0 0.0 0.0 1.0
todo(glsl) draw triangle list 27
probe rtv 0 (160, 120) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(1.0, 1.0, 1.0, 1.0)
vkd3d-shader/dxil: Also map destination write masks for system values. Currently, on what we consider normalized vsir, destination write masks are not relative to the signature element's mask, even though source swizzles are. Also for most instructions, the source swizzles are masked by the destination write mask, as given by vsir_src_is_masked(). The DXIL parser however, is not derelativizing the destination write masks for system value signature elements, so we fix that to make it consistent with how other front-ends are handled. For instance, when the test introduced in commit ca5bc63e5e0e01fbf06979af788b82b0590fc6ba is compiled to DXIL using DXC, and then parsed using vkd3d-compiler, we get the following store instructions: vs_6_0 .input .param POSITION.xyzw, v0.xyzw, float .output .param SV_Position.xyzw, o0.xyzw, float, POS .param SV_CullDistance.x, o1.x, float, CULLDST .param SV_ClipDistance.y, o1.y, float, CLIPDST .descriptors .text label l1 ... mov o1.x <v4:f32>, sr1 <s:f32> mov o2.x <v4:f32>, sr2 <s:f32> // Note the .x write mask! ret whereas, when compiling using FXC and parsing the TPF using vkd3d-compiler we get: vs_4_0 .input .param POSITION.xyzw, v0.xyzw, float .output .param SV_POSITION.xyzw, o0.xyzw, float, POS .param SV_CULLDISTANCE.x, o1.x, float, CULLDST .param SV_CLIPDISTANCE.y, o1.y, float, CLIPDST .descriptors .text label l1 mov o0.xyzw <v4:f32>, v0.xyzw <v4:f32> mov o1.x <v4:f32>, v0.x <v4:f32> mov o2.y <v4:f32>, v0.y <v4:f32> // Note the .y write mask. ret This only really matters for cases where we have a system value semantic whose mask doesn't start at .x, which is very rare. For instance, it requires the clip/cull distance combo, which share registers, so one of them pushes the other to start on another component. According to the tests, the only thing relying on this behaviour is the handling of private variables for system value semantics on the SPIR-V backend, which expects destination write masks as if the element started at .x even though it might not. This is modified then.
2025-10-17 02:51:04 -03:00
probe rtv 0 (320, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 1.0, 1.0)
vkd3d-shader/dxil: Also map destination write masks for system values. Currently, on what we consider normalized vsir, destination write masks are not relative to the signature element's mask, even though source swizzles are. Also for most instructions, the source swizzles are masked by the destination write mask, as given by vsir_src_is_masked(). The DXIL parser however, is not derelativizing the destination write masks for system value signature elements, so we fix that to make it consistent with how other front-ends are handled. For instance, when the test introduced in commit ca5bc63e5e0e01fbf06979af788b82b0590fc6ba is compiled to DXIL using DXC, and then parsed using vkd3d-compiler, we get the following store instructions: vs_6_0 .input .param POSITION.xyzw, v0.xyzw, float .output .param SV_Position.xyzw, o0.xyzw, float, POS .param SV_CullDistance.x, o1.x, float, CULLDST .param SV_ClipDistance.y, o1.y, float, CLIPDST .descriptors .text label l1 ... mov o1.x <v4:f32>, sr1 <s:f32> mov o2.x <v4:f32>, sr2 <s:f32> // Note the .x write mask! ret whereas, when compiling using FXC and parsing the TPF using vkd3d-compiler we get: vs_4_0 .input .param POSITION.xyzw, v0.xyzw, float .output .param SV_POSITION.xyzw, o0.xyzw, float, POS .param SV_CULLDISTANCE.x, o1.x, float, CULLDST .param SV_CLIPDISTANCE.y, o1.y, float, CLIPDST .descriptors .text label l1 mov o0.xyzw <v4:f32>, v0.xyzw <v4:f32> mov o1.x <v4:f32>, v0.x <v4:f32> mov o2.y <v4:f32>, v0.y <v4:f32> // Note the .y write mask. ret This only really matters for cases where we have a system value semantic whose mask doesn't start at .x, which is very rare. For instance, it requires the clip/cull distance combo, which share registers, so one of them pushes the other to start on another component. According to the tests, the only thing relying on this behaviour is the handling of private variables for system value semantics on the SPIR-V backend, which expects destination write masks as if the element started at .x even though it might not. This is modified then.
2025-10-17 02:51:04 -03:00
probe rtv 0 (480, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 239) f32(1.0, 1.0, 1.0, 1.0)
[require]
shader model >= 4.0
cull-distance
% Test clip/cull distance inputs.
[vertex shader todo]
struct vertex_data
{
float4 position : SV_POSITION;
float3 cullA : SV_CULLDISTANCE;
float2 clip : SV_CLIPDISTANCE;
float cullB : SV_CULLDISTANCE1;
};
void main(float4 position : POSITION, out vertex_data vertex)
{
vertex.position = position;
vertex.cullA = float3(10, 20, 30);
vertex.clip = float2(40, 50);
vertex.cullB = -position.x; // Removes all 3 triangles on the right column.
}
[pixel shader todo]
struct vertex_data
{
float4 position : SV_POSITION;
float3 cullA : SV_CULLDISTANCE;
float2 clip : SV_CLIPDISTANCE;
float cullB : SV_CULLDISTANCE1;
};
float4 main(struct vertex_data vertex) : SV_Target
{
// Interpolated cull distance is quantized since there is a variation of
// many ULPs across drivers.
return float4(vertex.cullA.xz, vertex.clip.y, round(10000 * vertex.cullB));
}
[test]
clear rtv 0 0.0 0.0 0.0 1.0
todo(sm<6) draw triangle list 27
probe rtv 0 (160, 120) f32(10.0, 30.0, 50.0, 4984)
probe rtv 0 (160, 240) f32(10.0, 30.0, 50.0, 4984)
probe rtv 0 (160, 360) f32(10.0, 30.0, 50.0, 4984)
probe rtv 0 (320, 120) f32(10.0, 30.0, 50.0, -16)
probe rtv 0 (320, 240) f32(10.0, 30.0, 50.0, -16)
probe rtv 0 (320, 360) f32(10.0, 30.0, 50.0, -16)
probe rtv 0 (480, 120) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(0.0, 0.0, 0.0, 1.0)
[vertex shader fail(sm<6)]
struct vertex_data
{
float4 position : SV_POSITION; // o0.xyzw
float3 clipA : SV_CLIPDISTANCE2; // o1.xyz
float2 clipB : SV_CLIPDISTANCE1; // o2.xy
float cull : SV_CULLDISTANCE; // o1.w
float clipC : SV_CLIPDISTANCE0; // o2.z
};
void main(float4 position : POSITION, out vertex_data vertex)
{
vertex.position = position;
vertex.clipA = float3(10, 20, 30);
vertex.clipB = float2(40, 50);
vertex.cull = 1.0;
vertex.clipC = -position.x; // Removes all pixels on the right side of the render target.
}
[pixel shader fail(sm<6)]
struct vertex_data
{
float4 position : SV_POSITION; // v0.xyzw
float3 clipA : SV_CLIPDISTANCE2; // v1.xyz
float2 clipB : SV_CLIPDISTANCE1; // v2.xy
float cull : SV_CULLDISTANCE; // v1.w
float clipC : SV_CLIPDISTANCE0; // v2.z
};
float4 main(struct vertex_data vertex) : SV_Target
{
return float4(vertex.clipA.z, vertex.clipB.y, vertex.cull, round(10000 * vertex.clipC));
}
[test]
clear rtv 0 0.0 0.0 0.0 1.0
todo(sm<6) draw triangle list 27
probe rtv 0 (160, 120) f32(30.0, 50.0, 1.0, 4984)
probe rtv 0 (160, 240) f32(30.0, 50.0, 1.0, 4984)
probe rtv 0 (160, 360) f32(30.0, 50.0, 1.0, 4984)
probe rtv 0 (319, 120) f32(30.0, 50.0, 1.0, 16)
probe rtv 0 (319, 240) f32(30.0, 50.0, 1.0, 16)
probe rtv 0 (319, 360) f32(30.0, 50.0, 1.0, 16)
probe rtv 0 (320, 120) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(0.0, 0.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(0.0, 0.0, 0.0, 1.0)
[require]
shader model >= 4.0
[input layout]
0 r32g32-float POSITION
1 r32-float CLIP_DISTANCE
[vb 0]
-1.0 -1.0
-1.0 1.0
1.0 -1.0
1.0 1.0
[vb 1]
1.0
1.0
1.0
1.0
[rtv 0]
format r32g32b32a32-float
size (2d, 640, 480)
[vertex shader todo]
struct input
{
float4 position : POSITION;
float distance : CLIP_DISTANCE;
};
struct vertex
{
float4 position : SV_POSITION;
float clip : SV_ClipDistance;
};
void main(input vin, out vertex vertex)
{
vertex.position = vin.position;
vertex.clip = vin.distance;
}
[pixel shader]
float4 main(const in float4 position : SV_Position) : SV_Target
{
return float4(0.0f, 1.0f, 0.0f, 1.0f);
}
[test]
clear rtv 0 1.0 1.0 1.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe (0, 0, 640, 480) rgba(0.0, 1.0, 0.0, 1.0)
[vb 1]
0.0
0.0
0.0
0.0
[test]
clear rtv 0 1.0 1.0 1.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe (0, 0, 640, 480) rgba(0.0, 1.0, 0.0, 1.0)
[vb 1]
-1.0
-1.0
-1.0
-1.0
[test]
clear rtv 0 1.0 1.0 1.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe (0, 0, 640, 480) rgba(1.0, 1.0, 1.0, 1.0)
[vb 1]
1.0
1.0
-1.0
-1.0
[test]
clear rtv 0 1.0 1.0 1.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe rtv 0 (160, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) rgba(1.0, 1.0, 1.0, 1.0)
[vb 1]
-1.0
1.0
-1.0
1.0
[test]
clear rtv 0 1.0 1.0 1.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe rtv 0 (320, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) rgba(1.0, 1.0, 1.0, 1.0)
% A single clip distance.
[vertex shader todo]
static const float2 vertices[3] =
{
{-1.0f, 1.0f},
{ 3.0f, 1.0f},
{-1.0f, -3.0f},
};
struct vs_out
{
float4 position : SV_Position;
float clip : SV_ClipDistance;
};
void main(uint id : SV_VertexID, out vs_out o)
{
const float2 pos = vertices[id];
o.position = float4(pos, 0.0f, 1.0f);
o.clip = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe rtv 0 (160, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) rgba(0.0, 1.0, 0.0, 1.0)
% A single clip distance, disguised as an array.
[vertex shader todo]
static const float2 vertices[3] =
{
{-1.0f, 1.0f},
{ 3.0f, 1.0f},
{-1.0f, -3.0f},
};
struct vs_out
{
float4 position : SV_Position;
float clip[1] : SV_ClipDistance1;
};
void main(uint id : SV_VertexID, out vs_out o)
{
const float2 pos = vertices[id];
o.position = float4(pos, 0.0f, 1.0f);
o.clip[0] = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe rtv 0 (160, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) rgba(0.0, 1.0, 0.0, 1.0)
% Two clip distances.
[vertex shader todo]
static const float2 vertices[3] =
{
{-1.0f, 1.0f},
{ 3.0f, 1.0f},
{-1.0f, -3.0f},
};
struct vs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
};
void main(uint id : SV_VertexID, out vs_out o)
{
const float2 pos = vertices[id];
o.position = float4(pos, 0.0f, 1.0f);
o.clip.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
o.clip.y = 0.15f + 0.6f * pos.x - 0.4f * pos.y;
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe rtv 0 (160, 120) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) rgba(0.0, 1.0, 0.0, 1.0)
% Five clip distances.
[vertex shader todo]
static const float2 vertices[3] =
{
{-1.0f, 1.0f},
{ 3.0f, 1.0f},
{-1.0f, -3.0f},
};
struct vs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float3 clip2 : SV_ClipDistance1;
};
void main(uint id : SV_VertexID, out vs_out o)
{
const float2 pos = vertices[id];
o.position = float4(pos, 0.0f, 1.0f);
o.clip.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
o.clip.y = 0.15f + 0.6f * pos.x - 0.4f * pos.y;
o.clip2.x = 0.55f - 0.6f * pos.x + 0.4f * pos.y;
o.clip2.y = 0.25f - 0.6f * pos.x + 0.4f * pos.y;
o.clip2.z = 0.25f - 0.6f * pos.x - 0.4f * pos.y;
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6 | msl) draw triangle strip 4
probe rtv 0 (160, 120) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) rgba(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) rgba(1.0, 1.0, 0.0, 1.0)
[require]
shader model >= 4.0
cull-distance
% Now it works. Here all the cull distances are effectively ignored, because
% they do not leave the only triangle entirely on one side. (Also, they
% coincide with other clip distances.)
[vertex shader todo]
static const float2 vertices[3] =
{
{-1.0f, 1.0f},
{ 3.0f, 1.0f},
{-1.0f, -3.0f},
};
struct vs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float3 clip2 : SV_ClipDistance1;
float2 cull2 : SV_CullDistance1;
float1 cull : SV_CullDistance;
};
void main(uint id : SV_VertexID, out vs_out o)
{
const float2 pos = vertices[id];
o.position = float4(pos, 0.0f, 1.0f);
o.clip.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
o.clip.y = 0.15f + 0.6f * pos.x - 0.4f * pos.y;
o.clip2.x = 0.55f - 0.6f * pos.x + 0.4f * pos.y;
o.clip2.y = 0.25f - 0.6f * pos.x + 0.4f * pos.y;
o.clip2.z = 0.25f - 0.6f * pos.x - 0.4f * pos.y;
o.cull.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
o.cull2.x = 0.55f - 0.6f * pos.x + 0.4f * pos.y;
o.cull2.y = 0.25f - 0.6f * pos.x + 0.4f * pos.y;
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6) draw triangle strip 4
probe rtv 0 (160, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(1.0, 1.0, 0.0, 1.0)
[require]
shader model >= 4.0
cull-distance
geometry-shader
% Let clip and cull distances go through a geometry shader.
[geometry shader todo]
struct vs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float3 clip2 : SV_ClipDistance1;
float2 cull2 : SV_CullDistance1;
float1 cull : SV_CullDistance;
};
[maxvertexcount(3)]
void main(triangle vs_out input[3], inout TriangleStream<vs_out> stream)
{
unsigned int i;
vs_out output;
for (i = 0; i < 3; ++i)
{
output = input[i];
stream.Append(output);
}
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6) draw triangle strip 4
probe rtv 0 (160, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(1.0, 1.0, 0.0, 1.0)
% Generate clip and cull distances in the geometry shader.
[vertex shader]
static const float2 vertices[3] =
{
{-1.0f, 1.0f},
{ 3.0f, 1.0f},
{-1.0f, -3.0f},
};
struct vs_out
{
float4 position : SV_Position;
uint id : VERTEXID;
};
void main(uint id : SV_VertexID, out vs_out o)
{
const float2 pos = vertices[id];
o.position = float4(pos, 0.0f, 1.0f);
o.id = id;
}
[geometry shader todo]
struct vs_out
{
float4 position : SV_Position;
uint id : VERTEXID;
};
struct gs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float3 clip2 : SV_ClipDistance1;
float2 cull2 : SV_CullDistance1;
float1 cull : SV_CullDistance;
};
void emit_position(float4 pos, inout TriangleStream<gs_out> stream)
{
gs_out output;
output.position = pos;
output.clip.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
output.clip.y = 0.15f + 0.6f * pos.x - 0.4f * pos.y;
output.clip2.x = 0.55f - 0.6f * pos.x + 0.4f * pos.y;
output.clip2.y = 0.25f - 0.6f * pos.x + 0.4f * pos.y;
output.clip2.z = 0.25f - 0.6f * pos.x - 0.4f * pos.y;
output.cull.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
output.cull2.x = 0.55f - 0.6f * pos.x + 0.4f * pos.y;
output.cull2.y = 0.25f - 0.6f * pos.x + 0.4f * pos.y;
stream.Append(output);
}
[maxvertexcount(3)]
void main(triangle vs_out input[3], inout TriangleStream<gs_out> stream)
{
unsigned int i;
for (i = 0; i < 3; ++i)
emit_position(input[i].position, stream);
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6) draw triangle strip 4
probe rtv 0 (160, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(1.0, 1.0, 0.0, 1.0)
% Now let's test cull distances for real: we remove the clip distances they
% duplicate and use the geometry shader to create many little triangles around
% the test points; first we check that we're drawing properly disabling all
% clipping and culling.
[geometry shader todo]
struct vs_out
{
float4 position : SV_Position;
uint id : VERTEXID;
};
struct gs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float2 cull2 : SV_CullDistance1;
float1 cull : SV_CullDistance;
};
void emit_position(float4 pos, inout TriangleStream<gs_out> stream)
{
gs_out output;
output.position = pos;
output.clip = 1.0f;
output.cull = 1.0f;
output.cull2 = 1.0f;
stream.Append(output);
}
static const float4 displacements[3] =
{
{ 0.01f, 0.01f, 0.0f, 0.0f},
{-0.02f, 0.01f, 0.0f, 0.0f},
{ 0.01f, -0.02f, 0.0f, 0.0f},
};
[maxvertexcount(27)]
void main(triangle vs_out input[3], inout TriangleStream<gs_out> stream)
{
unsigned int i, j;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 3; ++j)
{
float4 pos = float4(0.0f, 0.0f, 0.0f, 1.0f);
pos.x = 0.5f - 0.5f * i;
pos.y = 0.5f - 0.5f * j;
emit_position(pos + displacements[0], stream);
emit_position(pos + displacements[1], stream);
emit_position(pos + displacements[2], stream);
stream.RestartStrip();
}
}
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6) draw triangle strip 4
probe rtv 0 (160, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) rgba(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) rgba(0.0, 1.0, 0.0, 1.0)
% Then we add clipping and culling: at first only a few distances.
[geometry shader todo]
struct vs_out
{
float4 position : SV_Position;
uint id : VERTEXID;
};
struct gs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float2 cull2 : SV_CullDistance1;
float1 cull : SV_CullDistance;
};
void emit_position(float4 pos, inout TriangleStream<gs_out> stream)
{
gs_out output;
output.position = pos;
output.clip = 1.0f;
output.clip.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
output.cull = 1.0f;
output.cull.x = 0.25f - 0.6f * pos.x - 0.4f * pos.y;
output.cull2 = 1.0f;
stream.Append(output);
}
static const float4 displacements[3] =
{
{ 0.01f, 0.01f, 0.0f, 0.0f},
{-0.02f, 0.01f, 0.0f, 0.0f},
{ 0.01f, -0.02f, 0.0f, 0.0f},
};
[maxvertexcount(27)]
void main(triangle vs_out input[3], inout TriangleStream<gs_out> stream)
{
unsigned int i, j;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 3; ++j)
{
float4 pos = float4(0.0f, 0.0f, 0.0f, 1.0f);
pos.x = 0.5f - 0.5f * i;
pos.y = 0.5f - 0.5f * j;
emit_position(pos + displacements[0], stream);
emit_position(pos + displacements[1], stream);
emit_position(pos + displacements[2], stream);
stream.RestartStrip();
}
}
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6) draw triangle strip 4
probe rtv 0 (160, 120) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 360) f32(0.0, 1.0, 0.0, 1.0)
% Then enough to get rid of nearly all test points.
[geometry shader todo]
struct vs_out
{
float4 position : SV_Position;
uint id : VERTEXID;
};
struct gs_out
{
float4 position : SV_Position;
float2 clip : SV_ClipDistance;
float2 cull2 : SV_CullDistance1;
float1 cull : SV_CullDistance;
};
void emit_position(float4 pos, inout TriangleStream<gs_out> stream)
{
gs_out output;
output.position = pos;
output.clip.x = 0.15f + 0.6f * pos.x + 0.4f * pos.y;
output.clip.y = 0.15f + 0.6f * pos.x - 0.4f * pos.y;
output.cull.x = 0.25f - 0.6f * pos.x - 0.4f * pos.y;
output.cull2.x = 0.55f - 0.6f * pos.x + 0.4f * pos.y;
output.cull2.y = 0.25f - 0.6f * pos.x + 0.4f * pos.y;
stream.Append(output);
}
static const float4 displacements[3] =
{
{ 0.05f, 0.05f, 0.0f, 0.0f},
{-0.1f, 0.05f, 0.0f, 0.0f},
{ 0.05f, -0.1f, 0.0f, 0.0f},
};
[maxvertexcount(27)]
void main(triangle vs_out input[3], inout TriangleStream<gs_out> stream)
{
unsigned int i, j;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 3; ++j)
{
float4 pos = float4(0.0f, 0.0f, 0.0f, 1.0f);
pos.x = 0.5f - 0.5f * i;
pos.y = 0.5f - 0.5f * j;
emit_position(pos + displacements[0], stream);
emit_position(pos + displacements[1], stream);
emit_position(pos + displacements[2], stream);
stream.RestartStrip();
}
}
}
[test]
clear rtv 0 1.0 1.0 0.0 1.0
todo(sm<6) draw triangle strip 4
probe rtv 0 (160, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 240) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (160, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 240) f32(0.0, 1.0, 0.0, 1.0)
probe rtv 0 (320, 360) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 120) f32(1.0, 1.0, 0.0, 1.0)
probe rtv 0 (480, 240) f32(1.0, 1.0, 0.0, 1.0)
bug(mesa<23.3) probe rtv 0 (480, 360) f32(1.0, 1.0, 0.0, 1.0)