On Mon, May 7, 2018 at 2:14 AM, <mathias.froehl...@gmx.net> wrote: > From: Mathias Fröhlich <mathias.froehl...@web.de> > > Finally make use of the binding information in the VAO when > setting up arrays for draw. > > v2: Emit less relocations also for interleaved userspace arrays. > > Signed-off-by: Mathias Fröhlich <mathias.froehl...@web.de>
This appears to break glmark2 (and, well, probably other things too) Thread 1 "glmark2" received signal SIGTRAP, Trace/breakpoint trap. 0x0000ffffbefc1c78 in kill () from /lib64/libc.so.6 (gdb) bt #0 0x0000ffffbefc1c78 in kill () from /lib64/libc.so.6 #1 0x0000ffffbde5ff90 in _debug_assert_fail (expr=0xffffbe6b9320 "desc", file=0xffffbe6b92f0 "../src/gallium/auxiliary/util/u_format.h", line=767, function=0xffffbe6b9830 <__func__.7922> "util_format_get_blocksizebits") at ../src/gallium/auxiliary/util/u_debug.c:322 #2 0x0000ffffbdec4384 in util_format_get_blocksizebits (format=1531) at ../src/gallium/auxiliary/util/u_format.h:767 #3 0x0000ffffbdec43bc in util_format_get_blocksize (format=1531) at ../src/gallium/auxiliary/util/u_format.h:781 #4 0x0000ffffbdec62a4 in u_vbuf_create_vertex_elements (mgr=0x7073b0, count=2, attribs=0xffffffffea20) at ../src/gallium/auxiliary/util/u_vbuf.c:761 #5 0x0000ffffbdec4da4 in u_vbuf_set_vertex_elements_internal (mgr=0x7073b0, count=2, states=0xffffffffea20) at ../src/gallium/auxiliary/util/u_vbuf.c:346 #6 0x0000ffffbdec4e94 in u_vbuf_set_vertex_elements (mgr=0x7073b0, count=2, states=0xffffffffea20) at ../src/gallium/auxiliary/util/u_vbuf.c:367 #7 0x0000ffffbde804dc in cso_set_vertex_elements (ctx=0x6e8190, count=2, states=0xffffffffea20) at ../src/gallium/auxiliary/cso_cache/cso_context.c:1067 #8 0x0000ffffbe3881d0 in set_vertex_attribs (st=0x6e2f20, vbuffers=0xffffffffeb20, num_vbuffers=0, velements=0xffffffffea20, num_velements=2) at ../src/mesa/state_tracker/st_atom_array.c:382 #9 0x0000ffffbe388708 in st_update_array (st=0x6e2f20) at ../src/mesa/state_tracker/st_atom_array.c:507 #10 0x0000ffffbe334634 in st_validate_state (st=0x6e2f20, pipeline=ST_PIPELINE_RENDER) at ../src/mesa/state_tracker/st_atom.c:261 #11 0x0000ffffbe2802ec in prepare_draw (st=0x6e2f20, ctx=0x6c74d0) at ../src/mesa/state_tracker/st_draw.c:123 #12 0x0000ffffbe280364 in st_draw_vbo (ctx=0x6c74d0, prims=0xffffffffef18, nr_prims=1, ib=0x0, index_bounds_valid=1 '\001', min_index=0, max_index=21515, tfb_vertcount=0x0, stream=0, indirect=0x0) at ../src/mesa/state_tracker/st_draw.c:153 #13 0x0000ffffbe270c48 in vbo_draw_arrays (ctx=0x6c74d0, mode=4, start=0, count=21516, numInstances=1, baseInstance=0, drawID=0) at ../src/mesa/vbo/vbo_exec_array.c:391 #14 0x0000ffffbe2715a4 in vbo_exec_DrawArrays (mode=4, start=0, count=21516) at ../src/mesa/vbo/vbo_exec_array.c:550 #15 0x0000ffffbebccc74 in shared_dispatch_stub_310 (mode=4, first=0, count=21516) at /home/robclark/src/mesa/debug/src/mapi/shared-glapi/glapi_mapi_tmp.h:19545 #16 0x00000000004731f8 in Mesh::render_array (this=this@entry=0x4e7ee8) at ../src/mesh.cpp:554 #17 0x000000000041ba98 in SceneBuild::draw (this=0x4e7da0) at ../src/scene-build.cpp:244 #18 0x0000000000410d00 in MainLoop::draw (this=0x58b420) at ../src/main-loop.cpp:133 #19 0x0000000000411594 in MainLoop::step (this=this@entry=0x58b420) at ../src/main-loop.cpp:108 #20 0x0000000000409498 in do_benchmark (canvas=...) at ../src/main.cpp:117 #21 0x00000000004071b0 in main (argc=<optimized out>, argv=<optimized out>) at ../src/main.cpp:210 looks like it is getting some garbage value for 'format'.. BR, -R > --- > src/mesa/state_tracker/st_atom_array.c | 432 > ++++++++------------------------- > 1 file changed, 107 insertions(+), 325 deletions(-) > > diff --git a/src/mesa/state_tracker/st_atom_array.c > b/src/mesa/state_tracker/st_atom_array.c > index 2fd67e8d84..6b39b4186d 100644 > --- a/src/mesa/state_tracker/st_atom_array.c > +++ b/src/mesa/state_tracker/st_atom_array.c > @@ -48,6 +48,7 @@ > #include "main/bufferobj.h" > #include "main/glformats.h" > #include "main/varray.h" > +#include "main/arrayobj.h" > > /* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */ > static const uint16_t vertex_formats[][4][4] = { > @@ -306,79 +307,6 @@ st_pipe_vertex_format(const struct gl_array_attributes > *attrib) > return vertex_formats[type - GL_BYTE][index][size-1]; > } > > -static const struct gl_vertex_array * > -get_client_array(const struct gl_vertex_array *arrays, > - unsigned mesaAttr) > -{ > - /* st_program uses 0xffffffff to denote a double placeholder attribute */ > - if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER) > - return NULL; > - return &arrays[mesaAttr]; > -} > - > -/** > - * Examine the active arrays to determine if we have interleaved > - * vertex arrays all living in one VBO, or all living in user space. > - */ > -static GLboolean > -is_interleaved_arrays(const struct st_vertex_program *vp, > - const struct gl_vertex_array *arrays, > - unsigned num_inputs) > -{ > - GLuint attr; > - const struct gl_buffer_object *firstBufObj = NULL; > - GLint firstStride = -1; > - const GLubyte *firstPtr = NULL; > - GLboolean userSpaceBuffer = GL_FALSE; > - > - for (attr = 0; attr < num_inputs; attr++) { > - const struct gl_vertex_array *array; > - const struct gl_vertex_buffer_binding *binding; > - const struct gl_array_attributes *attrib; > - const GLubyte *ptr; > - const struct gl_buffer_object *bufObj; > - GLsizei stride; > - > - array = get_client_array(arrays, vp->index_to_input[attr]); > - if (!array) > - continue; > - > - binding = array->BufferBinding; > - attrib = array->VertexAttrib; > - stride = binding->Stride; /* in bytes */ > - ptr = _mesa_vertex_attrib_address(attrib, binding); > - > - /* To keep things simple, don't allow interleaved zero-stride attribs. > */ > - if (stride == 0) > - return false; > - > - bufObj = binding->BufferObj; > - if (attr == 0) { > - /* save info about the first array */ > - firstStride = stride; > - firstPtr = ptr; > - firstBufObj = bufObj; > - userSpaceBuffer = !_mesa_is_bufferobj(bufObj); > - } > - else { > - /* check if other arrays interleave with the first, in same buffer > */ > - if (stride != firstStride) > - return GL_FALSE; /* strides don't match */ > - > - if (bufObj != firstBufObj) > - return GL_FALSE; /* arrays in different VBOs */ > - > - if (llabs(ptr - firstPtr) > firstStride) > - return GL_FALSE; /* arrays start too far apart */ > - > - if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer) > - return GL_FALSE; /* mix of VBO and user-space arrays */ > - } > - } > - > - return GL_TRUE; > -} > - > static void init_velement(struct pipe_vertex_element *velement, > int src_offset, int format, > int instance_divisor, int vbo_index) > @@ -392,13 +320,14 @@ static void init_velement(struct pipe_vertex_element > *velement, > > static void init_velement_lowered(const struct st_vertex_program *vp, > struct pipe_vertex_element *velements, > - int src_offset, int format, > - int instance_divisor, int vbo_index, > - int nr_components, GLboolean doubles, > - GLuint *attr_idx) > + const struct gl_array_attributes *attrib, > + int src_offset, int instance_divisor, > + int vbo_index, int idx) > { > - int idx = *attr_idx; > - if (doubles) { > + const unsigned format = st_pipe_vertex_format(attrib); > + const GLubyte nr_components = attrib->Size; > + > + if (attrib->Doubles) { > int lower_format; > > if (nr_components < 2) > @@ -427,15 +356,11 @@ static void init_velement_lowered(const struct > st_vertex_program *vp, > init_velement(&velements[idx], src_offset, > PIPE_FORMAT_R32G32_UINT, > instance_divisor, vbo_index); > } > - > - idx++; > } > } else { > init_velement(&velements[idx], src_offset, > format, instance_divisor, vbo_index); > - idx++; > } > - *attr_idx = idx; > } > > static void > @@ -457,274 +382,131 @@ set_vertex_attribs(struct st_context *st, > cso_set_vertex_elements(cso, num_velements, velements); > } > > -/** > - * Set up for drawing interleaved arrays that all live in one VBO > - * or all live in user space. > - * \param vbuffer returns vertex buffer info > - * \param velements returns vertex element info > - */ > -static void > -setup_interleaved_attribs(struct st_context *st, > - const struct st_vertex_program *vp, > - const struct gl_vertex_array *arrays, > - unsigned num_inputs) > -{ > - struct pipe_vertex_buffer vbuffer; > - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}}; > - GLuint attr; > - const GLubyte *low_addr = NULL; > - GLboolean usingVBO; /* all arrays in a VBO? */ > - struct gl_buffer_object *bufobj; > - GLsizei stride; > - > - /* Find the lowest address of the arrays we're drawing, > - * Init bufobj and stride. > - */ > - if (num_inputs) { > - const struct gl_vertex_array *array; > - const struct gl_vertex_buffer_binding *binding; > - const struct gl_array_attributes *attrib; > - > - array = get_client_array(arrays, vp->index_to_input[0]); > - assert(array); > - > - binding = array->BufferBinding; > - attrib = array->VertexAttrib; > - > - /* Since we're doing interleaved arrays, we know there'll be at most > - * one buffer object and the stride will be the same for all arrays. > - * Grab them now. > - */ > - bufobj = binding->BufferObj; > - stride = binding->Stride; > - > - low_addr = _mesa_vertex_attrib_address(attrib, binding); > - > - for (attr = 1; attr < num_inputs; attr++) { > - const GLubyte *start; > - array = get_client_array(arrays, vp->index_to_input[attr]); > - if (!array) > - continue; > - binding = array->BufferBinding; > - attrib = array->VertexAttrib; > - start = _mesa_vertex_attrib_address(attrib, binding); > - low_addr = MIN2(low_addr, start); > - } > - } > - else { > - /* not sure we'll ever have zero inputs, but play it safe */ > - bufobj = NULL; > - stride = 0; > - low_addr = 0; > - } > - > - /* are the arrays in user space? */ > - usingVBO = _mesa_is_bufferobj(bufobj); > - > - for (attr = 0; attr < num_inputs;) { > - const struct gl_vertex_array *array; > - const struct gl_vertex_buffer_binding *binding; > - const struct gl_array_attributes *attrib; > - const GLubyte *ptr; > - unsigned src_offset; > - unsigned src_format; > - > - array = get_client_array(arrays, vp->index_to_input[attr]); > - assert(array); > - > - binding = array->BufferBinding; > - attrib = array->VertexAttrib; > - ptr = _mesa_vertex_attrib_address(attrib, binding); > - > - src_offset = (unsigned) (ptr - low_addr); > - > - src_format = st_pipe_vertex_format(attrib); > - > - init_velement_lowered(vp, velements, src_offset, src_format, > - binding->InstanceDivisor, 0, > - attrib->Size, attrib->Doubles, &attr); > - } > - > - /* > - * Return the vbuffer info and setup user-space attrib info, if needed. > - */ > - if (num_inputs == 0) { > - /* just defensive coding here */ > - vbuffer.buffer.resource = NULL; > - vbuffer.is_user_buffer = false; > - vbuffer.buffer_offset = 0; > - vbuffer.stride = 0; > - } > - else if (usingVBO) { > - /* all interleaved arrays in a VBO */ > - struct st_buffer_object *stobj = st_buffer_object(bufobj); > - > - if (!stobj || !stobj->buffer) { > - st->vertex_array_out_of_memory = true; > - return; /* out-of-memory error probably */ > - } > - > - vbuffer.buffer.resource = stobj->buffer; > - vbuffer.is_user_buffer = false; > - vbuffer.buffer_offset = pointer_to_offset(low_addr); > - vbuffer.stride = stride; > - } > - else { > - /* all interleaved arrays in user memory */ > - vbuffer.buffer.user = low_addr; > - vbuffer.is_user_buffer = !!low_addr; /* if NULL, then unbind */ > - vbuffer.buffer_offset = 0; > - vbuffer.stride = stride; > - > - if (low_addr) > - st->draw_needs_minmax_index = true; > - } > - > - set_vertex_attribs(st, &vbuffer, num_inputs ? 1 : 0, > - velements, num_inputs); > -} > - > -/** > - * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each > - * vertex attribute. > - * \param vbuffer returns vertex buffer info > - * \param velements returns vertex element info > - */ > -static void > -setup_non_interleaved_attribs(struct st_context *st, > - const struct st_vertex_program *vp, > - const struct gl_vertex_array *arrays, > - unsigned num_inputs) > +void st_update_array(struct st_context *st) > { > struct gl_context *ctx = st->ctx; > + /* vertex program validation must be done before this */ > + const struct st_vertex_program *vp = st->vp; > + /* _NEW_PROGRAM, ST_NEW_VS_STATE */ > + const GLbitfield inputs_read = st->vp_variant->vert_attrib_mask; > + const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO; > + const ubyte *input_to_index = vp->input_to_index; > + > struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS]; > - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}}; > + struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; > unsigned num_vbuffers = 0; > - unsigned unref_buffers = 0; > - GLuint attr; > - > - for (attr = 0; attr < num_inputs;) { > - const unsigned mesaAttr = vp->index_to_input[attr]; > - const struct gl_vertex_array *array; > - const struct gl_vertex_buffer_binding *binding; > - const struct gl_array_attributes *attrib; > - struct gl_buffer_object *bufobj; > - GLsizei stride; > - unsigned src_format; > - unsigned bufidx; > - > - array = get_client_array(arrays, mesaAttr); > - assert(array); > - > - bufidx = num_vbuffers++; > - > - binding = array->BufferBinding; > - attrib = array->VertexAttrib; > - stride = binding->Stride; > - bufobj = binding->BufferObj; > - > - if (_mesa_is_bufferobj(bufobj)) { > - /* Attribute data is in a VBO. > - * Recall that for VBOs, the gl_vertex_array->Ptr field is > - * really an offset from the start of the VBO, not a pointer. > - */ > - struct st_buffer_object *stobj = st_buffer_object(bufobj); > > + st->vertex_array_out_of_memory = FALSE; > + st->draw_needs_minmax_index = false; > + > + /* _NEW_PROGRAM */ > + /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */ > + /* Process attribute array data. */ > + GLbitfield mask = inputs_read & _mesa_draw_array_bits(ctx); > + while (mask) { > + /* The attribute index to start pulling a binding */ > + const gl_vert_attrib i = ffs(mask) - 1; > + const struct gl_vertex_buffer_binding *const binding > + = _mesa_draw_buffer_binding(vao, i); > + const unsigned bufidx = num_vbuffers++; > + > + if (_mesa_is_bufferobj(binding->BufferObj)) { > + struct st_buffer_object *stobj = > st_buffer_object(binding->BufferObj); > if (!stobj || !stobj->buffer) { > st->vertex_array_out_of_memory = true; > return; /* out-of-memory error probably */ > } > > + /* Set the binding */ > vbuffer[bufidx].buffer.resource = stobj->buffer; > vbuffer[bufidx].is_user_buffer = false; > - vbuffer[bufidx].buffer_offset = > - binding->Offset + attrib->RelativeOffset; > + vbuffer[bufidx].buffer_offset = _mesa_draw_binding_offset(binding); > + } else { > + /* Set the binding */ > + const void *ptr = (const void *)_mesa_draw_binding_offset(binding); > + vbuffer[bufidx].buffer.user = ptr; > + vbuffer[bufidx].is_user_buffer = true; > + vbuffer[bufidx].buffer_offset = 0; > + > + if (!binding->InstanceDivisor) > + st->draw_needs_minmax_index = true; > } > - else { > - if (stride == 0) { > - unsigned size = attrib->_ElementSize; > - /* This is optimal for GPU cache line usage if the upload size > - * is <= cache line size. > - */ > - unsigned alignment = util_next_power_of_two(size); > - > - assert(attrib->Ptr); > - vbuffer[bufidx].buffer.user = attrib->Ptr; > - void *ptr = attrib->Ptr ? (void*)attrib->Ptr : > - (void*)ctx->Current.Attrib[mesaAttr]; > - > - vbuffer[bufidx].is_user_buffer = false; > - vbuffer[bufidx].buffer.resource = NULL; > - > - /* Use const_uploader for zero-stride vertex attributes, because > - * it may use a better memory placement than stream_uploader. > - * The reason is that zero-stride attributes can be fetched many > - * times (thousands of times), so a better placement is going to > - * perform better. > - * > - * Upload the maximum possible size, which is 4x GLdouble = 32. > - */ > - u_upload_data(st->can_bind_const_buffer_as_vertex ? > - st->pipe->const_uploader : > - st->pipe->stream_uploader, > - 0, size, alignment, ptr, > - &vbuffer[bufidx].buffer_offset, > - &vbuffer[bufidx].buffer.resource); > - unref_buffers |= 1u << bufidx; > - } else { > - assert(attrib->Ptr); > - vbuffer[bufidx].buffer.user = attrib->Ptr; > - vbuffer[bufidx].is_user_buffer = true; > - vbuffer[bufidx].buffer_offset = 0; > - > - if (!binding->InstanceDivisor) > - st->draw_needs_minmax_index = true; > - } > + vbuffer[bufidx].stride = binding->Stride; /* in bytes */ > + > + const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); > + GLbitfield attrmask = mask & boundmask; > + /* Mark the those attributes as processed */ > + mask &= ~boundmask; > + /* We can assume that we have array for the binding */ > + assert(attrmask); > + /* Walk attributes belonging to the binding */ > + while (attrmask) { > + const gl_vert_attrib attr = u_bit_scan(&attrmask); > + const struct gl_array_attributes *const attrib > + = _mesa_draw_array_attrib(vao, attr); > + const GLuint off = _mesa_draw_attributes_relative_offset(attrib); > + init_velement_lowered(vp, velements, attrib, off, > + binding->InstanceDivisor, bufidx, > + input_to_index[attr]); > } > + } > > - /* common-case setup */ > - vbuffer[bufidx].stride = stride; /* in bytes */ > + const unsigned first_current_vbuffer = num_vbuffers; > + /* _NEW_PROGRAM | _NEW_CURRENT_ATTRIB */ > + /* Process values that should have better been uniforms in the > application */ > + GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx); > + if (curmask) { > + /* For each attribute, upload the maximum possible size. */ > + GLubyte data[VERT_ATTRIB_MAX*sizeof(GLdouble)*4]; > + GLubyte *cursor = data; > + const unsigned bufidx = num_vbuffers++; > + unsigned max_alignment = 1; > + > + while (curmask) { > + const gl_vert_attrib attr = u_bit_scan(&curmask); > + const struct gl_array_attributes *const attrib > + = _mesa_draw_current_attrib(ctx, attr); > + const unsigned size = attrib->_ElementSize; > + const unsigned alignment = util_next_power_of_two(size); > + max_alignment = MAX2(max_alignment, alignment); > + memcpy(cursor, attrib->Ptr, size); > + if (alignment != size) > + memset(cursor + size, 0, alignment - size); > + > + init_velement_lowered(vp, velements, attrib, cursor - data, 0, > + bufidx, input_to_index[attr]); > + > + cursor += alignment; > + } > > - src_format = st_pipe_vertex_format(attrib); > + vbuffer[bufidx].is_user_buffer = false; > + vbuffer[bufidx].buffer.resource = NULL; > + /* vbuffer[bufidx].buffer_offset is set below */ > + vbuffer[bufidx].stride = 0; > > - init_velement_lowered(vp, velements, 0, src_format, > - binding->InstanceDivisor, bufidx, > - attrib->Size, attrib->Doubles, &attr); > + /* Use const_uploader for zero-stride vertex attributes, because > + * it may use a better memory placement than stream_uploader. > + * The reason is that zero-stride attributes can be fetched many > + * times (thousands of times), so a better placement is going to > + * perform better. > + */ > + u_upload_data(st->can_bind_const_buffer_as_vertex ? > + st->pipe->const_uploader : > + st->pipe->stream_uploader, > + 0, cursor - data, max_alignment, data, > + &vbuffer[bufidx].buffer_offset, > + &vbuffer[bufidx].buffer.resource); > } > > if (!ctx->Const.AllowMappedBuffersDuringExecution) { > u_upload_unmap(st->pipe->stream_uploader); > } > > + const unsigned num_inputs = st->vp_variant->num_inputs; > set_vertex_attribs(st, vbuffer, num_vbuffers, velements, num_inputs); > > /* Unreference uploaded zero-stride vertex buffers. */ > - while (unref_buffers) { > - unsigned i = u_bit_scan(&unref_buffers); > + for (unsigned i = first_current_vbuffer; i < num_vbuffers; ++i) { > pipe_resource_reference(&vbuffer[i].buffer.resource, NULL); > } > } > - > -void st_update_array(struct st_context *st) > -{ > - struct gl_context *ctx = st->ctx; > - const struct gl_vertex_array *arrays = ctx->Array._DrawArrays; > - const struct st_vertex_program *vp; > - unsigned num_inputs; > - > - st->vertex_array_out_of_memory = FALSE; > - st->draw_needs_minmax_index = false; > - > - /* No drawing has been done yet, so do nothing. */ > - if (!arrays) > - return; > - > - /* vertex program validation must be done before this */ > - vp = st->vp; > - num_inputs = st->vp_variant->num_inputs; > - > - if (is_interleaved_arrays(vp, arrays, num_inputs)) > - setup_interleaved_attribs(st, vp, arrays, num_inputs); > - else > - setup_non_interleaved_attribs(st, vp, arrays, num_inputs); > -} > -- > 2.14.3 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev