vbo: Implement vbo_loopback_vertex_list in terms of the VAO.

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.

v2: Insert asserts, constify local variables.

Reviewed-by: Brian Paul <brianp@vmware.com>
Signed-off-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
This commit is contained in:
Mathias Fröhlich
2018-02-25 18:01:07 +01:00
parent f7178d677c
commit 08aa0d9bf4
4 changed files with 149 additions and 91 deletions
+48 -7
View File
@@ -100,6 +100,52 @@ 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)
{
assert(node->prim_count > 0);
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)
{
assert(node->prim_count > 0);
const struct _mesa_prim *first_prim = &node->prims[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 +224,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:
*/
+18 -24
View File
@@ -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);
+6 -18
View File
@@ -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);
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);
unsigned buffer_offset =
aligned_vertex_buffer_offset(list) ? 0 : list->buffer_offset;
/* Note that the range of referenced vertices must be mapped already */
_vbo_loopback_vertex_list(ctx, list);
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);
ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
}
+77 -42
View File
@@ -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;
const GLuint end = start + prim->count;
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);
}
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]);
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);
}
/* 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);
}
}
}