1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "pipe/p_util.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "draw_private.h"
36 #include "draw_context.h"
43 * Fetch a float[4] vertex attribute from memory, doing format/type
44 * conversion as needed.
46 * This is probably needed/dupliocated elsewhere, eg format
47 * conversion, texture sampling etc.
49 #define FETCH_ATTRIB( NAME, SZ, CVT ) \
51 fetch_##NAME(const void *ptr, float *attrib) \
53 static const float defaults[4] = { 0,0,0,1 }; \
56 for (i = 0; i < SZ; i++) { \
60 for (; i < 4; i++) { \
61 attrib[i] = defaults[i]; \
65 #define CVT_64_FLOAT(i) (float) ((double *) ptr)[i]
66 #define CVT_32_FLOAT(i) ((float *) ptr)[i]
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]
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]
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
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
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
154 FETCH_ATTRIB( A8R8G8B8_UNORM
, 4, CVT_8_UNORM
)
155 //FETCH_ATTRIB( R8G8B8A8_UNORM, 4, CVT_8_UNORM )
160 fetch_B8G8R8A8_UNORM(const void *ptr
, float *attrib
)
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);
169 static fetch_func
get_fetch_func( enum pipe_format format
)
174 pf_sprint_name(tmp
, format
);
175 debug_printf("%s: %s\n", __FUNCTION__
, tmp
);
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
306 case PIPE_FORMAT_A8R8G8B8_UNORM
:
307 return fetch_A8R8G8B8_UNORM
;
310 case PIPE_FORMAT_B8G8R8A8_UNORM
:
311 return fetch_B8G8R8A8_UNORM
;
314 return NULL
; /* not sure why this is needed */
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
328 transpose_4x4( float *out
, const float *in
)
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
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];
342 static void fetch_xyz_rgb( struct draw_context
*draw
,
343 struct tgsi_exec_machine
*machine
,
344 const unsigned *elts
,
347 const unsigned *pitch
= draw
->vertex_fetch
.pitch
;
348 const ubyte
**src
= draw
->vertex_fetch
.src_ptr
;
353 // debug_printf("%s\n", __FUNCTION__);
355 /* loop over vertex attributes (vertex shader inputs)
358 for (i
= 0; i
< 4; i
++) {
360 const float *in
= (const float *)(src
[0] + elts
[i
] * pitch
[0]);
361 float *out
= &machine
->Inputs
[0].xyzw
[0].f
[i
];
369 const float *in
= (const float *)(src
[1] + elts
[i
] * pitch
[1]);
370 float *out
= &machine
->Inputs
[1].xyzw
[0].f
[i
];
382 static void fetch_xyz_rgb_st( struct draw_context
*draw
,
383 struct tgsi_exec_machine
*machine
,
384 const unsigned *elts
,
387 const unsigned *pitch
= draw
->vertex_fetch
.pitch
;
388 const ubyte
**src
= draw
->vertex_fetch
.src_ptr
;
393 /* loop over vertex attributes (vertex shader inputs)
396 for (i
= 0; i
< 4; i
++) {
398 const float *in
= (const float *)(src
[0] + elts
[i
] * pitch
[0]);
399 float *out
= &machine
->Inputs
[0].xyzw
[0].f
[i
];
407 const float *in
= (const float *)(src
[1] + elts
[i
] * pitch
[1]);
408 float *out
= &machine
->Inputs
[1].xyzw
[0].f
[i
];
416 const float *in
= (const float *)(src
[2] + elts
[i
] * pitch
[2]);
417 float *out
= &machine
->Inputs
[2].xyzw
[0].f
[i
];
430 * Fetch vertex attributes for 'count' vertices.
432 static void generic_vertex_fetch( struct draw_context
*draw
,
433 struct tgsi_exec_machine
*machine
,
434 const unsigned *elts
,
437 unsigned nr_attrs
= draw
->vertex_fetch
.nr_attrs
;
442 // debug_printf("%s %d\n", __FUNCTION__, count);
444 /* loop over vertex attributes (vertex shader inputs)
446 for (attr
= 0; attr
< nr_attrs
; attr
++) {
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
];
455 /* Fetch four attributes for four vertices.
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.
461 for (i
= 0; i
< count
; i
++)
462 fetch( src
+ elts
[i
] * pitch
, p
[i
] );
464 /* Be nice and zero out any missing vertices:
467 p
[i
][0] = p
[i
][1] = p
[i
][2] = p
[i
][3] = 0;
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.
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:
478 transpose_4x4( (float *)&machine
->Inputs
[attr
].xyzw
[0].f
[0], (float *)p
);
484 void draw_update_vertex_fetch( struct draw_context
*draw
)
486 unsigned nr_attrs
, i
;
488 // debug_printf("%s\n", __FUNCTION__);
490 /* this may happend during context init */
491 if (!draw
->vertex_shader
)
494 nr_attrs
= draw
->vertex_shader
->info
.num_inputs
;
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
;
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
;
504 draw
->vertex_fetch
.pitch
[i
] = draw
->vertex_buffer
[buf
].pitch
;
505 draw
->vertex_fetch
.fetch
[i
] = get_fetch_func( format
);
508 draw
->vertex_fetch
.nr_attrs
= nr_attrs
;
510 draw
->vertex_fetch
.fetch_func
= generic_vertex_fetch
;
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
;
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
;