[Mesa-dev] [PATCH 04/12] vbo: Implement vbo_loopback_vertex_list in terms of the VAO.
Brian Paul
brianp at vmware.com
Tue Feb 27 23:55:33 UTC 2018
Minor nit-picks below.
On 02/26/2018 11:12 PM, Mathias.Froehlich at gmx.net wrote:
> From: Mathias Fröhlich <mathias.froehlich at web.de>
>
> Use the information already present in the VAO to replay a display list
> node using immediate mode draw commands. Use a hand full of helper methods
> that will be useful for the next patches also.
>
> Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
> ---
> src/mesa/vbo/vbo_save.h | 53 ++++++++++++++---
> src/mesa/vbo/vbo_save_api.c | 42 ++++++--------
> src/mesa/vbo/vbo_save_draw.c | 28 +++------
> src/mesa/vbo/vbo_save_loopback.c | 119 +++++++++++++++++++++++++--------------
> 4 files changed, 149 insertions(+), 93 deletions(-)
>
> diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
> index 14ac831ffd..0672557c0e 100644
> --- a/src/mesa/vbo/vbo_save.h
> +++ b/src/mesa/vbo/vbo_save.h
> @@ -100,6 +100,50 @@ aligned_vertex_buffer_offset(const struct vbo_save_vertex_list *node)
> }
>
>
> +/**
> + * Return the stride in bytes of the display list node.
> + */
> +static inline GLsizei
> +_vbo_save_get_stride(const struct vbo_save_vertex_list *node)
> +{
> + return node->VAO[0]->BufferBinding[0].Stride;
> +}
> +
> +
> +/**
> + * Return the first referenced vertex index in the display list node.
> + */
> +static inline GLuint
> +_vbo_save_get_min_index(const struct vbo_save_vertex_list *node)
> +{
> + const struct _mesa_prim *first_prim = &node->prims[0];
> + return first_prim->start;
Maybe just return node->prims[0].start;
> +}
> +
> +
> +/**
> + * Return the last referenced vertex index in the display list node.
> + */
> +static inline GLuint
> +_vbo_save_get_max_index(const struct vbo_save_vertex_list *node)
> +{
assert (node->prim_count > 0);
> + const struct _mesa_prim *last_prim = &node->prims[node->prim_count - 1];
> + return last_prim->start + last_prim->count - 1;
> +}
> +
> +
> +/**
> + * Return the vertex count in the display list node.
> + */
> +static inline GLuint
> +_vbo_save_get_vertex_count(const struct vbo_save_vertex_list *node)
> +{
> + const struct _mesa_prim *first_prim = &node->prims[0];
assert (node->prim_count > 0);
> + const struct _mesa_prim *last_prim = &node->prims[node->prim_count - 1];
> + return last_prim->start - first_prim->start + last_prim->count;
> +}
> +
> +
> /* These buffers should be a reasonable size to support upload to
> * hardware. Current vbo implementation will re-upload on any
> * changes, so don't make too big or apps which dynamically create
> @@ -178,13 +222,8 @@ void vbo_save_fallback(struct gl_context *ctx, GLboolean fallback);
>
> /* save_loopback.c:
> */
> -void vbo_loopback_vertex_list(struct gl_context *ctx,
> - const GLfloat *buffer,
> - const GLubyte *attrsz,
> - const struct _mesa_prim *prim,
> - GLuint prim_count,
> - GLuint wrap_count,
> - GLuint vertex_size);
> +void _vbo_loopback_vertex_list(struct gl_context *ctx,
> + const struct vbo_save_vertex_list* node);
>
> /* Callbacks:
> */
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index b6fc7daa35..dc248934f7 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -641,6 +641,22 @@ compile_vertex_list(struct gl_context *ctx)
>
> merge_prims(node->prims, &node->prim_count);
>
> + /* Correct the primitive starts, we can only do this here as copy_vertices
> + * and convert_line_loop_to_strip above consume the uncorrected starts.
> + * On the other hand the _vbo_loopback_vertex_list call below needs the
> + * primitves to be corrected already.
> + */
> + if (aligned_vertex_buffer_offset(node)) {
> + const unsigned start_offset =
> + node->buffer_offset / (node->vertex_size * sizeof(GLfloat));
> + for (unsigned i = 0; i < node->prim_count; i++) {
> + node->prims[i].start += start_offset;
> + }
> + node->start_vertex = start_offset;
> + } else {
> + node->start_vertex = 0;
> + }
> +
> /* Deal with GL_COMPILE_AND_EXECUTE:
> */
> if (ctx->ExecuteFlag) {
> @@ -648,13 +664,8 @@ compile_vertex_list(struct gl_context *ctx)
>
> _glapi_set_dispatch(ctx->Exec);
>
> - const GLfloat *buffer = (const GLfloat *)
> - ((const char *) save->vertex_store->buffer_map +
> - node->buffer_offset);
> -
> - vbo_loopback_vertex_list(ctx, buffer,
> - node->attrsz, node->prims, node->prim_count,
> - node->wrap_count, node->vertex_size);
> + /* Note that the range of referenced vertices must be mapped already */
> + _vbo_loopback_vertex_list(ctx, node);
>
> _glapi_set_dispatch(dispatch);
> }
> @@ -693,23 +704,6 @@ compile_vertex_list(struct gl_context *ctx)
> save->prim_store = alloc_prim_store();
> }
>
> - /*
> - * If the vertex buffer offset is a multiple of the vertex size,
> - * we can use the _mesa_prim::start value to indicate where the
> - * vertices starts, instead of the buffer offset. Also see the
> - * bind_vertex_list() function.
> - */
> - if (aligned_vertex_buffer_offset(node)) {
> - const unsigned start_offset =
> - node->buffer_offset / (node->vertex_size * sizeof(GLfloat));
> - for (unsigned i = 0; i < save->prim_count; i++) {
> - save->prims[i].start += start_offset;
> - }
> - node->start_vertex = start_offset;
> - } else {
> - node->start_vertex = 0;
> - }
> -
> /* Reset our structures for the next run of vertices:
> */
> reset_counters(ctx);
> diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
> index 7cb6799668..0358ecd2f9 100644
> --- a/src/mesa/vbo/vbo_save_draw.c
> +++ b/src/mesa/vbo/vbo_save_draw.c
> @@ -144,26 +144,14 @@ static void
> loopback_vertex_list(struct gl_context *ctx,
> const struct vbo_save_vertex_list *list)
> {
> - const char *buffer =
> - ctx->Driver.MapBufferRange(ctx, 0,
> - list->vertex_store->bufferobj->Size,
> - GL_MAP_READ_BIT, /* ? */
> - list->vertex_store->bufferobj,
> - MAP_INTERNAL);
> -
> - unsigned buffer_offset =
> - aligned_vertex_buffer_offset(list) ? 0 : list->buffer_offset;
> -
> - vbo_loopback_vertex_list(ctx,
> - (const GLfloat *) (buffer + buffer_offset),
> - list->attrsz,
> - list->prims,
> - list->prim_count,
> - list->wrap_count,
> - list->vertex_size);
> -
> - ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj,
> - MAP_INTERNAL);
> + struct gl_buffer_object *bo = list->VAO[0]->BufferBinding[0].BufferObj;
> + ctx->Driver.MapBufferRange(ctx, 0, bo->Size, GL_MAP_READ_BIT, /* ? */
> + bo, MAP_INTERNAL);
> +
> + /* Note that the range of referenced vertices must be mapped already */
> + _vbo_loopback_vertex_list(ctx, list);
> +
> + ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
> }
>
>
> diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c
> index 43d458a7c0..55a6fb8180 100644
> --- a/src/mesa/vbo/vbo_save_loopback.c
> +++ b/src/mesa/vbo/vbo_save_loopback.c
> @@ -81,8 +81,8 @@ static attr_func vert_attrfunc[4] = {
>
>
> struct loopback_attr {
> - GLint index;
> - GLint sz;
> + enum vbo_attrib index;
> + GLuint offset;
> attr_func func;
> };
>
> @@ -94,17 +94,15 @@ struct loopback_attr {
> */
> static void
> loopback_prim(struct gl_context *ctx,
> - const GLfloat *buffer,
> + const GLubyte *buffer,
> const struct _mesa_prim *prim,
> GLuint wrap_count,
> - GLuint vertex_size,
> + GLuint stride,
> const struct loopback_attr *la, GLuint nr)
> {
> - GLint start = prim->start;
> - GLint end = start + prim->count;
> - const GLfloat *data;
> - GLint j;
> - GLuint k;
> + GLuint start = prim->start;
> + GLuint end = start + prim->count;
const on those two?
-Brian
> + const GLubyte *data;
>
> if (0)
> printf("loopback prim %s(%s,%s) verts %d..%d vsize %d\n",
> @@ -112,7 +110,7 @@ loopback_prim(struct gl_context *ctx,
> prim->begin ? "begin" : "..",
> prim->end ? "end" : "..",
> start, end,
> - vertex_size);
> + stride);
>
> if (prim->begin) {
> CALL_Begin(GET_DISPATCH(), (prim->mode));
> @@ -121,20 +119,13 @@ loopback_prim(struct gl_context *ctx,
> start += wrap_count;
> }
>
> - data = buffer + start * vertex_size;
> + data = buffer + start * stride;
>
> - for (j = start; j < end; j++) {
> - const GLfloat *tmp = data + la[0].sz;
> + for (GLuint j = start; j < end; j++) {
> + for (GLuint k = 0; k < nr; k++)
> + la[k].func(ctx, la[k].index, (const GLfloat *)(data + la[k].offset));
>
> - for (k = 1; k < nr; k++) {
> - la[k].func(ctx, la[k].index, tmp);
> - tmp += la[k].sz;
> - }
> -
> - /* Fire the vertex
> - */
> - la[0].func(ctx, VBO_ATTRIB_POS, data);
> - data = tmp;
> + data += stride;
> }
>
> if (prim->end) {
> @@ -167,36 +158,80 @@ loopback_weak_prim(struct gl_context *ctx,
> }
>
>
> +static inline void
> +append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
> + const struct gl_vertex_array_object *vao)
> +{
> + la[*nr].index = shift + i;
> + la[*nr].offset = vao->VertexAttrib[i].RelativeOffset;
> + la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Size - 1];
> + (*nr)++;
> +}
> +
> +
> void
> -vbo_loopback_vertex_list(struct gl_context *ctx,
> - const GLfloat *buffer,
> - const GLubyte *attrsz,
> - const struct _mesa_prim *prim,
> - GLuint prim_count,
> - GLuint wrap_count,
> - GLuint vertex_size)
> +_vbo_loopback_vertex_list(struct gl_context *ctx,
> + const struct vbo_save_vertex_list* node)
> {
> struct loopback_attr la[VBO_ATTRIB_MAX];
> - GLuint i, nr = 0;
> + GLuint nr = 0;
>
> /* All Legacy, NV, ARB and Material attributes are routed through
> * the NV attributes entrypoints:
> */
> - for (i = 0; i < VBO_ATTRIB_MAX; i++) {
> - if (attrsz[i]) {
> - la[nr].index = i;
> - la[nr].sz = attrsz[i];
> - la[nr].func = vert_attrfunc[attrsz[i]-1];
> - nr++;
> - }
> + const struct gl_vertex_array_object *vao = node->VAO[VP_MODE_FF];
> + GLbitfield mask = vao->_Enabled & VERT_BIT_MAT_ALL;
> + while (mask) {
> + const int i = u_bit_scan(&mask);
> + append_attr(&nr, la, i, VBO_MATERIAL_SHIFT, vao);
> + }
> +
> + vao = node->VAO[VP_MODE_SHADER];
> + mask = vao->_Enabled & ~(VERT_BIT_POS | VERT_BIT_GENERIC0);
> + while (mask) {
> + const int i = u_bit_scan(&mask);
> + append_attr(&nr, la, i, 0, vao);
> + }
> +
> + /* The last in the list should be the vertex provoking attribute */
> + if (vao->_Enabled & VERT_BIT_GENERIC0) {
> + append_attr(&nr, la, VERT_ATTRIB_GENERIC0, 0, vao);
> + } else if (vao->_Enabled & VERT_BIT_POS) {
> + append_attr(&nr, la, VERT_ATTRIB_POS, 0, vao);
> + }
> +
> + const GLuint wrap_count = node->wrap_count;
> + const GLuint stride = _vbo_save_get_stride(node);
> + const GLubyte *buffer = NULL;
> + if (0 < nr) {
> + /* Compute the minimal offset into the vertex buffer object */
> + GLuint offset = ~0u;
> + for (GLuint i = 0; i < nr; ++i)
> + offset = MIN2(offset, la[i].offset);
> + for (GLuint i = 0; i < nr; ++i)
> + la[i].offset -= offset;
> +
> + /* Get the mapped base pointer, assert sufficient mapping */
> + struct gl_buffer_object *bufferobj = vao->BufferBinding[0].BufferObj;
> + assert(bufferobj && bufferobj->Mappings[MAP_INTERNAL].Pointer);
> + buffer = bufferobj->Mappings[MAP_INTERNAL].Pointer;
> + assert(bufferobj->Mappings[MAP_INTERNAL].Offset
> + <= vao->BufferBinding[0].Offset + offset
> + + stride*(_vbo_save_get_min_index(node) + wrap_count));
> + buffer += vao->BufferBinding[0].Offset + offset
> + - bufferobj->Mappings[MAP_INTERNAL].Offset;
> + assert(stride*(_vbo_save_get_vertex_count(node) - wrap_count)
> + <= bufferobj->Mappings[MAP_INTERNAL].Length);
> }
>
> - for (i = 0; i < prim_count; i++) {
> - if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
> - _mesa_inside_begin_end(ctx)) {
> - loopback_weak_prim(ctx, &prim[i]);
> + /* Replay the primitives */
> + const struct _mesa_prim *prims = node->prims;
> + const GLuint prim_count = node->prim_count;
> + for (GLuint i = 0; i < prim_count; i++) {
> + if ((prims[i].mode & VBO_SAVE_PRIM_WEAK) && _mesa_inside_begin_end(ctx)) {
> + loopback_weak_prim(ctx, &prims[i]);
> } else {
> - loopback_prim(ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr);
> + loopback_prim(ctx, buffer, &prims[i], wrap_count, stride, la, nr);
> }
> }
> }
>
More information about the mesa-dev
mailing list