From: Mathias Fröhlich Date: Sat, 3 Feb 2018 21:25:50 +0000 (+0100) Subject: vbo: Make use of _DrawVAO from the dlist code. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4562a7b0e82bf664b30ee72da141d070adc659da;p=mesa.git vbo: Make use of _DrawVAO from the dlist code. Finally use an internal VAO to execute display list draws. Avoid duplicate state validation for display list draws. Remove client arrays previously used exclusively for display lists. Signed-off-by: Mathias Fröhlich Reviewed-by: Brian Paul --- diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c index 19c40ec5307..f106cf279ad 100644 --- a/src/mesa/vbo/vbo_save.c +++ b/src/mesa/vbo/vbo_save.c @@ -27,6 +27,7 @@ #include "main/mtypes.h" +#include "main/arrayobj.h" #include "main/bufferobj.h" #include "vbo_private.h" @@ -44,32 +45,8 @@ void vbo_save_init( struct gl_context *ctx ) vbo_save_api_init( save ); - { - struct gl_vertex_array *arrays = save->arrays; - unsigned i; - - memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS], - VERT_ATTRIB_FF_MAX * sizeof(arrays[0])); - for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) { - struct gl_vertex_array *array; - array = &arrays[VERT_ATTRIB_FF(i)]; - array->BufferObj = NULL; - _mesa_reference_buffer_object(ctx, &arrays->BufferObj, - vbo->currval[VBO_ATTRIB_POS+i].BufferObj); - } - - memcpy(arrays + VERT_ATTRIB_GENERIC(0), - &vbo->currval[VBO_ATTRIB_GENERIC0], - VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0])); - - for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) { - struct gl_vertex_array *array; - array = &arrays[VERT_ATTRIB_GENERIC(i)]; - array->BufferObj = NULL; - _mesa_reference_buffer_object(ctx, &array->BufferObj, - vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj); - } - } + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) + save->VAO[vpm] = NULL; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; } @@ -79,7 +56,9 @@ void vbo_save_destroy( struct gl_context *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; - GLuint i; + + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) + _mesa_reference_vao(ctx, &save->VAO[vpm], NULL); if (save->prim_store) { if ( --save->prim_store->refcount == 0 ) { @@ -93,10 +72,6 @@ void vbo_save_destroy( struct gl_context *ctx ) save->vertex_store = NULL; } } - - for (i = 0; i < VBO_ATTRIB_MAX; i++) { - _mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL); - } } diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index cb0bff23414..edbce3673d2 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -66,6 +66,7 @@ struct vbo_save_vertex_list { GLenum16 attrtype[VBO_ATTRIB_MAX]; GLuint offsets[VBO_ATTRIB_MAX]; GLuint vertex_size; /**< size in GLfloats */ + struct gl_vertex_array_object *VAO[VP_MODE_MAX]; /* Copy of the final vertex from node->vertex_store->bufferobj. * Keep this in regular (non-VBO) memory to avoid repeated @@ -140,14 +141,13 @@ struct vbo_save_context { struct gl_context *ctx; GLvertexformat vtxfmt; GLvertexformat vtxfmt_noop; /**< Used if out_of_memory is true */ - struct gl_vertex_array arrays[VBO_ATTRIB_MAX]; - const struct gl_vertex_array *inputs[VBO_ATTRIB_MAX]; GLbitfield64 enabled; /**< mask of enabled vbo arrays. */ GLubyte attrsz[VBO_ATTRIB_MAX]; /**< 1, 2, 3 or 4 */ GLenum16 attrtype[VBO_ATTRIB_MAX]; /**< GL_FLOAT, GL_INT, etc */ GLubyte active_sz[VBO_ATTRIB_MAX]; /**< 1, 2, 3 or 4 */ GLuint vertex_size; /**< size in GLfloats */ + struct gl_vertex_array_object *VAO[VP_MODE_MAX]; GLboolean out_of_memory; /**< True if last VBO allocation failed */ diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index fb51bdb84e4..1edf7b9dfa9 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -68,6 +68,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/glheader.h" +#include "main/arrayobj.h" #include "main/bufferobj.h" #include "main/context.h" #include "main/dlist.h" @@ -79,6 +80,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/vtxfmt.h" #include "main/dispatch.h" #include "main/state.h" +#include "main/varray.h" #include "util/bitscan.h" #include "vbo_noop.h" @@ -411,6 +413,112 @@ convert_line_loop_to_strip(struct vbo_save_context *save, } +/* Compare the present vao if it has the same setup. */ +static bool +compare_vao(gl_vertex_processing_mode mode, + const struct gl_vertex_array_object *vao, + const struct gl_buffer_object *bo, GLintptr buffer_offset, + GLuint stride, GLbitfield64 vao_enabled, + const GLubyte size[VBO_ATTRIB_MAX], + const GLenum16 type[VBO_ATTRIB_MAX], + const GLuint offset[VBO_ATTRIB_MAX]) +{ + if (!vao) + return false; + + /* If the enabled arrays are not the same we are not equal. */ + if (vao_enabled != vao->_Enabled) + return false; + + /* Check the buffer binding at 0 */ + if (vao->BufferBinding[0].BufferObj != bo) + return false; + /* BufferBinding[0].Offset != buffer_offset is checked per attribute */ + if (vao->BufferBinding[0].Stride != stride) + return false; + assert(vao->BufferBinding[0].InstanceDivisor == 0); + + /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */ + const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode]; + + /* Now check the enabled arrays */ + GLbitfield mask = vao_enabled; + while (mask) { + const int attr = u_bit_scan(&mask); + const unsigned char vbo_attr = vao_to_vbo_map[attr]; + const GLenum16 tp = type[vbo_attr]; + const GLintptr off = offset[vbo_attr] + buffer_offset; + const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr]; + if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off) + return false; + if (attrib->Type != tp) + return false; + if (attrib->Size != size[vbo_attr]) + return false; + assert(attrib->Format == GL_RGBA); + assert(attrib->Enabled == GL_TRUE); + assert(attrib->Normalized == GL_FALSE); + assert(attrib->Integer == vbo_attrtype_to_integer_flag(tp)); + assert(attrib->Doubles == vbo_attrtype_to_double_flag(tp)); + assert(attrib->BufferBindingIndex == 0); + } + + return true; +} + + +/* Create or reuse the vao for the vertex processing mode. */ +static void +update_vao(struct gl_context *ctx, + gl_vertex_processing_mode mode, + struct gl_vertex_array_object **vao, + struct gl_buffer_object *bo, GLintptr buffer_offset, + GLuint stride, GLbitfield64 vbo_enabled, + const GLubyte size[VBO_ATTRIB_MAX], + const GLenum16 type[VBO_ATTRIB_MAX], + const GLuint offset[VBO_ATTRIB_MAX]) +{ + /* Compute the bitmasks of vao_enabled arrays */ + GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled); + + /* + * Check if we can possibly reuse the exisiting one. + * In the long term we should reset them when something changes. + */ + if (compare_vao(mode, *vao, bo, buffer_offset, stride, + vao_enabled, size, type, offset)) + return; + + /* The initial refcount is 1 */ + _mesa_reference_vao(ctx, vao, NULL); + *vao = _mesa_new_vao(ctx, ~((GLuint)0)); + + /* Bind the buffer object at binding point 0 */ + _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false); + + /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space + * Note that the position/generic0 aliasing is done in the VAO. + */ + const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode]; + /* Now set the enable arrays */ + GLbitfield mask = vao_enabled; + while (mask) { + const int vao_attr = u_bit_scan(&mask); + const GLubyte vbo_attr = vao_to_vbo_map[vao_attr]; + + _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset, + size[vbo_attr], type[vbo_attr], offset[vbo_attr]); + _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0, false); + _mesa_enable_vertex_array_attrib(ctx, *vao, vao_attr, false); + } + assert(vao_enabled == (*vao)->_Enabled); + assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0); + + /* Finalize and freeze the VAO */ + _mesa_set_vao_immutable(ctx, *vao); +} + + /** * Insert the active immediate struct onto the display list currently * being built. @@ -420,6 +528,7 @@ compile_vertex_list(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; struct vbo_save_vertex_list *node; + GLintptr buffer_offset = 0; GLuint offset; unsigned i; @@ -470,6 +579,20 @@ compile_vertex_list(struct gl_context *ctx) node->vertex_store = save->vertex_store; node->prim_store = save->prim_store; + /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs + * Note that this may reuse the previous one of possible. + */ + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) { + /* create or reuse the vao */ + update_vao(ctx, vpm, &save->VAO[vpm], + node->vertex_store->bufferobj, buffer_offset, + node->vertex_size*sizeof(GLfloat), node->enabled, + node->attrsz, node->attrtype, node->offsets); + /* Reference the vao in the dlist */ + node->VAO[vpm] = NULL; + _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]); + } + node->vertex_store->refcount++; node->prim_store->refcount++; @@ -1700,7 +1823,9 @@ static void vbo_destroy_vertex_list(struct gl_context *ctx, void *data) { struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data; - (void) ctx; + + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) + _mesa_reference_vao(ctx, &node->VAO[vpm], NULL); if (--node->vertex_store->refcount == 0) free_vertex_store(ctx, node->vertex_store); @@ -1773,7 +1898,6 @@ void vbo_save_api_init(struct vbo_save_context *save) { struct gl_context *ctx = save->ctx; - GLuint i; save->opcode_vertex_list = _mesa_dlist_alloc_opcode(ctx, @@ -1785,8 +1909,4 @@ vbo_save_api_init(struct vbo_save_context *save) vtxfmt_init(ctx); current_init(ctx); _mesa_noop_vtxfmt_init(&save->vtxfmt_noop); - - /* These will actually get set again when binding/drawing */ - for (i = 0; i < VBO_ATTRIB_MAX; i++) - save->inputs[i] = &save->arrays[i]; } diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 8c58fecf406..7cb67996689 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -129,58 +129,14 @@ playback_copy_to_current(struct gl_context *ctx, /** - * Treat the vertex storage as a VBO, define vertex arrays pointing - * into it: + * Set the appropriate VAO to draw. */ static void bind_vertex_list(struct gl_context *ctx, const struct vbo_save_vertex_list *node) { - struct vbo_context *vbo = vbo_context(ctx); - struct vbo_save_context *save = &vbo->save; - struct gl_vertex_array *arrays = save->arrays; - GLuint attr; - GLbitfield varying_inputs = 0x0; - - const gl_vertex_processing_mode processing_mode - = ctx->VertexProgram._VPMode; - const GLubyte * const map = _vbo_attribute_alias_map[processing_mode]; - - /* Grab VERT_ATTRIB_{POS,GENERIC0} from VBO_ATTRIB_POS */ - const gl_attribute_map_mode mode = ATTRIBUTE_MAP_MODE_POSITION; - const GLubyte *const array_map = _mesa_vao_attribute_map[mode]; - for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { - const GLuint src = map[array_map[attr]]; - const GLubyte size = node->attrsz[src]; - - if (size == 0) { - save->inputs[attr] = &vbo->currval[map[attr]]; - } else { - struct gl_vertex_array *array = &arrays[attr]; - const GLenum16 type = node->attrtype[src]; - - /* override the default array set above */ - save->inputs[attr] = array; - - array->Ptr = (const GLubyte *) NULL + node->offsets[src]; - array->Size = size; - array->StrideB = node->vertex_size * sizeof(GLfloat); - array->Type = type; - array->Integer = vbo_attrtype_to_integer_flag(type); - array->Format = GL_RGBA; - array->_ElementSize = size * sizeof(GLfloat); - _mesa_reference_buffer_object(ctx, - &array->BufferObj, - node->vertex_store->bufferobj); - - assert(array->BufferObj->Name); - - varying_inputs |= VERT_BIT(attr); - } - } - - _mesa_set_varying_vp_inputs(ctx, varying_inputs); - ctx->NewDriverState |= ctx->DriverFlags.NewArray; + const gl_vertex_processing_mode mode = ctx->VertexProgram._VPMode; + _mesa_set_draw_vao(ctx, node->VAO[mode], _vbo_get_vao_filter(mode)); } @@ -258,6 +214,9 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) goto end; } + bind_vertex_list(ctx, node); + + /* Need that at least one time. */ if (ctx->NewState) _mesa_update_state(ctx); @@ -271,14 +230,11 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) return; } - bind_vertex_list(ctx, node); - - _mesa_set_drawing_arrays(ctx, vbo->save.inputs); + /* Finally update the inputs array */ + _vbo_update_inputs(ctx, &vbo->draw_arrays); + _mesa_set_drawing_arrays(ctx, vbo->draw_arrays.inputs); - /* Again... - */ - if (ctx->NewState) - _mesa_update_state(ctx); + assert(ctx->NewState == 0); if (node->vertex_count > 0) { GLuint min_index = node->start_vertex;