From 9be04243c92f024327e74ad8d48861581d83b7ed Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 24 Jan 2021 18:25:51 +0200 Subject: [PATCH] Further refactor Bufferable's API for derived classes --- source/batch.cpp | 3 +-- source/bufferable.cpp | 32 +++++++++++++++++++++----------- source/bufferable.h | 16 ++++++---------- source/uniformblock.cpp | 19 +++---------------- source/uniformblock.h | 3 +-- 5 files changed, 32 insertions(+), 41 deletions(-) diff --git a/source/batch.cpp b/source/batch.cpp index f2614c41..1f787d29 100644 --- a/source/batch.cpp +++ b/source/batch.cpp @@ -216,8 +216,7 @@ const void *Batch::setup_draw() const if(get_buffer()) { - if(dirty) - update_buffer(); + refresh(); return reinterpret_cast(get_offset()); } diff --git a/source/bufferable.cpp b/source/bufferable.cpp index 6b770a8f..e022a716 100644 --- a/source/bufferable.cpp +++ b/source/bufferable.cpp @@ -15,6 +15,7 @@ Bufferable::Bufferable(): offset(0), next_in_buffer(0), prev_in_buffer(0), + location_dirty(false), dirty(false) { } @@ -42,6 +43,7 @@ void Bufferable::use_buffer(Buffer *buf, Bufferable *prev) } } + location_dirty = true; dirty = true; update_offset(); } @@ -77,15 +79,17 @@ void Bufferable::update_offset() if(new_offset!=offset) { offset = new_offset; + location_dirty = true; dirty = true; - offset_changed(); } if(next_in_buffer) next_in_buffer->update_offset(); - - /* Do not resize the buffer here, as more bufferables may be added before - the buffer is actually used. */ + else if(buffer && offset+get_data_size()>buffer->get_size()) + { + location_dirty = true; + dirty = true; + } } bool Bufferable::resize_buffer() const @@ -107,12 +111,12 @@ bool Bufferable::resize_buffer() const return false; } -void Bufferable::update_buffer() const +void Bufferable::update_buffer_size() const { - Conditional _bind(!ARB_direct_state_access, buffer, buffer->get_type()); - if(resize_buffer()) { + Conditional _bind(!ARB_direct_state_access, buffer, buffer->get_type()); + /* Resizing the buffer invalidates its contents. Non-dirty data may be in use, so reupload it. */ for(const Bufferable *b=prev_in_buffer; b; b=b->prev_in_buffer) @@ -122,19 +126,25 @@ void Bufferable::update_buffer() const if(!b->dirty) b->upload_data(0); } - - upload_data(0); } void Bufferable::upload_data(char *target) const { + unsigned data_size = get_data_size(); + if(location_dirty) + { + update_buffer_size(); + location_changed(buffer, offset, data_size); + location_dirty = false; + } + if(target) { const char *source = reinterpret_cast(get_data_pointer()); - copy(source, source+get_data_size(), target); + copy(source, source+data_size, target); } else - buffer->sub_data(offset, get_data_size(), get_data_pointer()); + buffer->sub_data(offset, data_size, get_data_pointer()); dirty = false; } diff --git a/source/bufferable.h b/source/bufferable.h index f47ef4ca..9b2f0bf8 100644 --- a/source/bufferable.h +++ b/source/bufferable.h @@ -34,6 +34,7 @@ private: unsigned offset; Bufferable *next_in_buffer; Bufferable *prev_in_buffer; + mutable bool location_dirty; protected: mutable bool dirty; @@ -46,7 +47,7 @@ public: void use_buffer(Buffer *buf, Bufferable *prev = 0); /** Uploads new data into the buffer if necessary. */ - void refresh() const { if(buffer && dirty) update_buffer(); } + void refresh() const { if(buffer && dirty) upload_data(0); } AsyncUpdater *refresh_async() const; @@ -58,9 +59,6 @@ public: const Buffer *get_buffer() const { return buffer; } protected: - /** Returns the buffer in which the data is stored. */ - Buffer *get_mutable_buffer() const { return buffer; } - /** Returns the amount of data to be stored in the buffer, in bytes. */ virtual unsigned get_data_size() const = 0; @@ -79,19 +77,17 @@ protected: /** Returns the offset where the data should be uploaded. */ unsigned get_offset() const { return offset; } - /** Called when the offset for the data has changed. */ - virtual void offset_changed() { } + /** Called when the target buffer or offset within it has changed. */ + virtual void location_changed(Buffer *, unsigned, unsigned) const { } private: bool resize_buffer() const; -protected: - /** Resizes the buffer if necessary and calls upload_data(). */ - void update_buffer() const; + void update_buffer_size() const; /** Uploads data to the buffer. Receives pointer to mapped buffer memory as parameter. If null, buffer interface should be used instead. */ - virtual void upload_data(char *) const; + void upload_data(char *) const; }; } // namespace GL diff --git a/source/uniformblock.cpp b/source/uniformblock.cpp index ed862682..cc8945cf 100644 --- a/source/uniformblock.cpp +++ b/source/uniformblock.cpp @@ -42,22 +42,10 @@ unsigned UniformBlock::get_alignment() const return BufferRange::get_uniform_buffer_alignment(); } -void UniformBlock::offset_changed() +void UniformBlock::location_changed(Buffer *buf, unsigned off, unsigned) const { delete buf_range; - buf_range = 0; -} - -void UniformBlock::upload_data(char *target) const -{ - if(!buf_range) - buf_range = new BufferRange(*get_mutable_buffer(), get_offset(), size); - - if(target) - copy(data.begin(), data.end(), target); - else - buf_range->data(&data[0]); - dirty = false; + buf_range = new BufferRange(*buf, off, size); } void UniformBlock::attach(int index, const Uniform &uni) @@ -89,8 +77,7 @@ void UniformBlock::apply(int index) const if(!get_buffer()) throw invalid_operation("UniformBlock::apply"); - if(dirty) - update_buffer(); + refresh(); buf_range->bind_to(UNIFORM_BUFFER, index); } else diff --git a/source/uniformblock.h b/source/uniformblock.h index 02e9086e..c8b8d36a 100644 --- a/source/uniformblock.h +++ b/source/uniformblock.h @@ -38,8 +38,7 @@ private: virtual unsigned get_data_size() const { return size; } virtual const void *get_data_pointer() const { return &data[0]; } virtual unsigned get_alignment() const; - virtual void offset_changed(); - virtual void upload_data(char *) const; + virtual void location_changed(Buffer *, unsigned, unsigned) const; public: void attach(int, const Uniform &); -- 2.45.2