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:
parent
659be38760
commit
2dad2aa9b7
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue