diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_uniformbuffer.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_uniformbuffer.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c index affff54d407..46cf9d19a47 100644 --- a/source/blender/gpu/intern/gpu_uniformbuffer.c +++ b/source/blender/gpu/intern/gpu_uniformbuffer.c @@ -82,6 +82,10 @@ static void gpu_uniformbuffer_inputs_sort(struct ListBase *inputs); static GPUUniformBufferDynamicItem *gpu_uniformbuffer_populate( GPUUniformBufferDynamic *ubo, const GPUType gputype, float *num); +/* Only support up to this type, if you want to extend it, make sure the + * padding logic is correct for the new types. */ +#define MAX_UBO_GPU_TYPE GPU_VEC4 + static void gpu_uniformbuffer_initialize(GPUUniformBuffer *ubo, const void *data) { glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); @@ -263,7 +267,51 @@ static int inputs_cmp(const void *a, const void *b) */ static void gpu_uniformbuffer_inputs_sort(ListBase *inputs) { + /* Order them as vec4, vec3, vec2, float. */ BLI_listbase_sort(inputs, inputs_cmp); + + /* Creates a lookup table for the different types; */ + LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL}; + GPUType cur_type = MAX_UBO_GPU_TYPE + 1; + + for (LinkData *link = inputs->first; link; link = link->next) { + GPUInput *input = link->data; + if (input->type == cur_type) { + continue; + } + else { + inputs_lookup[input->type] = link; + cur_type = input->type; + } + } + + /* If there is no GPU_VEC3 there is no need for alignment. */ + if (inputs_lookup[GPU_VEC3] == NULL) { + return; + } + + LinkData *link = inputs_lookup[GPU_VEC3]; + while (link != NULL && ((GPUInput *)link->data)->type == GPU_VEC3) { + LinkData *link_next = link->next; + + /* If GPU_VEC3 is followed by nothing or a GPU_FLOAT, no need for aligment. */ + if ((link_next == NULL) || + ((GPUInput *)link_next->data)->type == GPU_FLOAT) + { + break; + } + + /* If there is a float, move it next to current vec3. */ + if (inputs_lookup[GPU_FLOAT] != NULL) { + LinkData *float_input = inputs_lookup[GPU_FLOAT]; + inputs_lookup[GPU_FLOAT] = float_input->next; + + BLI_remlink(inputs, float_input); + BLI_insertlinkafter(inputs, link, float_input); + } + + link = link_next; + } } /** @@ -273,7 +321,7 @@ static void gpu_uniformbuffer_inputs_sort(ListBase *inputs) static GPUUniformBufferDynamicItem *gpu_uniformbuffer_populate( GPUUniformBufferDynamic *ubo, const GPUType gputype, float *num) { - BLI_assert(gputype <= GPU_VEC4); + BLI_assert(gputype <= MAX_UBO_GPU_TYPE); GPUUniformBufferDynamicItem *item = MEM_callocN(sizeof(GPUUniformBufferDynamicItem), __func__); item->gputype = gputype; @@ -318,3 +366,5 @@ void GPU_uniformbuffer_tag_dirty(GPUUniformBuffer *ubo_) { GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_; ubo->flag |= GPU_UBO_FLAG_DIRTY; } + +#undef MAX_UBO_GPU_TYPE |