VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
vertexBuffer.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 13.09.2025.
5//
6#include "vertexBuffer.h"
7
8#include <assert.h>
9#include <spdlog/spdlog.h>
10
11#include "graphicsDevice.h"
12
13namespace visutwin::canvas
14{
15 int VertexBuffer::_nextId = 0;
16
17 VertexBuffer::VertexBuffer(GraphicsDevice* graphicsDevice, std::shared_ptr<VertexFormat> format,
18 int numVertices, const VertexBufferOptions& options)
19 : _device(graphicsDevice), _format(format), _numVertices(numVertices), _usage(options.usage), _id(_nextId++) {
20
21 assert(graphicsDevice != nullptr && "GraphicsDevice cannot be null");
22 assert(format != nullptr && "VertexFormat cannot be null");
23 assert(numVertices > 0 && "Number of vertices must be greater than 0");
24
25 // Calculate the size. If format contains verticesByteSize (non-interleaved format), use it
26 _numBytes = format->verticesByteSize() ? format->verticesByteSize() : format->size() * numVertices;
27
28 // Track VRAM usage
29 adjustVramSizeTracking(_device->_vram, _numBytes);
30
31 // Allocate the storage
32 if (!options.data.empty()) {
33 if (options.data.size() != static_cast<size_t>(_numBytes)) {
34 spdlog::error("VertexBuffer: wrong initial data size: expected {}, got {}", _numBytes, options.data.size());
35 _storage.resize(_numBytes, 0);
36 } else {
37 _storage = options.data;
38 }
39 } else {
40 _storage.resize(_numBytes, 0); // Initialize with zeros
41 }
42 }
43
44 VertexBuffer::VertexBuffer(GraphicsDevice* device, std::shared_ptr<VertexFormat> format,
45 int numVertices, int numBytes)
46 : _device(device), _format(std::move(format)), _numVertices(numVertices),
47 _numBytes(numBytes), _usage(BUFFER_STATIC), _id(_nextId++) {
48 // Zero-copy: _storage intentionally left empty — GPU buffer provided externally.
49 adjustVramSizeTracking(_device->_vram, _numBytes);
50 }
51
53 {
54 const auto it = std::find(_device->_buffers.begin(), _device->_buffers.end(), this);
55 if (it != _device->_buffers.end())
56 {
57 _device->_buffers.erase(it);
58 }
59
60 // Use _numBytes (not _storage.size()) — correct for both regular and zero-copy paths.
61 adjustVramSizeTracking(_device->_vram, -_numBytes);
62 }
63
64 void VertexBuffer::adjustVramSizeTracking(DeviceVRAM& vram, int size) {
65 spdlog::trace("${this.id} size: ${size} vram.vb: ${vram.vb} => ${vram.vb + size}");
66 vram.vb += size;
67 }
68
69 bool VertexBuffer::setData(const std::vector<uint8_t>& data)
70 {
71 if (data.size() != _numBytes) {
72 spdlog::error("VertexBuffer: wrong initial data size: expected " +
73 std::to_string(_numBytes) + ", got " + std::to_string(data.size()));
74 return false;
75 }
76
77 _storage = data;
78 unlock();
79 return true;
80 }
81}
Abstract GPU interface for resource creation, state management, and draw submission.
bool setData(const std::vector< uint8_t > &data)
std::shared_ptr< VertexFormat > format() const
std::vector< uint8_t > _storage
VertexBuffer(GraphicsDevice *graphicsDevice, std::shared_ptr< VertexFormat > format, int numVertices, const VertexBufferOptions &options=VertexBufferOptions{})