diff --git a/test/Graphics/gs_selective_output.test b/test/Graphics/gs_selective_output.test new file mode 100644 index 000000000..e9bf07f41 --- /dev/null +++ b/test/Graphics/gs_selective_output.test @@ -0,0 +1,106 @@ +#--- vertex.hlsl +struct VSOutput { + float4 position : SV_POSITION; +}; + +VSOutput main(float4 position : POSITION) { + VSOutput o; + o.position = position; + return o; +} + +#--- geometry.hlsl +struct GSInput { + float4 position : SV_POSITION; +}; + +struct GSOutput { + float4 position : SV_POSITION; +}; + +// Selective-output GS, keyed on SV_PrimitiveID (auto-generated by the input +// assembler). Primitive 0 (the bottom-half triangle) is emitted; primitive 1 +// (the top-half triangle) is dropped by returning without any Append() calls. +[maxvertexcount(3)] +void main(triangle GSInput input[3], + uint primID : SV_PrimitiveID, + inout TriangleStream stream) { + if (primID != 0) + return; + + GSOutput v; + v.position = input[0].position; stream.Append(v); + v.position = input[1].position; stream.Append(v); + v.position = input[2].position; stream.Append(v); +} + +#--- pixel.hlsl +struct PSInput { + float4 position : SV_POSITION; +}; + +float4 main(PSInput input) : SV_TARGET { + return float4(1.0, 0.0, 0.0, 1.0); +} + +#--- pipeline.yaml +--- +Shaders: + - Stage: Vertex + Entry: main + - Stage: Geometry + Entry: main + - Stage: Pixel + Entry: main +Buffers: + # Two CCW-wound triangles tiling the 2x2 viewport: primitive 0 covers the + # bottom half (NDC y < 0), primitive 1 covers the top half (NDC y > 0). + # Both are oversized so coverage is unambiguous at every pixel center. + - Name: VertexData + Format: Float32 + Stride: 16 # 6 vertices, 16 bytes each + Data: [ -3.0, -1.0, 0.0, 1.0, + 3.0, -1.0, 0.0, 1.0, + 0.0, 0.0, 0.0, 1.0, + -3.0, 1.0, 0.0, 1.0, + 0.0, 0.0, 0.0, 1.0, + 3.0, 1.0, 0.0, 1.0 ] + - Name: Output + Format: Float32 + Channels: 4 + FillSize: 64 # 2x2 @ 16 bytes per pixel + OutputProps: + Height: 2 + Width: 2 + Depth: 1 +Bindings: + VertexBuffer: VertexData + VertexAttributes: + - Format: Float32 + Channels: 4 + Offset: 0 + Name: POSITION + RenderTarget: Output +DescriptorSets: [] +... +#--- end + +# Metal has no native geometry shader stage. +# UNSUPPORTED: Metal + +# Clang's HLSL frontend does not yet support geometry shader stream types. +# Tracked upstream: https://github.com/llvm/llvm-project/issues/136963 +# XFAIL: Clang + +# RUN: split-file %s %t +# RUN: %dxc_target -T vs_6_0 -Fo %t-vertex.o %t/vertex.hlsl +# RUN: %dxc_target -T gs_6_0 -Fo %t-geometry.o %t/geometry.hlsl +# RUN: %dxc_target -T ps_6_0 -Fo %t-pixel.o %t/pixel.hlsl +# RUN: %offloader %t/pipeline.yaml %t-vertex.o %t-geometry.o %t-pixel.o | FileCheck %s + +# Readback is top-left origin, row-major. The top row (image rows 0) was +# covered by the dropped primitive 1, so it stays at the default clear +# (0, 0, 0, 0). The bottom row (image row 1) was covered by the kept +# primitive 0, so it is opaque red. +# CHECK: Name: Output +# CHECK: Data: [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1 ]