DRW: Use name buffer to request uniform location before drawing.
This is in order to avoid GL call during the "cache creation" phase and support multithreading.
This commit is contained in:
@@ -103,6 +103,17 @@ extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */
|
||||
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
|
||||
{
|
||||
memset(dst, 0x0, offsetof(DRWManager, gl_context));
|
||||
|
||||
/* Maybe not the best place for this. */
|
||||
if (!DST.uniform_names.buffer) {
|
||||
DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer");
|
||||
DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
|
||||
}
|
||||
else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) {
|
||||
DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME);
|
||||
DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
|
||||
}
|
||||
DST.uniform_names.buffer_ofs = 0;
|
||||
}
|
||||
|
||||
/* This function is used to reset draw manager to a state
|
||||
@@ -2616,6 +2627,8 @@ void DRW_engines_free(void)
|
||||
MEM_SAFE_FREE(DST.RST.bound_ubos);
|
||||
MEM_SAFE_FREE(DST.RST.bound_ubo_slots);
|
||||
|
||||
MEM_SAFE_FREE(DST.uniform_names.buffer);
|
||||
|
||||
DRW_opengl_context_disable();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
|
||||
#define USE_GPU_SELECT
|
||||
|
||||
#define DRW_DEBUG_USE_UNIFORM_NAME 0
|
||||
#define DRW_UNIFORM_BUFFER_NAME 64
|
||||
#define DRW_UNIFORM_BUFFER_NAME_INC 1024
|
||||
|
||||
/* ------------ Profiling --------------- */
|
||||
|
||||
#define USE_PROFILE
|
||||
@@ -186,8 +190,6 @@ typedef enum {
|
||||
DRW_UNIFORM_BLOCK_PERSIST
|
||||
} DRWUniformType;
|
||||
|
||||
#define MAX_UNIFORM_NAME 13
|
||||
|
||||
struct DRWUniform {
|
||||
DRWUniform *next; /* single-linked list */
|
||||
union {
|
||||
@@ -197,13 +199,11 @@ struct DRWUniform {
|
||||
float fvalue;
|
||||
int ivalue;
|
||||
};
|
||||
int name_ofs; /* name offset in name buffer. */
|
||||
int location;
|
||||
char type; /* DRWUniformType */
|
||||
char length; /* cannot be more than 16 */
|
||||
char arraysize; /* cannot be more than 16 too */
|
||||
#ifndef NDEBUG
|
||||
char name[MAX_UNIFORM_NAME];
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -402,6 +402,12 @@ typedef struct DRWManager {
|
||||
DRWDebugLine *lines;
|
||||
DRWDebugSphere *spheres;
|
||||
} debug;
|
||||
|
||||
struct {
|
||||
char *buffer;
|
||||
uint buffer_len;
|
||||
uint buffer_ofs;
|
||||
} uniform_names;
|
||||
} DRWManager;
|
||||
|
||||
extern DRWManager DST; /* TODO : get rid of this and allow multithreaded rendering */
|
||||
|
||||
@@ -134,10 +134,24 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, const char *name,
|
||||
|
||||
drw_shgroup_uniform_create_ex(shgroup, location, type, value, length, arraysize);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Save uniform name to easily identify it when debugging. */
|
||||
BLI_strncpy(shgroup->uniforms->name, name, MAX_UNIFORM_NAME);
|
||||
#endif
|
||||
/* If location is -2, the uniform has not yet been queried.
|
||||
* We save the name for query just before drawing. */
|
||||
if (location == -2 || DRW_DEBUG_USE_UNIFORM_NAME) {
|
||||
int ofs = DST.uniform_names.buffer_ofs;
|
||||
int max_len = DST.uniform_names.buffer_len - ofs;
|
||||
size_t len = strlen(name) + 1;
|
||||
|
||||
if (len >= max_len) {
|
||||
DST.uniform_names.buffer_len += DRW_UNIFORM_BUFFER_NAME_INC;
|
||||
DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DST.uniform_names.buffer_len);
|
||||
}
|
||||
|
||||
char *dst = DST.uniform_names.buffer + ofs;
|
||||
memcpy(dst, name, len); /* Copies NULL terminator. */
|
||||
|
||||
DST.uniform_names.buffer_ofs += len;
|
||||
shgroup->uniforms->name_ofs = ofs;
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
|
||||
|
||||
@@ -1050,6 +1050,12 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
||||
|
||||
/* Binding Uniform */
|
||||
for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
|
||||
if (uni->location == -2) {
|
||||
uni->location = GPU_shader_get_uniform_ensure(shgroup->shader, DST.uniform_names.buffer + uni->name_ofs);
|
||||
if (uni->location == -1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch (uni->type) {
|
||||
case DRW_UNIFORM_SHORT_TO_INT:
|
||||
val = (int)*((short *)uni->pvalue);
|
||||
|
||||
@@ -563,18 +563,7 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
|
||||
{
|
||||
BLI_assert(shader && shader->program);
|
||||
const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name);
|
||||
#if 1 /* Remove this when we have transitionned all uniforms. */
|
||||
if (uniform == NULL) {
|
||||
# ifndef NDEBUG
|
||||
printf("Uniform \"%s\" needs to be added to shader interface after shader creation.\n", name);
|
||||
# endif
|
||||
/* Fallback to avoid issues. */
|
||||
return GPU_shader_get_uniform_ensure(shader, name);
|
||||
}
|
||||
#else
|
||||
BLI_assert(uniform);
|
||||
#endif
|
||||
return uniform->location;
|
||||
return uniform ? uniform->location : -2;
|
||||
}
|
||||
|
||||
int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name)
|
||||
|
||||
Reference in New Issue
Block a user