<div dir="ltr"><div>So interleaved attribs are unsupported, right?<br><br>is_interleaved_arrays was probably slowing things down, so I'm OK with that.<br><br></div>Marek<br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Apr 1, 2018 at 2:13 PM, <span dir="ltr"><<a href="mailto:Mathias.Froehlich@gmx.net" target="_blank">Mathias.Froehlich@gmx.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Mathias Fröhlich <<a href="mailto:mathias.froehlich@web.de" target="_blank">mathias.froehlich@web.de</a>><br>
<br>
Finally make use of the binding information in the VAO when<br>
setting up arrays for draw.<br>
<br>
Signed-off-by: Mathias Fröhlich <<a href="mailto:Mathias.Froehlich@web.de" target="_blank">Mathias.Froehlich@web.de</a>><br>
---<br>
src/mesa/state_tracker/st_ato<wbr>m_array.c | 448 +++++++++---------------------<wbr>---<br>
1 file changed, 124 insertions(+), 324 deletions(-)<br>
<br>
diff --git a/src/mesa/state_tracker/st_at<wbr>om_array.c b/src/mesa/state_tracker/st_at<wbr>om_array.c<br>
index 2fd67e8d84..46934a718a 100644<br>
--- a/src/mesa/state_tracker/st_at<wbr>om_array.c<br>
+++ b/src/mesa/state_tracker/st_at<wbr>om_array.c<br>
@@ -48,6 +48,7 @@<br>
#include "main/bufferobj.h"<br>
#include "main/glformats.h"<br>
#include "main/varray.h"<br>
+#include "main/arrayobj.h"<br>
<br>
/* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */<br>
static const uint16_t vertex_formats[][4][4] = {<br>
@@ -306,79 +307,6 @@ st_pipe_vertex_format(const struct gl_array_attributes *attrib)<br>
return vertex_formats[type - GL_BYTE][index][size-1];<br>
}<br>
<br>
-static const struct gl_vertex_array *<br>
-get_client_array(const struct gl_vertex_array *arrays,<br>
- unsigned mesaAttr)<br>
-{<br>
- /* st_program uses 0xffffffff to denote a double placeholder attribute */<br>
- if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)<br>
- return NULL;<br>
- return &arrays[mesaAttr];<br>
-}<br>
-<br>
-/**<br>
- * Examine the active arrays to determine if we have interleaved<br>
- * vertex arrays all living in one VBO, or all living in user space.<br>
- */<br>
-static GLboolean<br>
-is_interleaved_arrays(const struct st_vertex_program *vp,<br>
- const struct gl_vertex_array *arrays,<br>
- unsigned num_inputs)<br>
-{<br>
- GLuint attr;<br>
- const struct gl_buffer_object *firstBufObj = NULL;<br>
- GLint firstStride = -1;<br>
- const GLubyte *firstPtr = NULL;<br>
- GLboolean userSpaceBuffer = GL_FALSE;<br>
-<br>
- for (attr = 0; attr < num_inputs; attr++) {<br>
- const struct gl_vertex_array *array;<br>
- const struct gl_vertex_buffer_binding *binding;<br>
- const struct gl_array_attributes *attrib;<br>
- const GLubyte *ptr;<br>
- const struct gl_buffer_object *bufObj;<br>
- GLsizei stride;<br>
-<br>
- array = get_client_array(arrays, vp->index_to_input[attr]);<br>
- if (!array)<br>
- continue;<br>
-<br>
- binding = array->BufferBinding;<br>
- attrib = array->VertexAttrib;<br>
- stride = binding->Stride; /* in bytes */<br>
- ptr = _mesa_vertex_attrib_address(at<wbr>trib, binding);<br>
-<br>
- /* To keep things simple, don't allow interleaved zero-stride attribs. */<br>
- if (stride == 0)<br>
- return false;<br>
-<br>
- bufObj = binding->BufferObj;<br>
- if (attr == 0) {<br>
- /* save info about the first array */<br>
- firstStride = stride;<br>
- firstPtr = ptr;<br>
- firstBufObj = bufObj;<br>
- userSpaceBuffer = !_mesa_is_bufferobj(bufObj);<br>
- }<br>
- else {<br>
- /* check if other arrays interleave with the first, in same buffer */<br>
- if (stride != firstStride)<br>
- return GL_FALSE; /* strides don't match */<br>
-<br>
- if (bufObj != firstBufObj)<br>
- return GL_FALSE; /* arrays in different VBOs */<br>
-<br>
- if (llabs(ptr - firstPtr) > firstStride)<br>
- return GL_FALSE; /* arrays start too far apart */<br>
-<br>
- if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer)<br>
- return GL_FALSE; /* mix of VBO and user-space arrays */<br>
- }<br>
- }<br>
-<br>
- return GL_TRUE;<br>
-}<br>
-<br>
static void init_velement(struct pipe_vertex_element *velement,<br>
int src_offset, int format,<br>
int instance_divisor, int vbo_index)<br>
@@ -392,13 +320,14 @@ static void init_velement(struct pipe_vertex_element *velement,<br>
<br>
static void init_velement_lowered(const struct st_vertex_program *vp,<br>
struct pipe_vertex_element *velements,<br>
- int src_offset, int format,<br>
- int instance_divisor, int vbo_index,<br>
- int nr_components, GLboolean doubles,<br>
- GLuint *attr_idx)<br>
+ const struct gl_array_attributes *attrib,<br>
+ int src_offset, int instance_divisor,<br>
+ int vbo_index, int idx)<br>
{<br>
- int idx = *attr_idx;<br>
- if (doubles) {<br>
+ const unsigned format = st_pipe_vertex_format(attrib);<br>
+ const GLubyte nr_components = attrib->Size;<br>
+<br>
+ if (attrib->Doubles) {<br>
int lower_format;<br>
<br>
if (nr_components < 2)<br>
@@ -427,15 +356,11 @@ static void init_velement_lowered(const struct st_vertex_program *vp,<br>
init_velement(&velements[idx]<wbr>, src_offset, PIPE_FORMAT_R32G32_UINT,<br>
instance_divisor, vbo_index);<br>
}<br>
-<br>
- idx++;<br>
}<br>
} else {<br>
init_velement(&velements[idx]<wbr>, src_offset,<br>
format, instance_divisor, vbo_index);<br>
- idx++;<br>
}<br>
- *attr_idx = idx;<br>
}<br>
<br>
static void<br>
@@ -457,274 +382,149 @@ set_vertex_attribs(struct st_context *st,<br>
cso_set_vertex_elements(cso, num_velements, velements);<br>
}<br>
<br>
-/**<br>
- * Set up for drawing interleaved arrays that all live in one VBO<br>
- * or all live in user space.<br>
- * \param vbuffer returns vertex buffer info<br>
- * \param velements returns vertex element info<br>
- */<br>
-static void<br>
-setup_interleaved_attribs(str<wbr>uct st_context *st,<br>
- const struct st_vertex_program *vp,<br>
- const struct gl_vertex_array *arrays,<br>
- unsigned num_inputs)<br>
+void st_update_array(struct st_context *st)<br>
{<br>
- struct pipe_vertex_buffer vbuffer;<br>
- struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}};<br>
- GLuint attr;<br>
- const GLubyte *low_addr = NULL;<br>
- GLboolean usingVBO; /* all arrays in a VBO? */<br>
- struct gl_buffer_object *bufobj;<br>
- GLsizei stride;<br>
-<br>
- /* Find the lowest address of the arrays we're drawing,<br>
- * Init bufobj and stride.<br>
- */<br>
- if (num_inputs) {<br>
- const struct gl_vertex_array *array;<br>
- const struct gl_vertex_buffer_binding *binding;<br>
- const struct gl_array_attributes *attrib;<br>
-<br>
- array = get_client_array(arrays, vp->index_to_input[0]);<br>
- assert(array);<br>
-<br>
- binding = array->BufferBinding;<br>
- attrib = array->VertexAttrib;<br>
-<br>
- /* Since we're doing interleaved arrays, we know there'll be at most<br>
- * one buffer object and the stride will be the same for all arrays.<br>
- * Grab them now.<br>
- */<br>
- bufobj = binding->BufferObj;<br>
- stride = binding->Stride;<br>
-<br>
- low_addr = _mesa_vertex_attrib_address(at<wbr>trib, binding);<br>
-<br>
- for (attr = 1; attr < num_inputs; attr++) {<br>
- const GLubyte *start;<br>
- array = get_client_array(arrays, vp->index_to_input[attr]);<br>
- if (!array)<br>
- continue;<br>
- binding = array->BufferBinding;<br>
- attrib = array->VertexAttrib;<br>
- start = _mesa_vertex_attrib_address(at<wbr>trib, binding);<br>
- low_addr = MIN2(low_addr, start);<br>
- }<br>
- }<br>
- else {<br>
- /* not sure we'll ever have zero inputs, but play it safe */<br>
- bufobj = NULL;<br>
- stride = 0;<br>
- low_addr = 0;<br>
- }<br>
-<br>
- /* are the arrays in user space? */<br>
- usingVBO = _mesa_is_bufferobj(bufobj);<br>
-<br>
- for (attr = 0; attr < num_inputs;) {<br>
- const struct gl_vertex_array *array;<br>
- const struct gl_vertex_buffer_binding *binding;<br>
- const struct gl_array_attributes *attrib;<br>
- const GLubyte *ptr;<br>
- unsigned src_offset;<br>
- unsigned src_format;<br>
-<br>
- array = get_client_array(arrays, vp->index_to_input[attr]);<br>
- assert(array);<br>
-<br>
- binding = array->BufferBinding;<br>
- attrib = array->VertexAttrib;<br>
- ptr = _mesa_vertex_attrib_address(at<wbr>trib, binding);<br>
+ struct gl_context *ctx = st->ctx;<br>
+ /* vertex program validation must be done before this */<br>
+ const struct st_vertex_program *vp = st->vp;<br>
+ /* _NEW_PROGRAM, ST_NEW_VS_STATE */<br>
+ const GLbitfield inputs_read = st->vp_variant->vert_attrib_ma<wbr>sk;<br>
+ const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;<br>
+ const ubyte *input_to_index = vp->input_to_index;<br>
<br>
- src_offset = (unsigned) (ptr - low_addr);<br>
+ struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];<br>
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];<br>
+ unsigned num_vbuffers = 0;<br>
<br>
- src_format = st_pipe_vertex_format(attrib);<br>
+ st->vertex_array_out_of_memor<wbr>y = FALSE;<br>
+ st->draw_needs_minmax_index = false;<br>
<br>
- init_velement_lowered(vp, velements, src_offset, src_format,<br>
- binding->InstanceDivisor, 0,<br>
- attrib->Size, attrib->Doubles, &attr);<br>
- }<br>
+ /* _NEW_PROGRAM */<br>
+ /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */<br>
+ /* Attribute data is in a VBO. */<br>
+ GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx)<wbr>;<br>
+ while (vbomask) {<br>
+ /* The attribute index to start pulling a binding */<br>
+ const gl_vert_attrib i = ffs(vbomask) - 1;<br>
+ const struct gl_vertex_buffer_binding *const binding<br>
+ = _mesa_draw_buffer_binding(vao, i);<br>
+ const unsigned bufidx = num_vbuffers++;<br>
<br>
- /*<br>
- * Return the vbuffer info and setup user-space attrib info, if needed.<br>
- */<br>
- if (num_inputs == 0) {<br>
- /* just defensive coding here */<br>
- vbuffer.buffer.resource = NULL;<br>
- vbuffer.is_user_buffer = false;<br>
- vbuffer.buffer_offset = 0;<br>
- vbuffer.stride = 0;<br>
- }<br>
- else if (usingVBO) {<br>
- /* all interleaved arrays in a VBO */<br>
- struct st_buffer_object *stobj = st_buffer_object(bufobj);<br>
+ assert(_mesa_is_bufferobj(bind<wbr>ing->BufferObj));<br>
<br>
+ struct st_buffer_object *stobj = st_buffer_object(binding->Buff<wbr>erObj);<br>
if (!stobj || !stobj->buffer) {<br>
st->vertex_array_out_of_memory = true;<br>
return; /* out-of-memory error probably */<br>
}<br>
<br>
- vbuffer.buffer.resource = stobj->buffer;<br>
- vbuffer.is_user_buffer = false;<br>
- vbuffer.buffer_offset = pointer_to_offset(low_addr);<br>
- vbuffer.stride = stride;<br>
- }<br>
- else {<br>
- /* all interleaved arrays in user memory */<br>
- vbuffer.buffer.user = low_addr;<br>
- vbuffer.is_user_buffer = !!low_addr; /* if NULL, then unbind */<br>
- vbuffer.buffer_offset = 0;<br>
- vbuffer.stride = stride;<br>
-<br>
- if (low_addr)<br>
- st->draw_needs_minmax_index = true;<br>
+ /* Set the binding */<br>
+ vbuffer[bufidx].buffer.resourc<wbr>e = stobj->buffer;<br>
+ vbuffer[bufidx].is_user_buffer = false;<br>
+ vbuffer[bufidx].buffer_offset = _mesa_draw_binding_offset(bind<wbr>ing);<br>
+ vbuffer[bufidx].stride = binding->Stride; /* in bytes */<br>
+<br>
+ const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(b<wbr>inding);<br>
+ GLbitfield attrmask = vbomask & boundmask;<br>
+ /* Mark the those attributes as processed */<br>
+ vbomask &= ~boundmask;<br>
+ /* We can assume that we have array for the binding */<br>
+ assert(attrmask);<br>
+ /* Walk attributes belonging to the binding */<br>
+ while (attrmask) {<br>
+ const gl_vert_attrib attr = u_bit_scan(&attrmask);<br>
+ const struct gl_array_attributes *const attrib<br>
+ = _mesa_draw_array_attrib(vao, attr);<br>
+ const GLuint off = _mesa_draw_attributes_relative<wbr>_offset(attrib);<br>
+ init_velement_lowered(vp, velements, attrib, off,<br>
+ binding->InstanceDivisor, bufidx,<br>
+ input_to_index[attr]);<br>
+ }<br>
}<br>
<br>
- set_vertex_attribs(st, &vbuffer, num_inputs ? 1 : 0,<br>
- velements, num_inputs);<br>
-}<br>
-<br>
-/**<br>
- * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each<br>
- * vertex attribute.<br>
- * \param vbuffer returns vertex buffer info<br>
- * \param velements returns vertex element info<br>
- */<br>
-static void<br>
-setup_non_interleaved_attribs<wbr>(struct st_context *st,<br>
- const struct st_vertex_program *vp,<br>
- const struct gl_vertex_array *arrays,<br>
- unsigned num_inputs)<br>
-{<br>
- struct gl_context *ctx = st->ctx;<br>
- struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];<br>
- struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS] = {{0}};<br>
- unsigned num_vbuffers = 0;<br>
- unsigned unref_buffers = 0;<br>
- GLuint attr;<br>
-<br>
- for (attr = 0; attr < num_inputs;) {<br>
- const unsigned mesaAttr = vp->index_to_input[attr];<br>
- const struct gl_vertex_array *array;<br>
- const struct gl_vertex_buffer_binding *binding;<br>
- const struct gl_array_attributes *attrib;<br>
- struct gl_buffer_object *bufobj;<br>
- GLsizei stride;<br>
- unsigned src_format;<br>
- unsigned bufidx;<br>
-<br>
- array = get_client_array(arrays, mesaAttr);<br>
- assert(array);<br>
-<br>
- bufidx = num_vbuffers++;<br>
-<br>
- binding = array->BufferBinding;<br>
- attrib = array->VertexAttrib;<br>
- stride = binding->Stride;<br>
- bufobj = binding->BufferObj;<br>
-<br>
- if (_mesa_is_bufferobj(bufobj)) {<br>
- /* Attribute data is in a VBO.<br>
- * Recall that for VBOs, the gl_vertex_array->Ptr field is<br>
- * really an offset from the start of the VBO, not a pointer.<br>
- */<br>
- struct st_buffer_object *stobj = st_buffer_object(bufobj);<br>
-<br>
- if (!stobj || !stobj->buffer) {<br>
- st->vertex_array_out_of_memory = true;<br>
- return; /* out-of-memory error probably */<br>
- }<br>
+ /* _NEW_PROGRAM */<br>
+ /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */<br>
+ /* Process user space buffers */<br>
+ GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx<wbr>);<br>
+ while (usermask) {<br>
+ const gl_vert_attrib attr = u_bit_scan(&usermask);<br>
+ const struct gl_array_attributes *const attrib<br>
+ = _mesa_draw_array_attrib(vao, attr);<br>
+ const struct gl_vertex_buffer_binding *const binding<br>
+ = _mesa_draw_buffer_binding_from<wbr>_attrib(vao, attrib);<br>
+ const unsigned bufidx = num_vbuffers++;<br>
+<br>
+ assert(!_mesa_is_bufferobj(bin<wbr>ding->BufferObj));<br>
+<br>
+ vbuffer[bufidx].buffer.user = attrib->Ptr;<br>
+ vbuffer[bufidx].is_user_buffer = true;<br>
+ vbuffer[bufidx].buffer_offset = 0;<br>
+ vbuffer[bufidx].stride = binding->Stride; /* in bytes */<br>
+<br>
+ init_velement_lowered(vp, velements, attrib, 0,<br>
+ binding->InstanceDivisor, bufidx,<br>
+ input_to_index[attr]);<br>
<br>
- vbuffer[bufidx].buffer.resour<wbr>ce = stobj->buffer;<br>
- vbuffer[bufidx].is_user_buffe<wbr>r = false;<br>
- vbuffer[bufidx].buffer_offset =<br>
- binding->Offset + attrib->RelativeOffset;<br>
- }<br>
- else {<br>
- if (stride == 0) {<br>
- unsigned size = attrib->_ElementSize;<br>
- /* This is optimal for GPU cache line usage if the upload size<br>
- * is <= cache line size.<br>
- */<br>
- unsigned alignment = util_next_power_of_two(size);<br>
-<br>
- assert(attrib->Ptr);<br>
- vbuffer[bufidx].buffer.user = attrib->Ptr;<br>
- void *ptr = attrib->Ptr ? (void*)attrib->Ptr :<br>
- (void*)ctx->Current.Attrib[mes<wbr>aAttr];<br>
-<br>
- vbuffer[bufidx].is_user_buffer = false;<br>
- vbuffer[bufidx].buffer.resourc<wbr>e = NULL;<br>
-<br>
- /* Use const_uploader for zero-stride vertex attributes, because<br>
- * it may use a better memory placement than stream_uploader.<br>
- * The reason is that zero-stride attributes can be fetched many<br>
- * times (thousands of times), so a better placement is going to<br>
- * perform better.<br>
- *<br>
- * Upload the maximum possible size, which is 4x GLdouble = 32.<br>
- */<br>
- u_upload_data(st->can_bind_con<wbr>st_buffer_as_vertex ?<br>
- st->pipe->const_uploader :<br>
- st->pipe->stream_uploader,<br>
- 0, size, alignment, ptr,<br>
- &vbuffer[bufidx].buffer_offset<wbr>,<br>
- &vbuffer[bufidx].buffer.resour<wbr>ce);<br>
- unref_buffers |= 1u << bufidx;<br>
- } else {<br>
- assert(attrib->Ptr);<br>
- vbuffer[bufidx].buffer.user = attrib->Ptr;<br>
- vbuffer[bufidx].is_user_buffer = true;<br>
- vbuffer[bufidx].buffer_offset = 0;<br>
+ if (!binding->InstanceDivisor)<br>
+ st->draw_needs_minmax_index = true;<br>
+ }<br>
<br>
- if (!binding->InstanceDivisor)<br>
- st->draw_needs_minmax_index = true;<br>
- }<br>
+ const unsigned first_current_vbuffer = num_vbuffers;<br>
+ /* _NEW_PROGRAM | _NEW_CURRENT_ATTRIB */<br>
+ /* Process values that should have better been uniforms in the application */<br>
+ GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);<br>
+ if (curmask) {<br>
+ /* For each attribute, upload the maximum possible size. */<br>
+ GLubyte data[VERT_ATTRIB_MAX*sizeof(GL<wbr>double)*4];<br>
+ GLubyte *cursor = data;<br>
+ const unsigned bufidx = num_vbuffers++;<br>
+ unsigned max_alignment = 1;<br>
+<br>
+ while (curmask) {<br>
+ const gl_vert_attrib attr = u_bit_scan(&curmask);<br>
+ const struct gl_array_attributes *const attrib<br>
+ = _mesa_draw_current_attrib(ctx, attr);<br>
+ const unsigned size = attrib->_ElementSize;<br>
+ const unsigned alignment = util_next_power_of_two(size);<br>
+ max_alignment = MAX2(max_alignment, alignment);<br>
+ memcpy(cursor, attrib->Ptr, size);<br>
+ if (alignment != size)<br>
+ memset(cursor + size, 0, alignment - size);<br>
+<br>
+ init_velement_lowered(vp, velements, attrib, cursor - data, 0,<br>
+ bufidx, input_to_index[attr]);<br>
+<br>
+ cursor += alignment;<br>
}<br>
<br>
- /* common-case setup */<br>
- vbuffer[bufidx].stride = stride; /* in bytes */<br>
+ vbuffer[bufidx].is_user_buffer = false;<br>
+ vbuffer[bufidx].buffer.resourc<wbr>e = NULL;<br>
+ /* vbuffer[bufidx].buffer_offset is set below */<br>
+ vbuffer[bufidx].stride = 0;<br>
<br>
- src_format = st_pipe_vertex_format(attrib);<br>
-<br>
- init_velement_lowered(vp, velements, 0, src_format,<br>
- binding->InstanceDivisor, bufidx,<br>
- attrib->Size, attrib->Doubles, &attr);<br>
+ /* Use const_uploader for zero-stride vertex attributes, because<br>
+ * it may use a better memory placement than stream_uploader.<br>
+ * The reason is that zero-stride attributes can be fetched many<br>
+ * times (thousands of times), so a better placement is going to<br>
+ * perform better.<br>
+ */<br>
+ u_upload_data(st->can_bind_con<wbr>st_buffer_as_vertex ?<br>
+ st->pipe->const_uploader :<br>
+ st->pipe->stream_uploader,<br>
+ 0, cursor - data, max_alignment, data,<br>
+ &vbuffer[bufidx].buffer_offset<wbr>,<br>
+ &vbuffer[bufidx].buffer.resour<wbr>ce);<br>
}<br>
<br>
if (!ctx->Const.AllowMappedBuffer<wbr>sDuringExecution) {<br>
u_upload_unmap(st->pipe->stre<wbr>am_uploader);<br>
}<br>
<br>
+ const unsigned num_inputs = st->vp_variant->num_inputs;<br>
set_vertex_attribs(st, vbuffer, num_vbuffers, velements, num_inputs);<br>
<br>
/* Unreference uploaded zero-stride vertex buffers. */<br>
- while (unref_buffers) {<br>
- unsigned i = u_bit_scan(&unref_buffers);<br>
+ for (unsigned i = first_current_vbuffer; i < num_vbuffers; ++i) {<br>
pipe_resource_reference(&vbuf<wbr>fer[i].buffer.resource, NULL);<br>
}<br>
}<br>
-<br>
-void st_update_array(struct st_context *st)<br>
-{<br>
- struct gl_context *ctx = st->ctx;<br>
- const struct gl_vertex_array *arrays = ctx->Array._DrawArrays;<br>
- const struct st_vertex_program *vp;<br>
- unsigned num_inputs;<br>
-<br>
- st->vertex_array_out_of_memor<wbr>y = FALSE;<br>
- st->draw_needs_minmax_index = false;<br>
-<br>
- /* No drawing has been done yet, so do nothing. */<br>
- if (!arrays)<br>
- return;<br>
-<br>
- /* vertex program validation must be done before this */<br>
- vp = st->vp;<br>
- num_inputs = st->vp_variant->num_inputs;<br>
-<br>
- if (is_interleaved_arrays(vp, arrays, num_inputs))<br>
- setup_interleaved_attribs(st, vp, arrays, num_inputs);<br>
- else<br>
- setup_non_interleaved_attribs(<wbr>st, vp, arrays, num_inputs);<br>
-}<br>
<span class="m_2646313031866455377m_2261294026011248911HOEnZb"><font color="#888888">--<br>
2.14.3<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>