[Bf-blender-cvs] [358732c] GPU_data_request: OpenGL batched geometry API (experimental)

Mike Erwin noreply at git.blender.org
Fri Mar 20 23:35:34 CET 2015


Commit: 358732c463d041bc1b83c7c07cf2d2cab605d224
Author: Mike Erwin
Date:   Fri Mar 20 18:16:56 2015 -0400
Branches: GPU_data_request
https://developer.blender.org/rB358732c463d041bc1b83c7c07cf2d2cab605d224

OpenGL batched geometry API (experimental)

Clean slate design, with some overlap with existing Blender APIs. Using
GPUx_ prefix to avoid confusion with current GPU_ files.

- specify vertex attribs
- buffer in main memory & VRAM
- build element lists of points, lines, triangles
- draw these --^
- state tracking (fairly basic)
- lots of error & bounds checking!!! can turn this off

The idea is to handle things like VBOs, VAOs, other useful extensions
automatically so users of this API don't have to work hard to get it
right every time. This also lets us turn things on/off in one place for
debugging & perf measurements.

- - - -
Checking this code in now to give it a home & test on multiple systems.
It’s not being used yet and will probably evolve quite a bit as our
needs become clearer.

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

A	source/blender/gpu/GPUx_draw.h
A	source/blender/gpu/GPUx_element.h
A	source/blender/gpu/GPUx_state.h
A	source/blender/gpu/GPUx_vbo.h
A	source/blender/gpu/intern/GPUx_element_private.h
A	source/blender/gpu/intern/gpux_draw.c
A	source/blender/gpu/intern/gpux_element.c
A	source/blender/gpu/intern/gpux_state.c
A	source/blender/gpu/intern/gpux_vbo.c

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

diff --git a/source/blender/gpu/GPUx_draw.h b/source/blender/gpu/GPUx_draw.h
new file mode 100644
index 0000000..219159c
--- /dev/null
+++ b/source/blender/gpu/GPUx_draw.h
@@ -0,0 +1,19 @@
+#ifndef BLENDER_GL_DRAW_PRIMITIVES
+#define BLENDER_GL_DRAW_PRIMITIVES
+
+// Stateless draw functions for lists of primitives.
+// Mike Erwin, Dec 2014
+
+#include "GPUx_state.h"
+#include "GPUx_vbo.h"
+#include "GPUx_element.h"
+
+// pass ElementList = NULL to draw all vertices from VertexBuffer in order
+void draw_points(const CommonDrawState*, const PointDrawState*, const VertexBuffer*, const ElementList*);
+void draw_lines(const CommonDrawState*, const LineDrawState*, const VertexBuffer*, const ElementList*);
+void draw_triangles(const CommonDrawState*, const PolygonDrawState*, const VertexBuffer*, const ElementList*);
+
+// generic version uses ElementList's primitive type
+void draw_primitives(const CommonDrawState*, const void* primitive_state, const VertexBuffer*, const ElementList*);
+
+#endif // BLENDER_GL_DRAW_PRIMITIVES
diff --git a/source/blender/gpu/GPUx_element.h b/source/blender/gpu/GPUx_element.h
new file mode 100644
index 0000000..e5bc407
--- /dev/null
+++ b/source/blender/gpu/GPUx_element.h
@@ -0,0 +1,24 @@
+#ifndef BLENDER_GL_ELEMENT_LIST
+#define BLENDER_GL_ELEMENT_LIST
+
+// Element lists specify which vertices to use when drawing point,
+// line, or triangle primiitives. They don't care how the per-vertex
+// data (attributes) are laid out, only *which* vertices are used.
+// Mike Erwin, Dec 2014
+
+#include "GPU_glew.h"
+// ^-- for GLenum (and if you're including this file, you're probably calling OpenGL anyway)
+
+struct ElementList; // forward declaration
+typedef struct ElementList ElementList;
+
+ElementList* create_element_list(GLenum prim_type, unsigned prim_ct, unsigned max_index);
+void discard_element_list(ElementList*);
+
+void set_point_vertex(ElementList*, unsigned prim_idx, unsigned v1);
+void set_line_vertices(ElementList*, unsigned prim_idx, unsigned v1, unsigned v2);
+void set_triangle_vertices(ElementList*, unsigned prim_idx, unsigned v1, unsigned v2, unsigned v3);
+
+void optimize(ElementList*); // optionally call this after setting all vertex indices
+
+#endif // BLENDER_GL_ELEMENT_LIST
diff --git a/source/blender/gpu/GPUx_state.h b/source/blender/gpu/GPUx_state.h
new file mode 100644
index 0000000..7090310
--- /dev/null
+++ b/source/blender/gpu/GPUx_state.h
@@ -0,0 +1,49 @@
+#ifndef BLENDER_GL_STATE
+#define BLENDER_GL_STATE
+
+// Two goals:
+// -- batch draws by state so we don't have to "switch gears" as often
+// -- track current draw state internally so we don't have to bother the GL as often
+// Mike Erwin, Dec 2014
+
+#include <stdbool.h>
+
+typedef struct
+	{
+	bool blend; // + src & dst of glBlendFunc
+	bool depth_test;
+	bool depth_write;
+	bool lighting;
+	} CommonDrawState;
+
+typedef struct
+	{
+	bool smooth; // implies blend / transparency. Disable depth write! (p179 of AGPUO)
+	float size;
+	} PointDrawState;
+
+typedef struct
+	{
+	bool smooth; // implies blend / transparency. Disable depth write! (p179 of AGPUO)
+	float width;
+	int stipple; // = 0 for don't
+	} LineDrawState;
+
+typedef struct PolygonDrawState
+	{
+	bool draw_front;
+	bool draw_back;
+	int material_id;
+	int stipple; // = 0 for don't
+	} PolygonDrawState;
+
+#define MATERIAL_NONE -1
+
+void init_draw_state();
+
+void set_common_state(const CommonDrawState*);
+void set_point_state(const PointDrawState*);
+void set_line_state(const LineDrawState*);
+void set_polygon_state(const PolygonDrawState*);
+
+#endif // BLENDER_GL_STATE
diff --git a/source/blender/gpu/GPUx_vbo.h b/source/blender/gpu/GPUx_vbo.h
new file mode 100644
index 0000000..6ce1da2
--- /dev/null
+++ b/source/blender/gpu/GPUx_vbo.h
@@ -0,0 +1,65 @@
+#ifndef BLENDER_GL_VERTEX_BUFFER
+#define BLENDER_GL_VERTEX_BUFFER
+
+// vertex buffer support
+// Mike Erwin, Nov 2014
+
+#include "GPU_glew.h"
+// ^-- for GLenum (and if you're including this file, you're probably calling OpenGL anyway)
+#include <stdbool.h>
+
+#define TRUST_NO_ONE true
+#define PRINT false
+
+struct VertexBuffer; // forward declaration
+typedef struct VertexBuffer VertexBuffer;
+
+typedef enum
+	{
+	KEEP_FLOAT,
+	KEEP_INT, // requires EXT_gpu_shader4
+	NORMALIZE_INT_TO_FLOAT, // 127 (ubyte) -> 0.5 (and so on for other int types)
+	CONVERT_INT_TO_FLOAT // 127 (any int type) -> 127.0
+	} VertexFetchMode;
+
+VertexBuffer* vertex_buffer_create(unsigned attrib_ct, unsigned vertex_ct);
+void vertex_buffer_discard(VertexBuffer*);
+
+// how many vertices?
+unsigned vertex_ct(const VertexBuffer*);
+
+#if PRINT
+void attrib_print(const VertexBuffer*, unsigned attrib_num);
+#endif // PRINT
+
+void specify_attrib(VertexBuffer*, unsigned attrib_num, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode);
+
+// set value of single attribute of single vertex
+// incoming data must be of same type & size for this attribute
+void set_attrib(VertexBuffer*, unsigned attrib_num, unsigned vertex_num, const void* data);
+// convenience function for specific type and size
+// can add more like this if it's useful
+void set_attrib_3f(VertexBuffer*, unsigned attrib_num, unsigned vertex_num, float x, float y, float z);
+
+// bulk attribute filling routines (all vertices)
+// incoming data must be of same type & size for this attribute
+// must be tightly packed in memory, no padding
+void fill_attrib(VertexBuffer*, unsigned attrib_num, const void* data);
+// this version can have padding between attributes
+void fill_attrib_stride(VertexBuffer*, unsigned attrib_num, const void* data, unsigned stride);
+
+// call before drawing to make this vertex buffer part of current OpenGL state
+void vertex_buffer_use(VertexBuffer*);
+// call after drawing
+void vertex_buffer_done_using(const VertexBuffer*);
+
+// alternative to vertex_buffer_use:
+// prime does all the setup (create VBOs, send to GPU, etc.) so use_primed doesn't have to
+void vertex_buffer_prime(VertexBuffer*);
+void vertex_buffer_use_primed(const VertexBuffer*);
+// prime, use_primed, done_using, use_primed, done_using ...
+// use, done_using, use, done_using ... (first use auto-primes)
+// 'use' modifies VAO and VBO IDs on first run, so is non-const (no 'mutable' in C)
+// this was primary motivation for splitting into two functions
+
+#endif // BLENDER_GL_VERTEX_BUFFER
diff --git a/source/blender/gpu/intern/GPUx_element_private.h b/source/blender/gpu/intern/GPUx_element_private.h
new file mode 100644
index 0000000..712618d
--- /dev/null
+++ b/source/blender/gpu/intern/GPUx_element_private.h
@@ -0,0 +1,27 @@
+#ifndef BLENDER_GL_ELEMENT_LIST_PRIVATE
+#define BLENDER_GL_ELEMENT_LIST_PRIVATE
+
+#include "GPUx_element.h"
+
+// track min & max observed index (for glDrawRangeElements)
+#define TRACK_INDEX_RANGE true
+
+struct ElementList
+	{
+	unsigned prim_ct; 
+	GLenum prim_type; // GL_POINTS, GL_LINES, GL_TRIANGLES
+	GLenum index_type; // GL_UNSIGNED_BYTE, _SHORT (ES), also _INT (full GL)
+	unsigned max_allowed_index;
+#if TRACK_INDEX_RANGE
+	unsigned min_observed_index;
+	unsigned max_observed_index;
+#endif // TRACK_INDEX_RANGE
+	void* indices; // array of index_type
+	};
+
+#if TRACK_INDEX_RANGE
+unsigned min_index(const ElementList*);
+unsigned max_index(const ElementList*);
+#endif // TRACK_INDEX_RANGE
+
+#endif // BLENDER_GL_ELEMENT_LIST_PRIVATE
diff --git a/source/blender/gpu/intern/gpux_draw.c b/source/blender/gpu/intern/gpux_draw.c
new file mode 100644
index 0000000..eb530c7
--- /dev/null
+++ b/source/blender/gpu/intern/gpux_draw.c
@@ -0,0 +1,131 @@
+
+#include "GPUx_draw.h"
+#include "GPUx_element_private.h"
+
+#if TRUST_NO_ONE
+  #include <assert.h>
+#endif // TRUST_NO_ONE
+
+#define REALLY_DRAW true
+
+// generally useful utility function
+static unsigned chop_to_multiple(unsigned x, unsigned m)
+	{
+	return x - x % m;
+	}
+
+void draw_points(const CommonDrawState* common_state, const PointDrawState* point_state, const VertexBuffer* vbo, const ElementList* el)
+	{
+	set_common_state(common_state);
+	set_point_state(point_state);
+
+#if TRUST_NO_ONE
+	if (el)
+		{
+		assert(el->prim_type == GL_POINTS);
+		assert(el->max_allowed_index < vertex_ct(vbo));
+		}
+#endif // TRUST_NO_ONE
+
+#if REALLY_DRAW
+	vertex_buffer_use_primed(vbo);
+
+	if (el)
+		glDrawRangeElements(GL_POINTS, min_index(el), max_index(el), el->prim_ct, el->index_type, el->indices);
+	else
+		glDrawArrays(GL_POINTS, 0, vertex_ct(vbo));
+
+	vertex_buffer_done_using(vbo);
+#endif // REALLY_DRAW
+	}
+
+void draw_lines(const CommonDrawState* common_state, const LineDrawState* line_state, const VertexBuffer* vbo, const ElementList* el)
+	{
+	set_common_state(common_state);
+	set_line_state(line_state);
+
+#if TRUST_NO_ONE
+	if (el)
+		{
+		assert(el->prim_type == GL_LINES);
+		assert(el->max_allowed_index < vertex_ct(vbo));
+		}
+#endif // TRUST_NO_ONE
+
+#if REALLY_DRAW
+	vertex_buffer_use_primed(vbo);
+
+	if (el)
+		glDrawRangeElements(GL_LINES, min_index(el), max_index(el), el->prim_ct * 2, el->index_type, el->indices);
+	else
+		glDrawArrays(GL_LINES, 0, chop_to_multiple(vertex_ct(vbo), 2));
+
+	vertex_buffer_done_using(vbo);
+#endif // REALLY_DRAW
+	}
+
+void draw_triangles(const CommonDrawState* common_state, const PolygonDrawState* polygon_state, const VertexBuffer* vbo, const ElementList* el)
+	{
+	set_common_state(common_state);
+	set_polygon_state(polygon_state);
+
+#if TRUST_NO_ONE
+	if (el)
+		{
+		assert(el->prim_type == GL_TRIANGLES);
+		assert(el->max_allowed_index < vertex_ct(vbo));
+		}
+#endif // TRUST_NO_ONE
+
+#if REALLY_DRAW
+	vertex_buffer_use_primed(vbo);
+
+	if (el)
+		glDrawRangeElements(GL_TRIANGLES, min_index(el), max_index(el), el->prim_ct * 3, el->index_type, el->indices);
+	else
+		glDrawArrays(GL_TRIANGLES, 0, chop_to_multiple(vertex_ct(vbo), 3));
+
+	vertex_buffer_done_using(vbo);
+#endif // REALLY_DRAW
+	}
+
+void draw_primitives(const CommonDrawState* common_state, const void* primitive_state, const VertexBuffer* vbo, const ElementList* el)
+	{
+#if TRUST_NO_ONE
+	assert(el->max_allowed_index < vertex_ct(vbo));
+#endif // TRUST_NO_ONE
+
+	int vert_per_prim = 0;
+
+	switch (el->prim_type)
+		{
+		case GL_POINTS:
+			set_point_state((const PointDrawState*)primi

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list