8#include <Metal/Metal.hpp>
9#include <dispatch/dispatch.h>
48 size_t uniformStructSize,
const char* label =
"UniformRing")
50 _alignedSlotSize = alignUp(uniformStructSize,
kAlignment);
55 _buffer = device->newBuffer(_totalSize, MTL::ResourceStorageModeShared);
57 _buffer->setLabel(NS::String::string(label, NS::UTF8StringEncoding));
58 _basePtr =
static_cast<uint8_t*
>(_buffer->contents());
84 dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
96 [[nodiscard]]
size_t allocate(
const void* data,
size_t dataSize)
98 assert(data !=
nullptr);
99 assert(dataSize <= _alignedSlotSize &&
"Data exceeds aligned slot size");
100 assert(_drawCount < _maxDrawsPerFrame &&
"Ring buffer overflow: too many draws this frame");
102 const size_t offset = _frameIndex * _regionSize + _drawCount * _alignedSlotSize;
103 std::memcpy(_basePtr + offset, data, dataSize);
115 assert(commandBuffer !=
nullptr);
116 dispatch_semaphore_t sem = _frameSemaphore;
117 commandBuffer->addCompletedHandler(^(MTL::CommandBuffer*) {
118 dispatch_semaphore_signal(sem);
122 [[nodiscard]] MTL::Buffer*
buffer()
const {
return _buffer; }
126 [[nodiscard]]
size_t totalSize()
const {
return _totalSize; }
129 static size_t alignUp(
size_t value,
size_t alignment)
131 return (value + alignment - 1) & ~(alignment - 1);
134 MTL::Buffer* _buffer =
nullptr;
135 uint8_t* _basePtr =
nullptr;
136 dispatch_semaphore_t _frameSemaphore =
nullptr;
138 size_t _alignedSlotSize = 0;
139 size_t _regionSize = 0;
140 size_t _totalSize = 0;
141 size_t _maxDrawsPerFrame = 0;
143 int _frameIndex = -1;
144 size_t _drawCount = 0;