From c38debd39fac1e3d44b84e8092419da34f0b613d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 7 Sep 2020 01:20:55 +0200 Subject: GPUVertBuf: GL Backend Isolation Part of the Vulkan port T68990 This makes a few changes in how the data is being handled by the backend to allow more flexibility in the future. The overall code logic is left unchanged. --- source/blender/gpu/intern/gpu_vertex_buffer.cc | 221 ++++++++------------- .../gpu/intern/gpu_vertex_buffer_private.hh | 64 +++++- 2 files changed, 144 insertions(+), 141 deletions(-) (limited to 'source/blender/gpu/intern') diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc index 44c5c9deb37..62c07761b4c 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.cc +++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc @@ -35,8 +35,6 @@ #include -#define VRAM_USAGE 1 - /* -------------------------------------------------------------------- */ /** \name VertBuf * \{ */ @@ -45,6 +43,75 @@ namespace blender::gpu { size_t VertBuf::memory_usage = 0; +VertBuf::VertBuf() +{ + /* Needed by some code check. */ + format.attr_len = 0; +} + +VertBuf::~VertBuf() +{ + /* Should already have been cleared. */ + BLI_assert(flag == GPU_VERTBUF_INVALID); +} + +void VertBuf::init(const GPUVertFormat *format, GPUUsageType usage) +{ + usage_ = usage; + flag = GPU_VERTBUF_DATA_DIRTY; + GPU_vertformat_copy(&this->format, format); + if (!format->packed) { + VertexFormat_pack(&this->format); + } + flag |= GPU_VERTBUF_INIT; +} + +void VertBuf::clear(void) +{ + this->release_data(); + flag = GPU_VERTBUF_INVALID; +} + +VertBuf *VertBuf::duplicate(void) +{ + VertBuf *dst = GPUBackend::get()->vertbuf_alloc(); + /* Full copy. */ + *dst = *this; + /* Almost full copy... */ + dst->handle_refcount_ = 1; + /* Duplicate all needed implementation specifics data. */ + this->duplicate_data(dst); + return dst; +} + +void VertBuf::allocate(uint vert_len) +{ + BLI_assert(format.packed); + /* Catch any unnecessary usage. */ + BLI_assert(vertex_alloc != vert_len || data == nullptr); + vertex_len = vertex_alloc = vert_len; + + this->acquire_data(); + + flag |= GPU_VERTBUF_DATA_DIRTY; +} + +void VertBuf::resize(uint vert_len) +{ + /* Catch any unnecessary usage. */ + BLI_assert(vertex_alloc != vert_len); + vertex_len = vertex_alloc = vert_len; + + this->resize_data(); + + flag |= GPU_VERTBUF_DATA_DIRTY; +} + +void VertBuf::upload(void) +{ + this->upload_data(); +} + } // namespace blender::gpu /** \} */ @@ -56,8 +123,6 @@ size_t VertBuf::memory_usage = 0; using namespace blender; using namespace blender::gpu; -static uint GPU_vertbuf_size_get(const VertBuf *verts); - /* -------- Creation & deletion -------- */ GPUVertBuf *GPU_vertbuf_calloc(void) @@ -68,7 +133,7 @@ GPUVertBuf *GPU_vertbuf_calloc(void) GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *format, GPUUsageType usage) { GPUVertBuf *verts = GPU_vertbuf_calloc(); - GPU_vertbuf_init_with_format_ex(verts, format, usage); + unwrap(verts)->init(format, usage); return verts; } @@ -76,133 +141,48 @@ void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts_, const GPUVertFormat *format, GPUUsageType usage) { - VertBuf *verts = unwrap(verts_); - verts->usage = usage; - verts->flag = GPU_VERTBUF_DATA_DIRTY; - verts->handle_refcount = 1; - GPU_vertformat_copy(&verts->format, format); - if (!format->packed) { - VertexFormat_pack(&verts->format); - } - verts->flag |= GPU_VERTBUF_INIT; + unwrap(verts_)->init(format, usage); } GPUVertBuf *GPU_vertbuf_duplicate(GPUVertBuf *verts_) { - VertBuf *verts = unwrap(verts_); - VertBuf *verts_dst = unwrap(GPU_vertbuf_calloc()); - /* Full copy. */ - *verts_dst = *verts; - verts_dst->handle_refcount = 1; - GPU_vertformat_copy(&verts_dst->format, &verts->format); - - if (verts->vbo_id) { - uint buffer_sz = GPU_vertbuf_size_get(verts); - - verts_dst->vbo_id = GPU_buf_alloc(); - - glBindBuffer(GL_COPY_READ_BUFFER, verts->vbo_id); - glBindBuffer(GL_COPY_WRITE_BUFFER, verts_dst->vbo_id); - - glBufferData(GL_COPY_WRITE_BUFFER, buffer_sz, NULL, to_gl(verts->usage)); - - glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, buffer_sz); - - VertBuf::memory_usage += GPU_vertbuf_size_get(verts); - } - - if (verts->data) { - verts_dst->data = (uchar *)MEM_dupallocN(verts->data); - } - return wrap(verts_dst); + return wrap(unwrap(verts_)->duplicate()); } /** Same as discard but does not free. */ -void GPU_vertbuf_clear(GPUVertBuf *verts_) +void GPU_vertbuf_clear(GPUVertBuf *verts) { - VertBuf *verts = unwrap(verts_); - if (verts->vbo_id) { - GPU_buf_free(verts->vbo_id); - verts->vbo_id = 0; - VertBuf::memory_usage -= GPU_vertbuf_size_get(verts); - } - if (verts->data) { - MEM_SAFE_FREE(verts->data); - } - verts->flag = GPU_VERTBUF_INVALID; + unwrap(verts)->clear(); } void GPU_vertbuf_discard(GPUVertBuf *verts) { - GPU_vertbuf_clear(verts); - GPU_vertbuf_handle_ref_remove(verts); + unwrap(verts)->clear(); + unwrap(verts)->reference_remove(); } -void GPU_vertbuf_handle_ref_add(GPUVertBuf *verts_) +void GPU_vertbuf_handle_ref_add(GPUVertBuf *verts) { - VertBuf *verts = unwrap(verts_); - verts->handle_refcount++; + unwrap(verts)->reference_add(); } -void GPU_vertbuf_handle_ref_remove(GPUVertBuf *verts_) +void GPU_vertbuf_handle_ref_remove(GPUVertBuf *verts) { - VertBuf *verts = unwrap(verts_); - BLI_assert(verts->handle_refcount > 0); - verts->handle_refcount--; - if (verts->handle_refcount == 0) { - /* Should already have been cleared. */ - BLI_assert(verts->vbo_id == 0 && verts->data == NULL); - MEM_freeN(verts); - } -} - -uint GPU_vertbuf_size_get(const VertBuf *verts) -{ - return vertex_buffer_size(&verts->format, verts->vertex_len); + unwrap(verts)->reference_remove(); } /* -------- Data update -------- */ /* create a new allocation, discarding any existing data */ -void GPU_vertbuf_data_alloc(GPUVertBuf *verts_, uint v_len) +void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len) { - VertBuf *verts = unwrap(verts_); - GPUVertFormat *format = &verts->format; - if (!format->packed) { - VertexFormat_pack(format); - } -#if TRUST_NO_ONE - /* catch any unnecessary use */ - assert(verts->vertex_alloc != v_len || verts->data == NULL); -#endif - /* discard previous data if any */ - if (verts->data) { - MEM_freeN(verts->data); - } - - uint new_size = vertex_buffer_size(&verts->format, v_len); - VertBuf::memory_usage += new_size - GPU_vertbuf_size_get(verts); - - verts->flag |= GPU_VERTBUF_DATA_DIRTY; - verts->vertex_len = verts->vertex_alloc = v_len; - verts->data = (uchar *)MEM_mallocN(sizeof(GLubyte) * GPU_vertbuf_size_get(verts), __func__); + unwrap(verts)->allocate(v_len); } /* resize buffer keeping existing data */ -void GPU_vertbuf_data_resize(GPUVertBuf *verts_, uint v_len) +void GPU_vertbuf_data_resize(GPUVertBuf *verts, uint v_len) { - VertBuf *verts = unwrap(verts_); -#if TRUST_NO_ONE - assert(verts->data != NULL); - assert(verts->vertex_alloc != v_len); -#endif - - uint new_size = vertex_buffer_size(&verts->format, v_len); - VertBuf::memory_usage += new_size - GPU_vertbuf_size_get(verts); - - verts->flag |= GPU_VERTBUF_DATA_DIRTY; - verts->vertex_len = verts->vertex_alloc = v_len; - verts->data = (uchar *)MEM_reallocN(verts->data, sizeof(GLubyte) * GPU_vertbuf_size_get(verts)); + unwrap(verts)->resize(v_len); } /* Set vertex count but does not change allocation. @@ -214,9 +194,6 @@ void GPU_vertbuf_data_len_set(GPUVertBuf *verts_, uint v_len) BLI_assert(verts->data != NULL); /* Only for dynamic data. */ BLI_assert(v_len <= verts->vertex_alloc); - uint new_size = vertex_buffer_size(&verts->format, v_len); - VertBuf::memory_usage += new_size - GPU_vertbuf_size_get(verts); - verts->vertex_len = v_len; } @@ -359,34 +336,10 @@ uint GPU_vertbuf_get_memory_usage(void) return VertBuf::memory_usage; } -static void VertBuffer_upload_data(GPUVertBuf *verts_) +/* Should be rename to GPU_vertbuf_data_upload */ +void GPU_vertbuf_use(GPUVertBuf *verts) { - VertBuf *verts = unwrap(verts_); - uint buffer_sz = GPU_vertbuf_size_get(verts); - - /* orphan the vbo to avoid sync */ - glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, to_gl(verts->usage)); - /* upload data */ - glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data); - - if (verts->usage == GPU_USAGE_STATIC) { - MEM_SAFE_FREE(verts->data); - } - verts->flag &= ~GPU_VERTBUF_DATA_DIRTY; - verts->flag |= GPU_VERTBUF_DATA_UPLOADED; -} - -void GPU_vertbuf_use(GPUVertBuf *verts_) -{ - VertBuf *verts = unwrap(verts_); - /* only create the buffer the 1st time */ - if (verts->vbo_id == 0) { - verts->vbo_id = GPU_buf_alloc(); - } - glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id); - if (verts->flag & GPU_VERTBUF_DATA_DIRTY) { - VertBuffer_upload_data(verts_); - } + unwrap(verts)->upload(); } /** \} */ \ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh index eb7e0bc8b9b..61af0a215a9 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh @@ -29,7 +29,8 @@ namespace blender::gpu { -struct VertBuf { +class VertBuf { + public: static size_t memory_usage; GPUVertFormat format = {}; @@ -37,16 +38,65 @@ struct VertBuf { uint vertex_len = 0; /** Number of verts data. */ uint vertex_alloc = 0; - /** 0 indicates not yet allocated. */ - uint32_t vbo_id = 0; - /** Usage hint for GL optimisation. */ - GPUUsageType usage = GPU_USAGE_STATIC; /** Status flag. */ GPUVertBufStatus flag = GPU_VERTBUF_INVALID; - /** This counter will only avoid freeing the GPUVertBuf, not the data. */ - char handle_refcount = 0; /** NULL indicates data in VRAM (unmapped) */ uchar *data = NULL; + + protected: + /** Usage hint for GL optimisation. */ + GPUUsageType usage_ = GPU_USAGE_STATIC; + + private: + /** This counter will only avoid freeing the GPUVertBuf, not the data. */ + int handle_refcount_ = 1; + + public: + VertBuf(); + virtual ~VertBuf(); + + void init(const GPUVertFormat *format, GPUUsageType usage); + void clear(void); + + /* Data manament */ + void allocate(uint vert_len); + void resize(uint vert_len); + void upload(void); + + VertBuf *duplicate(void); + + /* Size of the data allocated. */ + size_t size_alloc_get(void) const + { + BLI_assert(format.packed); + return vertex_alloc * format.stride; + } + /* Size of the data uploaded to the GPU. */ + size_t size_used_get(void) const + { + BLI_assert(format.packed); + return vertex_len * format.stride; + } + + void reference_add(void) + { + handle_refcount_++; + } + void reference_remove(void) + { + BLI_assert(handle_refcount_ > 0); + handle_refcount_--; + if (handle_refcount_ == 0) { + delete this; + } + } + + protected: + virtual void acquire_data(void) = 0; + virtual void resize_data(void) = 0; + virtual void release_data(void) = 0; + virtual void upload_data(void) = 0; + virtual void duplicate_data(VertBuf *dst) = 0; }; /* Syntacting suggar. */ -- cgit v1.2.3