Commit: ab7e7a005bde711d14493d51ee26ea297fa99e47
Author: Clément Foucault
Date:   Wed Feb 14 17:59:48 2018 +0100
Branches: blender2.8
https://developer.blender.org/rBab7e7a005bde711d14493d51ee26ea297fa99e47

GWN: Add new dynamic type of batches and remove

Theses batches keeps their memory chuck allocated after transfer to be reused 
and updated very often.

NOTE: This commit break instancing in DRW. (it's fixed in the next commit)

===================================================================

M       intern/gawain/gawain/gwn_vertex_buffer.h
M       intern/gawain/src/gwn_vertex_buffer.c
M       source/blender/draw/intern/draw_manager.c

===================================================================

diff --git a/intern/gawain/gawain/gwn_vertex_buffer.h 
b/intern/gawain/gawain/gwn_vertex_buffer.h
index 50a4e1aa2f6..34f12754f40 100644
--- a/intern/gawain/gawain/gwn_vertex_buffer.h
+++ b/intern/gawain/gawain/gwn_vertex_buffer.h
@@ -13,6 +13,7 @@
 
 #include "gwn_vertex_format.h"
 
+#define VRAM_USAGE 1
 // How to create a Gwn_VertBuf:
 // 1) verts = GWN_vertbuf_create() or GWN_vertbuf_init(verts)
 // 2) GWN_vertformat_attr_add(verts->format, ...)
@@ -24,15 +25,22 @@
 typedef struct Gwn_VertBuf {
        Gwn_VertFormat format;
        unsigned vertex_ct;
-       bool own_data; // does gawain own the data an is able to free it
+       unsigned alloc_ct; // size in vertex of alloced data
+#if VRAM_USAGE
+       unsigned vram_size; // size in byte of data present in the VRAM
+#endif
+       unsigned data_dirty : 1; // does the data has been touched since last 
transfert
+       unsigned data_dynamic : 1; // do we keep the RAM allocation for further 
updates?
+       unsigned data_resized : 1; // does the data has been resized since last 
transfert
        GLubyte* data; // NULL indicates data in VRAM (unmapped) or not yet 
allocated
        GLuint vbo_id; // 0 indicates not yet sent to VRAM
 } Gwn_VertBuf;
 
 Gwn_VertBuf* GWN_vertbuf_create(void);
 Gwn_VertBuf* GWN_vertbuf_create_with_format(const Gwn_VertFormat*);
+Gwn_VertBuf* GWN_vertbuf_create_dynamic_with_format(const Gwn_VertFormat*);
 
-void GWN_vertbuf_clear(Gwn_VertBuf* verts);
+void GWN_vertbuf_clear(Gwn_VertBuf*);
 void GWN_vertbuf_discard(Gwn_VertBuf*);
 
 void GWN_vertbuf_init(Gwn_VertBuf*);
@@ -40,7 +48,6 @@ void GWN_vertbuf_init_with_format(Gwn_VertBuf*, const 
Gwn_VertFormat*);
 
 unsigned GWN_vertbuf_size_get(const Gwn_VertBuf*);
 void GWN_vertbuf_data_alloc(Gwn_VertBuf*, unsigned v_ct);
-void GWN_vertbuf_data_set(Gwn_VertBuf*, unsigned v_ct, void* data, bool 
pass_ownership);
 void GWN_vertbuf_data_resize(Gwn_VertBuf*, unsigned v_ct);
 
 // The most important set_attrib variant is the untyped one. Get it right 
first.
diff --git a/intern/gawain/src/gwn_vertex_buffer.c 
b/intern/gawain/src/gwn_vertex_buffer.c
index 2bab0bc378b..32bef765390 100644
--- a/intern/gawain/src/gwn_vertex_buffer.c
+++ b/intern/gawain/src/gwn_vertex_buffer.c
@@ -38,6 +38,13 @@ Gwn_VertBuf* GWN_vertbuf_create_with_format(const 
Gwn_VertFormat* format)
        // TODO: implement those memory savings
        }
 
+Gwn_VertBuf* GWN_vertbuf_create_dynamic_with_format(const Gwn_VertFormat* 
format)
+       {
+       Gwn_VertBuf* verts = GWN_vertbuf_create_with_format(format);
+       verts->data_dynamic = true;
+       return verts;
+       }
+
 void GWN_vertbuf_init(Gwn_VertBuf* verts)
        {
        memset(verts, 0, sizeof(Gwn_VertBuf));
@@ -58,12 +65,12 @@ void GWN_vertbuf_clear(Gwn_VertBuf* verts)
        {
        if (verts->vbo_id) {
                GWN_buf_id_free(verts->vbo_id);
-               vbo_memory_usage -= GWN_vertbuf_size_get(verts);
-       }
-#if KEEP_SINGLE_COPY
-       else
+#if VRAM_USAGE
+               vbo_memory_usage -= verts->vram_size;
 #endif
-       if (verts->data && verts->own_data)
+       }
+
+       if (verts->data)
                {
                free(verts->data);
                verts->data = NULL;
@@ -75,12 +82,12 @@ void GWN_vertbuf_discard(Gwn_VertBuf* verts)
        if (verts->vbo_id)
                {
                GWN_buf_id_free(verts->vbo_id);
-               vbo_memory_usage -= GWN_vertbuf_size_get(verts);
-               }
-#if KEEP_SINGLE_COPY
-       else
+#if VRAM_USAGE
+               vbo_memory_usage -= verts->vram_size;
 #endif
-       if (verts->data && verts->own_data)
+               }
+
+       if (verts->data)
                {
                free(verts->data);
                }
@@ -101,33 +108,22 @@ void GWN_vertbuf_data_alloc(Gwn_VertBuf* verts, unsigned 
v_ct)
                VertexFormat_pack(format);
 
        verts->vertex_ct = v_ct;
-       verts->own_data = true;
 
        // Data initially lives in main memory. Will be transferred to VRAM 
when we "prime" it.
        verts->data = malloc(GWN_vertbuf_size_get(verts));
        }
 
-void GWN_vertbuf_data_set(Gwn_VertBuf* verts, unsigned v_ct, void* data, bool 
pass_ownership)
-       {
-       Gwn_VertFormat* format = &verts->format;
-       if (!format->packed)
-               VertexFormat_pack(format);
-
-       verts->vertex_ct = v_ct;
-       verts->own_data = pass_ownership;
-
-       // Data initially lives in main memory. Will be transferred to VRAM 
when we "prime" it.
-       verts->data = data;
-       }
-
 void GWN_vertbuf_data_resize(Gwn_VertBuf* verts, unsigned v_ct)
        {
 #if TRUST_NO_ONE
        assert(verts->vertex_ct != v_ct); // allow this?
        assert(verts->data != NULL); // has already been allocated
-       assert(verts->vbo_id == 0); // has not been sent to VRAM
+       assert(verts->vbo_id == 0 || verts->data_dynamic); // has not been sent 
to VRAM
 #endif
 
+       // for dynamic buffers
+       verts->data_resized = true;
+
        verts->vertex_ct = v_ct;
        verts->data = realloc(verts->data, GWN_vertbuf_size_get(verts));
        // TODO: skip realloc if v_ct < existing vertex count
@@ -139,6 +135,8 @@ void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned 
a_idx, unsigned v_idx, co
        const Gwn_VertFormat* format = &verts->format;
        const Gwn_VertAttr* a = format->attribs + a_idx;
 
+       verts->data_dirty = true;
+
 #if TRUST_NO_ONE
        assert(a_idx < format->attrib_ct);
        assert(v_idx < verts->vertex_ct);
@@ -153,6 +151,8 @@ void GWN_vertbuf_attr_fill(Gwn_VertBuf* verts, unsigned 
a_idx, const void* data)
        const Gwn_VertFormat* format = &verts->format;
        const Gwn_VertAttr* a = format->attribs + a_idx;
 
+       verts->data_dirty = true;
+
 #if TRUST_NO_ONE
        assert(a_idx < format->attrib_ct);
 #endif
@@ -167,6 +167,8 @@ void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, 
unsigned a_idx, unsigned s
        const Gwn_VertFormat* format = &verts->format;
        const Gwn_VertAttr* a = format->attribs + a_idx;
 
+       verts->data_dirty = true;
+
 #if TRUST_NO_ONE
        assert(a_idx < format->attrib_ct);
        assert(verts->data != NULL); // data must be in main mem
@@ -209,31 +211,58 @@ void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, 
unsigned a_idx, Gwn_VertB
 
 static void VertexBuffer_prime(Gwn_VertBuf* verts)
        {
-       const unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+       unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+
+#if VRAM_USAGE
+       vbo_memory_usage += buffer_sz;
+       verts->vram_size = buffer_sz;
+#endif
 
        verts->vbo_id = GWN_buf_id_alloc();
        glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
        // fill with delicious data & send to GPU the first time only
-       glBufferData(GL_ARRAY_BUFFER, buffer_sz, verts->data, GL_STATIC_DRAW);
-
-       vbo_memory_usage += buffer_sz;
+       glBufferData(GL_ARRAY_BUFFER, verts->vram_size, verts->data, 
(verts->data_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
 
-#if KEEP_SINGLE_COPY
        // now that GL has a copy, discard original
-       if (verts->own_data)
+       if (!verts->data_dynamic)
                {
                free(verts->data);
                verts->data = NULL;
                }
+
+       verts->data_dirty = false;
+       }
+
+static void VertexBuffer_update(Gwn_VertBuf* verts)
+       {
+       unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+
+#if VRAM_USAGE
+       vbo_memory_usage -= verts->vram_size;
+       vbo_memory_usage += buffer_sz;
+       verts->vram_size = buffer_sz;
 #endif
+
+       glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+
+       // fill with delicious data & send to GPU ... AGAIN
+       if (verts->data_resized)
+               glBufferData(GL_ARRAY_BUFFER, buffer_sz, verts->data, 
GL_DYNAMIC_DRAW);
+       else
+               glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data); // 
.. todo try glMapBuffer
+
+       verts->data_dirty = false;
+       verts->data_resized = false;
        }
 
 void GWN_vertbuf_use(Gwn_VertBuf* verts)
        {
-       if (verts->vbo_id)
-               glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
-       else
+       if (!verts->vbo_id)
                VertexBuffer_prime(verts);
+       else if (verts->data_dirty)
+               VertexBuffer_update(verts);
+       else
+               glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
        }
 
 unsigned GWN_vertbuf_get_memory_usage(void)
diff --git a/source/blender/draw/intern/draw_manager.c 
b/source/blender/draw/intern/draw_manager.c
index db1046039d5..6feab32f8e1 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1188,13 +1188,9 @@ static void shgroup_dynamic_batch(DRWShadingGroup 
*shgroup)
 
        /* Upload Data */
        Gwn_VertBuf *vbo = 
GWN_vertbuf_create_with_format(&interface->vbo_format);
-       if (interface->inst_data) {
-               GWN_vertbuf_data_set(vbo, nbr, 
DRW_instance_data_get(interface->inst_data), false);
-       } else {
                /* Use unitialized memory. This is for dummy vertex buffers. */
                /* XXX TODO do not alloc at all. */
                GWN_vertbuf_data_alloc(vbo, nbr);
-       }
 
        /* TODO make the batch dynamic instead of freeing it every times */
        if (shgroup->batch_geom)
@@ -1218,13 +1214,9 @@ static void shgroup_dynamic_instance(DRWShadingGroup 
*shgroup)
 
        /* Upload Data */
        Gwn_VertBuf *vbo = 
GWN_vertbuf_create_with_format(&interface->vbo_format);
-       if (interface->inst_data) {
-               GWN_vertbuf_data_set(vbo, nbr, 
DRW_instance_data_get(interface->inst_data), false);
-       } else {
                /* Use unitialized memory. This is for dummy vertex buffers. */
                /* XXX TODO do not alloc at all. */
                GWN_vertbuf_data_alloc(vbo, nbr);
-       }
 
        /* TODO make the batch dynamic instead of freeing it every times */
        if (shgroup->instancing_geom)

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to