X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_array.c;h=1faf72b0db5e706dccdb496d47917dc7526bc1be;hb=HEAD;hp=be1729311e2e4bd4f083c3bf65a3d38ee3f1ef4d;hpb=e6448f993b157a6d3757b69d5d4c2424e8af737e;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c index be1729311e2..1faf72b0db5 100644 --- a/src/mesa/state_tracker/st_atom_array.c +++ b/src/mesa/state_tracker/st_atom_array.c @@ -50,7 +50,7 @@ #include "main/varray.h" #include "main/arrayobj.h" -static void init_velement(struct pipe_vertex_element *velement, +static void set_velement(struct pipe_vertex_element *velement, int src_offset, int format, int instance_divisor, int vbo_index) { @@ -61,58 +61,78 @@ static void init_velement(struct pipe_vertex_element *velement, assert(velement->src_format); } -static void init_velement_lowered(const struct st_vertex_program *vp, - struct pipe_vertex_element *velements, - const struct gl_vertex_format *vformat, - int src_offset, int instance_divisor, - int vbo_index, int idx) +static void init_velement_64bit(const struct st_vertex_program *vp, + struct pipe_vertex_element *velements, + const struct gl_vertex_format *vformat, + int src_offset, int instance_divisor, + int vbo_index, int idx) { const GLubyte nr_components = vformat->Size; - - if (vformat->Doubles) { - int lower_format; - - if (nr_components < 2) - lower_format = PIPE_FORMAT_R32G32_UINT; - else - lower_format = PIPE_FORMAT_R32G32B32A32_UINT; - - init_velement(&velements[idx], src_offset, - lower_format, instance_divisor, vbo_index); - idx++; - - if (idx < vp->num_inputs && - vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) { - if (nr_components >= 3) { - if (nr_components == 3) - lower_format = PIPE_FORMAT_R32G32_UINT; - else - lower_format = PIPE_FORMAT_R32G32B32A32_UINT; - - init_velement(&velements[idx], src_offset + 4 * sizeof(float), - lower_format, instance_divisor, vbo_index); - } else { - /* The values here are undefined. Fill in some conservative - * dummy values. - */ - init_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT, - instance_divisor, vbo_index); - } + int lower_format; + + if (nr_components < 2) + lower_format = PIPE_FORMAT_R32G32_UINT; + else + lower_format = PIPE_FORMAT_R32G32B32A32_UINT; + + set_velement(&velements[idx], src_offset, + lower_format, instance_divisor, vbo_index); + idx++; + + if (idx < vp->num_inputs && + vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) { + if (nr_components >= 3) { + if (nr_components == 3) + lower_format = PIPE_FORMAT_R32G32_UINT; + else + lower_format = PIPE_FORMAT_R32G32B32A32_UINT; + + set_velement(&velements[idx], src_offset + 4 * sizeof(float), + lower_format, instance_divisor, vbo_index); + } else { + /* The values here are undefined. Fill in some conservative + * dummy values. + */ + set_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT, + instance_divisor, vbo_index); } - } else { - init_velement(&velements[idx], src_offset, vformat->_PipeFormat, - instance_divisor, vbo_index); } } +/* Always inline the non-64bit element code, so that the compiler can see + * that velements is on the stack. + */ +static void ALWAYS_INLINE +init_velement(const struct st_vertex_program *vp, + struct pipe_vertex_element *velements, + const struct gl_vertex_format *vformat, + int src_offset, int instance_divisor, + int vbo_index, int idx) +{ + if (!vformat->Doubles) { + velements[idx].src_offset = src_offset; + velements[idx].src_format = vformat->_PipeFormat; + velements[idx].instance_divisor = instance_divisor; + velements[idx].vertex_buffer_index = vbo_index; + assert(velements[idx].src_format); + return; + } + + init_velement_64bit(vp, velements, vformat, src_offset, instance_divisor, + vbo_index, idx); +} + /* ALWAYS_INLINE helps the compiler realize that most of the parameters are * on the stack. */ -void ALWAYS_INLINE +void +#ifndef _MSC_VER /* MSVC doesn't like inlining public functions */ +ALWAYS_INLINE +#endif st_setup_arrays(struct st_context *st, const struct st_vertex_program *vp, const struct st_common_variant *vp_variant, - struct pipe_vertex_element *velements, + struct cso_velems_state *velements, struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers, bool *has_user_vertex_buffers) { @@ -120,10 +140,47 @@ st_setup_arrays(struct st_context *st, const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO; const GLbitfield inputs_read = vp_variant->vert_attrib_mask; const ubyte *input_to_index = vp->input_to_index; - bool uses_user_vertex_buffers = false; /* Process attribute array data. */ GLbitfield mask = inputs_read & _mesa_draw_array_bits(ctx); + GLbitfield userbuf_attribs = inputs_read & _mesa_draw_user_array_bits(ctx); + + *has_user_vertex_buffers = userbuf_attribs != 0; + st->draw_needs_minmax_index = + (userbuf_attribs & ~_mesa_draw_nonzero_divisor_bits(ctx)) != 0; + + if (vao->IsDynamic) { + while (mask) { + const gl_vert_attrib attr = u_bit_scan(&mask); + const struct gl_array_attributes *const attrib = + _mesa_draw_array_attrib(vao, attr); + const struct gl_vertex_buffer_binding *const binding = + &vao->BufferBinding[attrib->BufferBindingIndex]; + const unsigned bufidx = (*num_vbuffers)++; + + /* Set the vertex buffer. */ + if (binding->BufferObj) { + struct st_buffer_object *stobj = st_buffer_object(binding->BufferObj); + + vbuffer[bufidx].buffer.resource = stobj ? stobj->buffer : NULL; + vbuffer[bufidx].is_user_buffer = false; + vbuffer[bufidx].buffer_offset = binding->Offset + + attrib->RelativeOffset; + } else { + vbuffer[bufidx].buffer.user = attrib->Ptr; + vbuffer[bufidx].is_user_buffer = true; + vbuffer[bufidx].buffer_offset = 0; + } + vbuffer[bufidx].stride = binding->Stride; /* in bytes */ + + /* Set the vertex element. */ + init_velement(vp, velements->velems, &attrib->Format, 0, + binding->InstanceDivisor, bufidx, + input_to_index[attr]); + } + return; + } + while (mask) { /* The attribute index to start pulling a binding */ const gl_vert_attrib i = ffs(mask) - 1; @@ -131,7 +188,7 @@ st_setup_arrays(struct st_context *st, = _mesa_draw_buffer_binding(vao, i); const unsigned bufidx = (*num_vbuffers)++; - if (_mesa_is_bufferobj(binding->BufferObj)) { + if (binding->BufferObj) { /* Set the binding */ struct st_buffer_object *stobj = st_buffer_object(binding->BufferObj); @@ -144,10 +201,6 @@ st_setup_arrays(struct st_context *st, vbuffer[bufidx].buffer.user = ptr; vbuffer[bufidx].is_user_buffer = true; vbuffer[bufidx].buffer_offset = 0; - - uses_user_vertex_buffers = true; - if (!binding->InstanceDivisor) - st->draw_needs_minmax_index = true; } vbuffer[bufidx].stride = binding->Stride; /* in bytes */ @@ -158,27 +211,29 @@ st_setup_arrays(struct st_context *st, /* We can assume that we have array for the binding */ assert(attrmask); /* Walk attributes belonging to the binding */ - while (attrmask) { + do { 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->Format, off, - binding->InstanceDivisor, bufidx, - input_to_index[attr]); - } + init_velement(vp, velements->velems, &attrib->Format, off, + binding->InstanceDivisor, bufidx, + input_to_index[attr]); + } while (attrmask); } - *has_user_vertex_buffers = uses_user_vertex_buffers; } /* ALWAYS_INLINE helps the compiler realize that most of the parameters are * on the stack. + * + * Return the index of the vertex buffer where current attribs have been + * uploaded. */ -void ALWAYS_INLINE +static int ALWAYS_INLINE st_setup_current(struct st_context *st, const struct st_vertex_program *vp, const struct st_common_variant *vp_variant, - struct pipe_vertex_element *velements, + struct cso_velems_state *velements, struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers) { struct gl_context *ctx = st->ctx; @@ -194,7 +249,7 @@ st_setup_current(struct st_context *st, const unsigned bufidx = (*num_vbuffers)++; unsigned max_alignment = 1; - while (curmask) { + do { const gl_vert_attrib attr = u_bit_scan(&curmask); const struct gl_array_attributes *const attrib = _mesa_draw_current_attrib(ctx, attr); @@ -205,11 +260,11 @@ st_setup_current(struct st_context *st, if (alignment != size) memset(cursor + size, 0, alignment - size); - init_velement_lowered(vp, velements, &attrib->Format, cursor - data, 0, - bufidx, input_to_index[attr]); + init_velement(vp, velements->velems, &attrib->Format, cursor - data, + 0, bufidx, input_to_index[attr]); cursor += alignment; - } + } while (curmask); vbuffer[bufidx].is_user_buffer = false; vbuffer[bufidx].buffer.resource = NULL; @@ -231,14 +286,16 @@ st_setup_current(struct st_context *st, &vbuffer[bufidx].buffer.resource); /* Always unmap. The uploader might use explicit flushes. */ u_upload_unmap(uploader); + return bufidx; } + return -1; } void st_setup_current_user(struct st_context *st, const struct st_vertex_program *vp, const struct st_common_variant *vp_variant, - struct pipe_vertex_element *velements, + struct cso_velems_state *velements, struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers) { struct gl_context *ctx = st->ctx; @@ -254,8 +311,8 @@ st_setup_current_user(struct st_context *st, = _mesa_draw_current_attrib(ctx, attr); const unsigned bufidx = (*num_vbuffers)++; - init_velement_lowered(vp, velements, &attrib->Format, 0, 0, - bufidx, input_to_index[attr]); + init_velement(vp, velements->velems, &attrib->Format, 0, 0, + bufidx, input_to_index[attr]); vbuffer[bufidx].is_user_buffer = true; vbuffer[bufidx].buffer.user = attrib->Ptr; @@ -273,39 +330,34 @@ st_update_array(struct st_context *st) const struct st_common_variant *vp_variant = st->vp_variant; struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS]; - unsigned num_vbuffers = 0, first_upload_vbuffer; - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - unsigned num_velements; + unsigned num_vbuffers = 0; + struct cso_velems_state velements; bool uses_user_vertex_buffers; - st->draw_needs_minmax_index = false; - /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */ /* Setup arrays */ - st_setup_arrays(st, vp, vp_variant, velements, vbuffer, &num_vbuffers, + st_setup_arrays(st, vp, vp_variant, &velements, vbuffer, &num_vbuffers, &uses_user_vertex_buffers); /* _NEW_CURRENT_ATTRIB */ - /* Setup current uploads */ - first_upload_vbuffer = num_vbuffers; - st_setup_current(st, vp, vp_variant, velements, vbuffer, &num_vbuffers); + /* Setup zero-stride attribs. */ + int current_attrib_buffer = + st_setup_current(st, vp, vp_variant, &velements, vbuffer, &num_vbuffers); - /* Set the array into cso */ - num_velements = vp->num_inputs + vp_variant->key.passthrough_edgeflags; + velements.count = vp->num_inputs + vp_variant->key.passthrough_edgeflags; /* Set vertex buffers and elements. */ struct cso_context *cso = st->cso_context; unsigned unbind_trailing_vbuffers = st->last_num_vbuffers > num_vbuffers ? st->last_num_vbuffers - num_vbuffers : 0; - cso_set_vertex_buffers_and_elements(cso, num_velements, velements, + cso_set_vertex_buffers_and_elements(cso, &velements, num_vbuffers, unbind_trailing_vbuffers, vbuffer, uses_user_vertex_buffers); st->last_num_vbuffers = num_vbuffers; - /* Unreference uploaded buffer resources. */ - for (unsigned i = first_upload_vbuffer; i < num_vbuffers; ++i) { - pipe_resource_reference(&vbuffer[i].buffer.resource, NULL); - } + /* Unreference uploaded current attrib buffer. */ + if (current_attrib_buffer >= 0) + pipe_resource_reference(&vbuffer[current_attrib_buffer].buffer.resource, NULL); }