diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 89 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_uniformbuffer.c | 2 |
2 files changed, 63 insertions, 28 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 3072eb50429..724d63c2921 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -364,8 +364,8 @@ static struct DRWResourceState { GPUTexture **bound_texs; GPUUniformBuffer **bound_ubos; - int bind_tex_inc; - int bind_ubo_inc; + bool *bound_tex_slots; + bool *bound_ubo_slots; } RST = {NULL}; static struct DRWMatrixOveride { @@ -1833,35 +1833,55 @@ static void draw_geometry(DRWShadingGroup *shgroup, Gwn_Batch *geom, const float draw_geometry_execute(shgroup, geom); } -static void draw_bind_texture(GPUTexture *tex) +static void bind_texture(GPUTexture *tex) { - if (RST.bound_texs[RST.bind_tex_inc] != tex) { - if (RST.bind_tex_inc >= 0) { - if (RST.bound_texs[RST.bind_tex_inc] != NULL) { - GPU_texture_unbind(RST.bound_texs[RST.bind_tex_inc]); + int bind_num = GPU_texture_bound_number(tex); + if (bind_num == -1) { + for (int i = 0; i < GPU_max_textures(); ++i) { + if (RST.bound_tex_slots[i] == false) { + GPU_texture_bind(tex, i); + RST.bound_texs[i] = tex; + RST.bound_tex_slots[i] = true; + return; } - RST.bound_texs[RST.bind_tex_inc] = tex; - GPU_texture_bind(tex, RST.bind_tex_inc); - } - else { - printf("Not enough texture slots! Reduce number of textures used by your shader.\n"); } + + printf("Not enough texture slots! Reduce number of textures used by your shader.\n"); } - RST.bind_tex_inc--; + RST.bound_tex_slots[bind_num] = true; } -static void draw_bind_ubo(GPUUniformBuffer *ubo) +static void bind_ubo(GPUUniformBuffer *ubo) { - if (RST.bound_ubos[RST.bind_ubo_inc] != ubo) { - if (RST.bind_ubo_inc >= 0) { - RST.bound_ubos[RST.bind_ubo_inc] = ubo; - GPU_uniformbuffer_bind(ubo, RST.bind_ubo_inc); - } - else { - printf("Not enough ubo slots!\n"); + int bind_num = GPU_uniformbuffer_bindpoint(ubo); + if (bind_num == -1) { + for (int i = 0; i < GPU_max_ubo_binds(); ++i) { + if (RST.bound_ubo_slots[i] == false) { + GPU_uniformbuffer_bind(ubo, i); + RST.bound_ubos[i] = ubo; + RST.bound_ubo_slots[i] = true; + return; + } } + + /* This is not depending on user input. + * It is our responsability to make sure there enough slots. */ + BLI_assert(0 && "Not enough ubo slots! This should not happen!\n"); + + /* printf so user can report bad behaviour */ + printf("Not enough ubo slots! This should not happen!\n"); } - RST.bind_ubo_inc--; + RST.bound_ubo_slots[bind_num] = true; +} + +static void release_texture_slots(void) +{ + memset(RST.bound_tex_slots, 0x0, sizeof(bool) * GPU_max_textures()); +} + +static void release_ubo_slots(void) +{ + memset(RST.bound_ubo_slots, 0x0, sizeof(bool) * GPU_max_ubo_binds()); } static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) @@ -1869,8 +1889,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) BLI_assert(shgroup->shader); BLI_assert(shgroup->interface); - RST.bind_tex_inc = GPU_max_textures() - 1; /* Reset texture counter. */ - RST.bind_ubo_inc = GPU_max_ubo_binds() - 1; /* Reset UBO counter. */ DRWInterface *interface = shgroup->interface; GPUTexture *tex; GPUUniformBuffer *ubo; @@ -1889,8 +1907,12 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) shgroup_dynamic_batch_from_calls(shgroup); } + release_texture_slots(); + release_ubo_slots(); + DRW_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra); + /* Binding Uniform */ /* Don't check anything, Interface should already contain the least uniform as possible */ for (DRWUniform *uni = interface->uniforms.first; uni; uni = uni->next) { @@ -1919,7 +1941,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) case DRW_UNIFORM_TEXTURE: tex = (GPUTexture *)uni->value; BLI_assert(tex); - draw_bind_texture(tex); + bind_texture(tex); GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); break; case DRW_UNIFORM_BUFFER: @@ -1928,12 +1950,12 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) } tex = *((GPUTexture **)uni->value); BLI_assert(tex); - draw_bind_texture(tex); + bind_texture(tex); GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); break; case DRW_UNIFORM_BLOCK: ubo = (GPUUniformBuffer *)uni->value; - draw_bind_ubo(ubo); + bind_ubo(ubo); GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); break; } @@ -2054,7 +2076,10 @@ static void DRW_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWSha /* Clear Bound Ubos */ for (int i = 0; i < GPU_max_ubo_binds(); i++) { - RST.bound_ubos[i] = NULL; + if (RST.bound_ubos[i] != NULL) { + GPU_uniformbuffer_unbind(RST.bound_ubos[i]); + RST.bound_ubos[i] = NULL; + } } if (DST.shader) { @@ -2527,11 +2552,17 @@ static void DRW_viewport_var_init(void) if (RST.bound_texs == NULL) { RST.bound_texs = MEM_callocN(sizeof(GPUTexture *) * GPU_max_textures(), "Bound GPUTexture refs"); } + if (RST.bound_tex_slots == NULL) { + RST.bound_tex_slots = MEM_callocN(sizeof(GPUUniformBuffer *) * GPU_max_textures(), "Bound Texture Slots"); + } /* Alloc array of ubos reference. */ if (RST.bound_ubos == NULL) { RST.bound_ubos = MEM_callocN(sizeof(GPUUniformBuffer *) * GPU_max_ubo_binds(), "Bound GPUUniformBuffer refs"); } + if (RST.bound_ubo_slots == NULL) { + RST.bound_ubo_slots = MEM_callocN(sizeof(GPUUniformBuffer *) * GPU_max_textures(), "Bound UBO Slots"); + } } void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) @@ -3671,6 +3702,8 @@ void DRW_engines_free(void) MEM_SAFE_FREE(RST.bound_texs); MEM_SAFE_FREE(RST.bound_ubos); + MEM_SAFE_FREE(RST.bound_tex_slots); + MEM_SAFE_FREE(RST.bound_ubo_slots); #ifdef WITH_CLAY_ENGINE BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type); diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c index 652cd38b16b..3defbe1e55f 100644 --- a/source/blender/gpu/intern/gpu_uniformbuffer.c +++ b/source/blender/gpu/intern/gpu_uniformbuffer.c @@ -97,6 +97,7 @@ GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_ { GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBufferStatic), "GPUUniformBufferStatic"); ubo->size = size; + ubo->bindpoint = -1; /* Generate Buffer object */ glGenBuffers(1, &ubo->bindcode); @@ -134,6 +135,7 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou GPUUniformBufferDynamic *ubo = MEM_callocN(sizeof(GPUUniformBufferDynamic), "GPUUniformBufferDynamic"); ubo->buffer.type = GPU_UBO_DYNAMIC; + ubo->buffer.bindpoint = -1; ubo->flag = GPU_UBO_FLAG_DIRTY; /* Generate Buffer object. */ |