9041041006ec58864da49bad3df1c1da94a1578f
[mesa.git] / src / gallium / auxiliary / draw / draw_vertex_fetch.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33 #include "pipe/p_util.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "draw_private.h"
36 #include "draw_context.h"
37
38
39 #define DRAW_DBG 0
40
41
42 /**
43 * Fetch a float[4] vertex attribute from memory, doing format/type
44 * conversion as needed.
45 *
46 * This is probably needed/dupliocated elsewhere, eg format
47 * conversion, texture sampling etc.
48 */
49 #define FETCH_ATTRIB( NAME, SZ, CVT ) \
50 static void \
51 fetch_##NAME(const void *ptr, float *attrib) \
52 { \
53 static const float defaults[4] = { 0,0,0,1 }; \
54 int i; \
55 \
56 for (i = 0; i < SZ; i++) { \
57 attrib[i] = CVT(i); \
58 } \
59 \
60 for (; i < 4; i++) { \
61 attrib[i] = defaults[i]; \
62 } \
63 }
64
65 #define CVT_64_FLOAT(i) (float) ((double *) ptr)[i]
66 #define CVT_32_FLOAT(i) ((float *) ptr)[i]
67
68 #define CVT_8_USCALED(i) (float) ((unsigned char *) ptr)[i]
69 #define CVT_16_USCALED(i) (float) ((unsigned short *) ptr)[i]
70 #define CVT_32_USCALED(i) (float) ((unsigned int *) ptr)[i]
71
72 #define CVT_8_SSCALED(i) (float) ((char *) ptr)[i]
73 #define CVT_16_SSCALED(i) (float) ((short *) ptr)[i]
74 #define CVT_32_SSCALED(i) (float) ((int *) ptr)[i]
75
76 #define CVT_8_UNORM(i) (float) ((unsigned char *) ptr)[i] / 255.0f
77 #define CVT_16_UNORM(i) (float) ((unsigned short *) ptr)[i] / 65535.0f
78 #define CVT_32_UNORM(i) (float) ((unsigned int *) ptr)[i] / 4294967295.0f
79
80 #define CVT_8_SNORM(i) (float) ((char *) ptr)[i] / 127.0f
81 #define CVT_16_SNORM(i) (float) ((short *) ptr)[i] / 32767.0f
82 #define CVT_32_SNORM(i) (float) ((int *) ptr)[i] / 2147483647.0f
83
84 FETCH_ATTRIB( R64G64B64A64_FLOAT, 4, CVT_64_FLOAT )
85 FETCH_ATTRIB( R64G64B64_FLOAT, 3, CVT_64_FLOAT )
86 FETCH_ATTRIB( R64G64_FLOAT, 2, CVT_64_FLOAT )
87 FETCH_ATTRIB( R64_FLOAT, 1, CVT_64_FLOAT )
88
89 FETCH_ATTRIB( R32G32B32A32_FLOAT, 4, CVT_32_FLOAT )
90 FETCH_ATTRIB( R32G32B32_FLOAT, 3, CVT_32_FLOAT )
91 FETCH_ATTRIB( R32G32_FLOAT, 2, CVT_32_FLOAT )
92 FETCH_ATTRIB( R32_FLOAT, 1, CVT_32_FLOAT )
93
94 FETCH_ATTRIB( R32G32B32A32_USCALED, 4, CVT_32_USCALED )
95 FETCH_ATTRIB( R32G32B32_USCALED, 3, CVT_32_USCALED )
96 FETCH_ATTRIB( R32G32_USCALED, 2, CVT_32_USCALED )
97 FETCH_ATTRIB( R32_USCALED, 1, CVT_32_USCALED )
98
99 FETCH_ATTRIB( R32G32B32A32_SSCALED, 4, CVT_32_SSCALED )
100 FETCH_ATTRIB( R32G32B32_SSCALED, 3, CVT_32_SSCALED )
101 FETCH_ATTRIB( R32G32_SSCALED, 2, CVT_32_SSCALED )
102 FETCH_ATTRIB( R32_SSCALED, 1, CVT_32_SSCALED )
103
104 FETCH_ATTRIB( R32G32B32A32_UNORM, 4, CVT_32_UNORM )
105 FETCH_ATTRIB( R32G32B32_UNORM, 3, CVT_32_UNORM )
106 FETCH_ATTRIB( R32G32_UNORM, 2, CVT_32_UNORM )
107 FETCH_ATTRIB( R32_UNORM, 1, CVT_32_UNORM )
108
109 FETCH_ATTRIB( R32G32B32A32_SNORM, 4, CVT_32_SNORM )
110 FETCH_ATTRIB( R32G32B32_SNORM, 3, CVT_32_SNORM )
111 FETCH_ATTRIB( R32G32_SNORM, 2, CVT_32_SNORM )
112 FETCH_ATTRIB( R32_SNORM, 1, CVT_32_SNORM )
113
114 FETCH_ATTRIB( R16G16B16A16_USCALED, 4, CVT_16_USCALED )
115 FETCH_ATTRIB( R16G16B16_USCALED, 3, CVT_16_USCALED )
116 FETCH_ATTRIB( R16G16_USCALED, 2, CVT_16_USCALED )
117 FETCH_ATTRIB( R16_USCALED, 1, CVT_16_USCALED )
118
119 FETCH_ATTRIB( R16G16B16A16_SSCALED, 4, CVT_16_SSCALED )
120 FETCH_ATTRIB( R16G16B16_SSCALED, 3, CVT_16_SSCALED )
121 FETCH_ATTRIB( R16G16_SSCALED, 2, CVT_16_SSCALED )
122 FETCH_ATTRIB( R16_SSCALED, 1, CVT_16_SSCALED )
123
124 FETCH_ATTRIB( R16G16B16A16_UNORM, 4, CVT_16_UNORM )
125 FETCH_ATTRIB( R16G16B16_UNORM, 3, CVT_16_UNORM )
126 FETCH_ATTRIB( R16G16_UNORM, 2, CVT_16_UNORM )
127 FETCH_ATTRIB( R16_UNORM, 1, CVT_16_UNORM )
128
129 FETCH_ATTRIB( R16G16B16A16_SNORM, 4, CVT_16_SNORM )
130 FETCH_ATTRIB( R16G16B16_SNORM, 3, CVT_16_SNORM )
131 FETCH_ATTRIB( R16G16_SNORM, 2, CVT_16_SNORM )
132 FETCH_ATTRIB( R16_SNORM, 1, CVT_16_SNORM )
133
134 FETCH_ATTRIB( R8G8B8A8_USCALED, 4, CVT_8_USCALED )
135 FETCH_ATTRIB( R8G8B8_USCALED, 3, CVT_8_USCALED )
136 FETCH_ATTRIB( R8G8_USCALED, 2, CVT_8_USCALED )
137 FETCH_ATTRIB( R8_USCALED, 1, CVT_8_USCALED )
138
139 FETCH_ATTRIB( R8G8B8A8_SSCALED, 4, CVT_8_SSCALED )
140 FETCH_ATTRIB( R8G8B8_SSCALED, 3, CVT_8_SSCALED )
141 FETCH_ATTRIB( R8G8_SSCALED, 2, CVT_8_SSCALED )
142 FETCH_ATTRIB( R8_SSCALED, 1, CVT_8_SSCALED )
143
144 FETCH_ATTRIB( R8G8B8A8_UNORM, 4, CVT_8_UNORM )
145 FETCH_ATTRIB( R8G8B8_UNORM, 3, CVT_8_UNORM )
146 FETCH_ATTRIB( R8G8_UNORM, 2, CVT_8_UNORM )
147 FETCH_ATTRIB( R8_UNORM, 1, CVT_8_UNORM )
148
149 FETCH_ATTRIB( R8G8B8A8_SNORM, 4, CVT_8_SNORM )
150 FETCH_ATTRIB( R8G8B8_SNORM, 3, CVT_8_SNORM )
151 FETCH_ATTRIB( R8G8_SNORM, 2, CVT_8_SNORM )
152 FETCH_ATTRIB( R8_SNORM, 1, CVT_8_SNORM )
153
154 FETCH_ATTRIB( A8R8G8B8_UNORM, 4, CVT_8_UNORM )
155 //FETCH_ATTRIB( R8G8B8A8_UNORM, 4, CVT_8_UNORM )
156
157
158
159 static void
160 fetch_B8G8R8A8_UNORM(const void *ptr, float *attrib)
161 {
162 attrib[2] = CVT_8_UNORM(0);
163 attrib[1] = CVT_8_UNORM(1);
164 attrib[0] = CVT_8_UNORM(2);
165 attrib[3] = CVT_8_UNORM(3);
166 }
167
168
169 fetch_func draw_get_fetch_func( enum pipe_format format )
170 {
171 #if 0
172 {
173 char tmp[80];
174 pf_sprint_name(tmp, format);
175 debug_printf("%s: %s\n", __FUNCTION__, tmp);
176 }
177 #endif
178
179 switch (format) {
180 case PIPE_FORMAT_R64_FLOAT:
181 return fetch_R64_FLOAT;
182 case PIPE_FORMAT_R64G64_FLOAT:
183 return fetch_R64G64_FLOAT;
184 case PIPE_FORMAT_R64G64B64_FLOAT:
185 return fetch_R64G64B64_FLOAT;
186 case PIPE_FORMAT_R64G64B64A64_FLOAT:
187 return fetch_R64G64B64A64_FLOAT;
188
189 case PIPE_FORMAT_R32_FLOAT:
190 return fetch_R32_FLOAT;
191 case PIPE_FORMAT_R32G32_FLOAT:
192 return fetch_R32G32_FLOAT;
193 case PIPE_FORMAT_R32G32B32_FLOAT:
194 return fetch_R32G32B32_FLOAT;
195 case PIPE_FORMAT_R32G32B32A32_FLOAT:
196 return fetch_R32G32B32A32_FLOAT;
197
198 case PIPE_FORMAT_R32_UNORM:
199 return fetch_R32_UNORM;
200 case PIPE_FORMAT_R32G32_UNORM:
201 return fetch_R32G32_UNORM;
202 case PIPE_FORMAT_R32G32B32_UNORM:
203 return fetch_R32G32B32_UNORM;
204 case PIPE_FORMAT_R32G32B32A32_UNORM:
205 return fetch_R32G32B32A32_UNORM;
206
207 case PIPE_FORMAT_R32_USCALED:
208 return fetch_R32_USCALED;
209 case PIPE_FORMAT_R32G32_USCALED:
210 return fetch_R32G32_USCALED;
211 case PIPE_FORMAT_R32G32B32_USCALED:
212 return fetch_R32G32B32_USCALED;
213 case PIPE_FORMAT_R32G32B32A32_USCALED:
214 return fetch_R32G32B32A32_USCALED;
215
216 case PIPE_FORMAT_R32_SNORM:
217 return fetch_R32_SNORM;
218 case PIPE_FORMAT_R32G32_SNORM:
219 return fetch_R32G32_SNORM;
220 case PIPE_FORMAT_R32G32B32_SNORM:
221 return fetch_R32G32B32_SNORM;
222 case PIPE_FORMAT_R32G32B32A32_SNORM:
223 return fetch_R32G32B32A32_SNORM;
224
225 case PIPE_FORMAT_R32_SSCALED:
226 return fetch_R32_SSCALED;
227 case PIPE_FORMAT_R32G32_SSCALED:
228 return fetch_R32G32_SSCALED;
229 case PIPE_FORMAT_R32G32B32_SSCALED:
230 return fetch_R32G32B32_SSCALED;
231 case PIPE_FORMAT_R32G32B32A32_SSCALED:
232 return fetch_R32G32B32A32_SSCALED;
233
234 case PIPE_FORMAT_R16_UNORM:
235 return fetch_R16_UNORM;
236 case PIPE_FORMAT_R16G16_UNORM:
237 return fetch_R16G16_UNORM;
238 case PIPE_FORMAT_R16G16B16_UNORM:
239 return fetch_R16G16B16_UNORM;
240 case PIPE_FORMAT_R16G16B16A16_UNORM:
241 return fetch_R16G16B16A16_UNORM;
242
243 case PIPE_FORMAT_R16_USCALED:
244 return fetch_R16_USCALED;
245 case PIPE_FORMAT_R16G16_USCALED:
246 return fetch_R16G16_USCALED;
247 case PIPE_FORMAT_R16G16B16_USCALED:
248 return fetch_R16G16B16_USCALED;
249 case PIPE_FORMAT_R16G16B16A16_USCALED:
250 return fetch_R16G16B16A16_USCALED;
251
252 case PIPE_FORMAT_R16_SNORM:
253 return fetch_R16_SNORM;
254 case PIPE_FORMAT_R16G16_SNORM:
255 return fetch_R16G16_SNORM;
256 case PIPE_FORMAT_R16G16B16_SNORM:
257 return fetch_R16G16B16_SNORM;
258 case PIPE_FORMAT_R16G16B16A16_SNORM:
259 return fetch_R16G16B16A16_SNORM;
260
261 case PIPE_FORMAT_R16_SSCALED:
262 return fetch_R16_SSCALED;
263 case PIPE_FORMAT_R16G16_SSCALED:
264 return fetch_R16G16_SSCALED;
265 case PIPE_FORMAT_R16G16B16_SSCALED:
266 return fetch_R16G16B16_SSCALED;
267 case PIPE_FORMAT_R16G16B16A16_SSCALED:
268 return fetch_R16G16B16A16_SSCALED;
269
270 case PIPE_FORMAT_R8_UNORM:
271 return fetch_R8_UNORM;
272 case PIPE_FORMAT_R8G8_UNORM:
273 return fetch_R8G8_UNORM;
274 case PIPE_FORMAT_R8G8B8_UNORM:
275 return fetch_R8G8B8_UNORM;
276 case PIPE_FORMAT_R8G8B8A8_UNORM:
277 return fetch_R8G8B8A8_UNORM;
278
279 case PIPE_FORMAT_R8_USCALED:
280 return fetch_R8_USCALED;
281 case PIPE_FORMAT_R8G8_USCALED:
282 return fetch_R8G8_USCALED;
283 case PIPE_FORMAT_R8G8B8_USCALED:
284 return fetch_R8G8B8_USCALED;
285 case PIPE_FORMAT_R8G8B8A8_USCALED:
286 return fetch_R8G8B8A8_USCALED;
287
288 case PIPE_FORMAT_R8_SNORM:
289 return fetch_R8_SNORM;
290 case PIPE_FORMAT_R8G8_SNORM:
291 return fetch_R8G8_SNORM;
292 case PIPE_FORMAT_R8G8B8_SNORM:
293 return fetch_R8G8B8_SNORM;
294 case PIPE_FORMAT_R8G8B8A8_SNORM:
295 return fetch_R8G8B8A8_SNORM;
296
297 case PIPE_FORMAT_R8_SSCALED:
298 return fetch_R8_SSCALED;
299 case PIPE_FORMAT_R8G8_SSCALED:
300 return fetch_R8G8_SSCALED;
301 case PIPE_FORMAT_R8G8B8_SSCALED:
302 return fetch_R8G8B8_SSCALED;
303 case PIPE_FORMAT_R8G8B8A8_SSCALED:
304 return fetch_R8G8B8A8_SSCALED;
305
306 case PIPE_FORMAT_A8R8G8B8_UNORM:
307 return fetch_A8R8G8B8_UNORM;
308
309
310 case PIPE_FORMAT_B8G8R8A8_UNORM:
311 return fetch_B8G8R8A8_UNORM;
312
313 case 0:
314 return NULL; /* not sure why this is needed */
315
316 default:
317 /* This can get hit because draw-state-validation is too eager,
318 and can jump in here validating stuff before the state tracker has set
319 up everything.
320 */
321 /* assert(0); */
322 return NULL;
323 }
324 }
325
326
327 static void
328 transpose_4x4( float *out, const float *in )
329 {
330 /* This can be achieved in 12 sse instructions, plus the final
331 * stores I guess. This is probably a bit more than that - maybe
332 * 32 or so?
333 */
334 out[0] = in[0]; out[1] = in[4]; out[2] = in[8]; out[3] = in[12];
335 out[4] = in[1]; out[5] = in[5]; out[6] = in[9]; out[7] = in[13];
336 out[8] = in[2]; out[9] = in[6]; out[10] = in[10]; out[11] = in[14];
337 out[12] = in[3]; out[13] = in[7]; out[14] = in[11]; out[15] = in[15];
338 }
339
340
341
342 static void fetch_xyz_rgb( struct draw_context *draw,
343 struct tgsi_exec_machine *machine,
344 const unsigned *elts,
345 unsigned count )
346 {
347 const unsigned *pitch = draw->vertex_fetch.pitch;
348 const ubyte **src = draw->vertex_fetch.src_ptr;
349 int i;
350
351 assert(count <= 4);
352
353 // debug_printf("%s\n", __FUNCTION__);
354
355 /* loop over vertex attributes (vertex shader inputs)
356 */
357
358 for (i = 0; i < 4; i++) {
359 {
360 const float *in = (const float *)(src[0] + elts[i] * pitch[0]);
361 float *out = &machine->Inputs[0].xyzw[0].f[i];
362 out[0] = in[0];
363 out[4] = in[1];
364 out[8] = in[2];
365 out[12] = 1.0f;
366 }
367
368 {
369 const float *in = (const float *)(src[1] + elts[i] * pitch[1]);
370 float *out = &machine->Inputs[1].xyzw[0].f[i];
371 out[0] = in[0];
372 out[4] = in[1];
373 out[8] = in[2];
374 out[12] = 1.0f;
375 }
376 }
377 }
378
379
380
381
382 static void fetch_xyz_rgb_st( struct draw_context *draw,
383 struct tgsi_exec_machine *machine,
384 const unsigned *elts,
385 unsigned count )
386 {
387 const unsigned *pitch = draw->vertex_fetch.pitch;
388 const ubyte **src = draw->vertex_fetch.src_ptr;
389 int i;
390
391 assert(count <= 4);
392
393 /* loop over vertex attributes (vertex shader inputs)
394 */
395
396 for (i = 0; i < 4; i++) {
397 {
398 const float *in = (const float *)(src[0] + elts[i] * pitch[0]);
399 float *out = &machine->Inputs[0].xyzw[0].f[i];
400 out[0] = in[0];
401 out[4] = in[1];
402 out[8] = in[2];
403 out[12] = 1.0f;
404 }
405
406 {
407 const float *in = (const float *)(src[1] + elts[i] * pitch[1]);
408 float *out = &machine->Inputs[1].xyzw[0].f[i];
409 out[0] = in[0];
410 out[4] = in[1];
411 out[8] = in[2];
412 out[12] = 1.0f;
413 }
414
415 {
416 const float *in = (const float *)(src[2] + elts[i] * pitch[2]);
417 float *out = &machine->Inputs[2].xyzw[0].f[i];
418 out[0] = in[0];
419 out[4] = in[1];
420 out[8] = 0.0f;
421 out[12] = 1.0f;
422 }
423 }
424 }
425
426
427
428
429 /**
430 * Fetch vertex attributes for 'count' vertices.
431 */
432 static void generic_vertex_fetch( struct draw_context *draw,
433 struct tgsi_exec_machine *machine,
434 const unsigned *elts,
435 unsigned count )
436 {
437 unsigned nr_attrs = draw->vertex_fetch.nr_attrs;
438 unsigned attr;
439
440 assert(count <= 4);
441
442 // debug_printf("%s %d\n", __FUNCTION__, count);
443
444 /* loop over vertex attributes (vertex shader inputs)
445 */
446 for (attr = 0; attr < nr_attrs; attr++) {
447
448 const unsigned pitch = draw->vertex_fetch.pitch[attr];
449 const ubyte *src = draw->vertex_fetch.src_ptr[attr];
450 const fetch_func fetch = draw->vertex_fetch.fetch[attr];
451 unsigned i;
452 float p[4][4];
453
454
455 /* Fetch four attributes for four vertices.
456 *
457 * Could fetch directly into AOS format, but this is meant to be
458 * a prototype for an sse implementation, which would have
459 * difficulties doing that.
460 */
461 for (i = 0; i < count; i++)
462 fetch( src + elts[i] * pitch, p[i] );
463
464 /* Be nice and zero out any missing vertices:
465 */
466 for ( ; i < 4; i++)
467 p[i][0] = p[i][1] = p[i][2] = p[i][3] = 0;
468
469 /* Transpose/swizzle into sse-friendly format. Currently
470 * assuming that all vertex shader inputs are float[4], but this
471 * isn't true -- if the vertex shader only wants tex0.xy, we
472 * could optimize for that.
473 *
474 * To do so fully without codegen would probably require an
475 * excessive number of fetch functions, but we could at least
476 * minimize the transpose step:
477 */
478 transpose_4x4( (float *)&machine->Inputs[attr].xyzw[0].f[0], (float *)p );
479 }
480 }
481
482
483
484 void draw_update_vertex_fetch( struct draw_context *draw )
485 {
486 unsigned nr_attrs, i;
487
488 // debug_printf("%s\n", __FUNCTION__);
489
490 /* this may happend during context init */
491 if (!draw->vertex_shader)
492 return;
493
494 nr_attrs = draw->vertex_shader->info.num_inputs;
495
496 for (i = 0; i < nr_attrs; i++) {
497 unsigned buf = draw->vertex_element[i].vertex_buffer_index;
498 enum pipe_format format = draw->vertex_element[i].src_format;
499
500 draw->vertex_fetch.src_ptr[i] = (const ubyte *) draw->user.vbuffer[buf] +
501 draw->vertex_buffer[buf].buffer_offset +
502 draw->vertex_element[i].src_offset;
503
504 draw->vertex_fetch.pitch[i] = draw->vertex_buffer[buf].pitch;
505 draw->vertex_fetch.fetch[i] = draw_get_fetch_func( format );
506 }
507
508 draw->vertex_fetch.nr_attrs = nr_attrs;
509
510 draw->vertex_fetch.fetch_func = generic_vertex_fetch;
511
512 switch (nr_attrs) {
513 case 2:
514 if (draw->vertex_element[0].src_format == PIPE_FORMAT_R32G32B32_FLOAT &&
515 draw->vertex_element[1].src_format == PIPE_FORMAT_R32G32B32_FLOAT)
516 draw->vertex_fetch.fetch_func = fetch_xyz_rgb;
517 break;
518 case 3:
519 if (draw->vertex_element[0].src_format == PIPE_FORMAT_R32G32B32_FLOAT &&
520 draw->vertex_element[1].src_format == PIPE_FORMAT_R32G32B32_FLOAT &&
521 draw->vertex_element[2].src_format == PIPE_FORMAT_R32G32_FLOAT)
522 draw->vertex_fetch.fetch_func = fetch_xyz_rgb_st;
523 break;
524 default:
525 break;
526 }
527
528 }