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:
authorMike Erwin <significant.bit@gmail.com>2016-09-13 09:18:33 +0300
committerMike Erwin <significant.bit@gmail.com>2016-09-13 09:18:33 +0300
commitb6bd2993598712240bd354e4400d057732cda459 (patch)
treeb6ebbad35ddb8513dd430b5c15eefd0cfcb3819f /source/blender/gpu
parent18d49a8283f2490b0751798685770533cc814d29 (diff)
Gawain: reorganize source code
Put Gawain source code in a subfolder to make the boundary between the library and the rest of Blender clear. Changed Gawain’s license from Apache to Mozilla Public License. Has more essence of copyleft — closer to GPL but not as restrictive. Split immediate.c into several files so parts can be reused (adding more files soon…)
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt10
-rw-r--r--source/blender/gpu/GPU_immediate.h126
-rw-r--r--source/blender/gpu/gawain/attrib_binding.c79
-rw-r--r--source/blender/gpu/gawain/attrib_binding.h27
-rw-r--r--source/blender/gpu/gawain/common.h40
-rw-r--r--source/blender/gpu/gawain/immediate.c (renamed from source/blender/gpu/intern/gpu_immediate.c)235
-rw-r--r--source/blender/gpu/gawain/immediate.h57
-rw-r--r--source/blender/gpu/gawain/vertex_format.c150
-rw-r--r--source/blender/gpu/gawain/vertex_format.h47
9 files changed, 446 insertions, 325 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 40710046cc2..33ebb92791c 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -54,13 +54,20 @@ set(SRC
intern/gpu_draw.c
intern/gpu_extensions.c
intern/gpu_framebuffer.c
- intern/gpu_immediate.c
intern/gpu_init_exit.c
intern/gpu_material.c
intern/gpu_select.c
intern/gpu_shader.c
intern/gpu_texture.c
+ gawain/attrib_binding.c
+ gawain/attrib_binding.h
+ gawain/common.h
+ gawain/immediate.c
+ gawain/immediate.h
+ gawain/vertex_format.c
+ gawain/vertex_format.h
+
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
shaders/gpu_shader_fx_dof_frag.glsl
@@ -97,6 +104,7 @@ set(SRC
GPU_select.h
GPU_shader.h
GPU_texture.h
+
intern/gpu_codegen.h
intern/gpu_private.h
)
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
index ffd0a6d5afc..8b882751aca 100644
--- a/source/blender/gpu/GPU_immediate.h
+++ b/source/blender/gpu/GPU_immediate.h
@@ -1,99 +1,33 @@
-
-// Gawain immediate mode work-alike, take 2
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 Mike Erwin
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Immediate mode rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
#pragma once
-#include "GPU_glew.h"
-#include <stdbool.h>
-
-#define PER_THREAD
-// #define PER_THREAD __thread
-// MSVC uses __declspec(thread) for C code
-
-#define MAX_VERTEX_ATTRIBS 16
-
-#define TRUST_NO_ONE 1
-
-typedef enum {
- KEEP_FLOAT,
- KEEP_INT,
- 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;
-
-typedef struct {
- GLenum comp_type;
- unsigned comp_ct; // 1 to 4
- unsigned sz; // size in bytes, 1 to 16
- unsigned offset; // from beginning of vertex, in bytes
- VertexFetchMode fetch_mode;
- char* name; // TODO: shared allocation of all names within a VertexFormat
-} Attrib;
-
-typedef struct {
- unsigned attrib_ct; // 0 to 16 (MAX_VERTEX_ATTRIBS)
- unsigned stride; // stride in bytes, 1 to 256
- bool packed;
- Attrib attribs[MAX_VERTEX_ATTRIBS]; // TODO: variable-size attribs array
-} VertexFormat;
-
-void clear_VertexFormat(VertexFormat*);
-unsigned add_attrib(VertexFormat*, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode);
-void pack(VertexFormat*);
-// unsigned attrib_idx(const VertexFormat*, const char* name);
-void bind_attrib_locations(const VertexFormat*, GLuint program);
-
-// --- immediate mode work-alike --------------------------------
-
-void immInit(void);
-void immDestroy(void);
-
-VertexFormat* immVertexFormat(void); // returns a cleared vertex format, ready for add_attrib
-
-void immBindProgram(GLuint program);
-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 immAttrib1f(unsigned attrib_id, float x);
-void immAttrib2f(unsigned attrib_id, float x, float y);
-void immAttrib3f(unsigned attrib_id, float x, float y, float z);
-void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w);
-
-void immAttrib3fv(unsigned attrib_id, const float data[3]);
-void immAttrib4fv(unsigned attrib_id, const float data[4]);
-
-void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b);
-void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
-
-void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]);
-void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]);
-
-void immEndVertex(void); // and move on to the next vertex
-
-// provide 2D or 3D attribute value and end the current vertex, similar to glVertex:
-void immVertex2f(unsigned attrib_id, float x, float y);
-void immVertex3f(unsigned attrib_id, float x, float y, float z);
-
-void immVertex2fv(unsigned attrib_id, const float data[2]);
-void immVertex3fv(unsigned attrib_id, const float data[3]);
-
-// provide values that don't change for the entire draw call
-void immUniform4f(const char* name, float x, float y, float z, float w);
-
-// these set "uniform vec4 color"
-// TODO: treat as sRGB?
-void immUniformColor3ubv(const unsigned char data[3]);
-void immUniformColor4ubv(const unsigned char data[4]);
+#include "gawain/immediate.h"
diff --git a/source/blender/gpu/gawain/attrib_binding.c b/source/blender/gpu/gawain/attrib_binding.c
new file mode 100644
index 00000000000..902f33a133e
--- /dev/null
+++ b/source/blender/gpu/gawain/attrib_binding.c
@@ -0,0 +1,79 @@
+
+// Gawain vertex attribute binding
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "attrib_binding.h"
+
+void bind_attrib_locations(const VertexFormat* format, GLuint program)
+ {
+#if TRUST_NO_ONE
+ assert(glIsProgram(program));
+#endif
+
+ for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
+ {
+ const Attrib* a = format->attribs + a_idx;
+ glBindAttribLocation(program, a_idx, a->name);
+ }
+ }
+
+void clear_AttribBinding(AttribBinding* binding)
+ {
+ binding->loc_bits = 0;
+ binding->enabled_bits = 0;
+ }
+
+unsigned read_attrib_location(const AttribBinding* binding, unsigned a_idx)
+ {
+#if TRUST_NO_ONE
+ assert(MAX_VERTEX_ATTRIBS == 16);
+ assert(a_idx < MAX_VERTEX_ATTRIBS);
+ assert(binding->enabled_bits & (1 << a_idx));
+#endif
+
+ return (binding->loc_bits >> (4 * a_idx)) & 0xF;
+ }
+
+void write_attrib_location(AttribBinding* binding, unsigned a_idx, unsigned location)
+ {
+#if TRUST_NO_ONE
+ assert(MAX_VERTEX_ATTRIBS == 16);
+ assert(a_idx < MAX_VERTEX_ATTRIBS);
+ assert(location < MAX_VERTEX_ATTRIBS);
+#endif
+
+ const unsigned shift = 4 * a_idx;
+ const uint64_t mask = ((uint64_t)0xF) << shift;
+ // overwrite this attrib's previous location
+ binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift);
+ // mark this attrib as enabled
+ binding->enabled_bits |= 1 << a_idx;
+ }
+
+void get_attrib_locations(const VertexFormat* format, AttribBinding* binding, GLuint program)
+ {
+#if TRUST_NO_ONE
+ assert(glIsProgram(program));
+#endif
+
+ clear_AttribBinding(binding);
+
+ for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
+ {
+ const Attrib* a = format->attribs + a_idx;
+ GLint loc = glGetAttribLocation(program, a->name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ write_attrib_location(binding, a_idx, loc);
+ }
+ }
diff --git a/source/blender/gpu/gawain/attrib_binding.h b/source/blender/gpu/gawain/attrib_binding.h
new file mode 100644
index 00000000000..f22939cf1a0
--- /dev/null
+++ b/source/blender/gpu/gawain/attrib_binding.h
@@ -0,0 +1,27 @@
+
+// Gawain vertex attribute binding
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "vertex_format.h"
+
+typedef struct {
+ uint64_t loc_bits; // store 4 bits for each of the 16 attribs
+ uint16_t enabled_bits; // 1 bit for each attrib
+} AttribBinding;
+
+void clear_AttribBinding(AttribBinding*);
+
+unsigned read_attrib_location(const AttribBinding*, unsigned a_idx);
+void write_attrib_location(AttribBinding*, unsigned a_idx, unsigned location);
+
+void get_attrib_locations(const VertexFormat*, AttribBinding*, GLuint program);
+void bind_attrib_locations(const VertexFormat*, GLuint program);
diff --git a/source/blender/gpu/gawain/common.h b/source/blender/gpu/gawain/common.h
new file mode 100644
index 00000000000..77b953bd84a
--- /dev/null
+++ b/source/blender/gpu/gawain/common.h
@@ -0,0 +1,40 @@
+
+// Gawain common #defines and #includes
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#define TRUST_NO_ONE 1
+
+#include <GL/glew.h>
+#include <stdbool.h>
+
+#if TRUST_NO_ONE
+ #include <assert.h>
+#endif
+
+#define PER_THREAD
+// #define PER_THREAD __thread
+// MSVC uses __declspec(thread) for C code
+
+#define APPLE_LEGACY (defined(__APPLE__) && defined(WITH_GL_PROFILE_COMPAT))
+
+#if APPLE_LEGACY
+ #undef glGenVertexArrays
+ #define glGenVertexArrays glGenVertexArraysAPPLE
+
+ #undef glDeleteVertexArrays
+ #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
+
+ #undef glBindVertexArray
+ #define glBindVertexArray glBindVertexArrayAPPLE
+#endif
+
+#define PRIM_NONE 0xF
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/gawain/immediate.c
index 98568d14482..90a67dff014 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/gawain/immediate.c
@@ -1,238 +1,17 @@
-// Gawain immediate mode work-alike, take 2
+// Gawain immediate mode work-alike
//
// This code is part of the Gawain library, with modifications
// specific to integration with Blender.
//
// Copyright 2016 Mike Erwin
//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-
-#include "GPU_immediate.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#define PACK_DEBUG 0
-
-#if PACK_DEBUG
- #include <stdio.h>
-#endif
-
-#define APPLE_LEGACY (defined(__APPLE__) && defined(WITH_GL_PROFILE_COMPAT))
-
-#if APPLE_LEGACY
- #undef glGenVertexArrays
- #define glGenVertexArrays glGenVertexArraysAPPLE
-
- #undef glDeleteVertexArrays
- #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
-
- #undef glBindVertexArray
- #define glBindVertexArray glBindVertexArrayAPPLE
-#endif
-
-#define PRIM_NONE 0xF
-
-void clear_VertexFormat(VertexFormat* format)
- {
- for (unsigned a = 0; a < format->attrib_ct; ++a)
- free(format->attribs[a].name);
-
-#if TRUST_NO_ONE
- memset(format, 0, sizeof(VertexFormat));
-#else
- format->attrib_ct = 0;
- format->packed = false;
-#endif
- }
-
-static unsigned comp_sz(GLenum type)
- {
-#if TRUST_NO_ONE
- assert(type >= GL_BYTE && type <= GL_FLOAT);
-#endif
-
- const GLubyte sizes[] = {1,1,2,2,4,4,4};
- return sizes[type - GL_BYTE];
- }
-
-static unsigned attrib_sz(const Attrib *a)
- {
- return a->comp_ct * comp_sz(a->comp_type);
- }
-
-static unsigned attrib_align(const Attrib *a)
- {
- unsigned c = comp_sz(a->comp_type);
- if (a->comp_ct == 3 && c <= 2)
- return 4 * c; // AMD HW can't fetch these well, so pad it out (other vendors too?)
- else
- return c; // most fetches are ok if components are naturally aligned
- }
-
-static unsigned vertex_buffer_size(const VertexFormat* format, unsigned vertex_ct)
- {
-#if TRUST_NO_ONE
- assert(format->packed && format->stride > 0);
-#endif
-
- return format->stride * vertex_ct;
- }
-
-unsigned add_attrib(VertexFormat* format, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode fetch_mode)
- {
-#if TRUST_NO_ONE
- assert(format->attrib_ct < MAX_VERTEX_ATTRIBS); // there's room for more
- assert(!format->packed); // packed means frozen/locked
-#endif
-
- const unsigned attrib_id = format->attrib_ct++;
- Attrib* attrib = format->attribs + attrib_id;
-
- attrib->name = strdup(name);
- attrib->comp_type = comp_type;
- attrib->comp_ct = comp_ct;
- attrib->sz = attrib_sz(attrib);
- attrib->offset = 0; // offsets & stride are calculated later (during pack)
- attrib->fetch_mode = fetch_mode;
-
- return attrib_id;
- }
-
-static unsigned padding(unsigned offset, unsigned alignment)
- {
- const unsigned mod = offset % alignment;
- return (mod == 0) ? 0 : (alignment - mod);
- }
-
-#if PACK_DEBUG
-static void show_pack(unsigned a_idx, unsigned sz, unsigned pad)
- {
- const char c = 'A' + a_idx;
- for (unsigned i = 0; i < pad; ++i)
- putchar('-');
- for (unsigned i = 0; i < sz; ++i)
- putchar(c);
- }
-#endif
-
-void pack(VertexFormat* format)
- {
- // for now, attributes are packed in the order they were added,
- // making sure each attrib is naturally aligned (add padding where necessary)
-
- // later we can implement more efficient packing w/ reordering
-
- Attrib* a0 = format->attribs + 0;
- a0->offset = 0;
- unsigned offset = a0->sz;
-
-#if PACK_DEBUG
- show_pack(0, a0->sz, 0);
-#endif
-
- for (unsigned a_idx = 1; a_idx < format->attrib_ct; ++a_idx)
- {
- Attrib* a = format->attribs + a_idx;
- unsigned mid_padding = padding(offset, attrib_align(a));
- offset += mid_padding;
- a->offset = offset;
- offset += a->sz;
-
-#if PACK_DEBUG
- show_pack(a_idx, a->sz, mid_padding);
-#endif
- }
-
- unsigned end_padding = padding(offset, attrib_align(a0));
-
-#if PACK_DEBUG
- show_pack(0, 0, end_padding);
- putchar('\n');
-#endif
-
- format->stride = offset + end_padding;
- format->packed = true;
- }
-
-void bind_attrib_locations(const VertexFormat* format, GLuint program)
- {
-#if TRUST_NO_ONE
- assert(glIsProgram(program));
-#endif
-
- for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
- {
- const Attrib* a = format->attribs + a_idx;
- glBindAttribLocation(program, a_idx, a->name);
- }
- }
-
-typedef struct {
- uint64_t loc_bits; // store 4 bits for each of the 16 attribs
- uint16_t enabled_bits; // 1 bit for each attrib
-} AttribBinding;
-
-void clear_AttribBinding(AttribBinding* binding)
- {
- binding->loc_bits = 0;
- binding->enabled_bits = 0;
- }
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-unsigned read_attrib_location(const AttribBinding* binding, unsigned a_idx)
- {
-#if TRUST_NO_ONE
- assert(MAX_VERTEX_ATTRIBS == 16);
- assert(a_idx < MAX_VERTEX_ATTRIBS);
- assert(binding->enabled_bits & (1 << a_idx));
-#endif
-
- return (binding->loc_bits >> (4 * a_idx)) & 0xF;
- }
-
-void write_attrib_location(AttribBinding* binding, unsigned a_idx, unsigned location)
- {
-#if TRUST_NO_ONE
- assert(MAX_VERTEX_ATTRIBS == 16);
- assert(a_idx < MAX_VERTEX_ATTRIBS);
- assert(location < MAX_VERTEX_ATTRIBS);
-#endif
-
- const unsigned shift = 4 * a_idx;
- const uint64_t mask = ((uint64_t)0xF) << shift;
- // overwrite this attrib's previous location
- binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift);
- // mark this attrib as enabled
- binding->enabled_bits |= 1 << a_idx;
- }
-
-void get_attrib_locations(const VertexFormat* format, AttribBinding* binding, GLuint program)
- {
-#if TRUST_NO_ONE
- assert(glIsProgram(program));
-#endif
-
- clear_AttribBinding(binding);
-
- for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
- {
- const Attrib* a = format->attribs + a_idx;
- GLint loc = glGetAttribLocation(program, a->name);
-
-#if TRUST_NO_ONE
- assert(loc != -1);
-#endif
-
- write_attrib_location(binding, a_idx, loc);
- }
- }
-
-// --- immediate mode work-alike --------------------------------
+#include "immediate.h"
+#include "attrib_binding.h"
+#include <string.h>
typedef struct {
// TODO: organize this struct by frequency of change (run-time)
@@ -257,7 +36,7 @@ typedef struct {
GLuint bound_program;
AttribBinding attrib_binding;
- uint16_t prev_enabled_attrib_bits;
+ uint16_t prev_enabled_attrib_bits; // <-- only affects this VAO, so we're ok
} Immediate;
// size of internal buffer -- make this adjustable?
diff --git a/source/blender/gpu/gawain/immediate.h b/source/blender/gpu/gawain/immediate.h
new file mode 100644
index 00000000000..9a013528aa8
--- /dev/null
+++ b/source/blender/gpu/gawain/immediate.h
@@ -0,0 +1,57 @@
+
+// Gawain immediate mode work-alike
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "vertex_format.h"
+
+void immInit(void);
+void immDestroy(void);
+
+VertexFormat* immVertexFormat(void); // returns a cleared vertex format, ready for add_attrib
+
+void immBindProgram(GLuint program);
+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 immAttrib1f(unsigned attrib_id, float x);
+void immAttrib2f(unsigned attrib_id, float x, float y);
+void immAttrib3f(unsigned attrib_id, float x, float y, float z);
+void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w);
+
+void immAttrib3fv(unsigned attrib_id, const float data[3]);
+void immAttrib4fv(unsigned attrib_id, const float data[4]);
+
+void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b);
+void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]);
+void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]);
+
+void immEndVertex(void); // and move on to the next vertex
+
+// provide 2D or 3D attribute value and end the current vertex, similar to glVertex:
+void immVertex2f(unsigned attrib_id, float x, float y);
+void immVertex3f(unsigned attrib_id, float x, float y, float z);
+
+void immVertex2fv(unsigned attrib_id, const float data[2]);
+void immVertex3fv(unsigned attrib_id, const float data[3]);
+
+// provide values that don't change for the entire draw call
+void immUniform4f(const char* name, float x, float y, float z, float w);
+
+// these set "uniform vec4 color"
+// TODO: treat as sRGB?
+void immUniformColor3ubv(const unsigned char data[3]);
+void immUniformColor4ubv(const unsigned char data[4]);
diff --git a/source/blender/gpu/gawain/vertex_format.c b/source/blender/gpu/gawain/vertex_format.c
new file mode 100644
index 00000000000..3f373b2feae
--- /dev/null
+++ b/source/blender/gpu/gawain/vertex_format.c
@@ -0,0 +1,150 @@
+
+// Gawain vertex format
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "vertex_format.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define PACK_DEBUG 0
+
+#if PACK_DEBUG
+ #include <stdio.h>
+#endif
+
+void clear_VertexFormat(VertexFormat* format)
+ {
+ for (unsigned a = 0; a < format->attrib_ct; ++a)
+ free(format->attribs[a].name);
+
+#if TRUST_NO_ONE
+ memset(format, 0, sizeof(VertexFormat));
+#else
+ format->attrib_ct = 0;
+ format->packed = false;
+#endif
+ }
+
+static unsigned comp_sz(GLenum type)
+ {
+#if TRUST_NO_ONE
+ assert(type >= GL_BYTE && type <= GL_FLOAT);
+#endif
+
+ const GLubyte sizes[] = {1,1,2,2,4,4,4};
+ return sizes[type - GL_BYTE];
+ }
+
+static unsigned attrib_sz(const Attrib *a)
+ {
+ return a->comp_ct * comp_sz(a->comp_type);
+ }
+
+static unsigned attrib_align(const Attrib *a)
+ {
+ unsigned c = comp_sz(a->comp_type);
+ if (a->comp_ct == 3 && c <= 2)
+ return 4 * c; // AMD HW can't fetch these well, so pad it out (other vendors too?)
+ else
+ return c; // most fetches are ok if components are naturally aligned
+ }
+
+unsigned vertex_buffer_size(const VertexFormat* format, unsigned vertex_ct)
+ {
+#if TRUST_NO_ONE
+ assert(format->packed && format->stride > 0);
+#endif
+
+ return format->stride * vertex_ct;
+ }
+
+unsigned add_attrib(VertexFormat* format, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode fetch_mode)
+ {
+#if TRUST_NO_ONE
+ assert(format->attrib_ct < MAX_VERTEX_ATTRIBS); // there's room for more
+ assert(!format->packed); // packed means frozen/locked
+#endif
+
+ const unsigned attrib_id = format->attrib_ct++;
+ Attrib* attrib = format->attribs + attrib_id;
+
+ attrib->name = strdup(name);
+ attrib->comp_type = comp_type;
+ attrib->comp_ct = comp_ct;
+ attrib->sz = attrib_sz(attrib);
+ attrib->offset = 0; // offsets & stride are calculated later (during pack)
+ attrib->fetch_mode = fetch_mode;
+
+ return attrib_id;
+ }
+
+unsigned padding(unsigned offset, unsigned alignment)
+ {
+ const unsigned mod = offset % alignment;
+ return (mod == 0) ? 0 : (alignment - mod);
+ }
+
+#if PACK_DEBUG
+static void show_pack(unsigned a_idx, unsigned sz, unsigned pad)
+ {
+ const char c = 'A' + a_idx;
+ for (unsigned i = 0; i < pad; ++i)
+ putchar('-');
+ for (unsigned i = 0; i < sz; ++i)
+ putchar(c);
+ }
+#endif
+
+void pack(VertexFormat* format)
+ {
+ // for now, attributes are packed in the order they were added,
+ // making sure each attrib is naturally aligned (add padding where necessary)
+
+ // later we can implement more efficient packing w/ reordering
+ // (keep attrib ID order, adjust their offsets to reorder in buffer)
+
+ // TODO: concatentate name strings into attribs[0].name, point attribs[i] to
+ // offset into the combined string. Free all other name strings. Could save more
+ // space by storing combined string in VertexFormat, with each attrib having an
+ // offset into it. Could also append each name string as it's added... pack()
+ // could alloc just enough to hold the final combo string. And just enough to
+ // hold used attribs, not all 16.
+
+ Attrib* a0 = format->attribs + 0;
+ a0->offset = 0;
+ unsigned offset = a0->sz;
+
+#if PACK_DEBUG
+ show_pack(0, a0->sz, 0);
+#endif
+
+ for (unsigned a_idx = 1; a_idx < format->attrib_ct; ++a_idx)
+ {
+ Attrib* a = format->attribs + a_idx;
+ unsigned mid_padding = padding(offset, attrib_align(a));
+ offset += mid_padding;
+ a->offset = offset;
+ offset += a->sz;
+
+#if PACK_DEBUG
+ show_pack(a_idx, a->sz, mid_padding);
+#endif
+ }
+
+ unsigned end_padding = padding(offset, attrib_align(a0));
+
+#if PACK_DEBUG
+ show_pack(0, 0, end_padding);
+ putchar('\n');
+#endif
+
+ format->stride = offset + end_padding;
+ format->packed = true;
+ }
diff --git a/source/blender/gpu/gawain/vertex_format.h b/source/blender/gpu/gawain/vertex_format.h
new file mode 100644
index 00000000000..7921a47079f
--- /dev/null
+++ b/source/blender/gpu/gawain/vertex_format.h
@@ -0,0 +1,47 @@
+
+// Gawain vertex format
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "common.h"
+
+#define MAX_VERTEX_ATTRIBS 16
+
+typedef enum {
+ KEEP_FLOAT,
+ KEEP_INT,
+ 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;
+
+typedef struct {
+ GLenum comp_type;
+ unsigned comp_ct; // 1 to 4
+ unsigned sz; // size in bytes, 1 to 16
+ unsigned offset; // from beginning of vertex, in bytes
+ VertexFetchMode fetch_mode;
+ char* name; // TODO: shared allocation of all names within a VertexFormat
+} Attrib;
+
+typedef struct {
+ unsigned attrib_ct; // 0 to 16 (MAX_VERTEX_ATTRIBS)
+ unsigned stride; // stride in bytes, 1 to 256
+ bool packed;
+ Attrib attribs[MAX_VERTEX_ATTRIBS]; // TODO: variable-size attribs array
+} VertexFormat;
+
+void clear_VertexFormat(VertexFormat*);
+unsigned add_attrib(VertexFormat*, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode);
+
+// for internal use
+void pack(VertexFormat*);
+unsigned padding(unsigned offset, unsigned alignment);
+unsigned vertex_buffer_size(const VertexFormat*, unsigned vertex_ct);