diff options
author | Nicolai Hähnle <[email protected]> | 2016-10-10 20:20:22 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2016-10-13 15:41:36 +0200 |
commit | d413fbb159d0ddac16bb9d93bdda4fe598d39e17 (patch) | |
tree | b59559d33dcddafb8e5a7afa22d077b0133ed4a6 /src/mesa/state_tracker | |
parent | 15fc74905b64ab41e47d5b50407596ceaeced638 (diff) |
st/mesa: fix vertex elements setup for doubles
Whether one or two slots are taken up by one API array depends on the
vertex shader, not on how the array is configured. When an array is
set up with fewer components than the shader expects, the high components
are undefined.
Fixes GL45-CTS.vertex_attrib_binding.basic-inputL-case1.
Cc: [email protected]
Reviewed-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r-- | src/mesa/state_tracker/st_atom_array.c | 98 |
1 files changed, 50 insertions, 48 deletions
diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c index 1c2cfa791cd..e5b949fbaec 100644 --- a/src/mesa/state_tracker/st_atom_array.c +++ b/src/mesa/state_tracker/st_atom_array.c @@ -386,6 +386,7 @@ static void init_velement(struct pipe_vertex_element *velement, } static void init_velement_lowered(struct st_context *st, + const struct st_vertex_program *vp, struct pipe_vertex_element *velements, int src_offset, int format, int instance_divisor, int vbo_index, @@ -396,23 +397,33 @@ static void init_velement_lowered(struct st_context *st, if (doubles) { int lower_format; - if (nr_components == 1) + if (nr_components < 2) lower_format = PIPE_FORMAT_R32G32_UINT; - else if (nr_components >= 2) + else lower_format = PIPE_FORMAT_R32G32B32A32_UINT; init_velement(&velements[idx], src_offset, lower_format, instance_divisor, vbo_index); idx++; - if (nr_components > 2) { - if (nr_components == 3) - lower_format = PIPE_FORMAT_R32G32_UINT; - else if (nr_components >= 4) - lower_format = PIPE_FORMAT_R32G32B32A32_UINT; + 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); + } - init_velement(&velements[idx], src_offset + 4 * sizeof(float), - lower_format, instance_divisor, vbo_index); idx++; } } else { @@ -435,10 +446,9 @@ setup_interleaved_attribs(struct st_context *st, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, struct pipe_vertex_buffer *vbuffer, - struct pipe_vertex_element velements[], - unsigned *num_velements) + struct pipe_vertex_element velements[]) { - GLuint attr, attr_idx; + GLuint attr; const GLubyte *low_addr = NULL; GLboolean usingVBO; /* all arrays in a VBO? */ struct gl_buffer_object *bufobj; @@ -481,15 +491,13 @@ setup_interleaved_attribs(struct st_context *st, /* are the arrays in user space? */ usingVBO = _mesa_is_bufferobj(bufobj); - attr_idx = 0; - for (attr = 0; attr < vpv->num_inputs; attr++) { + for (attr = 0; attr < vpv->num_inputs;) { const struct gl_client_array *array; unsigned src_offset; unsigned src_format; array = get_client_array(vp, arrays, attr); - if (!array) - continue; + assert(array); src_offset = (unsigned) (array->Ptr - low_addr); assert(array->_ElementSize == @@ -501,13 +509,11 @@ setup_interleaved_attribs(struct st_context *st, array->Normalized, array->Integer); - init_velement_lowered(st, velements, src_offset, src_format, + init_velement_lowered(st, vp, velements, src_offset, src_format, array->InstanceDivisor, 0, - array->Size, array->Doubles, &attr_idx); + array->Size, array->Doubles, &attr); } - *num_velements = attr_idx; - /* * Return the vbuffer info and setup user-space attrib info, if needed. */ @@ -554,25 +560,25 @@ setup_non_interleaved_attribs(struct st_context *st, const struct gl_client_array **arrays, struct pipe_vertex_buffer vbuffer[], struct pipe_vertex_element velements[], - unsigned *num_velements) + unsigned *num_vbuffers) { struct gl_context *ctx = st->ctx; - GLuint attr, attr_idx = 0; + GLuint attr; - for (attr = 0; attr < vpv->num_inputs; attr++) { + *num_vbuffers = 0; + + for (attr = 0; attr < vpv->num_inputs;) { const GLuint mesaAttr = vp->index_to_input[attr]; const struct gl_client_array *array; struct gl_buffer_object *bufobj; GLsizei stride; unsigned src_format; + unsigned bufidx; array = get_client_array(vp, arrays, attr); - if (!array) { - vbuffer[attr].buffer = NULL; - vbuffer[attr].user_buffer = NULL; - vbuffer[attr].buffer_offset = 0; - continue; - } + assert(array); + + bufidx = (*num_vbuffers)++; stride = array->StrideB; bufobj = array->BufferObj; @@ -590,9 +596,9 @@ setup_non_interleaved_attribs(struct st_context *st, return FALSE; /* out-of-memory error probably */ } - vbuffer[attr].buffer = stobj->buffer; - vbuffer[attr].user_buffer = NULL; - vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr); + vbuffer[bufidx].buffer = stobj->buffer; + vbuffer[bufidx].user_buffer = NULL; + vbuffer[bufidx].buffer_offset = pointer_to_offset(array->Ptr); } else { /* wrap user data */ @@ -609,13 +615,13 @@ setup_non_interleaved_attribs(struct st_context *st, assert(ptr); - vbuffer[attr].buffer = NULL; - vbuffer[attr].user_buffer = ptr; - vbuffer[attr].buffer_offset = 0; + vbuffer[bufidx].buffer = NULL; + vbuffer[bufidx].user_buffer = ptr; + vbuffer[bufidx].buffer_offset = 0; } /* common-case setup */ - vbuffer[attr].stride = stride; /* in bytes */ + vbuffer[bufidx].stride = stride; /* in bytes */ src_format = st_pipe_vertex_format(array->Type, array->Size, @@ -623,13 +629,11 @@ setup_non_interleaved_attribs(struct st_context *st, array->Normalized, array->Integer); - init_velement_lowered(st, velements, 0, src_format, - array->InstanceDivisor, attr, - array->Size, array->Doubles, &attr_idx); - + init_velement_lowered(st, vp, velements, 0, src_format, + array->InstanceDivisor, bufidx, + array->Size, array->Doubles, &attr); } - *num_velements = attr_idx; return TRUE; } @@ -641,7 +645,7 @@ static void update_array(struct st_context *st) const struct st_vp_variant *vpv; struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - unsigned num_vbuffers, num_velements; + unsigned num_vbuffers; st->vertex_array_out_of_memory = FALSE; @@ -659,23 +663,21 @@ static void update_array(struct st_context *st) * Setup the vbuffer[] and velements[] arrays. */ if (is_interleaved_arrays(vp, vpv, arrays)) { - if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) { + if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements)) { st->vertex_array_out_of_memory = TRUE; return; } num_vbuffers = 1; - if (num_velements == 0) + if (vpv->num_inputs == 0) num_vbuffers = 0; } else { if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer, - velements, &num_velements)) { + velements, &num_vbuffers)) { st->vertex_array_out_of_memory = TRUE; return; } - - num_vbuffers = vpv->num_inputs; } cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer); @@ -685,7 +687,7 @@ static void update_array(struct st_context *st) st->last_num_vbuffers - num_vbuffers, NULL); } st->last_num_vbuffers = num_vbuffers; - cso_set_vertex_elements(st->cso_context, num_velements, velements); + cso_set_vertex_elements(st->cso_context, vpv->num_inputs, velements); } |