Skip to content

Commit 88e9100

Browse files
Make vertex buffers optional in the TraditionalRaster pipeline and add VerticesFromVertexID.test (llvm#1155)
Fixes llvm#1154 Add a TraditionalRaster test that doesn't use a vertex buffer, but generates a triangle using the SV_VertexID. This is a pretty common use case in game engines. To make this work this changes makes the specifying a vertex buffer optional.
1 parent 6c4c12b commit 88e9100

5 files changed

Lines changed: 112 additions & 52 deletions

File tree

include/Support/Pipeline.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,11 +383,11 @@ struct VertexAttribute {
383383

384384
struct IOBindings {
385385
std::string VertexBuffer;
386-
CPUBuffer *VertexBufferPtr;
386+
CPUBuffer *VertexBufferPtr = nullptr;
387387
llvm::SmallVector<VertexAttribute> VertexAttributes;
388388

389389
std::string RenderTarget;
390-
CPUBuffer *RTargetBufferPtr;
390+
CPUBuffer *RTargetBufferPtr = nullptr;
391391

392392
uint32_t getVertexStride() const {
393393
uint32_t Stride = 0;

lib/API/DX/Device.cpp

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,16 @@ class DXDevice : public offloadtest::Device {
16381638
if (auto Err = CreateBuffer(Resource, IS.RootResources))
16391639
return Err;
16401640
}
1641+
1642+
if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) {
1643+
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
1644+
*this, *P.Bindings.VertexBufferPtr);
1645+
if (!VBOrErr)
1646+
return VBOrErr.takeError();
1647+
IS.VB = std::move(*VBOrErr);
1648+
llvm::outs() << "Vertex buffer created.\n";
1649+
}
1650+
16411651
return llvm::Error::success();
16421652
}
16431653

@@ -1911,39 +1921,11 @@ class DXDevice : public offloadtest::Device {
19111921
return llvm::Error::success();
19121922
}
19131923

1914-
llvm::Error createVertexBuffer(Pipeline &P, InvocationState &IS) {
1915-
if (!P.Bindings.VertexBufferPtr)
1916-
return llvm::createStringError(
1917-
std::errc::invalid_argument,
1918-
"No vertex buffer bound for graphics pipeline.");
1919-
1920-
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
1921-
*this, *P.Bindings.VertexBufferPtr);
1922-
if (!VBOrErr)
1923-
return VBOrErr.takeError();
1924-
IS.VB = std::move(*VBOrErr);
1925-
1926-
auto &VBBuf = llvm::cast<DXBuffer>(*IS.VB);
1927-
D3D12_VERTEX_BUFFER_VIEW VBView = {};
1928-
VBView.BufferLocation = VBBuf.Buffer->GetGPUVirtualAddress();
1929-
VBView.SizeInBytes = static_cast<UINT>(IS.VB->getSizeInBytes());
1930-
VBView.StrideInBytes = P.Bindings.getVertexStride();
1931-
1932-
IS.CB->CmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1933-
IS.CB->CmdList->IASetVertexBuffers(0, 1, &VBView);
1934-
1935-
return llvm::Error::success();
1936-
}
1937-
19381924
llvm::Error createGraphicsCommands(Pipeline &P, InvocationState &IS) {
19391925
auto &RT = llvm::cast<DXTexture>(*IS.RT);
19401926
auto &DS = llvm::cast<DXTexture>(*IS.DS);
19411927
auto &RTReadback = llvm::cast<DXBuffer>(*IS.RTReadback);
19421928

1943-
if (!IS.VB)
1944-
return llvm::createStringError(std::errc::invalid_argument,
1945-
"Vertex buffer not initialized.");
1946-
19471929
const DXPipelineState &DXPipeline =
19481930
llvm::cast<DXPipelineState>(*IS.Pipeline.get());
19491931
IS.CB->CmdList->SetGraphicsRootSignature(DXPipeline.RootSig.Get());
@@ -1981,6 +1963,17 @@ class DXDevice : public offloadtest::Device {
19811963
static_cast<LONG>(VP.Height)};
19821964
IS.CB->CmdList->RSSetScissorRects(1, &Scissor);
19831965

1966+
if (IS.VB) {
1967+
auto &VBBuf = llvm::cast<DXBuffer>(*IS.VB);
1968+
D3D12_VERTEX_BUFFER_VIEW VBView = {};
1969+
VBView.BufferLocation = VBBuf.Buffer->GetGPUVirtualAddress();
1970+
VBView.SizeInBytes = static_cast<UINT>(IS.VB->getSizeInBytes());
1971+
VBView.StrideInBytes = P.Bindings.getVertexStride();
1972+
IS.CB->CmdList->IASetVertexBuffers(0, 1, &VBView);
1973+
}
1974+
1975+
IS.CB->CmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1976+
19841977
IS.CB->CmdList->DrawInstanced(P.getVertexCount(), 1, 0, 0);
19851978

19861979
// Transition the render target to copy source and copy to the readback
@@ -2108,9 +2101,6 @@ class DXDevice : public offloadtest::Device {
21082101
if (auto Err = createDepthStencil(P, State))
21092102
return Err;
21102103
llvm::outs() << "Depth stencil created.\n";
2111-
if (auto Err = createVertexBuffer(P, State))
2112-
return Err;
2113-
llvm::outs() << "Vertex buffer created.\n";
21142104

21152105
ShaderContainer VS = {};
21162106
ShaderContainer PS = {};

lib/API/MTL/MTLDevice.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -955,17 +955,13 @@ class MTLDevice : public offloadtest::Device {
955955
}
956956
}
957957

958-
if (P.isTraditionalRaster()) {
959-
if (!P.Bindings.VertexBufferPtr)
960-
return llvm::createStringError(
961-
std::errc::invalid_argument,
962-
"No vertex buffer specified for graphics pipeline.");
963-
958+
if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) {
964959
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
965960
*this, *P.Bindings.VertexBufferPtr);
966961
if (!VBOrErr)
967962
return VBOrErr.takeError();
968963
IS.VB = std::move(*VBOrErr);
964+
llvm::outs() << "Vertex buffer created.\n";
969965
}
970966
return llvm::Error::success();
971967
}
@@ -1146,9 +1142,10 @@ class MTLDevice : public offloadtest::Device {
11461142
CmdEncoder->setCullMode(MTL::CullModeNone);
11471143
CmdEncoder->setFrontFacingWinding(MTL::WindingCounterClockwise);
11481144

1149-
// Bind vertex buffer at slot 0 to match the vertex descriptor which
1150-
// references buffer index 0.
1151-
CmdEncoder->setVertexBuffer(llvm::cast<MTLBuffer>(*IS.VB).Buf, 0, 0);
1145+
if (IS.VB)
1146+
// Bind vertex buffer at slot 0 to match the vertex descriptor which
1147+
// references buffer index 0.
1148+
CmdEncoder->setVertexBuffer(llvm::cast<MTLBuffer>(*IS.VB).Buf, 0, 0);
11521149

11531150
CmdEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0),
11541151
P.getVertexCount());
@@ -1388,8 +1385,8 @@ class MTLDevice : public offloadtest::Device {
13881385
"Mismatch between vertex shader attribute count and pipeline "
13891386
"vertex input count.");
13901387

1391-
// Collect the attribute indices the shader expects so that we can map the
1392-
// specified attributes onto the correct indices.
1388+
// Collect the attribute indices the shader expects so that we can map
1389+
// the specified attributes onto the correct indices.
13931390
llvm::StringMap<uint32_t> ShaderAttrIndices;
13941391
for (uint32_t I = 0; I < FnAttrs->count(); ++I) {
13951392
auto *A = static_cast<MTL::VertexAttribute *>(FnAttrs->object(I));

lib/API/VK/Device.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,17 +1931,15 @@ class VulkanDevice : public offloadtest::Device {
19311931
// conditional on the pipeline definition.
19321932
if (auto Err = createDepthStencil(P, IS))
19331933
return Err;
1934+
}
19341935

1935-
if (P.Bindings.VertexBufferPtr == nullptr)
1936-
return llvm::createStringError(
1937-
std::errc::invalid_argument,
1938-
"No Vertex buffer specified for graphics pipeline.");
1939-
1936+
if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) {
19401937
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
19411938
*this, *P.Bindings.VertexBufferPtr);
19421939
if (!VBOrErr)
19431940
return VBOrErr.takeError();
19441941
IS.VB = std::move(*VBOrErr);
1942+
llvm::outs() << "Vertex buffer created.\n";
19451943
}
19461944

19471945
return llvm::Error::success();
@@ -2737,9 +2735,10 @@ class VulkanDevice : public offloadtest::Device {
27372735
<< P.DispatchParameters.DispatchGroupCount[2] << " }\n";
27382736
} else {
27392737
VkDeviceSize Offsets[1]{0};
2740-
assert(IS.VB);
2741-
VkBuffer VBHandle = llvm::cast<VulkanBuffer>(*IS.VB).Buffer;
2742-
vkCmdBindVertexBuffers(IS.CB->CmdBuffer, 0, 1, &VBHandle, Offsets);
2738+
if (IS.VB) {
2739+
VkBuffer VBHandle = llvm::cast<VulkanBuffer>(*IS.VB).Buffer;
2740+
vkCmdBindVertexBuffers(IS.CB->CmdBuffer, 0, 1, &VBHandle, Offsets);
2741+
}
27432742
// instanceCount must be >=1 to draw; previously was 0 which draws nothing
27442743
vkCmdDraw(IS.CB->CmdBuffer, P.getVertexCount(), 1, 0, 0);
27452744
llvm::outs() << "Drew " << P.getVertexCount() << " vertices.\n";
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#--- vertex.hlsl
2+
struct PSInput
3+
{
4+
float4 position : SV_POSITION;
5+
float4 color : COLOR;
6+
};
7+
8+
PSInput main(uint vertexID : SV_VertexID)
9+
{
10+
PSInput result;
11+
12+
if (vertexID == 0) {
13+
result.position = float4(0.0, 0.25, 0.0, 1.0);
14+
result.color = float4(1.0, 0.0, 0.0, 1.0);
15+
} else if (vertexID == 1) {
16+
result.position = float4(0.25, -0.25, 0.0, 1.0);
17+
result.color = float4(0.0, 1.0, 0.0, 1.0);
18+
} else {
19+
result.position = float4(-0.25, -0.25, 0.0, 1.0);
20+
result.color = float4(0.0, 0.0, 1.0, 1.0);
21+
}
22+
23+
return result;
24+
}
25+
26+
27+
#--- pixel.hlsl
28+
struct PSInput
29+
{
30+
float4 position : SV_POSITION;
31+
float4 color : COLOR;
32+
};
33+
34+
float4 main(PSInput input) : SV_TARGET
35+
{
36+
return input.color;
37+
}
38+
#--- pipeline.yaml
39+
---
40+
Shaders:
41+
- Stage: Vertex
42+
Entry: main
43+
- Stage: Pixel
44+
Entry: main
45+
Buffers:
46+
- Name: Output
47+
Format: Float32
48+
Channels: 4
49+
FillSize: 1048576 # 256x256 @ 16 bytes per pixel
50+
OutputProps:
51+
Height: 256
52+
Width: 256
53+
Depth: 1
54+
Bindings:
55+
RenderTarget: Output
56+
DescriptorSets: []
57+
DispatchParameters:
58+
VertexCount: 3
59+
...
60+
#--- rules.yaml
61+
---
62+
- Type: PixelPercent
63+
Val: 0.2 # No more than 0.2% of pixels may be visibly different.
64+
...
65+
#--- end
66+
67+
# XFAIL: Clang && !Vulkan
68+
# REQUIRES: goldenimage
69+
70+
# RUN: split-file %s %t
71+
# RUN: %dxc_target -T vs_6_0 -Fo %t-vertex.o %t/vertex.hlsl
72+
# RUN: %dxc_target -T ps_6_0 -Fo %t-pixel.o %t/pixel.hlsl
73+
# RUN: %offloader %t/pipeline.yaml %t-vertex.o %t-pixel.o -r Output -o %t/Output.png
74+
# RUN: imgdiff %t/Output.png %goldenimage_dir/hlsl/Graphics/SimpleTriangle.png -rules %t/rules.yaml

0 commit comments

Comments
 (0)