[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) 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 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 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 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 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 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 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 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 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 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 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)