OSDN Git Service

Remove redundant R5G6R5 conversions
[android-x86/external-swiftshader.git] / src / Shader / SamplerCore.cpp
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "SamplerCore.hpp"
16
17 #include "Constants.hpp"
18 #include "Debug.hpp"
19
20 namespace
21 {
22         void applySwizzle(sw::SwizzleType swizzle, sw::Short4& s, const sw::Vector4s& c)
23         {
24                 switch(swizzle)
25                 {
26                 case sw::SWIZZLE_RED:   s = c.x; break;
27                 case sw::SWIZZLE_GREEN: s = c.y; break;
28                 case sw::SWIZZLE_BLUE:  s = c.z; break;
29                 case sw::SWIZZLE_ALPHA: s = c.w; break;
30                 case sw::SWIZZLE_ZERO:  s = sw::Short4(0x0000); break;
31                 case sw::SWIZZLE_ONE:   s = sw::Short4(0x1000); break;
32                 default: ASSERT(false);
33                 }
34         }
35
36         void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c)
37         {
38                 switch(swizzle)
39                 {
40                 case sw::SWIZZLE_RED:   f = c.x; break;
41                 case sw::SWIZZLE_GREEN: f = c.y; break;
42                 case sw::SWIZZLE_BLUE:  f = c.z; break;
43                 case sw::SWIZZLE_ALPHA: f = c.w; break;
44                 case sw::SWIZZLE_ZERO:  f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break;
45                 case sw::SWIZZLE_ONE:   f = sw::Float4(1.0f, 1.0f, 1.0f, 1.0f); break;
46                 default: ASSERT(false);
47                 }
48         }
49 }
50
51 namespace sw
52 {
53         SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
54         {
55         }
56
57         void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy)
58         {
59                 sampleTexture(texture, c, u, v, w, q, dsx, dsy, dsx, Implicit, true);
60         }
61
62         void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function, bool fixed12)
63         {
64                 #if PERF_PROFILE
65                         AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
66
67                         if(state.compressedFormat)
68                         {
69                                 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
70                         }
71                 #endif
72
73                 Float4 uuuu = u;
74                 Float4 vvvv = v;
75                 Float4 wwww = w;
76
77                 if(state.textureType == TEXTURE_NULL)
78                 {
79                         c.x = Short4(0x0000);
80                         c.y = Short4(0x0000);
81                         c.z = Short4(0x0000);
82
83                         if(fixed12)   // FIXME: Convert to fixed12 at higher level, when required
84                         {
85                                 c.w = Short4(0x1000);
86                         }
87                         else
88                         {
89                                 c.w = Short4(0xFFFFu);   // FIXME
90                         }
91                 }
92                 else
93                 {
94                         Int face[4];
95                         Float4 lodX;
96                         Float4 lodY;
97                         Float4 lodZ;
98
99                         if(state.textureType == TEXTURE_CUBE)
100                         {
101                                 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
102                         }
103
104                         Float lod;
105                         Float anisotropy;
106                         Float4 uDelta;
107                         Float4 vDelta;
108                         Float lodBias = (function == Fetch) ? Float4(As<Int4>(q)).x : q.x;
109
110                         if(state.textureType != TEXTURE_3D)
111                         {
112                                 if(state.textureType != TEXTURE_CUBE)
113                                 {
114                                         computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodBias, dsx, dsy, function);
115                                 }
116                                 else
117                                 {
118                                         computeLodCube(texture, lod, lodX, lodY, lodZ, lodBias, dsx, dsy, function);
119                                 }
120                         }
121                         else
122                         {
123                                 computeLod3D(texture, lod, uuuu, vvvv, wwww, lodBias, dsx, dsy, function);
124                         }
125
126                         if(!hasFloatTexture())
127                         {
128                                 sampleFilter(texture, c, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
129                         }
130                         else
131                         {
132                                 Vector4f cf;
133
134                                 sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
135
136                                 convertFixed12(c, cf);
137                         }
138
139                         if(fixed12 && !hasFloatTexture())
140                         {
141                                 if(has16bitTextureFormat())
142                                 {
143                                         switch(state.textureFormat)
144                                         {
145                                         case FORMAT_R5G6B5:
146                                                 if(state.sRGB)
147                                                 {
148                                                         sRGBtoLinear16_5_12(c.x);
149                                                         sRGBtoLinear16_6_12(c.y);
150                                                         sRGBtoLinear16_5_12(c.z);
151                                                 }
152                                                 else
153                                                 {
154                                                         c.x = MulHigh(As<UShort4>(c.x), UShort4(0x10000000 / 0xF800));
155                                                         c.y = MulHigh(As<UShort4>(c.y), UShort4(0x10000000 / 0xFC00));
156                                                         c.z = MulHigh(As<UShort4>(c.z), UShort4(0x10000000 / 0xF800));
157                                                 }
158                                                 break;
159                                         default:
160                                                 ASSERT(false);
161                                         }
162                                 }
163                                 else
164                                 {
165                                         for(int component = 0; component < textureComponentCount(); component++)
166                                         {
167                                                 if(state.sRGB && isRGBComponent(component))
168                                                 {
169                                                         sRGBtoLinear16_8_12(c[component]);   // FIXME: Perform linearization at surface level for read-only textures
170                                                 }
171                                                 else
172                                                 {
173                                                         if(hasUnsignedTextureComponent(component))
174                                                         {
175                                                                 c[component] = As<UShort4>(c[component]) >> 4;
176                                                         }
177                                                         else
178                                                         {
179                                                                 c[component] = c[component] >> 3;
180                                                         }
181                                                 }
182                                         }
183                                 }
184                         }
185
186                         if(fixed12 && state.textureFilter != FILTER_GATHER)
187                         {
188                                 int componentCount = textureComponentCount();
189
190                                 switch(state.textureFormat)
191                                 {
192                                 case FORMAT_R8I_SNORM:
193                                 case FORMAT_G8R8I_SNORM:
194                                 case FORMAT_X8B8G8R8I_SNORM:
195                                 case FORMAT_A8B8G8R8I_SNORM:
196                                 case FORMAT_R8:
197                                 case FORMAT_R5G6B5:
198                                 case FORMAT_G8R8:
199                                 case FORMAT_R8I:
200                                 case FORMAT_R8UI:
201                                 case FORMAT_G8R8I:
202                                 case FORMAT_G8R8UI:
203                                 case FORMAT_X8B8G8R8I:
204                                 case FORMAT_X8B8G8R8UI:
205                                 case FORMAT_A8B8G8R8I:
206                                 case FORMAT_A8B8G8R8UI:
207                                 case FORMAT_R16I:
208                                 case FORMAT_R16UI:
209                                 case FORMAT_G16R16:
210                                 case FORMAT_G16R16I:
211                                 case FORMAT_G16R16UI:
212                                 case FORMAT_X16B16G16R16I:
213                                 case FORMAT_X16B16G16R16UI:
214                                 case FORMAT_A16B16G16R16:
215                                 case FORMAT_A16B16G16R16I:
216                                 case FORMAT_A16B16G16R16UI:
217                                 case FORMAT_R32I:
218                                 case FORMAT_R32UI:
219                                 case FORMAT_G32R32I:
220                                 case FORMAT_G32R32UI:
221                                 case FORMAT_X32B32G32R32I:
222                                 case FORMAT_X32B32G32R32UI:
223                                 case FORMAT_A32B32G32R32I:
224                                 case FORMAT_A32B32G32R32UI:
225                                 case FORMAT_X8R8G8B8:
226                                 case FORMAT_X8B8G8R8:
227                                 case FORMAT_A8R8G8B8:
228                                 case FORMAT_A8B8G8R8:
229                                 case FORMAT_SRGB8_X8:
230                                 case FORMAT_SRGB8_A8:
231                                 case FORMAT_V8U8:
232                                 case FORMAT_Q8W8V8U8:
233                                 case FORMAT_X8L8V8U8:
234                                 case FORMAT_V16U16:
235                                 case FORMAT_A16W16V16U16:
236                                 case FORMAT_Q16W16V16U16:
237                                 case FORMAT_YV12_BT601:
238                                 case FORMAT_YV12_BT709:
239                                 case FORMAT_YV12_JFIF:
240                                         if(componentCount < 2) c.y = Short4(0x1000);
241                                         if(componentCount < 3) c.z = Short4(0x1000);
242                                         if(componentCount < 4) c.w = Short4(0x1000);
243                                         break;
244                                 case FORMAT_A8:
245                                         c.w = c.x;
246                                         c.x = Short4(0x0000);
247                                         c.y = Short4(0x0000);
248                                         c.z = Short4(0x0000);
249                                         break;
250                                 case FORMAT_L8:
251                                 case FORMAT_L16:
252                                         c.y = c.x;
253                                         c.z = c.x;
254                                         c.w = Short4(0x1000);
255                                         break;
256                                 case FORMAT_A8L8:
257                                         c.w = c.y;
258                                         c.y = c.x;
259                                         c.z = c.x;
260                                         break;
261                                 case FORMAT_R32F:
262                                         c.y = Short4(0x1000);
263                                 case FORMAT_G32R32F:
264                                         c.z = Short4(0x1000);
265                                 case FORMAT_X32B32G32R32F:
266                                         c.w = Short4(0x1000);
267                                 case FORMAT_A32B32G32R32F:
268                                         break;
269                                 case FORMAT_D32F:
270                                 case FORMAT_D32F_LOCKABLE:
271                                 case FORMAT_D32FS8_TEXTURE:
272                                 case FORMAT_D32FS8_SHADOW:
273                                         c.y = c.x;
274                                         c.z = c.x;
275                                         c.w = c.x;
276                                         break;
277                                 default:
278                                         ASSERT(false);
279                                 }
280                         }
281                 }
282
283                 if(fixed12 &&
284                    ((state.swizzleR != SWIZZLE_RED) ||
285                     (state.swizzleG != SWIZZLE_GREEN) ||
286                     (state.swizzleB != SWIZZLE_BLUE) ||
287                     (state.swizzleA != SWIZZLE_ALPHA)))
288                 {
289                         const Vector4s col(c);
290                         applySwizzle(state.swizzleR, c.x, col);
291                         applySwizzle(state.swizzleG, c.y, col);
292                         applySwizzle(state.swizzleB, c.z, col);
293                         applySwizzle(state.swizzleA, c.w, col);
294                 }
295         }
296
297         void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
298         {
299                 #if PERF_PROFILE
300                         AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
301
302                         if(state.compressedFormat)
303                         {
304                                 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
305                         }
306                 #endif
307
308                 if(state.textureType == TEXTURE_NULL)
309                 {
310                         c.x = Float4(0.0f);
311                         c.y = Float4(0.0f);
312                         c.z = Float4(0.0f);
313                         c.w = Float4(1.0f);
314                 }
315                 else
316                 {
317                         if(hasFloatTexture())   // FIXME: Mostly identical to integer sampling
318                         {
319                                 Float4 uuuu = u;
320                                 Float4 vvvv = v;
321                                 Float4 wwww = w;
322
323                                 Int face[4];
324                                 Float4 lodX;
325                                 Float4 lodY;
326                                 Float4 lodZ;
327
328                                 if(state.textureType == TEXTURE_CUBE)
329                                 {
330                                         cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
331                                 }
332
333                                 Float lod;
334                                 Float anisotropy;
335                                 Float4 uDelta;
336                                 Float4 vDelta;
337                                 Float lodBias = (function == Fetch) ? Float4(As<Int4>(q)).x : q.x;
338
339                                 if(state.textureType != TEXTURE_3D)
340                                 {
341                                         if(state.textureType != TEXTURE_CUBE)
342                                         {
343                                                 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodBias, dsx, dsy, function);
344                                         }
345                                         else
346                                         {
347                                                 computeLodCube(texture, lod, lodX, lodY, lodZ, lodBias, dsx, dsy, function);
348                                         }
349                                 }
350                                 else
351                                 {
352                                         computeLod3D(texture, lod, uuuu, vvvv, wwww, lodBias, dsx, dsy, function);
353                                 }
354
355                                 sampleFloatFilter(texture, c, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
356                         }
357                         else
358                         {
359                                 Vector4s cs;
360
361                                 sampleTexture(texture, cs, u, v, w, q, dsx, dsy, offset, function, false);
362
363                                 if(has16bitTextureFormat())
364                                 {
365                                         switch(state.textureFormat)
366                                         {
367                                         case FORMAT_R5G6B5:
368                                                 if(state.sRGB)
369                                                 {
370                                                         sRGBtoLinear16_5_12(cs.x);
371                                                         sRGBtoLinear16_6_12(cs.y);
372                                                         sRGBtoLinear16_5_12(cs.z);
373
374                                                         convertSigned12(c.x, cs.x);
375                                                         convertSigned12(c.y, cs.y);
376                                                         convertSigned12(c.z, cs.z);
377                                                 }
378                                                 else
379                                                 {
380                                                         c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
381                                                         c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
382                                                         c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
383                                                 }
384                                                 break;
385                                         default:
386                                                 ASSERT(false);
387                                         }
388                                 }
389                                 else
390                                 {
391                                         for(int component = 0; component < textureComponentCount(); component++)
392                                         {
393                                                 switch(state.textureFormat)
394                                                 {
395                                                 case FORMAT_R8I:
396                                                 case FORMAT_G8R8I:
397                                                 case FORMAT_X8B8G8R8I:
398                                                 case FORMAT_A8B8G8R8I:
399                                                         c[component] = As<Float4>(Int4(cs[component]) >> 8);
400                                                         break;
401                                                 case FORMAT_R8UI:
402                                                 case FORMAT_G8R8UI:
403                                                 case FORMAT_X8B8G8R8UI:
404                                                 case FORMAT_A8B8G8R8UI:
405                                                         c[component] = As<Float4>(Int4(As<UShort4>(cs[component]) >> 8));
406                                                         break;
407                                                 case FORMAT_R16I:
408                                                 case FORMAT_G16R16I:
409                                                 case FORMAT_X16B16G16R16I:
410                                                 case FORMAT_A16B16G16R16I:
411                                                         c[component] = As<Float4>(Int4(cs[component]));
412                                                         break;
413                                                 case FORMAT_R16UI:
414                                                 case FORMAT_G16R16UI:
415                                                 case FORMAT_X16B16G16R16UI:
416                                                 case FORMAT_A16B16G16R16UI:
417                                                         c[component] = As<Float4>(Int4(As<UShort4>(cs[component])));
418                                                         break;
419                                                 default:
420                                                         // Normalized integer formats
421                                                         if(state.sRGB && isRGBComponent(component))
422                                                         {
423                                                                 sRGBtoLinear16_8_12(cs[component]);   // FIXME: Perform linearization at surface level for read-only textures
424                                                                 convertSigned12(c[component], cs[component]);
425                                                         }
426                                                         else
427                                                         {
428                                                                 if(hasUnsignedTextureComponent(component))
429                                                                 {
430                                                                         convertUnsigned16(c[component], cs[component]);
431                                                                 }
432                                                                 else
433                                                                 {
434                                                                         convertSigned15(c[component], cs[component]);
435                                                                 }
436                                                         }
437                                                         break;
438                                                 }
439                                         }
440                                 }
441                         }
442
443                         int componentCount = textureComponentCount();
444
445                         if(state.textureFilter != FILTER_GATHER)
446                         {
447                                 switch(state.textureFormat)
448                                 {
449                                 case FORMAT_R8I:
450                                 case FORMAT_R8UI:
451                                 case FORMAT_R16I:
452                                 case FORMAT_R16UI:
453                                 case FORMAT_R32I:
454                                 case FORMAT_R32UI:
455                                         c.y = As<Float4>(UInt4(0));
456                                 case FORMAT_G8R8I:
457                                 case FORMAT_G8R8UI:
458                                 case FORMAT_G16R16I:
459                                 case FORMAT_G16R16UI:
460                                 case FORMAT_G32R32I:
461                                 case FORMAT_G32R32UI:
462                                         c.z = As<Float4>(UInt4(0));
463                                 case FORMAT_X8B8G8R8I:
464                                 case FORMAT_X8B8G8R8UI:
465                                 case FORMAT_X16B16G16R16I:
466                                 case FORMAT_X16B16G16R16UI:
467                                 case FORMAT_X32B32G32R32I:
468                                 case FORMAT_X32B32G32R32UI:
469                                         c.w = As<Float4>(UInt4(1));
470                                 case FORMAT_A8B8G8R8I:
471                                 case FORMAT_A8B8G8R8UI:
472                                 case FORMAT_A16B16G16R16I:
473                                 case FORMAT_A16B16G16R16UI:
474                                 case FORMAT_A32B32G32R32I:
475                                 case FORMAT_A32B32G32R32UI:
476                                         break;
477                                 case FORMAT_R8I_SNORM:
478                                 case FORMAT_G8R8I_SNORM:
479                                 case FORMAT_X8B8G8R8I_SNORM:
480                                 case FORMAT_A8B8G8R8I_SNORM:
481                                 case FORMAT_R8:
482                                 case FORMAT_R5G6B5:
483                                 case FORMAT_G8R8:
484                                 case FORMAT_G16R16:
485                                 case FORMAT_A16B16G16R16:
486                                 case FORMAT_X8R8G8B8:
487                                 case FORMAT_X8B8G8R8:
488                                 case FORMAT_A8R8G8B8:
489                                 case FORMAT_A8B8G8R8:
490                                 case FORMAT_SRGB8_X8:
491                                 case FORMAT_SRGB8_A8:
492                                 case FORMAT_V8U8:
493                                 case FORMAT_Q8W8V8U8:
494                                 case FORMAT_X8L8V8U8:
495                                 case FORMAT_V16U16:
496                                 case FORMAT_A16W16V16U16:
497                                 case FORMAT_Q16W16V16U16:
498                                 case FORMAT_YV12_BT601:
499                                 case FORMAT_YV12_BT709:
500                                 case FORMAT_YV12_JFIF:
501                                         if(componentCount < 2) c.y = Float4(1.0f);
502                                         if(componentCount < 3) c.z = Float4(1.0f);
503                                         if(componentCount < 4) c.w = Float4(1.0f);
504                                         break;
505                                 case FORMAT_A8:
506                                         c.w = c.x;
507                                         c.x = Float4(0.0f);
508                                         c.y = Float4(0.0f);
509                                         c.z = Float4(0.0f);
510                                         break;
511                                 case FORMAT_L8:
512                                 case FORMAT_L16:
513                                         c.y = c.x;
514                                         c.z = c.x;
515                                         c.w = Float4(1.0f);
516                                         break;
517                                 case FORMAT_A8L8:
518                                         c.w = c.y;
519                                         c.y = c.x;
520                                         c.z = c.x;
521                                         break;
522                                 case FORMAT_R32F:
523                                         c.y = Float4(1.0f);
524                                 case FORMAT_G32R32F:
525                                         c.z = Float4(1.0f);
526                                 case FORMAT_X32B32G32R32F:
527                                         c.w = Float4(1.0f);
528                                 case FORMAT_A32B32G32R32F:
529                                         break;
530                                 case FORMAT_D32F:
531                                 case FORMAT_D32F_LOCKABLE:
532                                 case FORMAT_D32FS8_TEXTURE:
533                                 case FORMAT_D32FS8_SHADOW:
534                                         c.y = c.x;
535                                         c.z = c.x;
536                                         c.w = c.x;
537                                         break;
538                                 default:
539                                         ASSERT(false);
540                                 }
541                         }
542                 }
543
544                 if((state.swizzleR != SWIZZLE_RED) ||
545                    (state.swizzleG != SWIZZLE_GREEN) ||
546                    (state.swizzleB != SWIZZLE_BLUE) ||
547                    (state.swizzleA != SWIZZLE_ALPHA))
548                 {
549                         const Vector4f col(c);
550                         applySwizzle(state.swizzleR, c.x, col);
551                         applySwizzle(state.swizzleG, c.y, col);
552                         applySwizzle(state.swizzleB, c.z, col);
553                         applySwizzle(state.swizzleA, c.w, col);
554                 }
555         }
556
557         void SamplerCore::textureSize(Pointer<Byte> &texture, Vector4f &size, Float4 &lod)
558         {
559                 for(int i = 0; i < 4; ++i)
560                 {
561                         Int baseLevel = *Pointer<Int>(texture + OFFSET(Texture, baseLevel));
562                         Pointer<Byte> mipmap = texture + OFFSET(Texture, mipmap) + (As<Int>(Extract(lod, i)) + baseLevel) * sizeof(Mipmap);
563                         size.x = Insert(size.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
564                         size.y = Insert(size.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
565                         size.z = Insert(size.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
566                 }
567         }
568
569         void SamplerCore::border(Short4 &mask, Float4 &coordinates)
570         {
571                 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
572                 mask = As<Short4>(Int2(As<Int4>(Pack(border, border))));
573         }
574
575         void SamplerCore::border(Int4 &mask, Float4 &coordinates)
576         {
577                 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
578         }
579
580         Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
581         {
582                 Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
583
584                 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
585                 {
586                         offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
587                 }
588                 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
589                 {
590                         offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
591                 }
592
593                 if(wrap)
594                 {
595                         switch(count)
596                         {
597                         case -1: return uvw - offset;
598                         case  0: return uvw;
599                         case +1: return uvw + offset;
600                         case  2: return uvw + offset + offset;
601                         }
602                 }
603                 else   // Clamp or mirror
604                 {
605                         switch(count)
606                         {
607                         case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset));
608                         case  0: return uvw;
609                         case +1: return AddSat(As<UShort4>(uvw), As<UShort4>(offset));
610                         case  2: return AddSat(AddSat(As<UShort4>(uvw), As<UShort4>(offset)), As<UShort4>(offset));
611                         }
612                 }
613
614                 return uvw;
615         }
616
617         void SamplerCore::sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerFunction function)
618         {
619                 sampleAniso(texture, c, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
620
621                 if(function == Fetch)
622                 {
623                         return;
624                 }
625
626                 if(state.mipmapFilter > MIPMAP_POINT)
627                 {
628                         Vector4s cc;
629
630                         sampleAniso(texture, cc, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
631
632                         lod *= Float(1 << 16);
633
634                         UShort4 utri = UShort4(Float4(lod));   // FIXME: Optimize
635                         Short4 stri = utri >> 1;   // FIXME: Optimize
636
637                         if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri);
638                         if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri);
639                         if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri);
640                         if(hasUnsignedTextureComponent(3)) cc.w = MulHigh(As<UShort4>(cc.w), utri); else cc.w = MulHigh(cc.w, stri);
641
642                         utri = ~utri;
643                         stri = Short4(0x7FFF) - stri;
644
645                         if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri);
646                         if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri);
647                         if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri);
648                         if(hasUnsignedTextureComponent(3)) c.w = MulHigh(As<UShort4>(c.w), utri); else c.w = MulHigh(c.w, stri);
649
650                         c.x += cc.x;
651                         c.y += cc.y;
652                         c.z += cc.z;
653                         c.w += cc.w;
654
655                         if(!hasUnsignedTextureComponent(0)) c.x += c.x;
656                         if(!hasUnsignedTextureComponent(1)) c.y += c.y;
657                         if(!hasUnsignedTextureComponent(2)) c.z += c.z;
658                         if(!hasUnsignedTextureComponent(3)) c.w += c.w;
659                 }
660
661                 Short4 borderMask;
662
663                 if(state.addressingModeU == ADDRESSING_BORDER)
664                 {
665                         Short4 u0;
666
667                         border(u0, u);
668
669                         borderMask = u0;
670                 }
671
672                 if(state.addressingModeV == ADDRESSING_BORDER)
673                 {
674                         Short4 v0;
675
676                         border(v0, v);
677
678                         if(state.addressingModeU == ADDRESSING_BORDER)
679                         {
680                                 borderMask &= v0;
681                         }
682                         else
683                         {
684                                 borderMask = v0;
685                         }
686                 }
687
688                 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
689                 {
690                         Short4 s0;
691
692                         border(s0, w);
693
694                         if(state.addressingModeU == ADDRESSING_BORDER ||
695                            state.addressingModeV == ADDRESSING_BORDER)
696                         {
697                                 borderMask &= s0;
698                         }
699                         else
700                         {
701                                 borderMask = s0;
702                         }
703                 }
704
705                 if(state.addressingModeU == ADDRESSING_BORDER ||
706                    state.addressingModeV == ADDRESSING_BORDER ||
707                    (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
708                 {
709                         Short4 b;
710
711                         c.x = (borderMask & c.x) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1)));
712                         c.y = (borderMask & c.y) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1)));
713                         c.z = (borderMask & c.z) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1)));
714                         c.w = (borderMask & c.w) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1)));
715                 }
716         }
717
718         void SamplerCore::sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerFunction function)
719         {
720                 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
721                 {
722                         sampleQuad(texture, c, u, v, w, offset, lod, face, secondLOD, function);
723                 }
724                 else
725                 {
726                         Int a = RoundInt(anisotropy);
727
728                         Vector4s cSum;
729
730                         cSum.x = Short4(0);
731                         cSum.y = Short4(0);
732                         cSum.z = Short4(0);
733                         cSum.w = Short4(0);
734
735                         Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
736                         Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
737                         UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a);
738                         Short4 sw = Short4(cw >> 1);
739
740                         Float4 du = uDelta;
741                         Float4 dv = vDelta;
742
743                         Float4 u0 = u + B * du;
744                         Float4 v0 = v + B * dv;
745
746                         du *= A;
747                         dv *= A;
748
749                         Int i = 0;
750
751                         Do
752                         {
753                                 sampleQuad(texture, c, u0, v0, w, offset, lod, face, secondLOD, function);
754
755                                 u0 += du;
756                                 v0 += dv;
757
758                                 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw);
759                                 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw);
760                                 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw);
761                                 if(hasUnsignedTextureComponent(3)) cSum.w += As<Short4>(MulHigh(As<UShort4>(c.w), cw)); else cSum.w += MulHigh(c.w, sw);
762
763                                 i++;
764                         }
765                         Until(i >= a)
766
767                         if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x);
768                         if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y);
769                         if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z);
770                         if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w);
771                 }
772         }
773
774         void SamplerCore::sampleQuad(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
775         {
776                 if(state.textureType != TEXTURE_3D)
777                 {
778                         sampleQuad2D(texture, c, u, v, w, offset, lod, face, secondLOD, function);
779                 }
780                 else
781                 {
782                         sample3D(texture, c, u, v, w, offset, lod, secondLOD, function);
783                 }
784         }
785
786         void SamplerCore::sampleQuad2D(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
787         {
788                 int componentCount = textureComponentCount();
789                 bool gather = state.textureFilter == FILTER_GATHER;
790
791                 Pointer<Byte> mipmap;
792                 Pointer<Byte> buffer[4];
793
794                 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
795
796                 bool texelFetch = (function == Fetch);
797
798                 Short4 uuuu = texelFetch ? Short4(As<Int4>(u)) : address(u, state.addressingModeU, mipmap);
799                 Short4 vvvv = texelFetch ? Short4(As<Int4>(v)) : address(v, state.addressingModeV, mipmap);
800                 Short4 wwww = texelFetch ? Short4(As<Int4>(w)) : address(w, state.addressingModeW, mipmap);
801
802                 if(state.textureFilter == FILTER_POINT || texelFetch)
803                 {
804                         sampleTexel(c, uuuu, vvvv, wwww, offset, mipmap, buffer, function);
805                 }
806                 else
807                 {
808                         Vector4s c0;
809                         Vector4s c1;
810                         Vector4s c2;
811                         Vector4s c3;
812
813                         Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
814                         Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
815                         Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
816                         Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
817
818                         sampleTexel(c0, uuuu0, vvvv0, wwww, offset, mipmap, buffer, function);
819                         sampleTexel(c1, uuuu1, vvvv0, wwww, offset, mipmap, buffer, function);
820                         sampleTexel(c2, uuuu0, vvvv1, wwww, offset, mipmap, buffer, function);
821                         sampleTexel(c3, uuuu1, vvvv1, wwww, offset, mipmap, buffer, function);
822
823                         if(!gather)   // Blend
824                         {
825                                 // Fractions
826                                 UShort4 f0u = As<UShort4>(uuuu0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
827                                 UShort4 f0v = As<UShort4>(vvvv0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
828
829                                 UShort4 f1u = ~f0u;
830                                 UShort4 f1v = ~f0v;
831
832                                 UShort4 f0u0v = MulHigh(f0u, f0v);
833                                 UShort4 f1u0v = MulHigh(f1u, f0v);
834                                 UShort4 f0u1v = MulHigh(f0u, f1v);
835                                 UShort4 f1u1v = MulHigh(f1u, f1v);
836
837                                 // Signed fractions
838                                 Short4 f1u1vs;
839                                 Short4 f0u1vs;
840                                 Short4 f1u0vs;
841                                 Short4 f0u0vs;
842
843                                 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
844                                 {
845                                         f1u1vs = f1u1v >> 1;
846                                         f0u1vs = f0u1v >> 1;
847                                         f1u0vs = f1u0v >> 1;
848                                         f0u0vs = f0u0v >> 1;
849                                 }
850
851                                 // Bilinear interpolation
852                                 if(componentCount >= 1)
853                                 {
854                                         if(has16bitTextureComponents() && hasUnsignedTextureComponent(0))
855                                         {
856                                                 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u);
857                                                 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u);
858                                                 c.x  = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0v) + MulHigh(As<UShort4>(c2.x), f0v);
859                                         }
860                                         else
861                                         {
862                                                 if(hasUnsignedTextureComponent(0))
863                                                 {
864                                                         c0.x = MulHigh(As<UShort4>(c0.x), f1u1v);
865                                                         c1.x = MulHigh(As<UShort4>(c1.x), f0u1v);
866                                                         c2.x = MulHigh(As<UShort4>(c2.x), f1u0v);
867                                                         c3.x = MulHigh(As<UShort4>(c3.x), f0u0v);
868                                                 }
869                                                 else
870                                                 {
871                                                         c0.x = MulHigh(c0.x, f1u1vs);
872                                                         c1.x = MulHigh(c1.x, f0u1vs);
873                                                         c2.x = MulHigh(c2.x, f1u0vs);
874                                                         c3.x = MulHigh(c3.x, f0u0vs);
875                                                 }
876
877                                                 c.x = (c0.x + c1.x) + (c2.x + c3.x);
878                                                 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x);   // Correct for signed fractions
879                                         }
880                                 }
881
882                                 if(componentCount >= 2)
883                                 {
884                                         if(has16bitTextureComponents() && hasUnsignedTextureComponent(1))
885                                         {
886                                                 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u);
887                                                 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u);
888                                                 c.y  = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0v) + MulHigh(As<UShort4>(c2.y), f0v);
889                                         }
890                                         else
891                                         {
892                                                 if(hasUnsignedTextureComponent(1))
893                                                 {
894                                                         c0.y = MulHigh(As<UShort4>(c0.y), f1u1v);
895                                                         c1.y = MulHigh(As<UShort4>(c1.y), f0u1v);
896                                                         c2.y = MulHigh(As<UShort4>(c2.y), f1u0v);
897                                                         c3.y = MulHigh(As<UShort4>(c3.y), f0u0v);
898                                                 }
899                                                 else
900                                                 {
901                                                         c0.y = MulHigh(c0.y, f1u1vs);
902                                                         c1.y = MulHigh(c1.y, f0u1vs);
903                                                         c2.y = MulHigh(c2.y, f1u0vs);
904                                                         c3.y = MulHigh(c3.y, f0u0vs);
905                                                 }
906
907                                                 c.y = (c0.y + c1.y) + (c2.y + c3.y);
908                                                 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y);   // Correct for signed fractions
909                                         }
910                                 }
911
912                                 if(componentCount >= 3)
913                                 {
914                                         if(has16bitTextureComponents() && hasUnsignedTextureComponent(2))
915                                         {
916                                                 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u);
917                                                 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u);
918                                                 c.z  = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0v) + MulHigh(As<UShort4>(c2.z), f0v);
919                                         }
920                                         else
921                                         {
922                                                 if(hasUnsignedTextureComponent(2))
923                                                 {
924                                                         c0.z = MulHigh(As<UShort4>(c0.z), f1u1v);
925                                                         c1.z = MulHigh(As<UShort4>(c1.z), f0u1v);
926                                                         c2.z = MulHigh(As<UShort4>(c2.z), f1u0v);
927                                                         c3.z = MulHigh(As<UShort4>(c3.z), f0u0v);
928                                                 }
929                                                 else
930                                                 {
931                                                         c0.z = MulHigh(c0.z, f1u1vs);
932                                                         c1.z = MulHigh(c1.z, f0u1vs);
933                                                         c2.z = MulHigh(c2.z, f1u0vs);
934                                                         c3.z = MulHigh(c3.z, f0u0vs);
935                                                 }
936
937                                                 c.z = (c0.z + c1.z) + (c2.z + c3.z);
938                                                 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z);   // Correct for signed fractions
939                                         }
940                                 }
941
942                                 if(componentCount >= 4)
943                                 {
944                                         if(has16bitTextureComponents() && hasUnsignedTextureComponent(3))
945                                         {
946                                                 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u);
947                                                 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u);
948                                                 c.w  = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0v) + MulHigh(As<UShort4>(c2.w), f0v);
949                                         }
950                                         else
951                                         {
952                                                 if(hasUnsignedTextureComponent(3))
953                                                 {
954                                                         c0.w = MulHigh(As<UShort4>(c0.w), f1u1v);
955                                                         c1.w = MulHigh(As<UShort4>(c1.w), f0u1v);
956                                                         c2.w = MulHigh(As<UShort4>(c2.w), f1u0v);
957                                                         c3.w = MulHigh(As<UShort4>(c3.w), f0u0v);
958                                                 }
959                                                 else
960                                                 {
961                                                         c0.w = MulHigh(c0.w, f1u1vs);
962                                                         c1.w = MulHigh(c1.w, f0u1vs);
963                                                         c2.w = MulHigh(c2.w, f1u0vs);
964                                                         c3.w = MulHigh(c3.w, f0u0vs);
965                                                 }
966
967                                                 c.w = (c0.w + c1.w) + (c2.w + c3.w);
968                                                 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w);   // Correct for signed fractions
969                                         }
970                                 }
971                         }
972                         else
973                         {
974                                 c.x = c1.x;
975                                 c.y = c2.x;
976                                 c.z = c3.x;
977                                 c.w = c0.x;
978                         }
979                 }
980         }
981
982         void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4s &c_, Float4 &u_, Float4 &v_, Float4 &w_, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
983         {
984                 int componentCount = textureComponentCount();
985
986                 Pointer<Byte> mipmap;
987                 Pointer<Byte> buffer[4];
988                 Int face[4];
989
990                 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
991
992                 bool texelFetch = (function == Fetch);
993
994                 Short4 uuuu = texelFetch ? Short4(As<Int4>(u_)) : address(u_, state.addressingModeU, mipmap);
995                 Short4 vvvv = texelFetch ? Short4(As<Int4>(v_)) : address(v_, state.addressingModeV, mipmap);
996                 Short4 wwww = texelFetch ? Short4(As<Int4>(w_)) : address(w_, state.addressingModeW, mipmap);
997
998                 if(state.textureFilter == FILTER_POINT || texelFetch)
999                 {
1000                         sampleTexel(c_, uuuu, vvvv, wwww, offset, mipmap, buffer, function);
1001                 }
1002                 else
1003                 {
1004                         Vector4s c[2][2][2];
1005
1006                         Short4 u[2][2][2];
1007                         Short4 v[2][2][2];
1008                         Short4 s[2][2][2];
1009
1010                         for(int i = 0; i < 2; i++)
1011                         {
1012                                 for(int j = 0; j < 2; j++)
1013                                 {
1014                                         for(int k = 0; k < 2; k++)
1015                                         {
1016                                                 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
1017                                                 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
1018                                                 s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
1019                                         }
1020                                 }
1021                         }
1022
1023                         // Fractions
1024                         UShort4 f0u = As<UShort4>(u[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
1025                         UShort4 f0v = As<UShort4>(v[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
1026                         UShort4 f0s = As<UShort4>(s[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth));
1027
1028                         UShort4 f1u = ~f0u;
1029                         UShort4 f1v = ~f0v;
1030                         UShort4 f1s = ~f0s;
1031
1032                         UShort4 f[2][2][2];
1033                         Short4 fs[2][2][2];
1034
1035                         f[1][1][1] = MulHigh(f1u, f1v);
1036                         f[0][1][1] = MulHigh(f0u, f1v);
1037                         f[1][0][1] = MulHigh(f1u, f0v);
1038                         f[0][0][1] = MulHigh(f0u, f0v);
1039                         f[1][1][0] = MulHigh(f1u, f1v);
1040                         f[0][1][0] = MulHigh(f0u, f1v);
1041                         f[1][0][0] = MulHigh(f1u, f0v);
1042                         f[0][0][0] = MulHigh(f0u, f0v);
1043
1044                         f[1][1][1] = MulHigh(f[1][1][1], f1s);
1045                         f[0][1][1] = MulHigh(f[0][1][1], f1s);
1046                         f[1][0][1] = MulHigh(f[1][0][1], f1s);
1047                         f[0][0][1] = MulHigh(f[0][0][1], f1s);
1048                         f[1][1][0] = MulHigh(f[1][1][0], f0s);
1049                         f[0][1][0] = MulHigh(f[0][1][0], f0s);
1050                         f[1][0][0] = MulHigh(f[1][0][0], f0s);
1051                         f[0][0][0] = MulHigh(f[0][0][0], f0s);
1052
1053                         // Signed fractions
1054                         if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
1055                         {
1056                                 fs[0][0][0] = f[0][0][0] >> 1;
1057                                 fs[0][0][1] = f[0][0][1] >> 1;
1058                                 fs[0][1][0] = f[0][1][0] >> 1;
1059                                 fs[0][1][1] = f[0][1][1] >> 1;
1060                                 fs[1][0][0] = f[1][0][0] >> 1;
1061                                 fs[1][0][1] = f[1][0][1] >> 1;
1062                                 fs[1][1][0] = f[1][1][0] >> 1;
1063                                 fs[1][1][1] = f[1][1][1] >> 1;
1064                         }
1065
1066                         for(int i = 0; i < 2; i++)
1067                         {
1068                                 for(int j = 0; j < 2; j++)
1069                                 {
1070                                         for(int k = 0; k < 2; k++)
1071                                         {
1072                                                 sampleTexel(c[i][j][k], u[i][j][k], v[i][j][k], s[i][j][k], offset, mipmap, buffer, function);
1073
1074                                                 if(componentCount >= 1) { if(hasUnsignedTextureComponent(0)) c[i][j][k].x = MulHigh(As<UShort4>(c[i][j][k].x), f[1 - i][1 - j][1 - k]); else c[i][j][k].x = MulHigh(c[i][j][k].x, fs[1 - i][1 - j][1 - k]); }
1075                                                 if(componentCount >= 2) { if(hasUnsignedTextureComponent(1)) c[i][j][k].y = MulHigh(As<UShort4>(c[i][j][k].y), f[1 - i][1 - j][1 - k]); else c[i][j][k].y = MulHigh(c[i][j][k].y, fs[1 - i][1 - j][1 - k]); }
1076                                                 if(componentCount >= 3) { if(hasUnsignedTextureComponent(2)) c[i][j][k].z = MulHigh(As<UShort4>(c[i][j][k].z), f[1 - i][1 - j][1 - k]); else c[i][j][k].z = MulHigh(c[i][j][k].z, fs[1 - i][1 - j][1 - k]); }
1077                                                 if(componentCount >= 4) { if(hasUnsignedTextureComponent(3)) c[i][j][k].w = MulHigh(As<UShort4>(c[i][j][k].w), f[1 - i][1 - j][1 - k]); else c[i][j][k].w = MulHigh(c[i][j][k].w, fs[1 - i][1 - j][1 - k]); }
1078
1079                                                 if(i != 0 || j != 0 || k != 0)
1080                                                 {
1081                                                         if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x;
1082                                                         if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y;
1083                                                         if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z;
1084                                                         if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w;
1085                                                 }
1086                                         }
1087                                 }
1088                         }
1089
1090                         if(componentCount >= 1) c_.x = c[0][0][0].x;
1091                         if(componentCount >= 2) c_.y = c[0][0][0].y;
1092                         if(componentCount >= 3) c_.z = c[0][0][0].z;
1093                         if(componentCount >= 4) c_.w = c[0][0][0].w;
1094
1095                         // Correct for signed fractions
1096                         if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x);
1097                         if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y);
1098                         if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z);
1099                         if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w);
1100                 }
1101         }
1102
1103         void SamplerCore::sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerFunction function)
1104         {
1105                 sampleFloatAniso(texture, c, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
1106
1107                 if(function == Fetch)
1108                 {
1109                         return;
1110                 }
1111
1112                 if(state.mipmapFilter > MIPMAP_POINT)
1113                 {
1114                         Vector4f cc;
1115
1116                         sampleFloatAniso(texture, cc, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
1117
1118                         Float4 lod4 = Float4(Frac(lod));
1119
1120                         c.x = (cc.x - c.x) * lod4 + c.x;
1121                         c.y = (cc.y - c.y) * lod4 + c.y;
1122                         c.z = (cc.z - c.z) * lod4 + c.z;
1123                         c.w = (cc.w - c.w) * lod4 + c.w;
1124                 }
1125
1126                 Int4 borderMask;
1127
1128                 if(state.addressingModeU == ADDRESSING_BORDER)
1129                 {
1130                         Int4 u0;
1131
1132                         border(u0, u);
1133
1134                         borderMask = u0;
1135                 }
1136
1137                 if(state.addressingModeV == ADDRESSING_BORDER)
1138                 {
1139                         Int4 v0;
1140
1141                         border(v0, v);
1142
1143                         if(state.addressingModeU == ADDRESSING_BORDER)
1144                         {
1145                                 borderMask &= v0;
1146                         }
1147                         else
1148                         {
1149                                 borderMask = v0;
1150                         }
1151                 }
1152
1153                 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
1154                 {
1155                         Int4 s0;
1156
1157                         border(s0, w);
1158
1159                         if(state.addressingModeU == ADDRESSING_BORDER ||
1160                            state.addressingModeV == ADDRESSING_BORDER)
1161                         {
1162                                 borderMask &= s0;
1163                         }
1164                         else
1165                         {
1166                                 borderMask = s0;
1167                         }
1168                 }
1169
1170                 if(state.addressingModeU == ADDRESSING_BORDER ||
1171                    state.addressingModeV == ADDRESSING_BORDER ||
1172                    (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
1173                 {
1174                         Int4 b;
1175
1176                         c.x = As<Float4>((borderMask & As<Int4>(c.x)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0]))));
1177                         c.y = As<Float4>((borderMask & As<Int4>(c.y)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1]))));
1178                         c.z = As<Float4>((borderMask & As<Int4>(c.z)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2]))));
1179                         c.w = As<Float4>((borderMask & As<Int4>(c.w)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3]))));
1180                 }
1181         }
1182
1183         void SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerFunction function)
1184         {
1185                 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
1186                 {
1187                         sampleFloat(texture, c, u, v, w, offset, lod, face, secondLOD, function);
1188                 }
1189                 else
1190                 {
1191                         Int a = RoundInt(anisotropy);
1192
1193                         Vector4f cSum;
1194
1195                         cSum.x = Float4(0.0f);
1196                         cSum.y = Float4(0.0f);
1197                         cSum.z = Float4(0.0f);
1198                         cSum.w = Float4(0.0f);
1199
1200                         Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
1201                         Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
1202
1203                         Float4 du = uDelta;
1204                         Float4 dv = vDelta;
1205
1206                         Float4 u0 = u + B * du;
1207                         Float4 v0 = v + B * dv;
1208
1209                         du *= A;
1210                         dv *= A;
1211
1212                         Int i = 0;
1213
1214                         Do
1215                         {
1216                                 sampleFloat(texture, c, u0, v0, w, offset, lod, face, secondLOD, function);
1217
1218                                 u0 += du;
1219                                 v0 += dv;
1220
1221                                 cSum.x += c.x * A;
1222                                 cSum.y += c.y * A;
1223                                 cSum.z += c.z * A;
1224                                 cSum.w += c.w * A;
1225
1226                                 i++;
1227                         }
1228                         Until(i >= a)
1229
1230                         c.x = cSum.x;
1231                         c.y = cSum.y;
1232                         c.z = cSum.z;
1233                         c.w = cSum.w;
1234                 }
1235         }
1236
1237         void SamplerCore::sampleFloat(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
1238         {
1239                 if(state.textureType != TEXTURE_3D)
1240                 {
1241                         sampleFloat2D(texture, c, u, v, w, offset, lod, face, secondLOD, function);
1242                 }
1243                 else
1244                 {
1245                         sampleFloat3D(texture, c, u, v, w, offset, lod, secondLOD, function);
1246                 }
1247         }
1248
1249         void SamplerCore::sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
1250         {
1251                 int componentCount = textureComponentCount();
1252                 bool gather = state.textureFilter == FILTER_GATHER;
1253
1254                 Pointer<Byte> mipmap;
1255                 Pointer<Byte> buffer[4];
1256
1257                 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1258
1259                 bool texelFetch = (function == Fetch);
1260
1261                 Short4 uuuu = texelFetch ? Short4(As<Int4>(u)) : address(u, state.addressingModeU, mipmap);
1262                 Short4 vvvv = texelFetch ? Short4(As<Int4>(v)) : address(v, state.addressingModeV, mipmap);
1263                 Short4 wwww = texelFetch ? Short4(As<Int4>(w)) : address(w, state.addressingModeW, mipmap);
1264
1265                 if(state.textureFilter == FILTER_POINT || texelFetch)
1266                 {
1267                         sampleTexel(c, uuuu, vvvv, wwww, offset, w, mipmap, buffer, function);
1268                 }
1269                 else
1270                 {
1271                         Vector4f c0;
1272                         Vector4f c1;
1273                         Vector4f c2;
1274                         Vector4f c3;
1275
1276                         Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
1277                         Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
1278                         Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
1279                         Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
1280
1281                         sampleTexel(c0, uuuu0, vvvv0, wwww, offset, w, mipmap, buffer, function);
1282                         sampleTexel(c1, uuuu1, vvvv0, wwww, offset, w, mipmap, buffer, function);
1283                         sampleTexel(c2, uuuu0, vvvv1, wwww, offset, w, mipmap, buffer, function);
1284                         sampleTexel(c3, uuuu1, vvvv1, wwww, offset, w, mipmap, buffer, function);
1285
1286                         if(!gather)   // Blend
1287                         {
1288                                 // Fractions
1289                                 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth)));
1290                                 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight)));
1291
1292                                 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1293                                 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1294                                 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1295                                 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
1296
1297                                 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1298                                 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1299                                 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1300                                 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
1301
1302                                 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x);
1303                                 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y);
1304                                 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z);
1305                                 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w);
1306                         }
1307                         else
1308                         {
1309                                 c.x = c1.x;
1310                                 c.y = c2.x;
1311                                 c.z = c3.x;
1312                                 c.w = c0.x;
1313                         }
1314                 }
1315         }
1316
1317         void SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
1318         {
1319                 int componentCount = textureComponentCount();
1320
1321                 Pointer<Byte> mipmap;
1322                 Pointer<Byte> buffer[4];
1323                 Int face[4];
1324
1325                 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1326
1327                 bool texelFetch = (function == Fetch);
1328
1329                 Short4 uuuu = texelFetch ? Short4(As<Int4>(u)) : address(u, state.addressingModeU, mipmap);
1330                 Short4 vvvv = texelFetch ? Short4(As<Int4>(v)) : address(v, state.addressingModeV, mipmap);
1331                 Short4 wwww = texelFetch ? Short4(As<Int4>(w)) : address(w, state.addressingModeW, mipmap);
1332
1333                 if(state.textureFilter == FILTER_POINT || texelFetch)
1334                 {
1335                         sampleTexel(c, uuuu, vvvv, wwww, offset, w, mipmap, buffer, function);
1336                 }
1337                 else
1338                 {
1339                         Vector4f &c0 = c;
1340                         Vector4f c1;
1341                         Vector4f c2;
1342                         Vector4f c3;
1343                         Vector4f c4;
1344                         Vector4f c5;
1345                         Vector4f c6;
1346                         Vector4f c7;
1347
1348                         Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, -1, lod);
1349                         Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, -1, lod);
1350                         Short4 wwww0 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, -1, lod);
1351                         Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, +1, lod);
1352                         Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, +1, lod);
1353                         Short4 wwww1 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, +1, lod);
1354
1355                         sampleTexel(c0, uuuu0, vvvv0, wwww0, offset, w, mipmap, buffer, function);
1356                         sampleTexel(c1, uuuu1, vvvv0, wwww0, offset, w, mipmap, buffer, function);
1357                         sampleTexel(c2, uuuu0, vvvv1, wwww0, offset, w, mipmap, buffer, function);
1358                         sampleTexel(c3, uuuu1, vvvv1, wwww0, offset, w, mipmap, buffer, function);
1359                         sampleTexel(c4, uuuu0, vvvv0, wwww1, offset, w, mipmap, buffer, function);
1360                         sampleTexel(c5, uuuu1, vvvv0, wwww1, offset, w, mipmap, buffer, function);
1361                         sampleTexel(c6, uuuu0, vvvv1, wwww1, offset, w, mipmap, buffer, function);
1362                         sampleTexel(c7, uuuu1, vvvv1, wwww1, offset, w, mipmap, buffer, function);
1363
1364                         // Fractions
1365                         Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth)));
1366                         Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight)));
1367                         Float4 fw = Frac(Float4(As<UShort4>(wwww0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fDepth)));
1368
1369                         // Blend first slice
1370                         if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1371                         if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1372                         if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1373                         if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
1374
1375                         if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1376                         if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1377                         if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1378                         if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
1379
1380                         if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x);
1381                         if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y);
1382                         if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z);
1383                         if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w);
1384
1385                         // Blend second slice
1386                         if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x);
1387                         if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y);
1388                         if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z);
1389                         if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w);
1390
1391                         if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x);
1392                         if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y);
1393                         if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z);
1394                         if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w);
1395
1396                         if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x);
1397                         if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y);
1398                         if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z);
1399                         if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w);
1400
1401                         // Blend slices
1402                         if(componentCount >= 1) c0.x = c0.x + fw * (c4.x - c0.x);
1403                         if(componentCount >= 2) c0.y = c0.y + fw * (c4.y - c0.y);
1404                         if(componentCount >= 3) c0.z = c0.z + fw * (c4.z - c0.z);
1405                         if(componentCount >= 4) c0.w = c0.w + fw * (c4.w - c0.w);
1406                 }
1407         }
1408
1409         void SamplerCore::computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1410         {
1411                 if(function != Lod && function != Fetch)
1412                 {
1413                         Float4 duvdxy;
1414
1415                         if(function != Grad)
1416                         {
1417                                 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1418                         }
1419                         else
1420                         {
1421                                 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1422                                 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1423
1424                                 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1425                         }
1426
1427                         // Scale by texture dimensions and LOD
1428                         Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1429
1430                         Float4 dUV2dxy = dUVdxy * dUVdxy;
1431                         Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1432
1433                         lod = Max(Float(dUV2.x), Float(dUV2.y));   // Square length of major axis
1434
1435                         if(state.textureFilter == FILTER_ANISOTROPIC)
1436                         {
1437                                 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1438
1439                                 Float4 dudx = duvdxy.xxxx;
1440                                 Float4 dudy = duvdxy.yyyy;
1441                                 Float4 dvdx = duvdxy.zzzz;
1442                                 Float4 dvdy = duvdxy.wwww;
1443
1444                                 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
1445                                 uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
1446                                 vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
1447
1448                                 anisotropy = lod * Rcp_pp(det);
1449                                 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1450
1451                                 lod *= Rcp_pp(anisotropy * anisotropy);
1452                         }
1453
1454                         // log2(sqrt(lod))
1455                         lod = Float(As<Int>(lod));
1456                         lod -= Float(0x3F800000);
1457                         lod *= As<Float>(Int(0x33800000));
1458
1459                         if(function == Bias)
1460                         {
1461                                 lod += lodBias;
1462                         }
1463                 }
1464                 else
1465                 {
1466                         lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1467                 }
1468
1469                 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1470                 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1471         }
1472
1473         void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1474         {
1475                 if(function != Lod && function != Fetch)
1476                 {
1477                         if(function != Grad)
1478                         {
1479                                 Float4 dudxy = u.ywyw - u;
1480                                 Float4 dvdxy = v.ywyw - v;
1481                                 Float4 dsdxy = s.ywyw - s;
1482
1483                                 // Scale by texture dimensions and LOD
1484                                 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1485                                 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1486                                 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1487
1488                                 dudxy *= dudxy;
1489                                 dvdxy *= dvdxy;
1490                                 dsdxy *= dsdxy;
1491
1492                                 dudxy += dvdxy;
1493                                 dudxy += dsdxy;
1494
1495                                 lod = Max(Float(dudxy.x), Float(dudxy.y));   // FIXME: Max(dudxy.x, dudxy.y);
1496                         }
1497                         else
1498                         {
1499                                 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1500                                 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1501
1502                                 Float4 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1503
1504                                 // Scale by texture dimensions and LOD
1505                                 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1506
1507                                 Float4 dUV2dxy = dUVdxy * dUVdxy;
1508                                 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1509
1510                                 lod = Max(Float(dUV2.x), Float(dUV2.y));   // Square length of major axis
1511                         }
1512
1513                         // log2(sqrt(lod))
1514                         lod = Float(As<Int>(lod));
1515                         lod -= Float(0x3F800000);
1516                         lod *= As<Float>(Int(0x33800000));
1517
1518                         if(function == Bias)
1519                         {
1520                                 lod += lodBias;
1521                         }
1522                 }
1523                 else
1524                 {
1525                         lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1526                 }
1527
1528                 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1529                 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1530         }
1531
1532         void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1533         {
1534                 if(state.mipmapFilter == MIPMAP_NONE)
1535                 {
1536                 }
1537                 else   // Point and linear filter
1538                 {
1539                         if(function != Lod && function != Fetch)
1540                         {
1541                                 Float4 dudxy;
1542                                 Float4 dvdxy;
1543                                 Float4 dsdxy;
1544
1545                                 if(function != Grad)
1546                                 {
1547                                         dudxy = uuuu.ywyw - uuuu;
1548                                         dvdxy = vvvv.ywyw - vvvv;
1549                                         dsdxy = wwww.ywyw - wwww;
1550                                 }
1551                                 else
1552                                 {
1553                                         dudxy = dsx.x;
1554                                         dvdxy = dsx.y;
1555                                         dsdxy = dsx.z;
1556
1557                                         dudxy = Float4(dudxy.xx, dsy.x.xx);
1558                                         dvdxy = Float4(dvdxy.xx, dsy.y.xx);
1559                                         dsdxy = Float4(dsdxy.xx, dsy.z.xx);
1560
1561                                         dudxy = Float4(dudxy.xz, dudxy.xz);
1562                                         dvdxy = Float4(dvdxy.xz, dvdxy.xz);
1563                                         dsdxy = Float4(dsdxy.xz, dsdxy.xz);
1564                                 }
1565
1566                                 // Scale by texture dimensions and LOD
1567                                 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1568                                 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
1569                                 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
1570
1571                                 dudxy *= dudxy;
1572                                 dvdxy *= dvdxy;
1573                                 dsdxy *= dsdxy;
1574
1575                                 dudxy += dvdxy;
1576                                 dudxy += dsdxy;
1577
1578                                 lod = Max(Float(dudxy.x), Float(dudxy.y));   // FIXME: Max(dudxy.x, dudxy.y);
1579
1580                                 // log2(sqrt(lod))
1581                                 lod = Float(As<Int>(lod));
1582                                 lod -= Float(0x3F800000);
1583                                 lod *= As<Float>(Int(0x33800000));
1584
1585                                 if(function == Bias)
1586                                 {
1587                                         lod += lodBias;
1588                                 }
1589                         }
1590                         else
1591                         {
1592                                 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1593                         }
1594
1595                         lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1596                         lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1597                 }
1598         }
1599
1600         void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z)
1601         {
1602                 Int4 xn = CmpLT(x, Float4(0.0f));   // x < 0
1603                 Int4 yn = CmpLT(y, Float4(0.0f));   // y < 0
1604                 Int4 zn = CmpLT(z, Float4(0.0f));   // z < 0
1605
1606                 Float4 absX = Abs(x);
1607                 Float4 absY = Abs(y);
1608                 Float4 absZ = Abs(z);
1609
1610                 Int4 xy = CmpNLE(absX, absY);   // abs(x) > abs(y)
1611                 Int4 yz = CmpNLE(absY, absZ);   // abs(y) > abs(z)
1612                 Int4 zx = CmpNLE(absZ, absX);   // abs(z) > abs(x)
1613                 Int4 xMajor = xy & ~zx;   // abs(x) > abs(y) && abs(x) > abs(z)
1614                 Int4 yMajor = yz & ~xy;   // abs(y) > abs(z) && abs(y) > abs(x)
1615                 Int4 zMajor = zx & ~yz;   // abs(z) > abs(x) && abs(z) > abs(y)
1616
1617                 // FACE_POSITIVE_X = 000b
1618                 // FACE_NEGATIVE_X = 001b
1619                 // FACE_POSITIVE_Y = 010b
1620                 // FACE_NEGATIVE_Y = 011b
1621                 // FACE_POSITIVE_Z = 100b
1622                 // FACE_NEGATIVE_Z = 101b
1623
1624                 Int yAxis = SignMask(yMajor);
1625                 Int zAxis = SignMask(zMajor);
1626
1627                 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
1628                 Int negative = SignMask(n);
1629
1630                 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
1631                 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4);
1632                 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4);
1633                 face[1] = (face[0] >> 4)  & 0x7;
1634                 face[2] = (face[0] >> 8)  & 0x7;
1635                 face[3] = (face[0] >> 12) & 0x7;
1636                 face[0] &= 0x7;
1637
1638                 Float4 M = Max(Max(absX, absY), absZ);
1639
1640                 // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x)
1641                 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
1642
1643                 // V = !yMajor ? -y : (n ^ z)
1644                 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
1645
1646                 M = reciprocal(M) * Float4(0.5f);
1647                 U = U * M + Float4(0.5f);
1648                 V = V * M + Float4(0.5f);
1649
1650                 lodX = x * M;
1651                 lodY = y * M;
1652                 lodZ = z * M;
1653         }
1654
1655         Short4 SamplerCore::applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode)
1656         {
1657                 Int4 tmp = Int4(As<UShort4>(uvw));
1658                 tmp = tmp + As<Int4>(offset);
1659
1660                 switch (mode)
1661                 {
1662                 case AddressingMode::ADDRESSING_WRAP:
1663                         tmp = (tmp + whd * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % whd;
1664                         break;
1665                 case AddressingMode::ADDRESSING_CLAMP:
1666                 case AddressingMode::ADDRESSING_MIRROR:
1667                 case AddressingMode::ADDRESSING_MIRRORONCE:
1668                 case AddressingMode::ADDRESSING_BORDER: // FIXME: Implement and test ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, ADDRESSING_BORDER
1669                         tmp = Min(Max(tmp, Int4(0)), whd - Int4(1));
1670                         break;
1671                 case ADDRESSING_TEXELFETCH:
1672                         break;
1673                 default:
1674                         ASSERT(false);
1675                 }
1676
1677                 return As<Short4>(UShort4(tmp));
1678         }
1679
1680         void SamplerCore::computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function)
1681         {
1682                 bool texelFetch = (function == Fetch);
1683                 bool hasOffset = (function.option == Offset);
1684
1685                 if(!texelFetch)
1686                 {
1687                         uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width)));
1688                         vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height)));
1689                 }
1690
1691                 if(hasOffset)
1692                 {
1693                         uuuu = applyOffset(uuuu, offset.x, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, width))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeU);
1694                         vvvv = applyOffset(vvvv, offset.y, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, height))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeV);
1695                 }
1696
1697                 Short4 uuu2 = uuuu;
1698                 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1699                 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1700                 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1701                 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1702
1703                 if((state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY))
1704                 {
1705                         if(state.textureType != TEXTURE_2D_ARRAY)
1706                         {
1707                                 if(!texelFetch)
1708                                 {
1709                                         wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth)));
1710                                 }
1711                                 if(hasOffset)
1712                                 {
1713                                         wwww = applyOffset(wwww, offset.z, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeW);
1714                                 }
1715                         }
1716                         Short4 www2 = wwww;
1717                         wwww = As<Short4>(UnpackLow(wwww, Short4(0x0000)));
1718                         www2 = As<Short4>(UnpackHigh(www2, Short4(0x0000)));
1719                         wwww = As<Short4>(MulAdd(wwww, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP))));
1720                         www2 = As<Short4>(MulAdd(www2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP))));
1721                         uuuu = As<Short4>(As<Int2>(uuuu) + As<Int2>(wwww));
1722                         uuu2 = As<Short4>(As<Int2>(uuu2) + As<Int2>(www2));
1723                 }
1724
1725                 index[0] = Extract(As<Int2>(uuuu), 0);
1726                 index[1] = Extract(As<Int2>(uuuu), 1);
1727                 index[2] = Extract(As<Int2>(uuu2), 0);
1728                 index[3] = Extract(As<Int2>(uuu2), 1);
1729
1730                 if(texelFetch)
1731                 {
1732                         Int size = Int(*Pointer<Int>(mipmap + OFFSET(Mipmap, sliceP)));
1733                         if((state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY))
1734                         {
1735                                 size *= Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)));
1736                         }
1737                         UInt min = 0;
1738                         UInt max = size - 1;
1739
1740                         for(int i = 0; i < 4; i++)
1741                         {
1742                                 index[i] = Min(Max(index[i], min), max);
1743                         }
1744                 }
1745         }
1746
1747         void SamplerCore::sampleTexel(Vector4s &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Vector4f &offset, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
1748         {
1749                 UInt index[4];
1750
1751                 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
1752
1753                 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1754                 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1755                 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1756                 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1757
1758                 if(has16bitTextureFormat())
1759                 {
1760                         c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1761                         c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1762                         c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1763                         c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
1764
1765                         switch(state.textureFormat)
1766                         {
1767                         case FORMAT_R5G6B5:
1768                                 c.z = (c.x & Short4(0x001Fu)) << 11;
1769                                 c.y = (c.x & Short4(0x07E0u)) << 5;
1770                                 c.x = (c.x & Short4(0xF800u));
1771                                 break;
1772                         default:
1773                                 ASSERT(false);
1774                         }
1775                 }
1776                 else if(has8bitTextureComponents())
1777                 {
1778                         switch(textureComponentCount())
1779                         {
1780                         case 4:
1781                                 {
1782                                         Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1783                                         Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1784                                         Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1785                                         Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
1786                                         c.x = Unpack(c0, c1);
1787                                         c.y = Unpack(c2, c3);
1788
1789                                         switch(state.textureFormat)
1790                                         {
1791                                         case FORMAT_A8R8G8B8:
1792                                                 c.z = c.x;
1793                                                 c.z = As<Short4>(UnpackLow(c.z, c.y));
1794                                                 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1795                                                 c.y = c.z;
1796                                                 c.w = c.x;
1797                                                 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1798                                                 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1799                                                 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1800                                                 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
1801                                                 break;
1802                                         case FORMAT_A8B8G8R8:
1803                                         case FORMAT_A8B8G8R8I:
1804                                         case FORMAT_A8B8G8R8UI:
1805                                         case FORMAT_A8B8G8R8I_SNORM:
1806                                         case FORMAT_Q8W8V8U8:
1807                                         case FORMAT_SRGB8_A8:
1808                                                 c.z = c.x;
1809                                                 c.x = As<Short4>(UnpackLow(c.x, c.y));
1810                                                 c.z = As<Short4>(UnpackHigh(c.z, c.y));
1811                                                 c.y = c.x;
1812                                                 c.w = c.z;
1813                                                 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1814                                                 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1815                                                 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1816                                                 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
1817                                                 break;
1818                                         default:
1819                                                 ASSERT(false);
1820                                         }
1821                                 }
1822                                 break;
1823                         case 3:
1824                                 {
1825                                         Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1826                                         Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1827                                         Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1828                                         Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
1829                                         c.x = Unpack(c0, c1);
1830                                         c.y = Unpack(c2, c3);
1831
1832                                         switch(state.textureFormat)
1833                                         {
1834                                         case FORMAT_X8R8G8B8:
1835                                                 c.z = c.x;
1836                                                 c.z = As<Short4>(UnpackLow(c.z, c.y));
1837                                                 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1838                                                 c.y = c.z;
1839                                                 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1840                                                 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1841                                                 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1842                                                 break;
1843                                         case FORMAT_X8B8G8R8I_SNORM:
1844                                         case FORMAT_X8B8G8R8UI:
1845                                         case FORMAT_X8B8G8R8I:
1846                                         case FORMAT_X8B8G8R8:
1847                                         case FORMAT_X8L8V8U8:
1848                                         case FORMAT_SRGB8_X8:
1849                                                 c.z = c.x;
1850                                                 c.x = As<Short4>(UnpackLow(c.x, c.y));
1851                                                 c.z = As<Short4>(UnpackHigh(c.z, c.y));
1852                                                 c.y = c.x;
1853                                                 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1854                                                 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1855                                                 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1856                                                 break;
1857                                         default:
1858                                                 ASSERT(false);
1859                                         }
1860                                 }
1861                                 break;
1862                         case 2:
1863                                 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1864                                 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1865                                 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1866                                 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
1867
1868                                 switch(state.textureFormat)
1869                                 {
1870                                 case FORMAT_G8R8:
1871                                 case FORMAT_G8R8I:
1872                                 case FORMAT_G8R8UI:
1873                                 case FORMAT_G8R8I_SNORM:
1874                                 case FORMAT_V8U8:
1875                                 case FORMAT_A8L8:
1876                                         c.y = (c.x & Short4(0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
1877                                         c.x = (c.x & Short4(0x00FFu)) | (c.x << 8);
1878                                         break;
1879                                 default:
1880                                         ASSERT(false);
1881                                 }
1882                                 break;
1883                         case 1:
1884                                 {
1885                                         Int c0 = Int(*Pointer<Byte>(buffer[f0] + index[0]));
1886                                         Int c1 = Int(*Pointer<Byte>(buffer[f1] + index[1]));
1887                                         Int c2 = Int(*Pointer<Byte>(buffer[f2] + index[2]));
1888                                         Int c3 = Int(*Pointer<Byte>(buffer[f3] + index[3]));
1889                                         c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1890                                         c.x = Unpack(As<Byte4>(c0));
1891                                 }
1892                                 break;
1893                         default:
1894                                 ASSERT(false);
1895                         }
1896                 }
1897                 else if(has16bitTextureComponents())
1898                 {
1899                         switch(textureComponentCount())
1900                         {
1901                         case 4:
1902                                 c.x = Pointer<Short4>(buffer[f0])[index[0]];
1903                                 c.y = Pointer<Short4>(buffer[f1])[index[1]];
1904                                 c.z = Pointer<Short4>(buffer[f2])[index[2]];
1905                                 c.w = Pointer<Short4>(buffer[f3])[index[3]];
1906                                 transpose4x4(c.x, c.y, c.z, c.w);
1907                                 break;
1908                         case 2:
1909                                 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]);
1910                                 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1])));
1911                                 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]);
1912                                 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3])));
1913                                 c.y = c.x;
1914                                 c.x = UnpackLow(As<Int2>(c.x), As<Int2>(c.z));
1915                                 c.y = UnpackHigh(As<Int2>(c.y), As<Int2>(c.z));
1916                                 break;
1917                         case 1:
1918                                 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1919                                 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1920                                 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1921                                 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
1922                                 break;
1923                         default:
1924                                 ASSERT(false);
1925                         }
1926                 }
1927                 else if(hasYuvFormat())
1928                 {
1929                         // Generic YPbPr to RGB transformation
1930                         // R = Y                               +           2 * (1 - Kr) * Pr
1931                         // G = Y - 2 * Kb * (1 - Kb) / Kg * Pb - 2 * Kr * (1 - Kr) / Kg * Pr
1932                         // B = Y +           2 * (1 - Kb) * Pb
1933
1934                         float Kb = 0.114f;
1935                         float Kr = 0.299f;
1936                         int studioSwing = 1;
1937
1938                         switch(state.textureFormat)
1939                         {
1940                         case FORMAT_YV12_BT601:
1941                                 Kb = 0.114f;
1942                                 Kr = 0.299f;
1943                                 studioSwing = 1;
1944                                 break;
1945                         case FORMAT_YV12_BT709:
1946                                 Kb = 0.0722f;
1947                                 Kr = 0.2126f;
1948                                 studioSwing = 1;
1949                                 break;
1950                         case FORMAT_YV12_JFIF:
1951                                 Kb = 0.114f;
1952                                 Kr = 0.299f;
1953                                 studioSwing = 0;
1954                                 break;
1955                         default:
1956                                 ASSERT(false);
1957                         }
1958
1959                         const float Kg = 1.0f - Kr - Kb;
1960
1961                         const float Rr = 2 * (1 - Kr);
1962                         const float Gb = -2 * Kb * (1 - Kb) / Kg;
1963                         const float Gr = -2 * Kr * (1 - Kr) / Kg;
1964                         const float Bb = 2 * (1 - Kb);
1965
1966                         // Scaling and bias for studio-swing range: Y = [16 .. 235], U/V = [16 .. 240]
1967                         const float Yy = studioSwing ? 255.0f / (235 - 16) : 1.0f;
1968                         const float Uu = studioSwing ? 255.0f / (240 - 16) : 1.0f;
1969                         const float Vv = studioSwing ? 255.0f / (240 - 16) : 1.0f;
1970
1971                         const float Rv = Vv *  Rr;
1972                         const float Gu = Uu *  Gb;
1973                         const float Gv = Vv *  Gr;
1974                         const float Bu = Uu *  Bb;
1975
1976                         const float R0 = (studioSwing * -16 * Yy - 128 * Rv) / 255;
1977                         const float G0 = (studioSwing * -16 * Yy - 128 * Gu - 128 * Gv) / 255;
1978                         const float B0 = (studioSwing * -16 * Yy - 128 * Bu) / 255;
1979
1980                         Int c0 = Int(buffer[0][index[0]]);
1981                         Int c1 = Int(buffer[0][index[1]]);
1982                         Int c2 = Int(buffer[0][index[2]]);
1983                         Int c3 = Int(buffer[0][index[3]]);
1984                         c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1985                         UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0)));
1986
1987                         computeIndices(index, uuuu, vvvv, wwww, offset, mipmap + sizeof(Mipmap), function);
1988                         c0 = Int(buffer[1][index[0]]);
1989                         c1 = Int(buffer[1][index[1]]);
1990                         c2 = Int(buffer[1][index[2]]);
1991                         c3 = Int(buffer[1][index[3]]);
1992                         c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1993                         UShort4 V = As<UShort4>(Unpack(As<Byte4>(c0)));
1994
1995                         c0 = Int(buffer[2][index[0]]);
1996                         c1 = Int(buffer[2][index[1]]);
1997                         c2 = Int(buffer[2][index[2]]);
1998                         c3 = Int(buffer[2][index[3]]);
1999                         c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2000                         UShort4 U = As<UShort4>(Unpack(As<Byte4>(c0)));
2001
2002                         const UShort4 yY = UShort4(iround(Yy * 0x4000));
2003                         const UShort4 rV = UShort4(iround(Rv * 0x4000));
2004                         const UShort4 gU = UShort4(iround(-Gu * 0x4000));
2005                         const UShort4 gV = UShort4(iround(-Gv * 0x4000));
2006                         const UShort4 bU = UShort4(iround(Bu * 0x4000));
2007
2008                         const UShort4 r0 = UShort4(iround(-R0 * 0x4000));
2009                         const UShort4 g0 = UShort4(iround(G0 * 0x4000));
2010                         const UShort4 b0 = UShort4(iround(-B0 * 0x4000));
2011
2012                         UShort4 y = MulHigh(Y, yY);
2013                         UShort4 r = SubSat(y + MulHigh(V, rV), r0);
2014                         UShort4 g = SubSat(y + g0, MulHigh(U, gU) + MulHigh(V, gV));
2015                         UShort4 b = SubSat(y + MulHigh(U, bU), b0);
2016
2017                         c.x = Min(r, UShort4(0x3FFF)) << 2;
2018                         c.y = Min(g, UShort4(0x3FFF)) << 2;
2019                         c.z = Min(b, UShort4(0x3FFF)) << 2;
2020                 }
2021                 else ASSERT(false);
2022         }
2023
2024         void SamplerCore::sampleTexel(Vector4f &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Vector4f &offset, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
2025         {
2026                 UInt index[4];
2027
2028                 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
2029
2030                 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
2031                 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
2032                 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
2033                 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
2034
2035                 // Read texels
2036                 switch(textureComponentCount())
2037                 {
2038                 case 4:
2039                         c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2040                         c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2041                         c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2042                         c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2043                         transpose4x4(c.x, c.y, c.z, c.w);
2044                         break;
2045                 case 3:
2046                         ASSERT(state.textureFormat == FORMAT_X32B32G32R32F);
2047                         c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2048                         c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2049                         c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2050                         c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2051                         transpose4x3(c.x, c.y, c.z, c.w);
2052                         c.w = Float4(1.0f);
2053                         break;
2054                 case 2:
2055                         // FIXME: Optimal shuffling?
2056                         c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8);
2057                         c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8);
2058                         c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8);
2059                         c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8);
2060                         c.y = c.x;
2061                         c.x = Float4(c.x.xz, c.z.xz);
2062                         c.y = Float4(c.y.yw, c.z.yw);
2063                         break;
2064                 case 1:
2065                         // FIXME: Optimal shuffling?
2066                         c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4);
2067                         c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4);
2068                         c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4);
2069                         c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4);
2070
2071                         if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER)
2072                         {
2073                                 Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f));
2074
2075                                 c.x = As<Float4>(As<Int4>(CmpNLT(c.x, d)) & As<Int4>(Float4(1.0f)));   // FIXME: Only less-equal?
2076                         }
2077                         break;
2078                 default:
2079                         ASSERT(false);
2080                 }
2081         }
2082
2083         void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
2084         {
2085                 if(state.mipmapFilter < MIPMAP_POINT)
2086                 {
2087                         mipmap = texture + OFFSET(Texture,mipmap[0]);
2088                 }
2089                 else
2090                 {
2091                         Int ilod;
2092
2093                         if(state.mipmapFilter == MIPMAP_POINT)
2094                         {
2095                                 ilod = RoundInt(lod);
2096                         }
2097                         else   // Linear
2098                         {
2099                                 ilod = Int(lod);
2100                         }
2101
2102                         mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
2103                 }
2104
2105                 if(state.textureType != TEXTURE_CUBE)
2106                 {
2107                         buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
2108
2109                         if(hasYuvFormat())
2110                         {
2111                                 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1]));
2112                                 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2]));
2113                         }
2114                 }
2115                 else
2116                 {
2117                         for(int i = 0; i < 4; i++)
2118                         {
2119                                 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
2120                         }
2121                 }
2122         }
2123
2124         Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap)
2125         {
2126                 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2127                 {
2128                         return Short4();   // Unused
2129                 }
2130                 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY)
2131                 {
2132                         return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1));
2133                 }
2134                 else if(addressingMode == ADDRESSING_CLAMP)
2135                 {
2136                         Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
2137
2138                         return Short4(Int4(clamp * Float4(1 << 16)));
2139                 }
2140                 else if(addressingMode == ADDRESSING_MIRROR)
2141                 {
2142                         Int4 convert = Int4(uw * Float4(1 << 16));
2143                         Int4 mirror = (convert << 15) >> 31;
2144
2145                         convert ^= mirror;
2146
2147                         return Short4(convert);
2148                 }
2149                 else if(addressingMode == ADDRESSING_MIRRORONCE)
2150                 {
2151                         // Absolute value
2152                         Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
2153
2154                         // Clamp
2155                         convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
2156                         convert = As<Int4>(Pack(convert, convert));
2157
2158                         return As<Short4>(Int2(convert)) + Short4(0x8000u);
2159                 }
2160                 else   // Wrap (or border)
2161                 {
2162                         return Short4(Int4(uw * Float4(1 << 16)));
2163                 }
2164         }
2165
2166         void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
2167         {
2168                 cs = RoundShort4(cf * Float4(0x1000));
2169         }
2170
2171         void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
2172         {
2173                 convertFixed12(cs.x, cf.x);
2174                 convertFixed12(cs.y, cf.y);
2175                 convertFixed12(cs.z, cf.z);
2176                 convertFixed12(cs.w, cf.w);
2177         }
2178
2179         void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
2180         {
2181                 cf = Float4(cs) * Float4(1.0f / 0x0FFE);
2182         }
2183
2184 //      void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
2185 //      {
2186 //              convertSigned12(cf.x, cs.x);
2187 //              convertSigned12(cf.y, cs.y);
2188 //              convertSigned12(cf.z, cs.z);
2189 //              convertSigned12(cf.w, cs.w);
2190 //      }
2191
2192         void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
2193         {
2194                 cf = Float4(cs) * Float4(1.0f / 0x7FFF);
2195         }
2196
2197         void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
2198         {
2199                 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
2200         }
2201
2202         void SamplerCore::sRGBtoLinear16_8_12(Short4 &c)
2203         {
2204                 c = As<UShort4>(c) >> 8;
2205
2206                 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_12));
2207
2208                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2209                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2210                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2211                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2212         }
2213
2214         void SamplerCore::sRGBtoLinear16_6_12(Short4 &c)
2215         {
2216                 c = As<UShort4>(c) >> 10;
2217
2218                 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_12));
2219
2220                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2221                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2222                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2223                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2224         }
2225
2226         void SamplerCore::sRGBtoLinear16_5_12(Short4 &c)
2227         {
2228                 c = As<UShort4>(c) >> 11;
2229
2230                 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_12));
2231
2232                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2233                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2234                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2235                 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2236         }
2237
2238         bool SamplerCore::hasFloatTexture() const
2239         {
2240                 return Surface::isFloatFormat(state.textureFormat);
2241         }
2242
2243         bool SamplerCore::hasUnsignedTextureComponent(int component) const
2244         {
2245                 return Surface::isUnsignedComponent(state.textureFormat, component);
2246         }
2247
2248         int SamplerCore::textureComponentCount() const
2249         {
2250                 return Surface::componentCount(state.textureFormat);
2251         }
2252
2253         bool SamplerCore::has16bitTextureFormat() const
2254         {
2255                 switch(state.textureFormat)
2256                 {
2257                 case FORMAT_R5G6B5:
2258                         return true;
2259                 case FORMAT_R8I_SNORM:
2260                 case FORMAT_G8R8I_SNORM:
2261                 case FORMAT_X8B8G8R8I_SNORM:
2262                 case FORMAT_A8B8G8R8I_SNORM:
2263                 case FORMAT_R8I:
2264                 case FORMAT_R8UI:
2265                 case FORMAT_G8R8I:
2266                 case FORMAT_G8R8UI:
2267                 case FORMAT_X8B8G8R8I:
2268                 case FORMAT_X8B8G8R8UI:
2269                 case FORMAT_A8B8G8R8I:
2270                 case FORMAT_A8B8G8R8UI:
2271                 case FORMAT_R32I:
2272                 case FORMAT_R32UI:
2273                 case FORMAT_G32R32I:
2274                 case FORMAT_G32R32UI:
2275                 case FORMAT_X32B32G32R32I:
2276                 case FORMAT_X32B32G32R32UI:
2277                 case FORMAT_A32B32G32R32I:
2278                 case FORMAT_A32B32G32R32UI:
2279                 case FORMAT_G8R8:
2280                 case FORMAT_X8R8G8B8:
2281                 case FORMAT_X8B8G8R8:
2282                 case FORMAT_A8R8G8B8:
2283                 case FORMAT_A8B8G8R8:
2284                 case FORMAT_SRGB8_X8:
2285                 case FORMAT_SRGB8_A8:
2286                 case FORMAT_V8U8:
2287                 case FORMAT_Q8W8V8U8:
2288                 case FORMAT_X8L8V8U8:
2289                 case FORMAT_R32F:
2290                 case FORMAT_G32R32F:
2291                 case FORMAT_X32B32G32R32F:
2292                 case FORMAT_A32B32G32R32F:
2293                 case FORMAT_A8:
2294                 case FORMAT_R8:
2295                 case FORMAT_L8:
2296                 case FORMAT_A8L8:
2297                 case FORMAT_D32F:
2298                 case FORMAT_D32F_LOCKABLE:
2299                 case FORMAT_D32FS8_TEXTURE:
2300                 case FORMAT_D32FS8_SHADOW:
2301                 case FORMAT_L16:
2302                 case FORMAT_G16R16:
2303                 case FORMAT_A16B16G16R16:
2304                 case FORMAT_V16U16:
2305                 case FORMAT_A16W16V16U16:
2306                 case FORMAT_Q16W16V16U16:
2307                 case FORMAT_R16I:
2308                 case FORMAT_R16UI:
2309                 case FORMAT_G16R16I:
2310                 case FORMAT_G16R16UI:
2311                 case FORMAT_X16B16G16R16I:
2312                 case FORMAT_X16B16G16R16UI:
2313                 case FORMAT_A16B16G16R16I:
2314                 case FORMAT_A16B16G16R16UI:
2315                 case FORMAT_YV12_BT601:
2316                 case FORMAT_YV12_BT709:
2317                 case FORMAT_YV12_JFIF:
2318                         return false;
2319                 default:
2320                         ASSERT(false);
2321                 }
2322
2323                 return false;
2324         }
2325
2326         bool SamplerCore::has8bitTextureComponents() const
2327         {
2328                 switch(state.textureFormat)
2329                 {
2330                 case FORMAT_G8R8:
2331                 case FORMAT_X8R8G8B8:
2332                 case FORMAT_X8B8G8R8:
2333                 case FORMAT_A8R8G8B8:
2334                 case FORMAT_A8B8G8R8:
2335                 case FORMAT_SRGB8_X8:
2336                 case FORMAT_SRGB8_A8:
2337                 case FORMAT_V8U8:
2338                 case FORMAT_Q8W8V8U8:
2339                 case FORMAT_X8L8V8U8:
2340                 case FORMAT_A8:
2341                 case FORMAT_R8:
2342                 case FORMAT_L8:
2343                 case FORMAT_A8L8:
2344                 case FORMAT_R8I_SNORM:
2345                 case FORMAT_G8R8I_SNORM:
2346                 case FORMAT_X8B8G8R8I_SNORM:
2347                 case FORMAT_A8B8G8R8I_SNORM:
2348                 case FORMAT_R8I:
2349                 case FORMAT_R8UI:
2350                 case FORMAT_G8R8I:
2351                 case FORMAT_G8R8UI:
2352                 case FORMAT_X8B8G8R8I:
2353                 case FORMAT_X8B8G8R8UI:
2354                 case FORMAT_A8B8G8R8I:
2355                 case FORMAT_A8B8G8R8UI:
2356                         return true;
2357                 case FORMAT_R5G6B5:
2358                 case FORMAT_R32F:
2359                 case FORMAT_G32R32F:
2360                 case FORMAT_X32B32G32R32F:
2361                 case FORMAT_A32B32G32R32F:
2362                 case FORMAT_D32F:
2363                 case FORMAT_D32F_LOCKABLE:
2364                 case FORMAT_D32FS8_TEXTURE:
2365                 case FORMAT_D32FS8_SHADOW:
2366                 case FORMAT_L16:
2367                 case FORMAT_G16R16:
2368                 case FORMAT_A16B16G16R16:
2369                 case FORMAT_V16U16:
2370                 case FORMAT_A16W16V16U16:
2371                 case FORMAT_Q16W16V16U16:
2372                 case FORMAT_R32I:
2373                 case FORMAT_R32UI:
2374                 case FORMAT_G32R32I:
2375                 case FORMAT_G32R32UI:
2376                 case FORMAT_X32B32G32R32I:
2377                 case FORMAT_X32B32G32R32UI:
2378                 case FORMAT_A32B32G32R32I:
2379                 case FORMAT_A32B32G32R32UI:
2380                 case FORMAT_R16I:
2381                 case FORMAT_R16UI:
2382                 case FORMAT_G16R16I:
2383                 case FORMAT_G16R16UI:
2384                 case FORMAT_X16B16G16R16I:
2385                 case FORMAT_X16B16G16R16UI:
2386                 case FORMAT_A16B16G16R16I:
2387                 case FORMAT_A16B16G16R16UI:
2388                 case FORMAT_YV12_BT601:
2389                 case FORMAT_YV12_BT709:
2390                 case FORMAT_YV12_JFIF:
2391                         return false;
2392                 default:
2393                         ASSERT(false);
2394                 }
2395
2396                 return false;
2397         }
2398
2399         bool SamplerCore::has16bitTextureComponents() const
2400         {
2401                 switch(state.textureFormat)
2402                 {
2403                 case FORMAT_R5G6B5:
2404                 case FORMAT_R8I_SNORM:
2405                 case FORMAT_G8R8I_SNORM:
2406                 case FORMAT_X8B8G8R8I_SNORM:
2407                 case FORMAT_A8B8G8R8I_SNORM:
2408                 case FORMAT_R8I:
2409                 case FORMAT_R8UI:
2410                 case FORMAT_G8R8I:
2411                 case FORMAT_G8R8UI:
2412                 case FORMAT_X8B8G8R8I:
2413                 case FORMAT_X8B8G8R8UI:
2414                 case FORMAT_A8B8G8R8I:
2415                 case FORMAT_A8B8G8R8UI:
2416                 case FORMAT_R32I:
2417                 case FORMAT_R32UI:
2418                 case FORMAT_G32R32I:
2419                 case FORMAT_G32R32UI:
2420                 case FORMAT_X32B32G32R32I:
2421                 case FORMAT_X32B32G32R32UI:
2422                 case FORMAT_A32B32G32R32I:
2423                 case FORMAT_A32B32G32R32UI:
2424                 case FORMAT_G8R8:
2425                 case FORMAT_X8R8G8B8:
2426                 case FORMAT_X8B8G8R8:
2427                 case FORMAT_A8R8G8B8:
2428                 case FORMAT_A8B8G8R8:
2429                 case FORMAT_SRGB8_X8:
2430                 case FORMAT_SRGB8_A8:
2431                 case FORMAT_V8U8:
2432                 case FORMAT_Q8W8V8U8:
2433                 case FORMAT_X8L8V8U8:
2434                 case FORMAT_R32F:
2435                 case FORMAT_G32R32F:
2436                 case FORMAT_X32B32G32R32F:
2437                 case FORMAT_A32B32G32R32F:
2438                 case FORMAT_A8:
2439                 case FORMAT_R8:
2440                 case FORMAT_L8:
2441                 case FORMAT_A8L8:
2442                 case FORMAT_D32F:
2443                 case FORMAT_D32F_LOCKABLE:
2444                 case FORMAT_D32FS8_TEXTURE:
2445                 case FORMAT_D32FS8_SHADOW:
2446                 case FORMAT_YV12_BT601:
2447                 case FORMAT_YV12_BT709:
2448                 case FORMAT_YV12_JFIF:
2449                         return false;
2450                 case FORMAT_L16:
2451                 case FORMAT_G16R16:
2452                 case FORMAT_A16B16G16R16:
2453                 case FORMAT_R16I:
2454                 case FORMAT_R16UI:
2455                 case FORMAT_G16R16I:
2456                 case FORMAT_G16R16UI:
2457                 case FORMAT_X16B16G16R16I:
2458                 case FORMAT_X16B16G16R16UI:
2459                 case FORMAT_A16B16G16R16I:
2460                 case FORMAT_A16B16G16R16UI:
2461                 case FORMAT_V16U16:
2462                 case FORMAT_A16W16V16U16:
2463                 case FORMAT_Q16W16V16U16:
2464                         return true;
2465                 default:
2466                         ASSERT(false);
2467                 }
2468
2469                 return false;
2470         }
2471
2472         bool SamplerCore::hasYuvFormat() const
2473         {
2474                 switch(state.textureFormat)
2475                 {
2476                 case FORMAT_YV12_BT601:
2477                 case FORMAT_YV12_BT709:
2478                 case FORMAT_YV12_JFIF:
2479                         return true;
2480                 case FORMAT_R5G6B5:
2481                 case FORMAT_R8I_SNORM:
2482                 case FORMAT_G8R8I_SNORM:
2483                 case FORMAT_X8B8G8R8I_SNORM:
2484                 case FORMAT_A8B8G8R8I_SNORM:
2485                 case FORMAT_R8I:
2486                 case FORMAT_R8UI:
2487                 case FORMAT_G8R8I:
2488                 case FORMAT_G8R8UI:
2489                 case FORMAT_X8B8G8R8I:
2490                 case FORMAT_X8B8G8R8UI:
2491                 case FORMAT_A8B8G8R8I:
2492                 case FORMAT_A8B8G8R8UI:
2493                 case FORMAT_R32I:
2494                 case FORMAT_R32UI:
2495                 case FORMAT_G32R32I:
2496                 case FORMAT_G32R32UI:
2497                 case FORMAT_X32B32G32R32I:
2498                 case FORMAT_X32B32G32R32UI:
2499                 case FORMAT_A32B32G32R32I:
2500                 case FORMAT_A32B32G32R32UI:
2501                 case FORMAT_G8R8:
2502                 case FORMAT_X8R8G8B8:
2503                 case FORMAT_X8B8G8R8:
2504                 case FORMAT_A8R8G8B8:
2505                 case FORMAT_A8B8G8R8:
2506                 case FORMAT_SRGB8_X8:
2507                 case FORMAT_SRGB8_A8:
2508                 case FORMAT_V8U8:
2509                 case FORMAT_Q8W8V8U8:
2510                 case FORMAT_X8L8V8U8:
2511                 case FORMAT_R32F:
2512                 case FORMAT_G32R32F:
2513                 case FORMAT_X32B32G32R32F:
2514                 case FORMAT_A32B32G32R32F:
2515                 case FORMAT_A8:
2516                 case FORMAT_R8:
2517                 case FORMAT_L8:
2518                 case FORMAT_A8L8:
2519                 case FORMAT_D32F:
2520                 case FORMAT_D32F_LOCKABLE:
2521                 case FORMAT_D32FS8_TEXTURE:
2522                 case FORMAT_D32FS8_SHADOW:
2523                 case FORMAT_L16:
2524                 case FORMAT_G16R16:
2525                 case FORMAT_A16B16G16R16:
2526                 case FORMAT_R16I:
2527                 case FORMAT_R16UI:
2528                 case FORMAT_G16R16I:
2529                 case FORMAT_G16R16UI:
2530                 case FORMAT_X16B16G16R16I:
2531                 case FORMAT_X16B16G16R16UI:
2532                 case FORMAT_A16B16G16R16I:
2533                 case FORMAT_A16B16G16R16UI:
2534                 case FORMAT_V16U16:
2535                 case FORMAT_A16W16V16U16:
2536                 case FORMAT_Q16W16V16U16:
2537                         return false;
2538                 default:
2539                         ASSERT(false);
2540                 }
2541
2542                 return false;
2543         }
2544
2545         bool SamplerCore::isRGBComponent(int component) const
2546         {
2547                 switch(state.textureFormat)
2548                 {
2549                 case FORMAT_R5G6B5:         return component < 3;
2550                 case FORMAT_R8I_SNORM:      return component < 1;
2551                 case FORMAT_G8R8I_SNORM:    return component < 2;
2552                 case FORMAT_X8B8G8R8I_SNORM: return component < 3;
2553                 case FORMAT_A8B8G8R8I_SNORM: return component < 3;
2554                 case FORMAT_R8I:            return component < 1;
2555                 case FORMAT_R8UI:           return component < 1;
2556                 case FORMAT_G8R8I:          return component < 2;
2557                 case FORMAT_G8R8UI:         return component < 2;
2558                 case FORMAT_X8B8G8R8I:      return component < 3;
2559                 case FORMAT_X8B8G8R8UI:     return component < 3;
2560                 case FORMAT_A8B8G8R8I:      return component < 3;
2561                 case FORMAT_A8B8G8R8UI:     return component < 3;
2562                 case FORMAT_R32I:           return component < 1;
2563                 case FORMAT_R32UI:          return component < 1;
2564                 case FORMAT_G32R32I:        return component < 2;
2565                 case FORMAT_G32R32UI:       return component < 2;
2566                 case FORMAT_X32B32G32R32I:  return component < 3;
2567                 case FORMAT_X32B32G32R32UI: return component < 3;
2568                 case FORMAT_A32B32G32R32I:  return component < 3;
2569                 case FORMAT_A32B32G32R32UI: return component < 3;
2570                 case FORMAT_G8R8:           return component < 2;
2571                 case FORMAT_X8R8G8B8:       return component < 3;
2572                 case FORMAT_X8B8G8R8:       return component < 3;
2573                 case FORMAT_A8R8G8B8:       return component < 3;
2574                 case FORMAT_A8B8G8R8:       return component < 3;
2575                 case FORMAT_SRGB8_X8:       return component < 3;
2576                 case FORMAT_SRGB8_A8:       return component < 3;
2577                 case FORMAT_V8U8:           return false;
2578                 case FORMAT_Q8W8V8U8:       return false;
2579                 case FORMAT_X8L8V8U8:       return false;
2580                 case FORMAT_R32F:           return component < 1;
2581                 case FORMAT_G32R32F:        return component < 2;
2582                 case FORMAT_X32B32G32R32F:  return component < 3;
2583                 case FORMAT_A32B32G32R32F:  return component < 3;
2584                 case FORMAT_A8:             return false;
2585                 case FORMAT_R8:             return component < 1;
2586                 case FORMAT_L8:             return component < 1;
2587                 case FORMAT_A8L8:           return component < 1;
2588                 case FORMAT_D32F:           return false;
2589                 case FORMAT_D32F_LOCKABLE:  return false;
2590                 case FORMAT_D32FS8_TEXTURE: return false;
2591                 case FORMAT_D32FS8_SHADOW:  return false;
2592                 case FORMAT_L16:            return component < 1;
2593                 case FORMAT_G16R16:         return component < 2;
2594                 case FORMAT_A16B16G16R16:   return component < 3;
2595                 case FORMAT_R16I:           return component < 1;
2596                 case FORMAT_R16UI:          return component < 1;
2597                 case FORMAT_G16R16I:        return component < 2;
2598                 case FORMAT_G16R16UI:       return component < 2;
2599                 case FORMAT_X16B16G16R16I:  return component < 3;
2600                 case FORMAT_X16B16G16R16UI: return component < 3;
2601                 case FORMAT_A16B16G16R16I:  return component < 3;
2602                 case FORMAT_A16B16G16R16UI: return component < 3;
2603                 case FORMAT_V16U16:         return false;
2604                 case FORMAT_A16W16V16U16:   return false;
2605                 case FORMAT_Q16W16V16U16:   return false;
2606                 case FORMAT_YV12_BT601:     return component < 3;
2607                 case FORMAT_YV12_BT709:     return component < 3;
2608                 case FORMAT_YV12_JFIF:      return component < 3;
2609                 default:
2610                         ASSERT(false);
2611                 }
2612
2613                 return false;
2614         }
2615 }