From 6080120777fdf7b6e1184288eff9d205ca7ebf5f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 17 Nov 2021 14:48:58 +0200 Subject: [PATCH] Add a usage parameter to Buffer It has no real meaning on OpenGL but is needed on Vulkan --- source/backends/opengl/texture2d_backend.cpp | 2 +- source/core/buffer.cpp | 3 ++- source/core/buffer.h | 19 ++++++++++++++++--- source/core/mesh.cpp | 4 ++-- source/render/instancearray.cpp | 2 +- source/render/programdata.cpp | 2 +- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/source/backends/opengl/texture2d_backend.cpp b/source/backends/opengl/texture2d_backend.cpp index 2f396df4..45ba78cc 100644 --- a/source/backends/opengl/texture2d_backend.cpp +++ b/source/backends/opengl/texture2d_backend.cpp @@ -167,7 +167,7 @@ bool OpenGLTexture2D::AsyncLoader::process() } else if(phase==1) { - pixel_buffer.storage(n_bytes); + pixel_buffer.storage(n_bytes, STREAMING); mapped_address = reinterpret_cast(pixel_buffer.map()); } else if(phase==2) diff --git a/source/core/buffer.cpp b/source/core/buffer.cpp index 240fcd72..15a37397 100644 --- a/source/core/buffer.cpp +++ b/source/core/buffer.cpp @@ -8,7 +8,7 @@ using namespace std; namespace Msp { namespace GL { -void Buffer::storage(size_t sz) +void Buffer::storage(size_t sz, BufferUsage u) { if(size>0) { @@ -20,6 +20,7 @@ void Buffer::storage(size_t sz) throw invalid_argument("Buffer::storage"); size = sz; + usage = u; allocate(); } diff --git a/source/core/buffer.h b/source/core/buffer.h index b642738e..a12b3373 100644 --- a/source/core/buffer.h +++ b/source/core/buffer.h @@ -15,6 +15,12 @@ public: virtual ~buffer_too_small() throw() { } }; +enum BufferUsage +{ + STATIC, + STREAMING +}; + /** Stores data in GPU memory. @@ -22,6 +28,10 @@ Memory must be allocated for the buffer by calling storage(). Contents can then be modified either synchronously with the data() and sub_data() functions, or asynchronously by memory-mapping the buffer. +Buffers can have a static or streaming usage pattern. Streaming buffers can be +memory mapped for less update overhead, but memory space is more limited. If +the buffer is updated only rarely, static is recommended. + Applications normally don't need to deal with Buffers directly. They're managed by other classes such as Mesh and ProgramData. */ @@ -31,11 +41,13 @@ class Buffer: public BufferBackend private: std::size_t size = 0; + BufferUsage usage = STATIC; + bool mapped = false; public: - /** Sets the storage size and allocates memory for the buffer. Size cannot - be changed once set. */ - void storage(std::size_t); + /** Sets storage size and usage pattern and allocates memory for the buffer. + Size and usage cannot be changed once set. */ + void storage(std::size_t, BufferUsage); /** Replaces contents of the entire buffer. Allocated storage must exist. The data must have size matching the defined storage. */ @@ -46,6 +58,7 @@ public: void sub_data(std::size_t, std::size_t, const void *); std::size_t get_size() const { return size; } + BufferUsage get_usage() const { return usage; } void require_size(std::size_t) const; diff --git a/source/core/mesh.cpp b/source/core/mesh.cpp index 208126ef..360d588f 100644 --- a/source/core/mesh.cpp +++ b/source/core/mesh.cpp @@ -211,9 +211,9 @@ void Mesh::draw(Renderer &renderer, const VertexSetup *vs, unsigned count) const void Mesh::resize_buffers() const { if(dirty&VERTEX_BUFFER) - vbuf->storage(vertices.get_required_buffer_size()); + vbuf->storage(vertices.get_required_buffer_size(), STATIC); if((dirty&INDEX_BUFFER) && !batches.empty()) - ibuf->storage(batches.front().get_required_buffer_size()); + ibuf->storage(batches.front().get_required_buffer_size(), STATIC); dirty = 0; } diff --git a/source/render/instancearray.cpp b/source/render/instancearray.cpp index 4a24ac45..eec72f98 100644 --- a/source/render/instancearray.cpp +++ b/source/render/instancearray.cpp @@ -105,7 +105,7 @@ void InstanceArray::render(Renderer &renderer, Tag tag) const const Mesh *mesh = object.get_mesh(); mesh->get_vertices().refresh(); if(instance_buffer->get_size()==0) - instance_buffer->storage(instance_data.get_required_buffer_size()); + instance_buffer->storage(instance_data.get_required_buffer_size(), STREAMING); instance_data.refresh(); Renderer::Push push(renderer); diff --git a/source/render/programdata.cpp b/source/render/programdata.cpp index a908284b..fc9b30a9 100644 --- a/source/render/programdata.cpp +++ b/source/render/programdata.cpp @@ -656,7 +656,7 @@ vector::const_iterator ProgramData::prepare_program(c #endif } - buffer->storage(required_size); + buffer->storage(required_size, STREAMING); } } } -- 2.45.2