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-08-10 11:45:23 +0300
committerMike Erwin <significant.bit@gmail.com>2016-08-10 11:45:23 +0300
commite7a32365cf9b43b97b1b1f8cd76e9834c9e4037a (patch)
tree06b838da9f9765369492c30737a4e4eb55d29867 /source/blender/gpu/intern/gpu_immediate.c
parent5320a0ad9b30a3c939221d2562c6ce686e51e2a2 (diff)
Gawain: map vertex format to shader inputs
glBindAttribLocation does not take effect until the program is re-linked. In other words I was doing it wrong! New code gets attrib locations from program, then remembers the attrib -> location mapping for subsequent draw calls. The program and VertexFormat are not modified (makes threading and reuse easier).
Diffstat (limited to 'source/blender/gpu/intern/gpu_immediate.c')
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c92
1 files changed, 81 insertions, 11 deletions
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index c8385810237..11e609c4ef8 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -14,6 +14,7 @@
#include "GPU_immediate.h"
#include <assert.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#define PACK_DEBUG 0
@@ -165,11 +166,70 @@ void bind_attrib_locations(const VertexFormat* format, GLuint program)
for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
{
- const Attrib* a = &format->attribs[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;
+ }
+
+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 --------------------------------
typedef struct {
@@ -189,6 +249,7 @@ typedef struct {
GLuint vao_id;
GLuint bound_program;
+ AttribBinding attrib_binding;
} Immediate;
// size of internal buffer -- make this adjustable?
@@ -246,7 +307,7 @@ void immBindProgram(GLuint program)
#endif
glUseProgram(program);
- bind_attrib_locations(&immVertexFormat, program);
+ get_attrib_locations(&immVertexFormat, &imm.attrib_binding, program);
imm.bound_program = program;
}
@@ -369,28 +430,37 @@ void immEnd()
const unsigned offset = imm.buffer_offset + a->offset;
const GLvoid* pointer = (const GLubyte*)0 + offset;
-// printf("enabling attrib %u '%s' at offset %u, stride %u\n", a_idx, a->name, offset, stride);
- glEnableVertexAttribArray(a_idx);
+ const unsigned loc = read_attrib_location(&imm.attrib_binding, a_idx);
+
+// printf("enabling attrib %u '%s' at offset %u, stride %u\n", loc, a->name, offset, stride);
+ glEnableVertexAttribArray(loc);
switch (a->fetch_mode)
{
case KEEP_FLOAT:
case CONVERT_INT_TO_FLOAT:
- glVertexAttribPointer(a_idx, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
break;
case NORMALIZE_INT_TO_FLOAT:
- glVertexAttribPointer(a_idx, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
break;
case KEEP_INT:
- glVertexAttribIPointer(a_idx, a->comp_ct, a->comp_type, stride, pointer);
+ glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
}
}
- for (unsigned a_idx = immVertexFormat.attrib_ct; a_idx < MAX_VERTEX_ATTRIBS; ++a_idx)
+ for (unsigned loc = 0; loc < MAX_VERTEX_ATTRIBS; ++loc)
{
-// printf("disabling attrib %u\n", a_idx);
- glDisableVertexAttribArray(a_idx);
- // TODO: compare with previous draw's attrib_ct
+ if (imm.attrib_binding.enabled_bits & (1 << loc))
+ {
+ }
+ else
+ {
+// printf("disabling attrib %u\n", loc);
+ glDisableVertexAttribArray(loc);
+ }
+
+ // TODO: compare with previous draw's attrib binding
// will always need to update pointers, but can reduce Enable/Disable calls
}