Skip to content

Commit 8a68c02

Browse files
authored
Selective output geometry shader test (#1222)
Adds a geometry shader test that exercises selective primitive output via `SV_PrimitiveID`. Two CCW triangles tile a 2×2 render target — primitive 0 covers the bottom half, primitive 1 the top half. The GS emits primitive 0 unchanged and drops primitive 1 by returning without any `Append()` calls.
1 parent d2421d6 commit 8a68c02

1 file changed

Lines changed: 106 additions & 0 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#--- vertex.hlsl
2+
struct VSOutput {
3+
float4 position : SV_POSITION;
4+
};
5+
6+
VSOutput main(float4 position : POSITION) {
7+
VSOutput o;
8+
o.position = position;
9+
return o;
10+
}
11+
12+
#--- geometry.hlsl
13+
struct GSInput {
14+
float4 position : SV_POSITION;
15+
};
16+
17+
struct GSOutput {
18+
float4 position : SV_POSITION;
19+
};
20+
21+
// Selective-output GS, keyed on SV_PrimitiveID (auto-generated by the input
22+
// assembler). Primitive 0 (the bottom-half triangle) is emitted; primitive 1
23+
// (the top-half triangle) is dropped by returning without any Append() calls.
24+
[maxvertexcount(3)]
25+
void main(triangle GSInput input[3],
26+
uint primID : SV_PrimitiveID,
27+
inout TriangleStream<GSOutput> stream) {
28+
if (primID != 0)
29+
return;
30+
31+
GSOutput v;
32+
v.position = input[0].position; stream.Append(v);
33+
v.position = input[1].position; stream.Append(v);
34+
v.position = input[2].position; stream.Append(v);
35+
}
36+
37+
#--- pixel.hlsl
38+
struct PSInput {
39+
float4 position : SV_POSITION;
40+
};
41+
42+
float4 main(PSInput input) : SV_TARGET {
43+
return float4(1.0, 0.0, 0.0, 1.0);
44+
}
45+
46+
#--- pipeline.yaml
47+
---
48+
Shaders:
49+
- Stage: Vertex
50+
Entry: main
51+
- Stage: Geometry
52+
Entry: main
53+
- Stage: Pixel
54+
Entry: main
55+
Buffers:
56+
# Two CCW-wound triangles tiling the 2x2 viewport: primitive 0 covers the
57+
# bottom half (NDC y < 0), primitive 1 covers the top half (NDC y > 0).
58+
# Both are oversized so coverage is unambiguous at every pixel center.
59+
- Name: VertexData
60+
Format: Float32
61+
Stride: 16 # 6 vertices, 16 bytes each
62+
Data: [ -3.0, -1.0, 0.0, 1.0,
63+
3.0, -1.0, 0.0, 1.0,
64+
0.0, 0.0, 0.0, 1.0,
65+
-3.0, 1.0, 0.0, 1.0,
66+
0.0, 0.0, 0.0, 1.0,
67+
3.0, 1.0, 0.0, 1.0 ]
68+
- Name: Output
69+
Format: Float32
70+
Channels: 4
71+
FillSize: 64 # 2x2 @ 16 bytes per pixel
72+
OutputProps:
73+
Height: 2
74+
Width: 2
75+
Depth: 1
76+
Bindings:
77+
VertexBuffer: VertexData
78+
VertexAttributes:
79+
- Format: Float32
80+
Channels: 4
81+
Offset: 0
82+
Name: POSITION
83+
RenderTarget: Output
84+
DescriptorSets: []
85+
...
86+
#--- end
87+
88+
# Metal has no native geometry shader stage.
89+
# UNSUPPORTED: Metal
90+
91+
# Clang's HLSL frontend does not yet support geometry shader stream types.
92+
# Tracked upstream: https://github.com/llvm/llvm-project/issues/136963
93+
# XFAIL: Clang
94+
95+
# RUN: split-file %s %t
96+
# RUN: %dxc_target -T vs_6_0 -Fo %t-vertex.o %t/vertex.hlsl
97+
# RUN: %dxc_target -T gs_6_0 -Fo %t-geometry.o %t/geometry.hlsl
98+
# RUN: %dxc_target -T ps_6_0 -Fo %t-pixel.o %t/pixel.hlsl
99+
# RUN: %offloader %t/pipeline.yaml %t-vertex.o %t-geometry.o %t-pixel.o | FileCheck %s
100+
101+
# Readback is top-left origin, row-major. The top row (image rows 0) was
102+
# covered by the dropped primitive 1, so it stays at the default clear
103+
# (0, 0, 0, 0). The bottom row (image row 1) was covered by the kept
104+
# primitive 0, so it is opaque red.
105+
# CHECK: Name: Output
106+
# CHECK: Data: [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1 ]

0 commit comments

Comments
 (0)