diff --git a/include/API/Buffer.h b/include/API/Buffer.h index c530873aa..dcfadd5dc 100644 --- a/include/API/Buffer.h +++ b/include/API/Buffer.h @@ -16,13 +16,20 @@ namespace offloadtest { +enum class BufferUsage { + Storage, + VertexBuffer, +}; + struct BufferCreateDesc { MemoryLocation Location; + BufferUsage Usage; }; class Buffer { public: virtual ~Buffer(); + virtual size_t getSizeInBytes() const = 0; Buffer(const Buffer &) = delete; Buffer &operator=(const Buffer &) = delete; diff --git a/include/API/Resources.h b/include/API/Resources.h index c7610a00a..0b4b81dcf 100644 --- a/include/API/Resources.h +++ b/include/API/Resources.h @@ -121,6 +121,35 @@ inline uint32_t getFormatSizeInBytes(Format Format) { llvm_unreachable("All Format cases handled"); } +// Returns the number of components per element for the given format. +inline uint32_t getComponentCount(Format Format) { + switch (Format) { + case Format::R16Sint: + case Format::R16Uint: + case Format::R32Sint: + case Format::R32Uint: + case Format::R32Float: + case Format::D32Float: + return 1; + case Format::RG16Sint: + case Format::RG16Uint: + case Format::RG32Sint: + case Format::RG32Uint: + case Format::RG32Float: + case Format::D32FloatS8Uint: + return 2; + case Format::RGB32Float: + return 3; + case Format::RGBA16Sint: + case Format::RGBA16Uint: + case Format::RGBA32Sint: + case Format::RGBA32Uint: + case Format::RGBA32Float: + return 4; + } + llvm_unreachable("All Format cases handled"); +} + inline bool isDepthFormat(Format Format) { switch (Format) { case Format::R16Sint: diff --git a/include/Support/Pipeline.h b/include/Support/Pipeline.h index 01da45b76..81966a865 100644 --- a/include/Support/Pipeline.h +++ b/include/Support/Pipeline.h @@ -13,10 +13,14 @@ #ifndef OFFLOADTEST_SUPPORT_PIPELINE_H #define OFFLOADTEST_SUPPORT_PIPELINE_H +#include "API/Resources.h" + #include "llvm/ADT/SmallVector.h" + #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/YAMLTraits.h" +#include #include #include #include @@ -336,35 +340,65 @@ struct RuntimeSettings { dx::Settings DX; }; -struct VertexAttribute { - DataFormat Format; - int Channels; - int Offset; - std::string Name; - - uint32_t size() const { return getFormatSize(Format) * Channels; } +// Parsed vertex stream from the YAML VertexBuffers section. Holds per-stream +// data before interleaving into the final vertex buffer. +// +// Values are stored as doubles (the YAML parser's native numeric type) rather +// than in the target format's storage type. This avoids needing format-specific +// parsing and lets us derive the vertex count directly from the number of +// values. +// +// Conversion to the target byte representation happens during interleaving +// into ParsedVertexBuffer::InterleavedData. +struct VertexStreamData { + std::string Name; // Semantic name (e.g. POSITION, COLOR). + Format Fmt; + llvm::SmallVector Values; }; -struct IOBindings { - std::string VertexBuffer; - CPUBuffer *VertexBufferPtr; - llvm::SmallVector VertexAttributes; - - std::string RenderTarget; - CPUBuffer *RTargetBufferPtr; +// Parsed vertex buffer from the YAML VertexBuffers section. The parser +// interleaves per-stream data into InterleavedData. +// +// TODO: Add support for de-interleaved data? +struct ParsedVertexBuffer { + std::string Name; + llvm::SmallVector Streams; + // Interleaved vertex data, computed by the parser from per-stream data. + std::unique_ptr InterleavedData; + size_t InterleavedSize = 0; - uint32_t getVertexStride() const { + uint32_t getStride() const { uint32_t Stride = 0; - for (auto VA : VertexAttributes) - Stride += VA.size(); + for (const auto &S : Streams) + Stride += getFormatSizeInBytes(S.Fmt); return Stride; } + // Returns the byte offset of the stream at the given index. + uint32_t getOffset(uint32_t Index) const { + assert(Index < Streams.size() && "Stream index out of bounds"); + uint32_t Offset = 0; + for (uint32_t I = 0; I < Index; ++I) + Offset += getFormatSizeInBytes(Streams[I].Fmt); + return Offset; + } + uint32_t getVertexCount() const { - return VertexBufferPtr->size() / getVertexStride(); + uint32_t Stride = getStride(); + if (Stride == 0) + return 0; + return InterleavedSize / Stride; } }; +struct IOBindings { + std::string VertexBuffer; + ParsedVertexBuffer *VertexBufferPtr = nullptr; + + std::string RenderTarget; + CPUBuffer *RTargetBufferPtr = nullptr; +}; + // Describes a contiguous group of bytes in a push constant block. struct PushConstantValue { // Format used to describe those bytes in the YAML. @@ -415,6 +449,7 @@ struct Pipeline { IOBindings Bindings; llvm::SmallVector PushConstants; llvm::SmallVector Buffers; + llvm::SmallVector VertexBuffers; llvm::SmallVector Samplers; llvm::SmallVector Results; llvm::SmallVector Sets; @@ -441,6 +476,13 @@ struct Pipeline { return nullptr; } + ParsedVertexBuffer *getVertexBuffer(llvm::StringRef Name) { + for (auto &VB : VertexBuffers) + if (Name == VB.Name) + return &VB; + return nullptr; + } + Sampler *getSampler(llvm::StringRef Name) { for (auto &S : Samplers) if (Name == S.Name) @@ -463,7 +505,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Sampler) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Shader) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::dx::RootParameter) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Result) -LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::VertexAttribute) +LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::VertexStreamData) +LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::ParsedVertexBuffer) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::SpecializationConstant) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::PushConstantBlock) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::PushConstantValue) @@ -515,8 +558,12 @@ template <> struct MappingTraits { static void mapping(IO &I, offloadtest::PushConstantBlock &B); }; -template <> struct MappingTraits { - static void mapping(IO &I, offloadtest::VertexAttribute &A); +template <> struct MappingTraits { + static void mapping(IO &I, offloadtest::VertexStreamData &S); +}; + +template <> struct MappingTraits { + static void mapping(IO &I, offloadtest::ParsedVertexBuffer &VB); }; template <> struct MappingTraits { @@ -547,6 +594,31 @@ template <> struct MappingTraits { static void mapping(IO &I, offloadtest::SpecializationConstant &C); }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &I, offloadtest::Format &V) { +#define ENUM_CASE(Val) I.enumCase(V, #Val, offloadtest::Format::Val) + ENUM_CASE(R16Sint); + ENUM_CASE(R16Uint); + ENUM_CASE(RG16Sint); + ENUM_CASE(RG16Uint); + ENUM_CASE(RGBA16Sint); + ENUM_CASE(RGBA16Uint); + ENUM_CASE(R32Sint); + ENUM_CASE(R32Uint); + ENUM_CASE(R32Float); + ENUM_CASE(RG32Sint); + ENUM_CASE(RG32Uint); + ENUM_CASE(RG32Float); + ENUM_CASE(RGB32Float); + ENUM_CASE(RGBA32Sint); + ENUM_CASE(RGBA32Uint); + ENUM_CASE(RGBA32Float); + ENUM_CASE(D32Float); + ENUM_CASE(D32FloatS8Uint); +#undef ENUM_CASE + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &I, offloadtest::Rule &V) { #define ENUM_CASE(Val) I.enumCase(V, #Val, offloadtest::Rule::Val) diff --git a/lib/API/DX/Device.cpp b/lib/API/DX/Device.cpp index c74913d27..ef8e0600e 100644 --- a/lib/API/DX/Device.cpp +++ b/lib/API/DX/Device.cpp @@ -33,6 +33,7 @@ #include "API/Capabilities.h" #include "API/Device.h" +#include "API/FormatConversion.h" #include "DXFeatures.h" #include "Support/Pipeline.h" #include "Support/WinError.h" @@ -293,6 +294,8 @@ class DXBuffer : public offloadtest::Buffer { DXBuffer(ComPtr Buffer, llvm::StringRef Name, BufferCreateDesc Desc, size_t SizeInBytes) : Buffer(Buffer), Name(Name), Desc(Desc), SizeInBytes(SizeInBytes) {} + + size_t getSizeInBytes() const override { return SizeInBytes; } }; class DXTexture : public offloadtest::Texture { @@ -482,7 +485,7 @@ class DXDevice : public offloadtest::Device { std::shared_ptr RT; std::shared_ptr RTReadback; std::shared_ptr DS; - ComPtr VB; + std::shared_ptr VB; llvm::SmallVector DescTables; llvm::SmallVector RootResources; @@ -514,9 +517,9 @@ class DXDevice : public offloadtest::Device { const D3D12_HEAP_TYPE HeapType = getDXHeapType(Desc.Location); const D3D12_RESOURCE_FLAGS Flags = - HeapType == D3D12_HEAP_TYPE_READBACK - ? D3D12_RESOURCE_FLAG_NONE - : D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + HeapType == D3D12_HEAP_TYPE_DEFAULT + ? D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS + : D3D12_RESOURCE_FLAG_NONE; const D3D12_HEAP_PROPERTIES HeapProps = CD3DX12_HEAP_PROPERTIES(HeapType); const D3D12_RESOURCE_DESC BufferDesc = @@ -1585,6 +1588,7 @@ class DXDevice : public offloadtest::Device { // Create readback buffer sized for the pixel data (raw bytes). BufferCreateDesc BufDesc = {}; BufDesc.Location = MemoryLocation::GpuToCpu; + BufDesc.Usage = BufferUsage::Storage; auto BufOrErr = createBuffer("RTReadback", BufDesc, OutBuf.size()); if (!BufOrErr) return BufOrErr.takeError(); @@ -1608,29 +1612,31 @@ class DXDevice : public offloadtest::Device { return llvm::createStringError( std::errc::invalid_argument, "No vertex buffer bound for graphics pipeline."); - const CPUBuffer &VB = *P.Bindings.VertexBufferPtr; - const uint64_t VBSize = VB.size(); - D3D12_RESOURCE_DESC const Desc = CD3DX12_RESOURCE_DESC::Buffer(VBSize); - CD3DX12_HEAP_PROPERTIES HeapProps = - CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); - if (auto Err = HR::toError(Device->CreateCommittedResource( - &HeapProps, D3D12_HEAP_FLAG_NONE, &Desc, - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, - IID_PPV_ARGS(&IS.VB)), - "Failed to create vertex buffer")) - return Err; + const ParsedVertexBuffer &PVB = *P.Bindings.VertexBufferPtr; + + BufferCreateDesc BufDesc = {}; + BufDesc.Location = MemoryLocation::CpuToGpu; + BufDesc.Usage = BufferUsage::VertexBuffer; + auto BufOrErr = createBuffer("VertexBuffer", BufDesc, PVB.InterleavedSize); + if (!BufOrErr) + return BufOrErr.takeError(); + IS.VB = std::static_pointer_cast(*BufOrErr); + + // TODO: Currently uses a single CpuToGpu mapped buffer. For optimal GPU + // performance on discrete GPUs, use a staging buffer + copy to a GpuOnly + // vertex buffer instead. void *Ptr = nullptr; - if (auto Err = HR::toError(IS.VB->Map(0, nullptr, &Ptr), + if (auto Err = HR::toError(IS.VB->Buffer->Map(0, nullptr, &Ptr), "Failed to map vertex buffer")) return Err; - memcpy(Ptr, VB.Data[0].get(), VBSize); - IS.VB->Unmap(0, nullptr); + memcpy(Ptr, PVB.InterleavedData.get(), IS.VB->getSizeInBytes()); + IS.VB->Buffer->Unmap(0, nullptr); D3D12_VERTEX_BUFFER_VIEW VBView = {}; - VBView.BufferLocation = IS.VB->GetGPUVirtualAddress(); - VBView.SizeInBytes = static_cast(VBSize); - VBView.StrideInBytes = P.Bindings.getVertexStride(); + VBView.BufferLocation = IS.VB->Buffer->GetGPUVirtualAddress(); + VBView.SizeInBytes = static_cast(IS.VB->getSizeInBytes()); + VBView.StrideInBytes = PVB.getStride(); IS.CB->CmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); IS.CB->CmdList->IASetVertexBuffers(0, 1, &VBView); @@ -1639,13 +1645,16 @@ class DXDevice : public offloadtest::Device { } llvm::Error createGraphicsPSO(Pipeline &P, InvocationState &IS) { - // Create the input layout based on the vertex attributes. + if (!IS.VB) + return llvm::createStringError(std::errc::invalid_argument, + "Vertex buffer not initialized."); + // Create the input layout from the parsed vertex buffer streams. + const ParsedVertexBuffer &PVB = *P.Bindings.VertexBufferPtr; std::vector InputLayout; - for (size_t I = 0; I < P.Bindings.VertexAttributes.size(); ++I) { - const VertexAttribute &Attr = P.Bindings.VertexAttributes[I]; - InputLayout.push_back({Attr.Name.c_str(), 0, - getDXFormat(Attr.Format, Attr.Channels), 0, - static_cast(Attr.Offset), + for (uint32_t I = 0; I < PVB.Streams.size(); ++I) { + const VertexStreamData &S = PVB.Streams[I]; + InputLayout.push_back({S.Name.c_str(), 0, getDXGIFormat(S.Fmt), 0, + PVB.getOffset(I), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}); } @@ -1699,6 +1708,9 @@ class DXDevice : public offloadtest::Device { } llvm::Error createGraphicsCommands(Pipeline &P, InvocationState &IS) { + if (!IS.VB) + return llvm::createStringError(std::errc::invalid_argument, + "Vertex buffer not initialized."); IS.CB->CmdList->SetGraphicsRootSignature(IS.RootSig.Get()); if (IS.DescHeap) { ID3D12DescriptorHeap *const Heaps[] = {IS.DescHeap.Get()}; @@ -1735,7 +1747,8 @@ class DXDevice : public offloadtest::Device { static_cast(VP.Height)}; IS.CB->CmdList->RSSetScissorRects(1, &Scissor); - IS.CB->CmdList->DrawInstanced(P.Bindings.getVertexCount(), 1, 0, 0); + IS.CB->CmdList->DrawInstanced(P.Bindings.VertexBufferPtr->getVertexCount(), + 1, 0, 0); // Transition the render target to copy source and copy to the readback // buffer. diff --git a/lib/API/MTL/MTLDevice.cpp b/lib/API/MTL/MTLDevice.cpp index 4adb5ca0f..c70c1d453 100644 --- a/lib/API/MTL/MTLDevice.cpp +++ b/lib/API/MTL/MTLDevice.cpp @@ -10,6 +10,7 @@ #include "metal_irconverter_runtime.h" #include "API/Device.h" +#include "API/FormatConversion.h" #include "MTLResources.h" #include "Support/Pipeline.h" @@ -127,6 +128,8 @@ class MTLBuffer : public offloadtest::Buffer { size_t SizeInBytes) : Buf(Buf), Name(Name), Desc(Desc), SizeInBytes(SizeInBytes) {} + size_t getSizeInBytes() const override { return SizeInBytes; } + ~MTLBuffer() override { if (Buf) Buf->release(); @@ -196,7 +199,7 @@ class MTLDevice : public offloadtest::Device { MTL::ComputePipelineState *ComputePipeline = nullptr; MTL::RenderPipelineState *RenderPipeline = nullptr; MTL::Buffer *ArgBuffer; - MTL::Buffer *VertexBuffer; + std::shared_ptr VB; MTL::VertexDescriptor *VertexDescriptor; llvm::SmallVector Textures; llvm::SmallVector Buffers; @@ -209,56 +212,58 @@ class MTLDevice : public offloadtest::Device { llvm::Error setupVertexShader(InvocationState &IS, const Pipeline &P, MTL::Function *Fn) { - if (P.Bindings.VertexBufferPtr) { - NS::Array *FnAttrs = Fn->vertexAttributes(); - // I'm not really sure if there's any valid case for a vertex shader with - // no vertex attributes, so we just error if that ever occurs. - if (!FnAttrs) - return llvm::createStringError( - std::errc::invalid_argument, - "Vertex shader has no vertex attributes."); - if (FnAttrs->count() != P.Bindings.VertexAttributes.size()) - return llvm::createStringError( - std::errc::invalid_argument, - "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. - llvm::StringMap ShaderAttrIndices; - for (uint32_t Ai = 0; Ai < FnAttrs->count(); ++Ai) { - auto *A = static_cast(FnAttrs->object(Ai)); - if (A && A->isActive()) { - ShaderAttrIndices.insert(std::make_pair( - llvm::StringRef(A->name()->utf8String()), A->attributeIndex())); - llvm::errs() << "Shader attr: " << A->name()->utf8String() - << " at index " << A->attributeIndex() << "\n"; - } - } + if (!IS.VB) + return llvm::Error::success(); + + const ParsedVertexBuffer &PVB = *P.Bindings.VertexBufferPtr; - IS.VertexDescriptor = MTL::VertexDescriptor::alloc()->init(); - const uint32_t Stride = P.Bindings.getVertexStride(); - for (const VertexAttribute &VA : P.Bindings.VertexAttributes) { - llvm::SmallString<32> AttrName(VA.Name); - llvm::transform(AttrName, AttrName.begin(), tolower); - // Append a zero since we're only supporting one attribute per name. - // We'll need to revisit this if we ever support indexed attributes. - AttrName += "0"; - MTL::VertexAttributeDescriptor *VADesc = - MTL::VertexAttributeDescriptor::alloc()->init(); - VADesc->setBufferIndex(0); - VADesc->setOffset(VA.Offset); - VADesc->setFormat(getMTLVertexFormat(VA.Format, VA.Channels)); - IS.VertexDescriptor->attributes()->setObject( - VADesc, ShaderAttrIndices[AttrName]); + NS::Array *FnAttrs = Fn->vertexAttributes(); + if (!FnAttrs) + return llvm::createStringError(std::errc::invalid_argument, + "Vertex shader has no vertex attributes."); + if (FnAttrs->count() != PVB.Streams.size()) + return llvm::createStringError( + std::errc::invalid_argument, + "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. + llvm::StringMap ShaderAttrIndices; + for (uint32_t Ai = 0; Ai < FnAttrs->count(); ++Ai) { + auto *A = static_cast(FnAttrs->object(Ai)); + if (A && A->active()) { + ShaderAttrIndices.insert(std::make_pair( + llvm::StringRef(A->name()->utf8String()), A->attributeIndex())); + llvm::errs() << "Shader attr: " << A->name()->utf8String() + << " at index " << A->attributeIndex() << "\n"; } + } - MTL::VertexBufferLayoutDescriptor *LDesc = - MTL::VertexBufferLayoutDescriptor::alloc()->init(); - LDesc->setStride(Stride); - LDesc->setStepRate(1); - LDesc->setStepFunction(MTL::VertexStepFunctionPerVertex); - IS.VertexDescriptor->layouts()->setObject(LDesc, 0); + IS.VertexDescriptor = MTL::VertexDescriptor::alloc()->init(); + for (uint32_t I = 0; I < PVB.Streams.size(); ++I) { + const VertexStreamData &S = PVB.Streams[I]; + llvm::SmallString<32> AttrName(S.Name); + llvm::transform(AttrName, AttrName.begin(), tolower); + // Append a zero since we're only supporting one attribute per name. + // We'll need to revisit this if we ever support indexed attributes. + AttrName += "0"; + MTL::VertexAttributeDescriptor *VADesc = + MTL::VertexAttributeDescriptor::alloc()->init(); + VADesc->setBufferIndex(0); + VADesc->setOffset(PVB.getOffset(I)); + VADesc->setFormat(getMetalVertexFormat(S.Fmt)); + IS.VertexDescriptor->attributes()->setObject(VADesc, + ShaderAttrIndices[AttrName]); } + + MTL::VertexBufferLayoutDescriptor *LDesc = + MTL::VertexBufferLayoutDescriptor::alloc()->init(); + LDesc->setStride(PVB.getStride()); + LDesc->setStepRate(1); + LDesc->setStepFunction(MTL::VertexStepFunctionPerVertex); + IS.VertexDescriptor->layouts()->setObject(LDesc, 0); + return llvm::Error::success(); } @@ -438,12 +443,29 @@ class MTLDevice : public offloadtest::Device { IS.ArgBuffer->didModifyRange(NS::Range::Make(0, IS.ArgBuffer->length())); } if (P.isGraphics()) { - // Create and mark the vertex buffer as modified. - IS.VertexBuffer = Device->newBuffer( - P.Bindings.VertexBufferPtr->Data.back().get(), - P.Bindings.VertexBufferPtr->size(), MTL::ResourceStorageModeManaged); - IS.VertexBuffer->didModifyRange( - NS::Range::Make(0, IS.VertexBuffer->length())); + if (!P.Bindings.VertexBufferPtr) + return llvm::createStringError( + std::errc::invalid_argument, + "No vertex buffer specified for graphics pipeline."); + + const ParsedVertexBuffer &PVB = *P.Bindings.VertexBufferPtr; + + BufferCreateDesc BufDesc = {}; + BufDesc.Location = MemoryLocation::CpuToGpu; + BufDesc.Usage = BufferUsage::VertexBuffer; + auto BufOrErr = + createBuffer("VertexBuffer", BufDesc, PVB.InterleavedSize); + if (!BufOrErr) + return BufOrErr.takeError(); + IS.VB = std::static_pointer_cast(*BufOrErr); + + // TODO: Currently uses a single CpuToGpu mapped buffer. On discrete GPUs + // (DX/VK), consider using a staging buffer + copy to a GpuOnly vertex + // buffer for optimal GPU read performance. On Apple Silicon this is + // unnecessary due to unified memory. + const size_t BufSize = IS.VB->getSizeInBytes(); + memcpy(IS.VB->Buf->contents(), PVB.InterleavedData.get(), BufSize); + IS.VB->Buf->didModifyRange(NS::Range::Make(0, BufSize)); } return llvm::Error::success(); } @@ -532,6 +554,7 @@ class MTLDevice : public offloadtest::Device { // Create a readback buffer for copying render target data to the CPU. BufferCreateDesc BufDesc = {}; BufDesc.Location = MemoryLocation::GpuToCpu; + BufDesc.Usage = BufferUsage::Storage; auto BufOrErr = createBuffer("RTReadback", BufDesc, OutBuf.size()); if (!BufOrErr) return BufOrErr.takeError(); @@ -622,10 +645,13 @@ class MTLDevice : public offloadtest::Device { // Bind vertex buffer at slot 0 to match the vertex descriptor which // references buffer index 0. - CmdEncoder->setVertexBuffer(IS.VertexBuffer, 0, 0); + if (!IS.VB) + return llvm::createStringError(std::errc::invalid_argument, + "Vertex buffer not initialized."); + CmdEncoder->setVertexBuffer(IS.VB->Buf, 0, 0); CmdEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), - P.Bindings.getVertexCount()); + P.Bindings.VertexBufferPtr->getVertexCount()); CmdEncoder->endEncoding(); diff --git a/lib/API/VK/Device.cpp b/lib/API/VK/Device.cpp index f77fb8760..77038def1 100644 --- a/lib/API/VK/Device.cpp +++ b/lib/API/VK/Device.cpp @@ -10,6 +10,7 @@ //===----------------------------------------------------------------------===// #include "API/Device.h" +#include "API/FormatConversion.h" #include "Support/Pipeline.h" #include "VKResources.h" #include "llvm/ADT/DenseSet.h" @@ -386,6 +387,8 @@ class VulkanBuffer : public offloadtest::Buffer { : Dev(Dev), Buffer(Buffer), Memory(Memory), Name(Name), Desc(Desc), SizeInBytes(SizeInBytes) {} + size_t getSizeInBytes() const override { return SizeInBytes; } + ~VulkanBuffer() override { vkDestroyBuffer(Dev, Buffer, nullptr); vkFreeMemory(Dev, Memory, nullptr); @@ -624,7 +627,7 @@ class VulkanDevice : public offloadtest::Device { std::shared_ptr RenderTarget; std::shared_ptr RTReadback; std::shared_ptr DepthStencil; - std::optional VertexBuffer = std::nullopt; + std::shared_ptr VB; VkRenderPass RenderPass = VK_NULL_HANDLE; uint32_t ShaderStageMask = 0; @@ -792,9 +795,17 @@ class VulkanDevice : public offloadtest::Device { VkBufferCreateInfo BufInfo = {}; BufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; BufInfo.size = SizeInBytes; - BufInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT; + BufInfo.usage = + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + switch (Desc.Usage) { + case BufferUsage::Storage: + BufInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + break; + case BufferUsage::VertexBuffer: + BufInfo.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + break; + } BufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VkBuffer DeviceBuffer; @@ -1232,6 +1243,7 @@ class VulkanDevice : public offloadtest::Device { // Create a host-visible staging buffer for readback. BufferCreateDesc BufDesc = {}; BufDesc.Location = MemoryLocation::GpuToCpu; + BufDesc.Usage = BufferUsage::Storage; auto BufOrErr = createBuffer("RTReadback", BufDesc, RTBuf.size()); if (!BufOrErr) return BufOrErr.takeError(); @@ -1266,34 +1278,30 @@ class VulkanDevice : public offloadtest::Device { if (auto Err = createDepthStencil(P, IS)) return Err; - if (P.Bindings.VertexBufferPtr == nullptr) + if (!P.Bindings.VertexBufferPtr) return llvm::createStringError( std::errc::invalid_argument, - "No Vertex buffer specified for graphics pipeline."); - const Resource VertexBuffer = {ResourceKind::StructuredBuffer, - "VertexBuffer", - {}, - {}, - P.Bindings.VertexBufferPtr, - nullptr, - false, - std::nullopt, - false}; - auto ExVHostBuf = createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - VertexBuffer.size(), VertexBuffer.BufferPtr->Data[0].get()); - if (!ExVHostBuf) - return ExVHostBuf.takeError(); - auto ExDeviceBuf = createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VertexBuffer.size()); - if (!ExDeviceBuf) - return ExDeviceBuf.takeError(); - VkBufferCopy Copy = {}; - Copy.size = VertexBuffer.size(); - vkCmdCopyBuffer(IS.CB->CmdBuffer, ExVHostBuf->Buffer, ExDeviceBuf->Buffer, - 1, &Copy); - IS.VertexBuffer = ResourceRef(*ExVHostBuf, *ExDeviceBuf); + "No vertex buffer specified for graphics pipeline."); + + const ParsedVertexBuffer &PVB = *P.Bindings.VertexBufferPtr; + + BufferCreateDesc BufDesc = {}; + BufDesc.Location = MemoryLocation::CpuToGpu; + BufDesc.Usage = BufferUsage::VertexBuffer; + auto BufOrErr = + createBuffer("VertexBuffer", BufDesc, PVB.InterleavedSize); + if (!BufOrErr) + return BufOrErr.takeError(); + IS.VB = std::static_pointer_cast(*BufOrErr); + + // TODO: Currently uses a single CpuToGpu mapped buffer. For optimal GPU + // performance on discrete GPUs, use a staging buffer + copy to a GpuOnly + // vertex buffer instead. + const size_t BufSize = IS.VB->getSizeInBytes(); + void *Mapped = nullptr; + vkMapMemory(Device, IS.VB->Memory, 0, BufSize, 0, &Mapped); + memcpy(Mapped, PVB.InterleavedData.get(), BufSize); + vkUnmapMemory(Device, IS.VB->Memory); } return llvm::Error::success(); @@ -1959,21 +1967,25 @@ class VulkanDevice : public offloadtest::Device { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; MultisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - const uint32_t Stride = P.Bindings.getVertexStride(); + // Build vertex input state from the parsed vertex buffer streams. + if (!IS.VB) + return llvm::createStringError(std::errc::invalid_argument, + "Vertex buffer not initialized."); + const ParsedVertexBuffer &PVB = *P.Bindings.VertexBufferPtr; VkVertexInputBindingDescription VertexInputBinding{}; VertexInputBinding.binding = 0; - VertexInputBinding.stride = Stride; + VertexInputBinding.stride = PVB.getStride(); VertexInputBinding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; llvm::SmallVector Attributes; - for (size_t I = 0; I < P.Bindings.VertexAttributes.size(); ++I) { - const VertexAttribute &VA = P.Bindings.VertexAttributes[I]; + for (uint32_t I = 0; I < PVB.Streams.size(); ++I) { + const VertexStreamData &S = PVB.Streams[I]; VkVertexInputAttributeDescription VkVA = {}; VkVA.location = I; VkVA.binding = 0; - VkVA.format = getVKFormat(VA.Format, VA.Channels); - VkVA.offset = VA.Offset; + VkVA.format = getVulkanFormat(S.Fmt); + VkVA.offset = PVB.getOffset(I); Attributes.push_back(VkVA); } @@ -2350,13 +2362,16 @@ class VulkanDevice : public offloadtest::Device { llvm::outs() << "Dispatched compute shader: { " << DispatchSize[0] << ", " << DispatchSize[1] << ", " << DispatchSize[2] << " }\n"; } else { + if (!IS.VB) + return llvm::createStringError(std::errc::invalid_argument, + "Vertex buffer not initialized."); VkDeviceSize Offsets[1]{0}; - assert(IS.VertexBuffer.has_value()); - vkCmdBindVertexBuffers(IS.CB->CmdBuffer, 0, 1, - &IS.VertexBuffer->Device.Buffer, Offsets); + VkBuffer VBHandle = IS.VB->Buffer; + vkCmdBindVertexBuffers(IS.CB->CmdBuffer, 0, 1, &VBHandle, Offsets); + const uint32_t VertexCount = P.Bindings.VertexBufferPtr->getVertexCount(); // instanceCount must be >=1 to draw; previously was 0 which draws nothing - vkCmdDraw(IS.CB->CmdBuffer, P.Bindings.getVertexCount(), 1, 0, 0); - llvm::outs() << "Drew " << P.Bindings.getVertexCount() << " vertices.\n"; + vkCmdDraw(IS.CB->CmdBuffer, VertexCount, 1, 0, 0); + llvm::outs() << "Drew " << VertexCount << " vertices.\n"; vkCmdEndRenderPass(IS.CB->CmdBuffer); copyTextureToReadback(IS.CB->CmdBuffer, *IS.RenderTarget, *IS.RTReadback, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, @@ -2466,12 +2481,6 @@ class VulkanDevice : public offloadtest::Device { } if (IS.getFullShaderStageMask() != VK_SHADER_STAGE_COMPUTE_BIT) { - if (IS.VertexBuffer.has_value()) { - vkDestroyBuffer(Device, IS.VertexBuffer->Device.Buffer, nullptr); - vkFreeMemory(Device, IS.VertexBuffer->Device.Memory, nullptr); - vkDestroyBuffer(Device, IS.VertexBuffer->Host.Buffer, nullptr); - vkFreeMemory(Device, IS.VertexBuffer->Host.Memory, nullptr); - } vkDestroyFramebuffer(Device, IS.FrameBuffer, nullptr); vkDestroyRenderPass(Device, IS.RenderPass, nullptr); } diff --git a/lib/Support/Pipeline.cpp b/lib/Support/Pipeline.cpp index d28f81182..e22ebd093 100644 --- a/lib/Support/Pipeline.cpp +++ b/lib/Support/Pipeline.cpp @@ -44,6 +44,7 @@ void MappingTraits::mapping(IO &I, I.mapOptional("RuntimeSettings", P.Settings); I.mapRequired("Buffers", P.Buffers); + I.mapOptional("VertexBuffers", P.VertexBuffers); I.mapOptional("Samplers", P.Samplers); I.mapOptional("Results", P.Results); I.mapRequired("DescriptorSets", P.Sets); @@ -121,10 +122,10 @@ void MappingTraits::mapping(IO &I, std::to_string(DescriptorTableCount)); if (!P.Bindings.VertexBuffer.empty()) { - P.Bindings.VertexBufferPtr = P.getBuffer(P.Bindings.VertexBuffer); + P.Bindings.VertexBufferPtr = P.getVertexBuffer(P.Bindings.VertexBuffer); if (!P.Bindings.VertexBufferPtr) I.setError(Twine("Referenced vertex buffer ") + - P.Bindings.VertexBuffer + " not found!"); + P.Bindings.VertexBuffer + " not found in VertexBuffers!"); } if (!P.Bindings.RenderTarget.empty()) { @@ -390,18 +391,125 @@ void MappingTraits::mapping( I.mapOptional("CounterBinding", B.CounterBinding); } -void MappingTraits::mapping( - IO &I, offloadtest::VertexAttribute &A) { - I.mapRequired("Format", A.Format); - I.mapRequired("Channels", A.Channels); - I.mapRequired("Offset", A.Offset); - I.mapRequired("Name", A.Name); +void MappingTraits::mapping( + IO &I, offloadtest::VertexStreamData &S) { + I.mapRequired("Name", S.Name); + I.mapRequired("Format", S.Fmt); + // Values are always parsed as doubles regardless of the target format. + // Conversion to the storage type happens during interleaving. + I.mapRequired("Data", S.Values); + + if (!I.outputting()) { + if (!offloadtest::isVertexCompatible(S.Fmt)) { + I.setError("Format '" + llvm::Twine(offloadtest::getFormatName(S.Fmt)) + + "' is not a valid vertex stream format."); + return; + } + const uint32_t Components = offloadtest::getComponentCount(S.Fmt); + if (S.Values.size() % Components != 0) { + I.setError("Data size is not a multiple of the format's component " + "count (" + + llvm::Twine(Components) + ")."); + return; + } + } +} + +// Converts a double value to the storage type for the given format and writes +// it to Dst. Returns the number of bytes written. +static uint32_t writeComponent(char *Dst, double Value, + offloadtest::Format Fmt) { + using F = offloadtest::Format; + switch (Fmt) { + case F::R16Sint: + case F::RG16Sint: + case F::RGBA16Sint: { + int16_t V = static_cast(Value); + memcpy(Dst, &V, sizeof(V)); + return sizeof(V); + } + case F::R16Uint: + case F::RG16Uint: + case F::RGBA16Uint: { + uint16_t V = static_cast(Value); + memcpy(Dst, &V, sizeof(V)); + return sizeof(V); + } + case F::R32Sint: + case F::RG32Sint: + case F::RGBA32Sint: { + int32_t V = static_cast(Value); + memcpy(Dst, &V, sizeof(V)); + return sizeof(V); + } + case F::R32Uint: + case F::RG32Uint: + case F::RGBA32Uint: { + uint32_t V = static_cast(Value); + memcpy(Dst, &V, sizeof(V)); + return sizeof(V); + } + case F::R32Float: + case F::RG32Float: + case F::RGB32Float: + case F::RGBA32Float: { + float V = static_cast(Value); + memcpy(Dst, &V, sizeof(V)); + return sizeof(V); + } + case F::D32Float: + case F::D32FloatS8Uint: + llvm_unreachable("Depth formats are not valid vertex stream formats"); + } + llvm_unreachable("All Format cases handled"); +} + +void MappingTraits::mapping( + IO &I, offloadtest::ParsedVertexBuffer &VB) { + I.mapRequired("Name", VB.Name); + I.mapRequired("Streams", VB.Streams); + + if (!I.outputting() && !VB.Streams.empty()) { + // Derive vertex count from the first stream's values and component count. + const uint32_t Components0 = + offloadtest::getComponentCount(VB.Streams[0].Fmt); + const uint32_t VertexCount = VB.Streams[0].Values.size() / Components0; + + // Validate all streams have the same vertex count. + for (size_t S = 1; S < VB.Streams.size(); ++S) { + const uint32_t Components = + offloadtest::getComponentCount(VB.Streams[S].Fmt); + const uint32_t Count = VB.Streams[S].Values.size() / Components; + if (Count != VertexCount) { + I.setError("All vertex streams must have the same vertex count."); + return; + } + } + + // Interleave per-stream data into a single buffer, converting each + // double value to the stream's target storage type. + const uint32_t Stride = VB.getStride(); + VB.InterleavedSize = static_cast(Stride) * VertexCount; + VB.InterleavedData = std::make_unique(VB.InterleavedSize); + + for (uint32_t V = 0; V < VertexCount; ++V) { + uint32_t StreamOffset = 0; + for (const auto &Stream : VB.Streams) { + const uint32_t Components = offloadtest::getComponentCount(Stream.Fmt); + char *Dst = VB.InterleavedData.get() + V * Stride + StreamOffset; + for (uint32_t C = 0; C < Components; ++C) { + const double Value = Stream.Values[V * Components + C]; + Dst += writeComponent(Dst, Value, Stream.Fmt); + } + StreamOffset += offloadtest::getFormatSizeInBytes(Stream.Fmt); + } + } + } } void MappingTraits::mapping( IO &I, offloadtest::IOBindings &B) { I.mapOptional("VertexBuffer", B.VertexBuffer); - I.mapOptional("VertexAttributes", B.VertexAttributes); I.mapOptional("RenderTarget", B.RenderTarget); } diff --git a/test/Feature/Semantics/ArraySemantics.test b/test/Feature/Semantics/ArraySemantics.test index afa4ba368..9b3a645c6 100644 --- a/test/Feature/Semantics/ArraySemantics.test +++ b/test/Feature/Semantics/ArraySemantics.test @@ -35,13 +35,15 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 16 - Data: [ 0.0, 3.0, 0.0, 1.0, - 3.0, -3.0, 0.0, 1.0, - -3.0, -3.0, 0.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGBA32Float + Data: [ 0.0, 3.0, 0.0, 1.0, + 3.0, -3.0, 0.0, 1.0, + -3.0, -3.0, 0.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -52,11 +54,6 @@ Buffers: Depth: 1 Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 4 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: [] ... diff --git a/test/Feature/Semantics/MatrixSemantics.test b/test/Feature/Semantics/MatrixSemantics.test index 743e7fcea..69ffe2660 100644 --- a/test/Feature/Semantics/MatrixSemantics.test +++ b/test/Feature/Semantics/MatrixSemantics.test @@ -49,13 +49,15 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 16 - Data: [ 0.0, 3.0, 0.0, 1.0, - 3.0, -3.0, 0.0, 1.0, - -3.0, -3.0, 0.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGBA32Float + Data: [ 0.0, 3.0, 0.0, 1.0, + 3.0, -3.0, 0.0, 1.0, + -3.0, -3.0, 0.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -73,11 +75,6 @@ Buffers: Data: [ 1, 2, 3, 4, 5, 6, 7 ] Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 4 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: - Resources: diff --git a/test/Feature/Semantics/NestedStructSemantics.test b/test/Feature/Semantics/NestedStructSemantics.test index e2f7aadda..882cc072e 100644 --- a/test/Feature/Semantics/NestedStructSemantics.test +++ b/test/Feature/Semantics/NestedStructSemantics.test @@ -52,13 +52,15 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 16 - Data: [ 0.0, 3.0, 0.0, 1.0, - 3.0, -3.0, 0.0, 1.0, - -3.0, -3.0, 0.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGBA32Float + Data: [ 0.0, 3.0, 0.0, 1.0, + 3.0, -3.0, 0.0, 1.0, + -3.0, -3.0, 0.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -76,11 +78,6 @@ Buffers: Data: [ 1, 2, 3 ] Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 4 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: - Resources: diff --git a/test/Feature/Semantics/SemanticTypes.test b/test/Feature/Semantics/SemanticTypes.test index c4842702a..73e0cea1c 100644 --- a/test/Feature/Semantics/SemanticTypes.test +++ b/test/Feature/Semantics/SemanticTypes.test @@ -50,13 +50,15 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 16 - Data: [ 0.0, 3.0, 0.0, 1.0, - 3.0, -3.0, 0.0, 1.0, - -3.0, -3.0, 0.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGBA32Float + Data: [ 0.0, 3.0, 0.0, 1.0, + 3.0, -3.0, 0.0, 1.0, + -3.0, -3.0, 0.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -78,11 +80,6 @@ Buffers: Data: [ 0xffffffff, 0x2, 0x40600000 ] Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 4 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: - Resources: diff --git a/test/Feature/Semantics/ShadowedSemantics.test b/test/Feature/Semantics/ShadowedSemantics.test index cf5a7153e..9b359b21f 100644 --- a/test/Feature/Semantics/ShadowedSemantics.test +++ b/test/Feature/Semantics/ShadowedSemantics.test @@ -57,13 +57,15 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 16 - Data: [ 0.0, 3.0, 0.0, 1.0, - 3.0, -3.0, 0.0, 1.0, - -3.0, -3.0, 0.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGBA32Float + Data: [ 0.0, 3.0, 0.0, 1.0, + 3.0, -3.0, 0.0, 1.0, + -3.0, -3.0, 0.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -81,11 +83,6 @@ Buffers: Data: [ 1, 2, 3 ] Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 4 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: - Resources: diff --git a/test/Feature/Semantics/UserSemantics.test b/test/Feature/Semantics/UserSemantics.test index 5adea4b4b..8c51aa25d 100644 --- a/test/Feature/Semantics/UserSemantics.test +++ b/test/Feature/Semantics/UserSemantics.test @@ -32,13 +32,15 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 16 - Data: [ 0.0, 3.0, 0.0, 1.0, - 3.0, -3.0, 0.0, 1.0, - -3.0, -3.0, 0.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGBA32Float + Data: [ 0.0, 3.0, 0.0, 1.0, + 3.0, -3.0, 0.0, 1.0, + -3.0, -3.0, 0.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -49,11 +51,6 @@ Buffers: Depth: 1 Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 4 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: [] ... diff --git a/test/Feature/Textures/Texture2D.CalculateLevelOfDetail.test.yaml b/test/Feature/Textures/Texture2D.CalculateLevelOfDetail.test.yaml index 74d3302fc..de748f99a 100644 --- a/test/Feature/Textures/Texture2D.CalculateLevelOfDetail.test.yaml +++ b/test/Feature/Textures/Texture2D.CalculateLevelOfDetail.test.yaml @@ -57,6 +57,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: Tex Format: Float32 @@ -80,20 +89,8 @@ Buffers: FillSize: 64 OutputProps: { Width: 2, Height: 2, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Textures/Texture2D.Sample.test.yaml b/test/Feature/Textures/Texture2D.Sample.test.yaml index 34ba1bff0..ba0daf177 100644 --- a/test/Feature/Textures/Texture2D.Sample.test.yaml +++ b/test/Feature/Textures/Texture2D.Sample.test.yaml @@ -73,6 +73,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: Tex Format: Float32 @@ -105,20 +114,8 @@ Buffers: FillSize: 64 OutputProps: { Width: 2, Height: 2, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Textures/Texture2D.SampleBias.test.yaml b/test/Feature/Textures/Texture2D.SampleBias.test.yaml index ff06f8348..49f541a74 100644 --- a/test/Feature/Textures/Texture2D.SampleBias.test.yaml +++ b/test/Feature/Textures/Texture2D.SampleBias.test.yaml @@ -64,6 +64,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: Tex Format: Float32 @@ -96,20 +105,8 @@ Buffers: FillSize: 64 OutputProps: { Width: 2, Height: 2, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Textures/Texture2D.SampleCmp.test.yaml b/test/Feature/Textures/Texture2D.SampleCmp.test.yaml index 52a06c512..78ba427f6 100644 --- a/test/Feature/Textures/Texture2D.SampleCmp.test.yaml +++ b/test/Feature/Textures/Texture2D.SampleCmp.test.yaml @@ -105,6 +105,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: Tex Format: Depth32 @@ -134,20 +143,8 @@ Buffers: FillSize: 16 OutputProps: { Width: 1, Height: 1, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Textures/Texture2D.Sampler.address.test.yaml b/test/Feature/Textures/Texture2D.Sampler.address.test.yaml index 844b8f5e7..36cf51398 100644 --- a/test/Feature/Textures/Texture2D.Sampler.address.test.yaml +++ b/test/Feature/Textures/Texture2D.Sampler.address.test.yaml @@ -62,6 +62,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: Tex Format: Float32 @@ -89,20 +98,8 @@ Buffers: FillSize: 16 OutputProps: { Width: 1, Height: 1, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml b/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml index 5dfd8255b..324a9d90c 100644 --- a/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml +++ b/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml @@ -49,6 +49,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: Tex Format: Float32 @@ -76,20 +85,8 @@ Buffers: FillSize: 16 OutputProps: { Width: 1, Height: 1, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.CalculateLevelOfDetail.test.yaml b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.CalculateLevelOfDetail.test.yaml index 9ef2900d7..93765d8ee 100644 --- a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.CalculateLevelOfDetail.test.yaml +++ b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.CalculateLevelOfDetail.test.yaml @@ -77,20 +77,17 @@ Buffers: FillSize: 64 OutputProps: { Width: 2, Height: 2, Depth: 1 } +VertexBuffers: - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sample.test.yaml b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sample.test.yaml index a82cd9396..cdbecc732 100644 --- a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sample.test.yaml +++ b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sample.test.yaml @@ -72,6 +72,15 @@ Shaders: - Stage: Pixel Entry: mainPS +VertexBuffers: + - Name: VB + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] + Buffers: - Name: SampledTex0 Format: Float32 @@ -114,20 +123,8 @@ Buffers: FillSize: 64 OutputProps: { Width: 2, Height: 2, Depth: 1 } - - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] - Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleBias.test.yaml b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleBias.test.yaml index 66cd2ead4..1b7464309 100644 --- a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleBias.test.yaml +++ b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleBias.test.yaml @@ -105,20 +105,17 @@ Buffers: FillSize: 64 OutputProps: { Width: 2, Height: 2, Depth: 1 } +VertexBuffers: - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleCmp.test.yaml b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleCmp.test.yaml index 7d9a605bc..cddb23424 100644 --- a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleCmp.test.yaml +++ b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.SampleCmp.test.yaml @@ -124,20 +124,17 @@ Buffers: FillSize: 16 OutputProps: { Width: 1, Height: 1, Depth: 1 } +VertexBuffers: - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.address.test.yaml b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.address.test.yaml index 7e20e24b9..a3e473887 100644 --- a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.address.test.yaml +++ b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.address.test.yaml @@ -108,20 +108,17 @@ Buffers: FillSize: 16 OutputProps: { Width: 1, Height: 1, Depth: 1 } +VertexBuffers: - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.filter.test.yaml b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.filter.test.yaml index 21a8b9b47..d20069f8f 100644 --- a/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.filter.test.yaml +++ b/test/Feature/Vk.SampledTextures/Vk.SampledTexture2D/Vk.SampledTexture2D.Sampler.filter.test.yaml @@ -82,20 +82,17 @@ Buffers: FillSize: 16 OutputProps: { Width: 1, Height: 1, Depth: 1 } +VertexBuffers: - Name: VB - Format: Float32 - Channels: 3 - Data: [-1.0, -1.0, 0.0, - 3.0, -1.0, 0.0, - -1.0, 3.0, 0.0] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [-1.0, -1.0, 0.0, + 3.0, -1.0, 0.0, + -1.0, 3.0, 0.0] Bindings: VertexBuffer: VB - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: RT Samplers: diff --git a/test/Graphics/SimpleTriangle.test b/test/Graphics/SimpleTriangle.test index 284ca3bd4..e4cb4e4c9 100644 --- a/test/Graphics/SimpleTriangle.test +++ b/test/Graphics/SimpleTriangle.test @@ -34,13 +34,20 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 28 # 32 bytes per vertex - Data: [ 0.0, 0.25, 0.0, 1.0, 0.0, 0.0, 1.0, - 0.25, -0.25, 0.0, 0.0, 1.0, 0.0, 1.0, - -0.25, -0.25, 0.0, 0.0, 0.0, 1.0, 1.0 ] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [ 0.0, 0.25, 0.0, + 0.25, -0.25, 0.0, + -0.25, -0.25, 0.0 ] + - Name: COLOR + Format: RGBA32Float + Data: [ 1.0, 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0, + 0.0, 0.0, 1.0, 1.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -51,15 +58,6 @@ Buffers: Depth: 1 Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION - - Format: Float32 - Channels: 4 - Offset: 12 - Name: COLOR RenderTarget: Output DescriptorSets: [] ... diff --git a/test/Graphics/ddx_fine.test b/test/Graphics/ddx_fine.test index 18e5e2344..6e55cb34a 100644 --- a/test/Graphics/ddx_fine.test +++ b/test/Graphics/ddx_fine.test @@ -46,16 +46,18 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 12 # 16 bytes per vertex - Data: [ -1.0, -1.0, 0.0, - -1.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 1.0, -1.0, 0.0, - -1.0, -1.0, 0.0 ] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [ -1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, -1.0, 0.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -66,11 +68,6 @@ Buffers: Depth: 1 Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: [] ... diff --git a/test/Graphics/ddy_fine.test b/test/Graphics/ddy_fine.test index 372fde968..56bac257e 100644 --- a/test/Graphics/ddy_fine.test +++ b/test/Graphics/ddy_fine.test @@ -46,16 +46,18 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 12 # 16 bytes per vertex - Data: [ -1.0, -1.0, 0.0, - -1.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 1.0, -1.0, 0.0, - -1.0, -1.0, 0.0 ] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [ -1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, -1.0, 0.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -66,11 +68,6 @@ Buffers: Depth: 1 Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: [] ... diff --git a/test/Graphics/fwidth.test b/test/Graphics/fwidth.test index 74670633a..1f7606ad1 100644 --- a/test/Graphics/fwidth.test +++ b/test/Graphics/fwidth.test @@ -45,16 +45,18 @@ Shaders: Entry: main - Stage: Pixel Entry: main -Buffers: +VertexBuffers: - Name: VertexData - Format: Float32 - Stride: 12 # 16 bytes per vertex - Data: [ -1.0, -1.0, 0.0, - -1.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 1.0, -1.0, 0.0, - -1.0, -1.0, 0.0 ] + Streams: + - Name: POSITION + Format: RGB32Float + Data: [ -1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, -1.0, 0.0 ] +Buffers: - Name: Output Format: Float32 Channels: 4 @@ -65,11 +67,6 @@ Buffers: Depth: 1 Bindings: VertexBuffer: VertexData - VertexAttributes: - - Format: Float32 - Channels: 3 - Offset: 0 - Name: POSITION RenderTarget: Output DescriptorSets: [] ...