diff --git a/intern/gawain/gawain/gwn_batch.h b/intern/gawain/gawain/gwn_batch.h index b2b2f00a5a1..9564d8cd587 100644 --- a/intern/gawain/gawain/gwn_batch.h +++ b/intern/gawain/gawain/gwn_batch.h @@ -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); diff --git a/intern/gawain/src/gwn_batch.c b/intern/gawain/src/gwn_batch.c index ee6de9d1126..677158e09df 100644 --- a/intern/gawain/src/gwn_batch.c +++ b/intern/gawain/src/gwn_batch.c @@ -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); } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 4a71cce666a..db1046039d5 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -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); } diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index f0b1b35a760..ca81ca72a32 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -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 */