#include "persistent_buffer.h" PersistentRingBuffer m_cylinderPersistentBuffer; void Backend::initializeCylinderPipeline() { constexpr std::size_t k_initial_persistent_capacity = 10000; constexpr int k_buffers_in_flight = 3; if (m_cylinderPersistentBuffer.initialize(k_initial_persistent_capacity, k_buffers_in_flight)) { } else { qWarning() << "Failed to init persistent buffer, falling back to old method"; } } void Backend::beginFrame() { if (m_cylinderPersistentBuffer.isValid()) { m_cylinderPersistentBuffer.beginFrame(); } } void Backend::uploadCylinderInstances(std::size_t count) { if (count == 0) return; if (m_cylinderPersistentBuffer.isValid()) { if (count > m_cylinderPersistentBuffer.capacity()) { qWarning() << "Too many cylinders:" << count << "max:" << m_cylinderPersistentBuffer.capacity(); count = m_cylinderPersistentBuffer.capacity(); } m_cylinderPersistentBuffer.write(m_cylinderScratch.data(), count); glBindBuffer(GL_ARRAY_BUFFER, m_cylinderPersistentBuffer.buffer()); return; } if (!m_cylinderInstanceBuffer) return; glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer); if (count > m_cylinderInstanceCapacity) { m_cylinderInstanceCapacity = std::max( count, m_cylinderInstanceCapacity ? m_cylinderInstanceCapacity * 2 : count); glBufferData(GL_ARRAY_BUFFER, m_cylinderInstanceCapacity * sizeof(CylinderInstanceGpu), nullptr, GL_DYNAMIC_DRAW); m_cylinderScratch.reserve(m_cylinderInstanceCapacity); } glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(CylinderInstanceGpu), m_cylinderScratch.data()); glBindBuffer(GL_ARRAY_BUFFER, 0); } void Backend::drawCylinders(std::size_t count) { if (!m_cylinderVao || m_cylinderIndexCount == 0 || count == 0) return; initializeOpenGLFunctions(); glBindVertexArray(m_cylinderVao); glDrawElementsInstanced(GL_TRIANGLES, m_cylinderIndexCount, GL_UNSIGNED_INT, nullptr, static_cast(count)); glBindVertexArray(0); } void Backend::shutdownCylinderPipeline() { m_cylinderPersistentBuffer.destroy(); }