[Bf-blender-cvs] [241c90c92d8] blender2.8: DRW/GWN: Bypass glUseProgram.
Clément Foucault
noreply at git.blender.org
Sun Feb 25 17:55:26 CET 2018
Commit: 241c90c92d8dfc4f98daad71fb75390793777a86
Author: Clément Foucault
Date: Sun Feb 25 05:24:06 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB241c90c92d8dfc4f98daad71fb75390793777a86
DRW/GWN: Bypass glUseProgram.
Turns out to be the call that was destroying performance.
I get 18ms->6ms improvement of drawing time with 10 000 unique objects.
And we can still improve upon this!
===================================================================
M intern/gawain/gawain/gwn_batch.h
M intern/gawain/src/gwn_batch.c
M source/blender/draw/intern/draw_manager.c
===================================================================
diff --git a/intern/gawain/gawain/gwn_batch.h b/intern/gawain/gawain/gwn_batch.h
index 4e7f6a15051..4f77ad9d65b 100644
--- a/intern/gawain/gawain/gwn_batch.h
+++ b/intern/gawain/gawain/gwn_batch.h
@@ -95,8 +95,8 @@ int GWN_batch_vertbuf_add_ex(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo);
#define GWN_batch_vertbuf_add(batch, verts) \
GWN_batch_vertbuf_add_ex(batch, verts, false)
+void GWN_batch_program_set_no_use(Gwn_Batch*, GLuint program, const Gwn_ShaderInterface*);
void GWN_batch_program_set(Gwn_Batch*, GLuint program, const Gwn_ShaderInterface*);
-void GWN_batch_program_unset(Gwn_Batch*);
// Entire batch draws with one shader program, but can be redrawn later with another program.
// Vertex shader's inputs must be compatible with the batch's vertex format.
diff --git a/intern/gawain/src/gwn_batch.c b/intern/gawain/src/gwn_batch.c
index 586112ccc9f..208740a4ef8 100644
--- a/intern/gawain/src/gwn_batch.c
+++ b/intern/gawain/src/gwn_batch.c
@@ -187,112 +187,118 @@ int GWN_batch_vertbuf_add_ex(
return -1;
}
-void GWN_batch_program_set(Gwn_Batch* batch, GLuint program, const Gwn_ShaderInterface* shaderface)
+static GLuint batch_vao_get(Gwn_Batch *batch)
{
-#if TRUST_NO_ONE
- assert(glIsProgram(shaderface->program));
- assert(batch->program_in_use == 0);
-#endif
-
- batch->vao_id = 0;
- batch->program = program;
- batch->interface = shaderface;
-
-
// Search through cache
if (batch->is_dynamic_vao_count)
{
- for (int i = 0; i < batch->dynamic_vaos.count && batch->vao_id == 0; ++i)
- if (batch->dynamic_vaos.interfaces[i] == shaderface)
- batch->vao_id = batch->dynamic_vaos.vao_ids[i];
+ for (int i = 0; i < batch->dynamic_vaos.count; ++i)
+ if (batch->dynamic_vaos.interfaces[i] == batch->interface)
+ return batch->dynamic_vaos.vao_ids[i];
}
else
{
- for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN && batch->vao_id == 0; ++i)
- if (batch->static_vaos.interfaces[i] == shaderface)
- batch->vao_id = batch->static_vaos.vao_ids[i];
+ for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
+ if (batch->static_vaos.interfaces[i] == batch->interface)
+ return batch->static_vaos.vao_ids[i];
}
- if (batch->vao_id == 0)
+ // Set context of this batch.
+ // It will be bound to it until gwn_batch_vao_cache_clear is called.
+ // Until then it can only be drawn with this context.
+ if (batch->context == NULL)
{
- if (batch->context == NULL)
- {
- batch->context = GWN_context_active_get();
- gwn_context_add_batch(batch->context, batch);
- }
+ batch->context = GWN_context_active_get();
+ gwn_context_add_batch(batch->context, batch);
+ }
#if TRUST_NO_ONE && 0 // disabled until we use a separate single context for UI.
- else // Make sure you are not trying to draw this batch in another context.
- assert(batch->context == GWN_context_active_get());
+ else // Make sure you are not trying to draw this batch in another context.
+ assert(batch->context == GWN_context_active_get());
#endif
- // Cache miss, time to add a new entry!
- if (!batch->is_dynamic_vao_count)
- {
- int i; // find first unused slot
- for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
- if (batch->static_vaos.vao_ids[i] == 0)
- break;
- if (i < GWN_BATCH_VAO_STATIC_LEN)
- {
- batch->static_vaos.interfaces[i] = shaderface;
- batch->static_vaos.vao_ids[i] = batch->vao_id = GWN_vao_alloc();
- }
- else
+ // Cache miss, time to add a new entry!
+ GLuint new_vao = 0;
+ if (!batch->is_dynamic_vao_count)
+ {
+ int i; // find first unused slot
+ for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
+ if (batch->static_vaos.vao_ids[i] == 0)
+ break;
+
+ if (i < GWN_BATCH_VAO_STATIC_LEN)
+ {
+ batch->static_vaos.interfaces[i] = batch->interface;
+ batch->static_vaos.vao_ids[i] = new_vao = GWN_vao_alloc();
+ }
+ else
+ {
+ // Not enough place switch to dynamic.
+ batch->is_dynamic_vao_count = true;
+ // Erase previous entries, they will be added back if drawn again.
+ for (int j = 0; j < GWN_BATCH_VAO_STATIC_LEN; ++j)
{
- // Not enough place switch to dynamic.
- batch->is_dynamic_vao_count = true;
- // Erase previous entries, they will be added back if drawn again.
- for (int j = 0; j < GWN_BATCH_VAO_STATIC_LEN; ++j)
- {
- GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface*)batch->static_vaos.interfaces[j], batch);
- GWN_vao_free(batch->static_vaos.vao_ids[j], batch->context);
- }
- // Init dynamic arrays and let the branch below set the values.
- batch->dynamic_vaos.count = GWN_BATCH_VAO_DYN_ALLOC_COUNT;
- batch->dynamic_vaos.interfaces = calloc(batch->dynamic_vaos.count, sizeof(Gwn_ShaderInterface*));
- batch->dynamic_vaos.vao_ids = calloc(batch->dynamic_vaos.count, sizeof(GLuint));
+ GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface*)batch->static_vaos.interfaces[j], batch);
+ GWN_vao_free(batch->static_vaos.vao_ids[j], batch->context);
}
+ // Init dynamic arrays and let the branch below set the values.
+ batch->dynamic_vaos.count = GWN_BATCH_VAO_DYN_ALLOC_COUNT;
+ batch->dynamic_vaos.interfaces = calloc(batch->dynamic_vaos.count, sizeof(Gwn_ShaderInterface*));
+ batch->dynamic_vaos.vao_ids = calloc(batch->dynamic_vaos.count, sizeof(GLuint));
}
+ }
+
+ if (batch->is_dynamic_vao_count)
+ {
+ int i; // find first unused slot
+ for (i = 0; i < batch->dynamic_vaos.count; ++i)
+ if (batch->dynamic_vaos.vao_ids[i] == 0)
+ break;
- if (batch->is_dynamic_vao_count)
+ if (i == batch->dynamic_vaos.count)
{
- int i; // find first unused slot
- for (i = 0; i < batch->dynamic_vaos.count; ++i)
- if (batch->dynamic_vaos.vao_ids[i] == 0)
- break;
+ // Not enough place, realloc the array.
+ i = batch->dynamic_vaos.count;
+ batch->dynamic_vaos.count += GWN_BATCH_VAO_DYN_ALLOC_COUNT;
+ batch->dynamic_vaos.interfaces = realloc(batch->dynamic_vaos.interfaces, sizeof(Gwn_ShaderInterface*) * batch->dynamic_vaos.count);
+ batch->dynamic_vaos.vao_ids = realloc(batch->dynamic_vaos.vao_ids, sizeof(GLuint) * batch->dynamic_vaos.count);
+ memset(batch->dynamic_vaos.interfaces + i, 0, sizeof(Gwn_ShaderInterface*) * GWN_BATCH_VAO_DYN_ALLOC_COUNT);
+ memset(batch->dynamic_vaos.vao_ids + i, 0, sizeof(GLuint) * GWN_BATCH_VAO_DYN_ALLOC_COUNT);
+ }
- if (i == batch->dynamic_vaos.count)
- {
- // Not enough place, realloc the array.
- i = batch->dynamic_vaos.count;
- batch->dynamic_vaos.count += GWN_BATCH_VAO_DYN_ALLOC_COUNT;
- batch->dynamic_vaos.interfaces = realloc(batch->dynamic_vaos.interfaces, sizeof(Gwn_ShaderInterface*) * batch->dynamic_vaos.count);
- batch->dynamic_vaos.vao_ids = realloc(batch->dynamic_vaos.vao_ids, sizeof(GLuint) * batch->dynamic_vaos.count);
- memset(batch->dynamic_vaos.interfaces + i, 0, sizeof(Gwn_ShaderInterface*) * GWN_BATCH_VAO_DYN_ALLOC_COUNT);
- memset(batch->dynamic_vaos.vao_ids + i, 0, sizeof(GLuint) * GWN_BATCH_VAO_DYN_ALLOC_COUNT);
- }
+ batch->dynamic_vaos.interfaces[i] = batch->interface;
+ batch->dynamic_vaos.vao_ids[i] = new_vao = GWN_vao_alloc();
+ }
- batch->dynamic_vaos.interfaces[i] = shaderface;
- batch->dynamic_vaos.vao_ids[i] = batch->vao_id = GWN_vao_alloc();
- }
+ GWN_shaderinterface_add_batch_ref((Gwn_ShaderInterface*)batch->interface, batch);
- GWN_shaderinterface_add_batch_ref((Gwn_ShaderInterface*)shaderface, batch);
+#if TRUST_NO_ONE
+ assert(new_vao != 0);
+#endif
- // We just got a fresh VAO we need to initialize it.
- glBindVertexArray(batch->vao_id);
- batch_update_program_bindings(batch, 0);
- glBindVertexArray(0);
- }
+ // We just got a fresh VAO we need to initialize it.
+ glBindVertexArray(new_vao);
+ batch_update_program_bindings(batch, 0);
+ glBindVertexArray(0);
- GWN_batch_program_use_begin(batch); // hack! to make Batch_Uniform* simpler
+ return new_vao;
+ }
+
+void GWN_batch_program_set_no_use(Gwn_Batch* batch, GLuint program, const Gwn_ShaderInterface* shaderface)
+ {
+#if TRUST_NO_ONE
+ assert(glIsProgram(shaderface->program));
+ assert(batch->program_in_use == 0);
+#endif
+
+ batch->interface = shaderface;
+ batch->program = program;
+ batch->vao_id = batch_vao_get(batch);
}
-// fclem : hack !
-// we need this because we don't want to unbind the shader between drawcalls
-// but we still want the correct shader to be bound outside the draw manager
-void GWN_batch_program_unset(Gwn_Batch* batch)
+void GWN_batch_program_set(Gwn_Batch* batch, GLuint program, const Gwn_ShaderInterface* shaderface)
{
- batch->program_in_use = false;
+ GWN_batch_program_set_no_use(batch, program, shaderface);
+ GWN_batch_program_use_begin(batch); // hack! to make Batch_Uniform* simpler
}
void gwn_batch_remove_interface_ref(Gwn_Batch* batch, const Gwn_ShaderInterface* interface)
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 4049108d286..99ea5b259c0 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1781,16 +1781,16 @@ static void draw_geometry_execute_ex(
}
/* step 2 : bind vertex array & draw */
- GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
+ GWN_batch_program_set_no_use(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
+ /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
+ geom->program_in_use = true;
if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) {
GWN_batch_draw_range_ex(geom, start, count, true);
}
else {
GWN_batch_draw_range(geom, start, count);
}
- /* XXX this just tells gawain we are done with the shader.
- * This does not unbind the shader. */
- GWN_batch_program_unset(geom);
+ geom->program_in_use = false; /* XXX hacking gawain */
}
static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
More information about the Bf-blender-cvs
mailing list