Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/gawain/gawain/gwn_vertex_buffer.h8
-rw-r--r--intern/gawain/src/gwn_vertex_buffer.c137
2 files changed, 65 insertions, 80 deletions
diff --git a/intern/gawain/gawain/gwn_vertex_buffer.h b/intern/gawain/gawain/gwn_vertex_buffer.h
index d9faae4f55f..ddb77368a02 100644
--- a/intern/gawain/gawain/gwn_vertex_buffer.h
+++ b/intern/gawain/gawain/gwn_vertex_buffer.h
@@ -25,13 +25,14 @@
typedef enum {
// can be extended to support more types
GWN_USAGE_STREAM,
- GWN_USAGE_STATIC,
+ GWN_USAGE_STATIC, // do not keep data in memory
GWN_USAGE_DYNAMIC
} Gwn_UsageType;
typedef struct Gwn_VertBuf {
Gwn_VertFormat format;
unsigned vertex_ct;
+ bool dirty;
GLubyte* data; // NULL indicates data in VRAM (unmapped)
GLuint vbo_id; // 0 indicates not yet allocated
Gwn_UsageType usage; // usage hint for GL optimisation
@@ -53,10 +54,7 @@ void GWN_vertbuf_init_with_format_ex(Gwn_VertBuf*, const Gwn_VertFormat*, Gwn_Us
unsigned GWN_vertbuf_size_get(const Gwn_VertBuf*);
void GWN_vertbuf_data_alloc(Gwn_VertBuf*, unsigned v_ct);
-void GWN_vertbuf_data_resize_ex(Gwn_VertBuf*, unsigned v_ct, bool keep_data);
-
-#define GWN_vertbuf_data_resize(verts, v_ct) \
- GWN_vertbuf_data_resize_ex(verts, v_ct, true)
+void GWN_vertbuf_data_resize(Gwn_VertBuf*, unsigned v_ct);
// The most important set_attrib variant is the untyped one. Get it right first.
// It takes a void* so the app developer is responsible for matching their app data types
diff --git a/intern/gawain/src/gwn_vertex_buffer.c b/intern/gawain/src/gwn_vertex_buffer.c
index 17c2a3e9364..39fc1885b92 100644
--- a/intern/gawain/src/gwn_vertex_buffer.c
+++ b/intern/gawain/src/gwn_vertex_buffer.c
@@ -52,6 +52,7 @@ void GWN_vertbuf_init(Gwn_VertBuf* verts, Gwn_UsageType usage)
{
memset(verts, 0, sizeof(Gwn_VertBuf));
verts->usage = usage;
+ verts->dirty = true;
}
void GWN_vertbuf_init_with_format_ex(Gwn_VertBuf* verts, const Gwn_VertFormat* format, Gwn_UsageType usage)
@@ -72,6 +73,9 @@ void GWN_vertbuf_discard(Gwn_VertBuf* verts)
#endif
}
+ if (verts->data)
+ free(verts->data);
+
free(verts);
}
@@ -80,90 +84,58 @@ unsigned GWN_vertbuf_size_get(const Gwn_VertBuf* verts)
return vertex_buffer_size(&verts->format, verts->vertex_ct);
}
+// create a new allocation, discarding any existing data
void GWN_vertbuf_data_alloc(Gwn_VertBuf* verts, unsigned v_ct)
{
Gwn_VertFormat* format = &verts->format;
if (!format->packed)
VertexFormat_pack(format);
- verts->vertex_ct = v_ct;
-
#if TRUST_NO_ONE
- assert(verts->vbo_id == 0);
+ // catch any unnecessary use
+ assert(verts->vertex_ct != v_ct || verts->data == NULL);
#endif
- unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+ // only create the buffer the 1st time
+ if (verts->vbo_id == 0)
+ verts->vbo_id = GWN_buf_id_alloc();
+
+ // discard previous data if any
+ if (verts->data)
+ free(verts->data);
+
#if VRAM_USAGE
- vbo_memory_usage += buffer_sz;
+ vbo_memory_usage -= GWN_vertbuf_size_get(verts);
#endif
- // create an array buffer and map it to memory
- verts->vbo_id = GWN_buf_id_alloc();
- glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
- glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage));
- verts->data = glMapBufferRange(GL_ARRAY_BUFFER, 0, buffer_sz, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ verts->dirty = true;
+ verts->vertex_ct = v_ct;
+ verts->data = malloc(sizeof(GLubyte) * GWN_vertbuf_size_get(verts));
+
+#if VRAM_USAGE
+ vbo_memory_usage += GWN_vertbuf_size_get(verts);
+#endif
}
-void GWN_vertbuf_data_resize_ex(Gwn_VertBuf* verts, unsigned v_ct, bool keep_data)
+// resize buffer keeping existing data
+void GWN_vertbuf_data_resize(Gwn_VertBuf* verts, unsigned v_ct)
{
#if TRUST_NO_ONE
- assert(verts->vbo_id != 0);
+ assert(verts->data != NULL);
+ assert(verts->vertex_ct != v_ct);
#endif
- if (verts->vertex_ct == v_ct)
- return;
-
- unsigned old_buf_sz = GWN_vertbuf_size_get(verts);
- verts->vertex_ct = v_ct;
- unsigned new_buf_sz = GWN_vertbuf_size_get(verts);
#if VRAM_USAGE
- vbo_memory_usage += new_buf_sz - old_buf_sz;
+ vbo_memory_usage -= GWN_vertbuf_size_get(verts);
#endif
- if (keep_data)
- {
- // we need to do a copy to keep the existing data
- GLuint vbo_tmp;
- glGenBuffers(1, &vbo_tmp);
- // only copy the data that can fit in the new buffer
- unsigned copy_sz = (old_buf_sz < new_buf_sz) ? old_buf_sz : new_buf_sz;
- glBindBuffer(GL_COPY_WRITE_BUFFER, vbo_tmp);
- glBufferData(GL_COPY_WRITE_BUFFER, copy_sz, NULL, GL_STREAM_COPY);
-
- glBindBuffer(GL_COPY_READ_BUFFER, verts->vbo_id);
- // we cannot copy from/to a mapped buffer
- if (verts->data)
- glUnmapBuffer(GL_COPY_READ_BUFFER);
-
- // save data, resize the buffer, restore data
- glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, copy_sz);
- glBufferData(GL_COPY_READ_BUFFER, new_buf_sz, NULL, convert_usage_type_to_gl(verts->usage));
- glCopyBufferSubData(GL_COPY_WRITE_BUFFER, GL_COPY_READ_BUFFER, 0, 0, copy_sz);
-
- glDeleteBuffers(1, &vbo_tmp);
- }
- else
- {
- glBindBuffer(GL_COPY_READ_BUFFER, verts->vbo_id);
- glBufferData(GL_COPY_READ_BUFFER, new_buf_sz, NULL, convert_usage_type_to_gl(verts->usage));
- }
-
- // if the buffer was mapped, update it's pointer
- if (verts->data)
- verts->data = glMapBufferRange(GL_COPY_READ_BUFFER, 0, new_buf_sz, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
- }
-
-static void VertexBuffer_map(Gwn_VertBuf* verts)
- {
- glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
- verts->data = glMapBufferRange(GL_ARRAY_BUFFER, 0, GWN_vertbuf_size_get(verts), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
- }
+ verts->dirty = true;
+ verts->vertex_ct = v_ct;
+ verts->data = realloc(verts->data, sizeof(GLubyte) * GWN_vertbuf_size_get(verts));
-static void VertexBuffer_unmap(Gwn_VertBuf* verts)
- {
- glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
- glUnmapBuffer(GL_ARRAY_BUFFER);
- verts->data = NULL;
+#if VRAM_USAGE
+ vbo_memory_usage += GWN_vertbuf_size_get(verts);
+#endif
}
void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned a_idx, unsigned v_idx, const void* data)
@@ -174,11 +146,10 @@ void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned a_idx, unsigned v_idx, co
#if TRUST_NO_ONE
assert(a_idx < format->attrib_ct);
assert(v_idx < verts->vertex_ct);
+ assert(verts->data != NULL);
#endif
- if (verts->data == NULL)
- VertexBuffer_map(verts);
-
+ verts->dirty = true;
memcpy((GLubyte*)verts->data + a->offset + v_idx * format->stride, data, a->sz);
}
@@ -203,13 +174,12 @@ void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, unsigned a_idx, unsigned s
#if TRUST_NO_ONE
assert(a_idx < format->attrib_ct);
+ assert(verts->data != NULL);
#endif
+ verts->dirty = true;
const unsigned vertex_ct = verts->vertex_ct;
- if (verts->data == NULL)
- VertexBuffer_map(verts);
-
if (format->attrib_ct == 1 && stride == format->stride)
{
// we can copy it all at once
@@ -230,10 +200,10 @@ void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertB
#if TRUST_NO_ONE
assert(a_idx < format->attrib_ct);
+ assert(verts->data != NULL);
#endif
- if (verts->data == NULL)
- VertexBuffer_map(verts);
+ verts->dirty = true;
access->size = a->sz;
access->stride = format->stride;
@@ -244,13 +214,30 @@ void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertB
#endif
}
+static void VertBuffer_upload_data(Gwn_VertBuf* verts)
+ {
+ unsigned buffer_sz = GWN_vertbuf_size_get(verts);
+
+ // orphan the vbo to avoid sync
+ glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage));
+ // upload data
+ glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data);
+
+ if (verts->usage == GWN_USAGE_STATIC)
+ {
+ free(verts->data);
+ verts->data = NULL;
+ }
+
+ verts->dirty = false;
+ }
+
void GWN_vertbuf_use(Gwn_VertBuf* verts)
{
- if (verts->data)
- // this also calls glBindBuffer
- VertexBuffer_unmap(verts);
- else
- glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+ glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+
+ if (verts->dirty)
+ VertBuffer_upload_data(verts);
}
unsigned GWN_vertbuf_get_memory_usage(void)