Skip to content

Add VertexBuffer abstraction with typed streams and per-backend support#1087

Open
EmilioLaiso wants to merge 9 commits intollvm:mainfrom
Traverse-Research:render-backend-api-vertex-buffer
Open

Add VertexBuffer abstraction with typed streams and per-backend support#1087
EmilioLaiso wants to merge 9 commits intollvm:mainfrom
Traverse-Research:render-backend-api-vertex-buffer

Conversation

@EmilioLaiso
Copy link
Copy Markdown
Contributor

@EmilioLaiso EmilioLaiso commented Apr 14, 2026

Summary

This PR introduces a dedicated VertexBuffer abstraction into the offload test suite, replacing the previous approach where vertex data was defined as a raw CPUBuffer entry under Buffers: and manually described via VertexAttributes: in Bindings:.

New YAML schema: VertexBuffers

A new VertexBuffers: section is added to test pipeline definitions.
Each vertex buffer declares named streams with a typed Format and inline Data:

VertexBuffers:
  - Name: VB
    Streams:
      - Name: POSITION
        Format: RGB32Float
        Data: [...]
      - Name: COLOR
        Format: RGBA32Float
        Data: [...]
Bindings:
  VertexBuffer: VB

This replaces the old pattern where vertex data lived in Buffers: and layout was specified separately in Bindings: > VertexAttributes:. Channels, Offsets and Stride are now inferred.

# Old (removed)
Buffers:
  - Name: VB
    Format: Float32
    Channels: 3
    Data: [...]
Bindings:
  VertexBuffer: VB
  VertexAttributes:
    - Format: Float32
      Channels: 3
      Offset: 0
      Name: POSITION

API-level VertexBuffer type

  • VertexBuffer / VertexBufferDesc / VertexStream (include/API/VertexBuffer.h) -- a new value type that pairs a GPU Buffer with a layout descriptor (VertexBufferDesc). The descriptor holds an ordered list of VertexStream entries (semantic name + Format), and provides helpers for computing stride, per-stream byte offsets, and vertex count.
  • ParsedVertexBuffer / VertexStreamData (include/Support/Pipeline.h) -- YAML-side parsed representation. Stream values are stored as double and then interleaved + type-converted during parsing into a single InterleavedData buffer ready for GPU upload.
  • createVertexBuffer(Device&, ParsedVertexBuffer&) (lib/API/Device.cpp) -- API-agnostic factory that allocates a CpuToGpu buffer with VertexBuffer usage and builds the VertexBufferDesc.

BufferUsage enum and per-backend changes

A BufferUsage enum (Storage / VertexBuffer) is added to BufferCreateDesc so backends can set the correct usage flags:

  • Vulkan (lib/API/VK/Device.cpp): sets VK_BUFFER_USAGE_VERTEX_BUFFER_BIT for vertex buffers; eliminates the old host-staging + device-copy pair in favor of a single CpuToGpu mapped buffer (with a TODO to revisit for discrete GPUs).
  • DirectX 12 (lib/API/DX/Device.cpp): uses D3D12_HEAP_TYPE_UPLOAD for CpuToGpu vertex buffers; builds D3D12_INPUT_ELEMENT_DESC from VertexBufferDesc streams instead of VertexAttribute.
  • Metal (lib/API/MTL/MTLDevice.cpp): builds MTL::VertexDescriptor from VertexBufferDesc streams; copies interleaved data into a managed Metal buffer.

All three backends now use VertexBuffer::getVertexCount() for draw calls and derive input layout / vertex descriptors from VertexBufferDesc rather than the removed VertexAttribute struct.

Buffer::getSizeInBytes()

A new pure virtual getSizeInBytes() is added to Buffer, implemented by DXBuffer, VulkanBuffer, and MTLBuffer. This is used by VertexBuffer::getVertexCount() to derive the vertex count from buffer size and stride.

Resources.h helpers

  • getComponentCount(Format) -- returns the number of components per element for a format.

Pipeline parser changes (lib/Support/Pipeline.cpp)

  • Parses the new VertexBuffers: section with VertexStreamData mapping (Name, Format, Data).
  • Validates format compatibility (isVertexCompatible), data-size-to-component-count alignment, and consistent vertex count across streams.
  • Interleaves per-stream double values into a packed byte buffer (InterleavedData) with format-specific type conversion via writeComponent().
  • Resolves Bindings::VertexBuffer against Pipeline::VertexBuffers instead of Pipeline::Buffers.
  • Removes VertexAttribute mapping and the VertexAttributes binding key.
  • Adds ScalarEnumerationTraits<Format> so that the new Format enum can be used directly in YAML fields.

Test migrations

All 22 graphics test files are migrated from the old schema to the new VertexBuffers: + Streams: format.

Comment on lines +52 to +62
struct VertexBuffer {
VertexBufferDesc Desc;
std::shared_ptr<Buffer> Data;

uint32_t getVertexCount() const {
uint32_t Stride = Desc.getStride();
if (Stride == 0)
return 0;
return static_cast<uint32_t>(Data->getSizeInBytes()) / Stride;
}
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the right abstraction.
The layout is part of the pipelinelayout/inputlayout which is part of the PipelineState.
A vertex buffer should just be Buffer type with the VertexBuffer usage.

Copy link
Copy Markdown
Contributor Author

@EmilioLaiso EmilioLaiso Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future we want to build RT acceleration structures, right?
It might be useful to have this information at hand when filling BLAS descriptions as you'll need the vertex format and stride.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For acceleration structures we don't need the semantics name, just offset and stride for the positions. I would first like to see how this fits into my PR #1070 as this creates an interface for specifying the input layout. After the semantics have been specified we don't need them anymore to bind the buffer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants