diff --git a/include/Support/Pipeline.h b/include/Support/Pipeline.h index c38ca24b1..6f0f2019e 100644 --- a/include/Support/Pipeline.h +++ b/include/Support/Pipeline.h @@ -383,11 +383,11 @@ struct VertexAttribute { struct IOBindings { std::string VertexBuffer; - CPUBuffer *VertexBufferPtr; + CPUBuffer *VertexBufferPtr = nullptr; llvm::SmallVector VertexAttributes; std::string RenderTarget; - CPUBuffer *RTargetBufferPtr; + CPUBuffer *RTargetBufferPtr = nullptr; uint32_t getVertexStride() const { uint32_t Stride = 0; diff --git a/lib/API/DX/Device.cpp b/lib/API/DX/Device.cpp index aabba47c6..003d541c1 100644 --- a/lib/API/DX/Device.cpp +++ b/lib/API/DX/Device.cpp @@ -1638,6 +1638,16 @@ class DXDevice : public offloadtest::Device { if (auto Err = CreateBuffer(Resource, IS.RootResources)) return Err; } + + if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) { + auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer( + *this, *P.Bindings.VertexBufferPtr); + if (!VBOrErr) + return VBOrErr.takeError(); + IS.VB = std::move(*VBOrErr); + llvm::outs() << "Vertex buffer created.\n"; + } + return llvm::Error::success(); } @@ -1911,39 +1921,11 @@ class DXDevice : public offloadtest::Device { return llvm::Error::success(); } - llvm::Error createVertexBuffer(Pipeline &P, InvocationState &IS) { - if (!P.Bindings.VertexBufferPtr) - return llvm::createStringError( - std::errc::invalid_argument, - "No vertex buffer bound for graphics pipeline."); - - auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer( - *this, *P.Bindings.VertexBufferPtr); - if (!VBOrErr) - return VBOrErr.takeError(); - IS.VB = std::move(*VBOrErr); - - auto &VBBuf = llvm::cast(*IS.VB); - D3D12_VERTEX_BUFFER_VIEW VBView = {}; - VBView.BufferLocation = VBBuf.Buffer->GetGPUVirtualAddress(); - VBView.SizeInBytes = static_cast(IS.VB->getSizeInBytes()); - VBView.StrideInBytes = P.Bindings.getVertexStride(); - - IS.CB->CmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - IS.CB->CmdList->IASetVertexBuffers(0, 1, &VBView); - - return llvm::Error::success(); - } - llvm::Error createGraphicsCommands(Pipeline &P, InvocationState &IS) { auto &RT = llvm::cast(*IS.RT); auto &DS = llvm::cast(*IS.DS); auto &RTReadback = llvm::cast(*IS.RTReadback); - if (!IS.VB) - return llvm::createStringError(std::errc::invalid_argument, - "Vertex buffer not initialized."); - const DXPipelineState &DXPipeline = llvm::cast(*IS.Pipeline.get()); IS.CB->CmdList->SetGraphicsRootSignature(DXPipeline.RootSig.Get()); @@ -1981,6 +1963,17 @@ class DXDevice : public offloadtest::Device { static_cast(VP.Height)}; IS.CB->CmdList->RSSetScissorRects(1, &Scissor); + if (IS.VB) { + auto &VBBuf = llvm::cast(*IS.VB); + D3D12_VERTEX_BUFFER_VIEW VBView = {}; + VBView.BufferLocation = VBBuf.Buffer->GetGPUVirtualAddress(); + VBView.SizeInBytes = static_cast(IS.VB->getSizeInBytes()); + VBView.StrideInBytes = P.Bindings.getVertexStride(); + IS.CB->CmdList->IASetVertexBuffers(0, 1, &VBView); + } + + IS.CB->CmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + IS.CB->CmdList->DrawInstanced(P.getVertexCount(), 1, 0, 0); // Transition the render target to copy source and copy to the readback @@ -2108,9 +2101,6 @@ class DXDevice : public offloadtest::Device { if (auto Err = createDepthStencil(P, State)) return Err; llvm::outs() << "Depth stencil created.\n"; - if (auto Err = createVertexBuffer(P, State)) - return Err; - llvm::outs() << "Vertex buffer created.\n"; ShaderContainer VS = {}; ShaderContainer PS = {}; diff --git a/lib/API/MTL/MTLDevice.cpp b/lib/API/MTL/MTLDevice.cpp index a5ce8d3ed..8e5e78d73 100644 --- a/lib/API/MTL/MTLDevice.cpp +++ b/lib/API/MTL/MTLDevice.cpp @@ -955,17 +955,13 @@ class MTLDevice : public offloadtest::Device { } } - if (P.isTraditionalRaster()) { - if (!P.Bindings.VertexBufferPtr) - return llvm::createStringError( - std::errc::invalid_argument, - "No vertex buffer specified for graphics pipeline."); - + if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) { auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer( *this, *P.Bindings.VertexBufferPtr); if (!VBOrErr) return VBOrErr.takeError(); IS.VB = std::move(*VBOrErr); + llvm::outs() << "Vertex buffer created.\n"; } return llvm::Error::success(); } @@ -1146,9 +1142,10 @@ class MTLDevice : public offloadtest::Device { CmdEncoder->setCullMode(MTL::CullModeNone); CmdEncoder->setFrontFacingWinding(MTL::WindingCounterClockwise); - // Bind vertex buffer at slot 0 to match the vertex descriptor which - // references buffer index 0. - CmdEncoder->setVertexBuffer(llvm::cast(*IS.VB).Buf, 0, 0); + if (IS.VB) + // Bind vertex buffer at slot 0 to match the vertex descriptor which + // references buffer index 0. + CmdEncoder->setVertexBuffer(llvm::cast(*IS.VB).Buf, 0, 0); CmdEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), P.getVertexCount()); @@ -1388,8 +1385,8 @@ class MTLDevice : public offloadtest::Device { "Mismatch between vertex shader attribute count and pipeline " "vertex input count."); - // Collect the attribute indices the shader expects so that we can map the - // specified attributes onto the correct indices. + // Collect the attribute indices the shader expects so that we can map + // the specified attributes onto the correct indices. llvm::StringMap ShaderAttrIndices; for (uint32_t I = 0; I < FnAttrs->count(); ++I) { auto *A = static_cast(FnAttrs->object(I)); diff --git a/lib/API/VK/Device.cpp b/lib/API/VK/Device.cpp index 6ee8adaa8..908145e3c 100644 --- a/lib/API/VK/Device.cpp +++ b/lib/API/VK/Device.cpp @@ -1931,17 +1931,15 @@ class VulkanDevice : public offloadtest::Device { // conditional on the pipeline definition. if (auto Err = createDepthStencil(P, IS)) return Err; + } - if (P.Bindings.VertexBufferPtr == nullptr) - return llvm::createStringError( - std::errc::invalid_argument, - "No Vertex buffer specified for graphics pipeline."); - + if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) { auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer( *this, *P.Bindings.VertexBufferPtr); if (!VBOrErr) return VBOrErr.takeError(); IS.VB = std::move(*VBOrErr); + llvm::outs() << "Vertex buffer created.\n"; } return llvm::Error::success(); @@ -2737,9 +2735,10 @@ class VulkanDevice : public offloadtest::Device { << P.DispatchParameters.DispatchGroupCount[2] << " }\n"; } else { VkDeviceSize Offsets[1]{0}; - assert(IS.VB); - VkBuffer VBHandle = llvm::cast(*IS.VB).Buffer; - vkCmdBindVertexBuffers(IS.CB->CmdBuffer, 0, 1, &VBHandle, Offsets); + if (IS.VB) { + VkBuffer VBHandle = llvm::cast(*IS.VB).Buffer; + vkCmdBindVertexBuffers(IS.CB->CmdBuffer, 0, 1, &VBHandle, Offsets); + } // instanceCount must be >=1 to draw; previously was 0 which draws nothing vkCmdDraw(IS.CB->CmdBuffer, P.getVertexCount(), 1, 0, 0); llvm::outs() << "Drew " << P.getVertexCount() << " vertices.\n"; diff --git a/test/Graphics/VerticesFromVertexID.test b/test/Graphics/VerticesFromVertexID.test new file mode 100644 index 000000000..c3bd1288a --- /dev/null +++ b/test/Graphics/VerticesFromVertexID.test @@ -0,0 +1,74 @@ +#--- vertex.hlsl +struct PSInput +{ + float4 position : SV_POSITION; + float4 color : COLOR; +}; + +PSInput main(uint vertexID : SV_VertexID) +{ + PSInput result; + + if (vertexID == 0) { + result.position = float4(0.0, 0.25, 0.0, 1.0); + result.color = float4(1.0, 0.0, 0.0, 1.0); + } else if (vertexID == 1) { + result.position = float4(0.25, -0.25, 0.0, 1.0); + result.color = float4(0.0, 1.0, 0.0, 1.0); + } else { + result.position = float4(-0.25, -0.25, 0.0, 1.0); + result.color = float4(0.0, 0.0, 1.0, 1.0); + } + + return result; +} + + +#--- pixel.hlsl +struct PSInput +{ + float4 position : SV_POSITION; + float4 color : COLOR; +}; + +float4 main(PSInput input) : SV_TARGET +{ + return input.color; +} +#--- pipeline.yaml +--- +Shaders: + - Stage: Vertex + Entry: main + - Stage: Pixel + Entry: main +Buffers: + - Name: Output + Format: Float32 + Channels: 4 + FillSize: 1048576 # 256x256 @ 16 bytes per pixel + OutputProps: + Height: 256 + Width: 256 + Depth: 1 +Bindings: + RenderTarget: Output +DescriptorSets: [] +DispatchParameters: + VertexCount: 3 +... +#--- rules.yaml +--- +- Type: PixelPercent + Val: 0.2 # No more than 0.2% of pixels may be visibly different. +... +#--- end + +# XFAIL: Clang && !Vulkan +# REQUIRES: goldenimage + +# RUN: split-file %s %t +# RUN: %dxc_target -T vs_6_0 -Fo %t-vertex.o %t/vertex.hlsl +# RUN: %dxc_target -T ps_6_0 -Fo %t-pixel.o %t/pixel.hlsl +# RUN: %offloader %t/pipeline.yaml %t-vertex.o %t-pixel.o -r Output -o %t/Output.png +# RUN: imgdiff %t/Output.png %goldenimage_dir/hlsl/Graphics/SimpleTriangle.png -rules %t/rules.yaml