[Bf-blender-cvs] [76c99f3] blender2.8: Gawain improvements

Mike Erwin noreply at git.blender.org
Thu Sep 15 21:45:38 CEST 2016


Commit: 76c99f361f58752eff8054f5cff52cad9ce57145
Author: Mike Erwin
Date:   Thu Sep 15 21:45:10 2016 +0200
Branches: blender2.8
https://developer.blender.org/rB76c99f361f58752eff8054f5cff52cad9ce57145

Gawain improvements

Fixed compile error in debug build (thanks mont29)

Renamed some functions for consistency.

New features:

Create a Batch with immediate mode! Just use immBeginBatch instead of immBegin. You can keep the result and draw it as many times as you like. This partially replaces the need for display lists.

Copy a VertexFormat, and create a VertexBuffer using an existing format.

Resize a VertexBuffer to a different number of vertices. (can only resize BEFORE using it to draw)

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

M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/gpu/gawain/batch.c
M	source/blender/gpu/gawain/batch.h
M	source/blender/gpu/gawain/immediate.c
M	source/blender/gpu/gawain/immediate.h
M	source/blender/gpu/gawain/vertex_buffer.c
M	source/blender/gpu/gawain/vertex_buffer.h
M	source/blender/gpu/gawain/vertex_format.c
M	source/blender/gpu/gawain/vertex_format.h

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

diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 77f19d3..cb07dd8 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -740,7 +740,7 @@ static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
 
 		immUnbindProgram();
 
-		clear_VertexFormat(format);
+		VertexFormat_clear(format);
 		pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
 
 		immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c
index 96bf6dd..f8183ab 100644
--- a/source/blender/gpu/gawain/batch.c
+++ b/source/blender/gpu/gawain/batch.c
@@ -25,6 +25,7 @@ Batch* Batch_create(GLenum prim_type, VertexBuffer* verts, ElementList* elem)
 	batch->verts = verts;
 	batch->elem = elem;
 	batch->prim_type = prim_type;
+	batch->phase = READY_TO_DRAW;
 
 	return batch;
 	}
@@ -38,7 +39,7 @@ void Batch_set_program(Batch* batch, GLuint program)
 static void Batch_update_program_bindings(Batch* batch)
 	{
 #if TRUST_NO_ONE
-	assert(glIsProgram(program));
+	assert(glIsProgram(batch->program));
 #endif
 
 	const VertexFormat* format = &batch->verts->format;
@@ -88,6 +89,10 @@ static void Batch_prime(Batch* batch)
 
 void Batch_draw(Batch* batch)
 	{
+#if TRUST_NO_ONE
+	assert(batch->phase == READY_TO_DRAW);
+#endif
+
 	if (batch->vao_id)
 		glBindVertexArray(batch->vao_id);
 	else
diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h
index 8387b01..8b132aa 100644
--- a/source/blender/gpu/gawain/batch.h
+++ b/source/blender/gpu/gawain/batch.h
@@ -14,6 +14,13 @@
 #include "vertex_buffer.h"
 #include "element.h"
 
+typedef enum {
+	READY_TO_FORMAT,
+	READY_TO_BUILD,
+	BUILDING,
+	READY_TO_DRAW
+} BatchPhase;
+
 typedef struct {
 	// geometry
 	VertexBuffer* verts;
@@ -22,6 +29,7 @@ typedef struct {
 
 	// book-keeping
 	GLuint vao_id; // remembers all geometry state (vertex attrib bindings & element buffer)
+	BatchPhase phase;
 	bool program_dirty;
 
 	// state
@@ -30,6 +38,9 @@ typedef struct {
 
 Batch* Batch_create(GLenum prim_type, VertexBuffer*, ElementList*);
 
+// TODO: void Batch_discard(Batch*);
+// must first decide how sharing of vertex buffers & index buffers should work
+
 void Batch_set_program(Batch*, GLuint program);
 // Entire batch draws with one shader program, but can be redrawn later with another program.
 // Vertex shader's inputs must be compatible with the batch's vertex format.
@@ -46,20 +57,6 @@ void Batch_draw(Batch*);
 // Can multiple batches share a VertexBuffer? Use ref count?
 
 
-// for multithreaded batch building:
-typedef enum {
-	READY_TO_FORMAT,
-	READY_TO_BUILD,
-	BUILDING, BUILDING_IMM, // choose one
-	READY_TO_DRAW
-} BatchPhase;
-
-
-Batch* immBeginBatch(GLenum prim_type, unsigned v_ct);
-// use standard immFunctions after this. immEnd will finalize the batch instead
-// of drawing.
-
-
 // We often need a batch with its own data, to be created and discarded together.
 // WithOwn variants reduce number of system allocations.
 
diff --git a/source/blender/gpu/gawain/immediate.c b/source/blender/gpu/gawain/immediate.c
index 90a67df..650bccb 100644
--- a/source/blender/gpu/gawain/immediate.c
+++ b/source/blender/gpu/gawain/immediate.c
@@ -16,6 +16,10 @@
 typedef struct {
 	// TODO: organize this struct by frequency of change (run-time)
 
+#if IMM_BATCH_COMBO
+	Batch* batch;
+#endif
+
 	// current draw call
 	GLubyte* buffer_data;
 	unsigned buffer_offset;
@@ -79,7 +83,7 @@ void immDestroy()
 	assert(imm.primitive == PRIM_NONE); // make sure we're not between a Begin/End pair
 #endif
 
-	clear_VertexFormat(&imm.vertex_format);
+	VertexFormat_clear(&imm.vertex_format);
 	glDeleteVertexArrays(1, &imm.vao_id);
 	glDeleteBuffers(1, &imm.vbo_id);
 	initialized = false;
@@ -87,7 +91,7 @@ void immDestroy()
 
 VertexFormat* immVertexFormat()
 	{
-	clear_VertexFormat(&imm.vertex_format);
+	VertexFormat_clear(&imm.vertex_format);
 	return &imm.vertex_format;
 	}
 
@@ -98,7 +102,7 @@ void immBindProgram(GLuint program)
 #endif
 
 	if (!imm.vertex_format.packed)
-		pack(&imm.vertex_format);
+		VertexFormat_pack(&imm.vertex_format);
 
 	glUseProgram(program);
 	get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, program);
@@ -151,8 +155,6 @@ void immBegin(GLenum primitive, unsigned vertex_ct)
 
 	imm.primitive = primitive;
 	imm.vertex_ct = vertex_ct;
-	imm.vertex_idx = 0;
-	imm.attrib_value_bits = 0;
 
 	// how many bytes do we need for this draw call?
 	const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_ct);
@@ -206,40 +208,43 @@ void immBeginAtMost(GLenum primitive, unsigned vertex_ct)
 	immBegin(primitive, vertex_ct);
 	}
 
-void immEnd()
+#if IMM_BATCH_COMBO
+
+Batch* immBeginBatch(GLenum prim_type, unsigned vertex_ct)
 	{
 #if TRUST_NO_ONE
-	assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+	assert(initialized);
+	assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun
+	assert(vertex_count_makes_sense_for_primitive(vertex_ct, prim_type));
 #endif
 
-	unsigned buffer_bytes_used;
-	if (imm.strict_vertex_ct)
-		{
-#if TRUST_NO_ONE
-		assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined
-#endif
-		buffer_bytes_used = imm.buffer_bytes_mapped;
-		}
-	else
-		{
-#if TRUST_NO_ONE
-		assert(imm.vertex_idx <= imm.vertex_ct);
-		assert(vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.primitive));
-#endif
-		// printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct);
-		imm.vertex_ct = imm.vertex_idx;
-		buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct);
-		// unused buffer bytes are available to the next immBegin
-		// printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped);
-		}
+	imm.primitive = prim_type;
+	imm.vertex_ct = vertex_ct;
 
-#if APPLE_LEGACY
-	// tell OpenGL what range was modified so it doesn't copy the whole buffer
-	glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used);
-//	printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
-#endif
-	glUnmapBuffer(GL_ARRAY_BUFFER);
+	VertexBuffer* verts = VertexBuffer_create_with_format(&imm.vertex_format);
+	VertexBuffer_allocate_data(verts, vertex_ct);
+
+	imm.buffer_bytes_mapped = VertexBuffer_size(verts);
+	imm.vertex_data = verts->data;
+
+	imm.batch = Batch_create(prim_type, verts, NULL);
+	imm.batch->phase = BUILDING;
 
+	Batch_set_program(imm.batch, imm.bound_program);
+
+	return imm.batch;
+	}
+
+Batch* immBeginBatchAtMost(GLenum prim_type, unsigned vertex_ct)
+	{
+	imm.strict_vertex_ct = false;
+	return immBeginBatch(prim_type, vertex_ct);
+	}
+
+#endif // IMM_BATCH_COMBO
+
+static void immDrawSetup()
+	{
 	// set up VAO -- can be done during Begin or End really
 	glBindVertexArray(imm.vao_id);
 
@@ -292,21 +297,78 @@ void immEnd()
 				glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
 			}
 		}
+	}
 
-	glDrawArrays(imm.primitive, 0, imm.vertex_ct);
+void immEnd()
+	{
+#if TRUST_NO_ONE
+	assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
 
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
-	glBindVertexArray(0);
+	unsigned buffer_bytes_used;
+	if (imm.strict_vertex_ct)
+		{
+#if TRUST_NO_ONE
+		assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined
+#endif
+		buffer_bytes_used = imm.buffer_bytes_mapped;
+		}
+	else
+		{
+#if TRUST_NO_ONE
+		assert(imm.vertex_idx <= imm.vertex_ct);
+		assert(vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.primitive));
+#endif
+		// printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct);
+		imm.vertex_ct = imm.vertex_idx;
+		buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct);
+		// unused buffer bytes are available to the next immBegin
+		// printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped);
+		}
+
+#if IMM_BATCH_COMBO
+	if (imm.batch)
+		{
+		if (buffer_bytes_used != imm.buffer_bytes_mapped)
+			{
+			VertexBuffer_resize_data(imm.batch->verts, imm.vertex_ct);
+			// TODO: resize only if vertex count is much smaller
+			}
+
+		imm.batch->phase = READY_TO_DRAW;
+		imm.batch = NULL; // don't free, batch belongs to caller
+		}
+	else
+#endif
+		{
+#if APPLE_LEGACY
+		// tell OpenGL what range was modified so it doesn't copy the whole buffer
+		glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used);
+//		printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
+#endif
+		glUnmapBuffer(GL_ARRAY_BUFFER);
+
+		immDrawSetup();
+
+		glDrawArrays(imm.primitive, 0, imm.vertex_ct);
+
+		glBindBuffer(GL_ARRAY_BUFFER, 0);
+		glBindVertexArray(0);
+
+		// prep for next immBegin
+		imm.buffer_offset += buffer_bytes_used;
+		}
 
 	// prep for next immBegin
-	imm.buffer_offset += buffer_bytes_used;
 	imm.primitive = PRIM_NONE;
 	imm.strict_vertex_ct = true;
+	imm.vertex_idx = 0;
+	imm.attrib_value_bits = 0;
 
 	// further optional cleanup
-	imm.buffer_bytes_mapped = 0;
-	imm.buffer_data = NULL;
-	imm.vertex_data = NULL;
+//	imm.buffer_bytes_mapped = 0;
+//	imm.buffer_data = NULL;
+//	imm.vertex_data = NULL;
 	}
 
 static void setAttribValueBit(unsigned attrib_id)
diff --git a/source/blender/gpu/gawain/immediate.h b/source/blender/gpu/gawain/immediate.h
index 9a01352..1854819 100644
--- a/source/blender/gpu/gawain/immediate.h
+++ b/source/blender/gpu/gawain/immediate.h
@@ -13,6 +13,8 @@
 
 #include "vertex_format.h"
 
+#define IMM_BATCH_COMBO 1
+
 void immInit(void);
 void immDestroy(void);
 
@@ -23,7 +25,16 @@ void immUnbindProgram(void);
 
 void immBegin(GLenum primitive, unsigned vertex_ct); // must supply exactly vertex_ct vertices
 void immBeginAtMost(GLenum primitive, unsigned max_vertex_ct); // can supply fewer vertices
-void immEnd(void);
+void immEnd(void); // finishes and draws
+
+#if IMM_BATCH_COMBO
+#include "gawain/batch.h"
+// immBegin a batch, then use standard immFunctions as usual.
+// immEnd will finalize the batch instead of drawing.
+// Then you can draw it as many times as you like! Partially replaces the need for dis

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list