st/mesa: fix assertion failures with GL_UNSIGNED_INT64_ARB (v2)
[mesa.git] / src / mesa / state_tracker / st_atom_array.c
1
2 /**************************************************************************
3 *
4 * Copyright 2007 VMware, Inc.
5 * Copyright 2012 Marek Olšák <maraeo@gmail.com>
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30 /*
31 * This converts the VBO's vertex attribute/array information into
32 * Gallium vertex state and binds it.
33 *
34 * Authors:
35 * Keith Whitwell <keithw@vmware.com>
36 * Marek Olšák <maraeo@gmail.com>
37 */
38
39 #include "st_context.h"
40 #include "st_atom.h"
41 #include "st_cb_bufferobjects.h"
42 #include "st_draw.h"
43 #include "st_program.h"
44
45 #include "cso_cache/cso_context.h"
46 #include "util/u_math.h"
47 #include "util/u_upload_mgr.h"
48 #include "main/bufferobj.h"
49 #include "main/glformats.h"
50 #include "main/varray.h"
51 #include "main/arrayobj.h"
52
53 /* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */
54 static const uint16_t vertex_formats[][4][4] = {
55 { /* GL_BYTE */
56 {
57 PIPE_FORMAT_R8_SSCALED,
58 PIPE_FORMAT_R8G8_SSCALED,
59 PIPE_FORMAT_R8G8B8_SSCALED,
60 PIPE_FORMAT_R8G8B8A8_SSCALED
61 },
62 {
63 PIPE_FORMAT_R8_SNORM,
64 PIPE_FORMAT_R8G8_SNORM,
65 PIPE_FORMAT_R8G8B8_SNORM,
66 PIPE_FORMAT_R8G8B8A8_SNORM
67 },
68 {
69 PIPE_FORMAT_R8_SINT,
70 PIPE_FORMAT_R8G8_SINT,
71 PIPE_FORMAT_R8G8B8_SINT,
72 PIPE_FORMAT_R8G8B8A8_SINT
73 },
74 },
75 { /* GL_UNSIGNED_BYTE */
76 {
77 PIPE_FORMAT_R8_USCALED,
78 PIPE_FORMAT_R8G8_USCALED,
79 PIPE_FORMAT_R8G8B8_USCALED,
80 PIPE_FORMAT_R8G8B8A8_USCALED
81 },
82 {
83 PIPE_FORMAT_R8_UNORM,
84 PIPE_FORMAT_R8G8_UNORM,
85 PIPE_FORMAT_R8G8B8_UNORM,
86 PIPE_FORMAT_R8G8B8A8_UNORM
87 },
88 {
89 PIPE_FORMAT_R8_UINT,
90 PIPE_FORMAT_R8G8_UINT,
91 PIPE_FORMAT_R8G8B8_UINT,
92 PIPE_FORMAT_R8G8B8A8_UINT
93 },
94 },
95 { /* GL_SHORT */
96 {
97 PIPE_FORMAT_R16_SSCALED,
98 PIPE_FORMAT_R16G16_SSCALED,
99 PIPE_FORMAT_R16G16B16_SSCALED,
100 PIPE_FORMAT_R16G16B16A16_SSCALED
101 },
102 {
103 PIPE_FORMAT_R16_SNORM,
104 PIPE_FORMAT_R16G16_SNORM,
105 PIPE_FORMAT_R16G16B16_SNORM,
106 PIPE_FORMAT_R16G16B16A16_SNORM
107 },
108 {
109 PIPE_FORMAT_R16_SINT,
110 PIPE_FORMAT_R16G16_SINT,
111 PIPE_FORMAT_R16G16B16_SINT,
112 PIPE_FORMAT_R16G16B16A16_SINT
113 },
114 },
115 { /* GL_UNSIGNED_SHORT */
116 {
117 PIPE_FORMAT_R16_USCALED,
118 PIPE_FORMAT_R16G16_USCALED,
119 PIPE_FORMAT_R16G16B16_USCALED,
120 PIPE_FORMAT_R16G16B16A16_USCALED
121 },
122 {
123 PIPE_FORMAT_R16_UNORM,
124 PIPE_FORMAT_R16G16_UNORM,
125 PIPE_FORMAT_R16G16B16_UNORM,
126 PIPE_FORMAT_R16G16B16A16_UNORM
127 },
128 {
129 PIPE_FORMAT_R16_UINT,
130 PIPE_FORMAT_R16G16_UINT,
131 PIPE_FORMAT_R16G16B16_UINT,
132 PIPE_FORMAT_R16G16B16A16_UINT
133 },
134 },
135 { /* GL_INT */
136 {
137 PIPE_FORMAT_R32_SSCALED,
138 PIPE_FORMAT_R32G32_SSCALED,
139 PIPE_FORMAT_R32G32B32_SSCALED,
140 PIPE_FORMAT_R32G32B32A32_SSCALED
141 },
142 {
143 PIPE_FORMAT_R32_SNORM,
144 PIPE_FORMAT_R32G32_SNORM,
145 PIPE_FORMAT_R32G32B32_SNORM,
146 PIPE_FORMAT_R32G32B32A32_SNORM
147 },
148 {
149 PIPE_FORMAT_R32_SINT,
150 PIPE_FORMAT_R32G32_SINT,
151 PIPE_FORMAT_R32G32B32_SINT,
152 PIPE_FORMAT_R32G32B32A32_SINT
153 },
154 },
155 { /* GL_UNSIGNED_INT */
156 {
157 PIPE_FORMAT_R32_USCALED,
158 PIPE_FORMAT_R32G32_USCALED,
159 PIPE_FORMAT_R32G32B32_USCALED,
160 PIPE_FORMAT_R32G32B32A32_USCALED
161 },
162 {
163 PIPE_FORMAT_R32_UNORM,
164 PIPE_FORMAT_R32G32_UNORM,
165 PIPE_FORMAT_R32G32B32_UNORM,
166 PIPE_FORMAT_R32G32B32A32_UNORM
167 },
168 {
169 PIPE_FORMAT_R32_UINT,
170 PIPE_FORMAT_R32G32_UINT,
171 PIPE_FORMAT_R32G32B32_UINT,
172 PIPE_FORMAT_R32G32B32A32_UINT
173 },
174 },
175 { /* GL_FLOAT */
176 {
177 PIPE_FORMAT_R32_FLOAT,
178 PIPE_FORMAT_R32G32_FLOAT,
179 PIPE_FORMAT_R32G32B32_FLOAT,
180 PIPE_FORMAT_R32G32B32A32_FLOAT
181 },
182 {
183 PIPE_FORMAT_R32_FLOAT,
184 PIPE_FORMAT_R32G32_FLOAT,
185 PIPE_FORMAT_R32G32B32_FLOAT,
186 PIPE_FORMAT_R32G32B32A32_FLOAT
187 },
188 },
189 {{0}}, /* GL_2_BYTES */
190 {{0}}, /* GL_3_BYTES */
191 {{0}}, /* GL_4_BYTES */
192 { /* GL_DOUBLE */
193 {
194 PIPE_FORMAT_R64_FLOAT,
195 PIPE_FORMAT_R64G64_FLOAT,
196 PIPE_FORMAT_R64G64B64_FLOAT,
197 PIPE_FORMAT_R64G64B64A64_FLOAT
198 },
199 {
200 PIPE_FORMAT_R64_FLOAT,
201 PIPE_FORMAT_R64G64_FLOAT,
202 PIPE_FORMAT_R64G64B64_FLOAT,
203 PIPE_FORMAT_R64G64B64A64_FLOAT
204 },
205 },
206 { /* GL_HALF_FLOAT */
207 {
208 PIPE_FORMAT_R16_FLOAT,
209 PIPE_FORMAT_R16G16_FLOAT,
210 PIPE_FORMAT_R16G16B16_FLOAT,
211 PIPE_FORMAT_R16G16B16A16_FLOAT
212 },
213 {
214 PIPE_FORMAT_R16_FLOAT,
215 PIPE_FORMAT_R16G16_FLOAT,
216 PIPE_FORMAT_R16G16B16_FLOAT,
217 PIPE_FORMAT_R16G16B16A16_FLOAT
218 },
219 },
220 { /* GL_FIXED */
221 {
222 PIPE_FORMAT_R32_FIXED,
223 PIPE_FORMAT_R32G32_FIXED,
224 PIPE_FORMAT_R32G32B32_FIXED,
225 PIPE_FORMAT_R32G32B32A32_FIXED
226 },
227 {
228 PIPE_FORMAT_R32_FIXED,
229 PIPE_FORMAT_R32G32_FIXED,
230 PIPE_FORMAT_R32G32B32_FIXED,
231 PIPE_FORMAT_R32G32B32A32_FIXED
232 },
233 },
234 };
235
236
237 /**
238 * Return a PIPE_FORMAT_x for the given GL datatype and size.
239 */
240 enum pipe_format
241 st_pipe_vertex_format(const struct gl_array_attributes *attrib)
242 {
243 const GLubyte size = attrib->Size;
244 const GLenum16 format = attrib->Format;
245 const bool normalized = attrib->Normalized;
246 const bool integer = attrib->Integer;
247 GLenum16 type = attrib->Type;
248 unsigned index;
249
250 assert(size >= 1 && size <= 4);
251 assert(format == GL_RGBA || format == GL_BGRA);
252 assert(attrib->_ElementSize == _mesa_bytes_per_vertex_attrib(size, type));
253
254 switch (type) {
255 case GL_HALF_FLOAT_OES:
256 type = GL_HALF_FLOAT;
257 break;
258
259 case GL_INT_2_10_10_10_REV:
260 assert(size == 4 && !integer);
261
262 if (format == GL_BGRA) {
263 if (normalized)
264 return PIPE_FORMAT_B10G10R10A2_SNORM;
265 else
266 return PIPE_FORMAT_B10G10R10A2_SSCALED;
267 } else {
268 if (normalized)
269 return PIPE_FORMAT_R10G10B10A2_SNORM;
270 else
271 return PIPE_FORMAT_R10G10B10A2_SSCALED;
272 }
273 break;
274
275 case GL_UNSIGNED_INT_2_10_10_10_REV:
276 assert(size == 4 && !integer);
277
278 if (format == GL_BGRA) {
279 if (normalized)
280 return PIPE_FORMAT_B10G10R10A2_UNORM;
281 else
282 return PIPE_FORMAT_B10G10R10A2_USCALED;
283 } else {
284 if (normalized)
285 return PIPE_FORMAT_R10G10B10A2_UNORM;
286 else
287 return PIPE_FORMAT_R10G10B10A2_USCALED;
288 }
289 break;
290
291 case GL_UNSIGNED_INT_10F_11F_11F_REV:
292 assert(size == 3 && !integer && format == GL_RGBA);
293 return PIPE_FORMAT_R11G11B10_FLOAT;
294
295 case GL_UNSIGNED_BYTE:
296 if (format == GL_BGRA) {
297 /* this is an odd-ball case */
298 assert(normalized);
299 return PIPE_FORMAT_B8G8R8A8_UNORM;
300 }
301 break;
302 }
303
304 index = integer*2 + normalized;
305 assert(index <= 2);
306 assert(type >= GL_BYTE && type <= GL_FIXED);
307 return vertex_formats[type - GL_BYTE][index][size-1];
308 }
309
310 static void init_velement(struct pipe_vertex_element *velement,
311 int src_offset, int format,
312 int instance_divisor, int vbo_index)
313 {
314 velement->src_offset = src_offset;
315 velement->src_format = format;
316 velement->instance_divisor = instance_divisor;
317 velement->vertex_buffer_index = vbo_index;
318 assert(velement->src_format);
319 }
320
321 static void init_velement_lowered(const struct st_vertex_program *vp,
322 struct pipe_vertex_element *velements,
323 const struct gl_array_attributes *attrib,
324 int src_offset, int instance_divisor,
325 int vbo_index, int idx)
326 {
327 const GLubyte nr_components = attrib->Size;
328
329 if (attrib->Doubles) {
330 int lower_format;
331
332 if (nr_components < 2)
333 lower_format = PIPE_FORMAT_R32G32_UINT;
334 else
335 lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
336
337 init_velement(&velements[idx], src_offset,
338 lower_format, instance_divisor, vbo_index);
339 idx++;
340
341 if (idx < vp->num_inputs &&
342 vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) {
343 if (nr_components >= 3) {
344 if (nr_components == 3)
345 lower_format = PIPE_FORMAT_R32G32_UINT;
346 else
347 lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
348
349 init_velement(&velements[idx], src_offset + 4 * sizeof(float),
350 lower_format, instance_divisor, vbo_index);
351 } else {
352 /* The values here are undefined. Fill in some conservative
353 * dummy values.
354 */
355 init_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT,
356 instance_divisor, vbo_index);
357 }
358 }
359 } else {
360 const unsigned format = st_pipe_vertex_format(attrib);
361
362 init_velement(&velements[idx], src_offset,
363 format, instance_divisor, vbo_index);
364 }
365 }
366
367 static void
368 set_vertex_attribs(struct st_context *st,
369 struct pipe_vertex_buffer *vbuffers,
370 unsigned num_vbuffers,
371 struct pipe_vertex_element *velements,
372 unsigned num_velements)
373 {
374 struct cso_context *cso = st->cso_context;
375
376 cso_set_vertex_buffers(cso, 0, num_vbuffers, vbuffers);
377 if (st->last_num_vbuffers > num_vbuffers) {
378 /* Unbind remaining buffers, if any. */
379 cso_set_vertex_buffers(cso, num_vbuffers,
380 st->last_num_vbuffers - num_vbuffers, NULL);
381 }
382 st->last_num_vbuffers = num_vbuffers;
383 cso_set_vertex_elements(cso, num_velements, velements);
384 }
385
386 void
387 st_update_array(struct st_context *st)
388 {
389 struct gl_context *ctx = st->ctx;
390 /* vertex program validation must be done before this */
391 const struct st_vertex_program *vp = st->vp;
392 /* _NEW_PROGRAM, ST_NEW_VS_STATE */
393 const GLbitfield inputs_read = st->vp_variant->vert_attrib_mask;
394 const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
395 const ubyte *input_to_index = vp->input_to_index;
396
397 struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
398 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
399 unsigned num_vbuffers = 0;
400
401 st->vertex_array_out_of_memory = FALSE;
402 st->draw_needs_minmax_index = false;
403
404 /* _NEW_PROGRAM */
405 /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */
406 /* Process attribute array data. */
407 GLbitfield mask = inputs_read & _mesa_draw_array_bits(ctx);
408 while (mask) {
409 /* The attribute index to start pulling a binding */
410 const gl_vert_attrib i = ffs(mask) - 1;
411 const struct gl_vertex_buffer_binding *const binding
412 = _mesa_draw_buffer_binding(vao, i);
413 const unsigned bufidx = num_vbuffers++;
414
415 if (_mesa_is_bufferobj(binding->BufferObj)) {
416 struct st_buffer_object *stobj = st_buffer_object(binding->BufferObj);
417 if (!stobj || !stobj->buffer) {
418 st->vertex_array_out_of_memory = true;
419 return; /* out-of-memory error probably */
420 }
421
422 /* Set the binding */
423 vbuffer[bufidx].buffer.resource = stobj->buffer;
424 vbuffer[bufidx].is_user_buffer = false;
425 vbuffer[bufidx].buffer_offset = _mesa_draw_binding_offset(binding);
426 } else {
427 /* Set the binding */
428 const void *ptr = (const void *)_mesa_draw_binding_offset(binding);
429 vbuffer[bufidx].buffer.user = ptr;
430 vbuffer[bufidx].is_user_buffer = true;
431 vbuffer[bufidx].buffer_offset = 0;
432
433 if (!binding->InstanceDivisor)
434 st->draw_needs_minmax_index = true;
435 }
436 vbuffer[bufidx].stride = binding->Stride; /* in bytes */
437
438 const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
439 GLbitfield attrmask = mask & boundmask;
440 /* Mark the those attributes as processed */
441 mask &= ~boundmask;
442 /* We can assume that we have array for the binding */
443 assert(attrmask);
444 /* Walk attributes belonging to the binding */
445 while (attrmask) {
446 const gl_vert_attrib attr = u_bit_scan(&attrmask);
447 const struct gl_array_attributes *const attrib
448 = _mesa_draw_array_attrib(vao, attr);
449 const GLuint off = _mesa_draw_attributes_relative_offset(attrib);
450 init_velement_lowered(vp, velements, attrib, off,
451 binding->InstanceDivisor, bufidx,
452 input_to_index[attr]);
453 }
454 }
455
456 const unsigned first_current_vbuffer = num_vbuffers;
457 /* _NEW_PROGRAM | _NEW_CURRENT_ATTRIB */
458 /* Process values that should have better been uniforms in the application */
459 GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
460 if (curmask) {
461 /* For each attribute, upload the maximum possible size. */
462 GLubyte data[VERT_ATTRIB_MAX * sizeof(GLdouble) * 4];
463 GLubyte *cursor = data;
464 const unsigned bufidx = num_vbuffers++;
465 unsigned max_alignment = 1;
466
467 while (curmask) {
468 const gl_vert_attrib attr = u_bit_scan(&curmask);
469 const struct gl_array_attributes *const attrib
470 = _mesa_draw_current_attrib(ctx, attr);
471 const unsigned size = attrib->_ElementSize;
472 const unsigned alignment = util_next_power_of_two(size);
473 max_alignment = MAX2(max_alignment, alignment);
474 memcpy(cursor, attrib->Ptr, size);
475 if (alignment != size)
476 memset(cursor + size, 0, alignment - size);
477
478 init_velement_lowered(vp, velements, attrib, cursor - data, 0,
479 bufidx, input_to_index[attr]);
480
481 cursor += alignment;
482 }
483
484 vbuffer[bufidx].is_user_buffer = false;
485 vbuffer[bufidx].buffer.resource = NULL;
486 /* vbuffer[bufidx].buffer_offset is set below */
487 vbuffer[bufidx].stride = 0;
488
489 /* Use const_uploader for zero-stride vertex attributes, because
490 * it may use a better memory placement than stream_uploader.
491 * The reason is that zero-stride attributes can be fetched many
492 * times (thousands of times), so a better placement is going to
493 * perform better.
494 */
495 u_upload_data(st->can_bind_const_buffer_as_vertex ?
496 st->pipe->const_uploader :
497 st->pipe->stream_uploader,
498 0, cursor - data, max_alignment, data,
499 &vbuffer[bufidx].buffer_offset,
500 &vbuffer[bufidx].buffer.resource);
501 }
502
503 if (!ctx->Const.AllowMappedBuffersDuringExecution) {
504 u_upload_unmap(st->pipe->stream_uploader);
505 }
506
507 const unsigned num_inputs = st->vp_variant->num_inputs;
508 set_vertex_attribs(st, vbuffer, num_vbuffers, velements, num_inputs);
509
510 /* Unreference uploaded zero-stride vertex buffers. */
511 for (unsigned i = first_current_vbuffer; i < num_vbuffers; ++i) {
512 pipe_resource_reference(&vbuffer[i].buffer.resource, NULL);
513 }
514 }