DRW: Refactor: Make use of the new Gawain long attrib support.

This commit is contained in:
2018-02-11 16:15:46 +01:00
parent df86e9cab5
commit 01244df007
4 changed files with 54 additions and 155 deletions

View File

@@ -87,10 +87,7 @@ void GWN_batch_draw(Gwn_Batch*);
// clement : temp stuff
void GWN_batch_draw_stupid(Gwn_Batch*, int v_first, int v_count);
void GWN_batch_draw_stupid_instanced(Gwn_Batch*, unsigned int instance_vbo, int instance_first, int instance_count,
int attrib_nbr, int attrib_stride, int attrib_loc[16], int attrib_size[16]);
void GWN_batch_draw_stupid_instanced_with_batch(Gwn_Batch*, Gwn_Batch*);
void GWN_batch_draw_stupid_instanced(Gwn_Batch*, Gwn_Batch*, int instance_first, int instance_count);

View File

@@ -194,15 +194,15 @@ static void Batch_update_program_bindings(Gwn_Batch* batch, unsigned int v_first
batch->program_dirty = false;
}
static void Batch_update_program_bindings_instancing(Gwn_Batch* batch, Gwn_Batch* batch_instancing, unsigned int v_first)
static void Batch_update_program_bindings_instancing(Gwn_Batch* batch, Gwn_Batch* batch_instancing, unsigned int instance_first)
{
// disable all as a precaution
// why are we not using prev_attrib_enabled_bits?? see immediate.c
for (unsigned a_idx = 0; a_idx < GWN_VERT_ATTR_MAX_LEN; ++a_idx)
glDisableVertexAttribArray(a_idx);
create_bindings(batch, batch->interface, v_first, false);
create_bindings(batch_instancing, batch->interface, v_first, true);
create_bindings(batch, batch->interface, 0, false);
create_bindings(batch_instancing, batch->interface, instance_first, true);
batch->program_dirty = false;
}
@@ -346,9 +346,6 @@ void GWN_batch_draw(Gwn_Batch* batch)
glBindVertexArray(0);
}
// clement : temp stuff
void GWN_batch_draw_stupid(Gwn_Batch* batch, int v_first, int v_count)
{
if (batch->vao_id)
@@ -364,9 +361,8 @@ void GWN_batch_draw_stupid(Gwn_Batch* batch, int v_first, int v_count)
//gpuBindMatrices(batch->program);
// Infer lenght if vertex count is not given
if (v_count == 0) {
if (v_count == 0)
v_count = (batch->elem) ? batch->elem->index_ct : batch->verts[0]->vertex_ct;
}
if (batch->elem)
{
@@ -388,64 +384,7 @@ void GWN_batch_draw_stupid(Gwn_Batch* batch, int v_first, int v_count)
glBindVertexArray(0);
}
// clement : temp stuff
void GWN_batch_draw_stupid_instanced(Gwn_Batch* batch, unsigned int instance_vbo, int instance_first, int instance_count,
int attrib_nbr, int attrib_stride, int attrib_size[16], int attrib_loc[16])
{
if (batch->vao_id)
glBindVertexArray(batch->vao_id);
else
Batch_prime(batch);
if (batch->program_dirty)
Batch_update_program_bindings(batch, 0);
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
int ptr_ofs = instance_first * attrib_stride;
for (int i = 0; i < attrib_nbr; ++i)
{
int size = attrib_size[i];
int loc = attrib_loc[i];
int atr_ofs = 0;
while (size > 0)
{
glEnableVertexAttribArray(loc + atr_ofs);
glVertexAttribPointer(loc + atr_ofs, (size > 4) ? 4 : size, GL_FLOAT, GL_FALSE,
sizeof(float) * attrib_stride, (GLvoid*)(sizeof(float) * ptr_ofs));
glVertexAttribDivisor(loc + atr_ofs, 1);
atr_ofs++;
ptr_ofs += (size > 4) ? 4 : size;
size -= 4;
}
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
// GWN_batch_program_use_begin(batch);
//gpuBindMatrices(batch->program);
if (batch->elem)
{
const Gwn_IndexBuf* el = batch->elem;
#if GWN_TRACK_INDEX_RANGE
glDrawElementsInstancedBaseVertex(batch->gl_prim_type, el->index_ct, el->gl_index_type, 0, instance_count, el->base_index);
#else
glDrawElementsInstanced(batch->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
#endif
}
else
glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_ct, instance_count);
// Reset divisor to prevent messing the next draw
for (unsigned a_idx = 0; a_idx < GWN_VERT_ATTR_MAX_LEN; ++a_idx)
glVertexAttribDivisor(a_idx, 0);
// GWN_batch_program_use_end(batch);
glBindVertexArray(0);
}
void GWN_batch_draw_stupid_instanced_with_batch(Gwn_Batch* batch_instanced, Gwn_Batch* batch_instancing)
void GWN_batch_draw_stupid_instanced(Gwn_Batch* batch_instanced, Gwn_Batch* batch_instancing, int instance_first, int instance_count)
{
if (batch_instanced->vao_id)
glBindVertexArray(batch_instanced->vao_id);
@@ -453,22 +392,25 @@ void GWN_batch_draw_stupid_instanced_with_batch(Gwn_Batch* batch_instanced, Gwn_
Batch_prime(batch_instanced);
if (batch_instanced->program_dirty)
Batch_update_program_bindings_instancing(batch_instanced, batch_instancing, 0);
Batch_update_program_bindings_instancing(batch_instanced, batch_instancing, instance_first);
Gwn_VertBuf* verts = batch_instancing->verts[0];
if (instance_count == 0)
instance_count = verts->vertex_ct;
if (batch_instanced->elem)
{
const Gwn_IndexBuf* el = batch_instanced->elem;
#if GWN_TRACK_INDEX_RANGE
glDrawElementsInstancedBaseVertex(batch_instanced->gl_prim_type, el->index_ct, el->gl_index_type, 0, verts->vertex_ct, el->base_index);
glDrawElementsInstancedBaseVertex(batch_instanced->gl_prim_type, el->index_ct, el->gl_index_type, 0, instance_count, el->base_index);
#else
glDrawElementsInstanced(batch_instanced->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, verts->vertex_ct);
glDrawElementsInstanced(batch_instanced->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
#endif
}
else
glDrawArraysInstanced(batch_instanced->gl_prim_type, 0, batch_instanced->verts[0]->vertex_ct, verts->vertex_ct);
glDrawArraysInstanced(batch_instanced->gl_prim_type, 0, batch_instanced->verts[0]->vertex_ct, instance_count);
glBindVertexArray(0);
}

View File

@@ -190,10 +190,6 @@ struct DRWUniform {
struct DRWInterface {
DRWUniform *uniforms; /* DRWUniform, single-linked list */
int attribs_count;
int attribs_stride;
int attribs_size[16];
int attribs_loc[16];
/* matrices locations */
int model;
int modelinverse;
@@ -213,15 +209,16 @@ struct DRWInterface {
int eye;
int clipplanes;
/* Dynamic batch */
Gwn_Batch *instance_batch; /* contains instances attributes */
GLuint instance_vbo; /* same as instance_batch but generated from DRWCalls */
struct DRWInstanceData *inst_data;
#ifdef USE_GPU_SELECT
struct DRWInstanceData *inst_selectid;
/* Override for single object instances. */
int override_selectid;
#endif
int instance_count;
unsigned int instance_count;
unsigned char attribs_count;
unsigned char attribs_stride;
unsigned char attribs_size[MAX_ATTRIB_COUNT];
Gwn_VertFormat vbo_format;
};
@@ -279,6 +276,7 @@ struct DRWShadingGroup {
ID *instance_data; /* Object->data to instance */
Gwn_Batch *instance_geom; /* Geometry to instance */
Gwn_Batch *instancing_geom;/* Instances attributes */
Gwn_Batch *batch_geom; /* Result of call batching */
#ifdef USE_GPU_SELECT
@@ -294,6 +292,7 @@ enum {
DRW_SHG_LINE_BATCH,
DRW_SHG_TRIANGLE_BATCH,
DRW_SHG_INSTANCE,
DRW_SHG_INSTANCE_EXTERNAL,
};
/* Used by DRWCall.type */
@@ -661,8 +660,6 @@ static void drw_interface_create(DRWInterface *interface, GPUShader *shader)
interface->instance_count = 0;
interface->attribs_count = 0;
interface->attribs_stride = 0;
interface->instance_vbo = 0;
interface->instance_batch = NULL;
interface->inst_data = NULL;
interface->uniforms = NULL;
#ifdef USE_GPU_SELECT
@@ -712,33 +709,16 @@ static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name,
static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType UNUSED(type), int size, bool dummy)
{
unsigned int attrib_id = shgroup->interface.attribs_count;
GLuint program = GPU_shader_get_program(shgroup->shader);
shgroup->interface.attribs_loc[attrib_id] = glGetAttribLocation(program, name);
shgroup->interface.attribs_size[attrib_id] = size;
shgroup->interface.attribs_stride += size;
shgroup->interface.attribs_count += 1;
if (shgroup->type != DRW_SHG_INSTANCE) {
BLI_assert(size <= 4); /* Matrices are not supported by Gawain. */
GWN_vertformat_attr_add(&shgroup->interface.vbo_format, name, GWN_COMP_F32, size, GWN_FETCH_FLOAT);
}
BLI_assert(ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_POINT_BATCH, DRW_SHG_LINE_BATCH, DRW_SHG_TRIANGLE_BATCH));
BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
/* Adding attribute even if not found for now (to keep memory alignment).
* Should ideally take vertex format automatically from batch eventually */
#if 0
if (attrib->location == -1 && !dummy) {
if (G.debug & G_DEBUG)
fprintf(stderr, "Attribute '%s' not found!\n", name);
BLI_assert(0);
MEM_freeN(attrib);
return;
}
#else
GWN_vertformat_attr_add(&shgroup->interface.vbo_format, name, GWN_COMP_F32, size, GWN_FETCH_FLOAT);
UNUSED_VARS(dummy);
#endif
}
/** \} */
@@ -771,6 +751,7 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
shgroup->state_extra_disable = ~0x0;
shgroup->stencil_mask = 0;
shgroup->batch_geom = NULL;
shgroup->instancing_geom = NULL;
shgroup->instance_geom = NULL;
shgroup->instance_data = NULL;
@@ -921,12 +902,9 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
{
if (shgroup->interface.instance_vbo &&
(shgroup->interface.instance_batch == 0))
{
glDeleteBuffers(1, &shgroup->interface.instance_vbo);
if (shgroup->type != DRW_SHG_INSTANCE_EXTERNAL) {
GWN_BATCH_DISCARD_SAFE(shgroup->instancing_geom);
}
GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom);
}
@@ -942,12 +920,14 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
call->head.prev = NULL; \
} ((void)0)
/* Specify an external batch instead of adding each attrib one by one. */
void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
{
BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
BLI_assert(shgroup->interface.instance_batch == NULL);
BLI_assert(shgroup->instancing_geom == NULL);
shgroup->interface.instance_batch = instances;
shgroup->type = DRW_SHG_INSTANCE_EXTERNAL;
shgroup->instancing_geom = instances;
#ifdef USE_GPU_SELECT
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
@@ -1226,48 +1206,35 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
{
DRWInterface *interface = &shgroup->interface;
int buffer_size = 0;
void *data = NULL;
int nbr = interface->instance_count;
if (interface->instance_batch != NULL) {
if (nbr == 0)
return;
/* XXX Add a dummy attr for simple instancing. */
if (interface->attribs_count == 0) {
drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
}
/* TODO We still need this because gawain does not support Matrix attribs. */
if (interface->instance_count == 0) {
if (interface->instance_vbo) {
glDeleteBuffers(1, &interface->instance_vbo);
interface->instance_vbo = 0;
}
return;
}
/* Gather Data */
buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count;
/* TODO poke mike to add this to gawain */
if (interface->instance_vbo) {
glDeleteBuffers(1, &interface->instance_vbo);
interface->instance_vbo = 0;
}
/* Upload Data */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
if (interface->inst_data) {
data = DRW_instance_data_get(interface->inst_data);
GWN_vertbuf_data_set(vbo, nbr, DRW_instance_data_get(interface->inst_data), false);
} else {
/* Use unitialized memory. This is for dummy vertex buffers. */
/* XXX TODO do not alloc at all. */
GWN_vertbuf_data_alloc(vbo, nbr);
}
glGenBuffers(1, &interface->instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, interface->instance_vbo);
glBufferData(GL_ARRAY_BUFFER, buffer_size, data, GL_STATIC_DRAW);
/* TODO make the batch dynamic instead of freeing it every times */
if (shgroup->instancing_geom)
GWN_batch_discard(shgroup->instancing_geom);
shgroup->instancing_geom = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
{
if ((shgroup->interface.instance_vbo || shgroup->batch_geom) &&
(G.debug_value == 667))
{
return;
}
if (shgroup->type == DRW_SHG_INSTANCE) {
shgroup_dynamic_instance(shgroup);
}
@@ -1797,17 +1764,10 @@ static void draw_geometry_prepare(
static void draw_geometry_execute_ex(
DRWShadingGroup *shgroup, Gwn_Batch *geom, unsigned int start, unsigned int count)
{
DRWInterface *interface = &shgroup->interface;
/* step 2 : bind vertex array & draw */
GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
if (interface->instance_batch) {
/* Used for Particles. Cannot do partial drawing. */
GWN_batch_draw_stupid_instanced_with_batch(geom, interface->instance_batch);
}
else if (interface->instance_vbo) {
GWN_batch_draw_stupid_instanced(
geom, interface->instance_vbo, start, count, interface->attribs_count,
interface->attribs_stride, interface->attribs_size, interface->attribs_loc);
if (shgroup->instancing_geom) {
GWN_batch_draw_stupid_instanced(geom, shgroup->instancing_geom, start, count);
}
else {
GWN_batch_draw_stupid(geom, start, count);
@@ -2033,10 +1993,10 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
float obmat[4][4];
unit_m4(obmat);
if (shgroup->type == DRW_SHG_INSTANCE &&
(interface->instance_count > 0 || interface->instance_batch != NULL))
if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL) &&
(shgroup->instancing_geom != NULL))
{
if (interface->instance_batch != NULL) {
if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) {
GPU_SELECT_LOAD_IF_PICKSEL((DRWCall *)shgroup->calls_first);
draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, 0, 0);
}

View File

@@ -1007,7 +1007,7 @@ bool GPU_fx_do_composite_pass(
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
// GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
GPU_texture_unbind(fx->dof_half_downsampled_far);
GPU_framebuffer_texture_detach(fx->dof_far_blur);
@@ -1023,7 +1023,7 @@ bool GPU_fx_do_composite_pass(
/* have to clear the buffer unfortunately */
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
// GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
GWN_batch_program_use_end(fx->point_batch);
/* disable bindings */