Uniform Buffer Objects: More complete padding solution

Move floats around when needed to accomodate vec3 arrays efficiently.

With this we use slightly less memory when possible. Basically vec3s are not
treated as vec4 unless we have no float to use for padding).

Reviewers: fclem, sergey

Differential Revision: https://developer.blender.org/D2800
This commit is contained in:
Dalai Felinto 2017-08-18 16:42:58 +02:00
parent 659be38760
commit 2dad2aa9b7
1 changed files with 51 additions and 1 deletions

View File

@ -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