[Bf-blender-cvs] [18d49a8] blender2.8: Gawain: add immBeginAtMost

Mike Erwin noreply at git.blender.org
Tue Sep 6 22:56:30 CEST 2016


Commit: 18d49a8283f2490b0751798685770533cc814d29
Author: Mike Erwin
Date:   Tue Sep 6 16:56:08 2016 -0400
Branches: blender2.8
https://developer.blender.org/rB18d49a8283f2490b0751798685770533cc814d29

Gawain: add immBeginAtMost

immBegin requires us to know how many vertices will be drawn. Most times this is fine, but sometimes it can be tricky. Do we make the effort to count everything in one pass, then draw it in a second?

immBeginAtMost makes this simple. Example: I'll draw at most 100 vertices. Supply only 6 verts and it draws only 6.

Any unused space is reclaimed and given to the next immBegin.

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

M	source/blender/gpu/GPU_immediate.h
M	source/blender/gpu/intern/gpu_immediate.c

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

diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
index 6bcfdc7..ffd0a6d 100644
--- a/source/blender/gpu/GPU_immediate.h
+++ b/source/blender/gpu/GPU_immediate.h
@@ -63,7 +63,8 @@ VertexFormat* immVertexFormat(void); // returns a cleared vertex format, ready f
 void immBindProgram(GLuint program);
 void immUnbindProgram(void);
 
-void immBegin(GLenum primitive, unsigned vertex_ct);
+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 immAttrib1f(unsigned attrib_id, float x);
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index 88a1479..98568d1 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -242,6 +242,7 @@ typedef struct {
 	unsigned buffer_offset;
 	unsigned buffer_bytes_mapped;
 	unsigned vertex_ct;
+	bool strict_vertex_ct;
 	GLenum primitive;
 
 	VertexFormat vertex_format;
@@ -285,7 +286,8 @@ void immInit()
 #endif
 
 	imm.primitive = PRIM_NONE;
-	
+	imm.strict_vertex_ct = true;
+
 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	glBindVertexArray(0);
 	initialized = true;
@@ -334,36 +336,38 @@ void immUnbindProgram()
 	imm.bound_program = 0;
 	}
 
-void immBegin(GLenum primitive, unsigned vertex_ct)
+static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, GLenum primitive)
 	{
-#if TRUST_NO_ONE
-	assert(initialized);
-	assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun
-
 	// does vertex_ct make sense for this primitive type?
-	assert(vertex_ct > 0);
+	if (vertex_ct == 0)
+		return false;
+
 	switch (primitive)
 		{
 		case GL_POINTS:
-			break;
+			return true;
 		case GL_LINES:
-			assert(vertex_ct % 2 == 0);
-			break;
+			return vertex_ct % 2 == 0;
 		case GL_LINE_STRIP:
 		case GL_LINE_LOOP:
-			assert(vertex_ct > 2); // otherwise why bother?
-			break;
+			return vertex_ct > 2; // otherwise why bother?
 		case GL_TRIANGLES:
-			assert(vertex_ct % 3 == 0);
-			break;
+			return vertex_ct % 3 == 0;
   #ifdef WITH_GL_PROFILE_COMPAT
 		case GL_QUADS:
-			assert(vertex_ct % 4 == 0);
-			break;
+			return vertex_ct % 4 == 0;
   #endif
 		default:
-			assert(false);
+			return false;
 		}
+	}
+
+void immBegin(GLenum primitive, unsigned vertex_ct)
+	{
+#if TRUST_NO_ONE
+	assert(initialized);
+	assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun
+	assert(vertex_count_makes_sense_for_primitive(vertex_ct, primitive));
 #endif
 
 	imm.primitive = primitive;
@@ -417,17 +421,43 @@ void immBegin(GLenum primitive, unsigned vertex_ct)
 	imm.vertex_data = imm.buffer_data;
 	}
 
+void immBeginAtMost(GLenum primitive, unsigned vertex_ct)
+	{
+	imm.strict_vertex_ct = false;
+	immBegin(primitive, vertex_ct);
+	}
+
 void immEnd()
 	{
 #if TRUST_NO_ONE
 	assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
-	assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined
 #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);
+		}
+
 #if APPLE_LEGACY
 	// tell OpenGL what range was modified so it doesn't copy the whole buffer
-	glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, imm.buffer_bytes_mapped);
-//	printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + imm.buffer_bytes_mapped - 1);
+	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);
 
@@ -490,8 +520,9 @@ void immEnd()
 	glBindVertexArray(0);
 
 	// prep for next immBegin
-	imm.buffer_offset += imm.buffer_bytes_mapped;
+	imm.buffer_offset += buffer_bytes_used;
 	imm.primitive = PRIM_NONE;
+	imm.strict_vertex_ct = true;
 
 	// further optional cleanup
 	imm.buffer_bytes_mapped = 0;




More information about the Bf-blender-cvs mailing list