From: Mikko Rasa Date: Tue, 23 Sep 2014 20:23:14 +0000 (+0300) Subject: Add an asynchronous update interface to Bufferable X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=6c525eff3eaaa617648a869449ed3bddf9c1936d Add an asynchronous update interface to Bufferable --- diff --git a/source/bufferable.cpp b/source/bufferable.cpp index 04793fb7..569ffb2f 100644 --- a/source/bufferable.cpp +++ b/source/bufferable.cpp @@ -43,6 +43,11 @@ void Bufferable::use_buffer(Buffer *buf, Bufferable *prev) update_offset(); } +Bufferable::AsyncUpdater *Bufferable::refresh_async() const +{ + return dirty ? new AsyncUpdater(*this) : 0; +} + void Bufferable::unlink_from_buffer() { if(prev_in_buffer) @@ -108,19 +113,56 @@ void Bufferable::update_buffer() const be in use, so reupload it. */ for(const Bufferable *b=prev_in_buffer; b; b=b->prev_in_buffer) if(!b->dirty) - b->upload_data(); + b->upload_data(0); for(const Bufferable *b=next_in_buffer; b; b=b->next_in_buffer) if(!b->dirty) - b->upload_data(); + b->upload_data(0); } - upload_data(); + upload_data(0); dirty = false; } -void Bufferable::upload_data() const +void Bufferable::upload_data(char *target) const +{ + if(target) + { + const char *source = reinterpret_cast(get_data_pointer()); + copy(source, source+get_data_size(), target); + } + else + buffer->sub_data(offset, get_data_size(), get_data_pointer()); +} + + +Bufferable::AsyncUpdater::AsyncUpdater(const Bufferable &b): + bufferable(b) { - buffer->sub_data(offset, get_data_size(), get_data_pointer()); + buffer_resized = bufferable.resize_buffer(); + mapped_address = reinterpret_cast(bufferable.buffer->map(WRITE_ONLY)); +} + +Bufferable::AsyncUpdater::~AsyncUpdater() +{ + bufferable.buffer->unmap(); +} + +void Bufferable::AsyncUpdater::upload_data() +{ + bufferable.upload_data(mapped_address+bufferable.offset); + // Update all bufferables in the same buffer at once + for(const Bufferable *b=bufferable.prev_in_buffer; b; b=b->prev_in_buffer) + if(b->dirty || buffer_resized) + { + b->upload_data(mapped_address+b->offset); + b->dirty = false; + } + for(const Bufferable *b=bufferable.next_in_buffer; b; b=b->next_in_buffer) + if(b->dirty || buffer_resized) + { + b->upload_data(mapped_address+b->offset); + b->dirty = false; + } } } // namespace GL diff --git a/source/bufferable.h b/source/bufferable.h index d7d7e45f..f157c628 100644 --- a/source/bufferable.h +++ b/source/bufferable.h @@ -14,6 +14,21 @@ uploading fresh data to the buffer. */ class Bufferable { +public: + class AsyncUpdater + { + private: + const Bufferable &bufferable; + char *mapped_address; + bool buffer_resized; + + public: + AsyncUpdater(const Bufferable &); + ~AsyncUpdater(); + + void upload_data(); + }; + private: Buffer *buffer; unsigned offset; @@ -34,6 +49,8 @@ public: /** Uploads new data into the buffer if necessary. */ void refresh() const { if(dirty) update_buffer(); } + AsyncUpdater *refresh_async() const; + private: void unlink_from_buffer(); @@ -69,8 +86,9 @@ protected: /** Resizes the buffer if necessary and calls upload_data(). */ void update_buffer() const; - /** Uploads data to the buffer. */ - virtual void upload_data() 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; }; } // namespace GL diff --git a/source/uniformblock.cpp b/source/uniformblock.cpp index 498973f9..09060eb7 100644 --- a/source/uniformblock.cpp +++ b/source/uniformblock.cpp @@ -44,11 +44,15 @@ void UniformBlock::offset_changed() buf_range = 0; } -void UniformBlock::upload_data() const +void UniformBlock::upload_data(char *target) const { if(!buf_range) buf_range = new BufferRange(*get_buffer(), get_offset(), size); - buf_range->data(&data[0]); + + if(target) + copy(data.begin(), data.end(), target); + else + buf_range->data(&data[0]); } void UniformBlock::attach(int index, const Uniform &uni) diff --git a/source/uniformblock.h b/source/uniformblock.h index 877a255f..02e9086e 100644 --- a/source/uniformblock.h +++ b/source/uniformblock.h @@ -39,7 +39,7 @@ private: virtual const void *get_data_pointer() const { return &data[0]; } virtual unsigned get_alignment() const; virtual void offset_changed(); - virtual void upload_data() const; + virtual void upload_data(char *) const; public: void attach(int, const Uniform &);