summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2016-10-10 20:20:22 +0200
committerNicolai Hähnle <nicolai.haehnle@amd.com>2016-10-13 15:41:36 +0200
commitd413fbb159d0ddac16bb9d93bdda4fe598d39e17 (patch)
treeb59559d33dcddafb8e5a7afa22d077b0133ed4a6
parent15fc74905b64ab41e47d5b50407596ceaeced638 (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: mesa-stable@lists.freedesktop.org Reviewed-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/mesa/state_tracker/st_atom_array.c98
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);
}