Commit: e7a32365cf9b43b97b1b1f8cd76e9834c9e4037a
Author: Mike Erwin
Date:   Wed Aug 10 04:45:23 2016 -0400
Branches: blender2.8
https://developer.blender.org/rBe7a32365cf9b43b97b1b1f8cd76e9834c9e4037a

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).

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

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

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

diff --git a/source/blender/gpu/intern/gpu_immediate.c 
b/source/blender/gpu/intern/gpu_immediate.c
index c838581..11e609c 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
                }

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to