1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "SamplerCore.hpp"
17 #include "Constants.hpp"
22 void applySwizzle(sw::SwizzleType swizzle, sw::Short4& s, const sw::Vector4s& c)
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);
36 void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c)
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);
53 SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
57 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy)
59 sampleTexture(texture, c, u, v, w, q, dsx, dsy, dsx, Implicit, true);
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)
65 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
67 if(state.compressedFormat)
69 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
77 if(state.textureType == TEXTURE_NULL)
83 if(fixed12) // FIXME: Convert to fixed12 at higher level, when required
89 c.w = Short4(0xFFFFu); // FIXME
99 if(state.textureType == TEXTURE_CUBE)
101 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
108 Float lodBias = (function == Fetch) ? Float4(As<Int4>(q)).x : q.x;
110 if(state.textureType != TEXTURE_3D)
112 if(state.textureType != TEXTURE_CUBE)
114 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodBias, dsx, dsy, function);
118 computeLodCube(texture, lod, lodX, lodY, lodZ, lodBias, dsx, dsy, function);
123 computeLod3D(texture, lod, uuuu, vvvv, wwww, lodBias, dsx, dsy, function);
126 if(!hasFloatTexture())
128 sampleFilter(texture, c, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
134 sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
136 convertFixed12(c, cf);
139 if(fixed12 && !hasFloatTexture())
141 if(has16bitTextureFormat())
143 switch(state.textureFormat)
148 sRGBtoLinear16_5_12(c.x);
149 sRGBtoLinear16_6_12(c.y);
150 sRGBtoLinear16_5_12(c.z);
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));
165 for(int component = 0; component < textureComponentCount(); component++)
167 if(state.sRGB && isRGBComponent(component))
169 sRGBtoLinear16_8_12(c[component]); // FIXME: Perform linearization at surface level for read-only textures
173 if(hasUnsignedTextureComponent(component))
175 c[component] = As<UShort4>(c[component]) >> 4;
179 c[component] = c[component] >> 3;
186 if(fixed12 && state.textureFilter != FILTER_GATHER)
188 int componentCount = textureComponentCount();
190 switch(state.textureFormat)
192 case FORMAT_R8I_SNORM:
193 case FORMAT_G8R8I_SNORM:
194 case FORMAT_X8B8G8R8I_SNORM:
195 case FORMAT_A8B8G8R8I_SNORM:
203 case FORMAT_X8B8G8R8I:
204 case FORMAT_X8B8G8R8UI:
205 case FORMAT_A8B8G8R8I:
206 case FORMAT_A8B8G8R8UI:
211 case FORMAT_G16R16UI:
212 case FORMAT_X16B16G16R16I:
213 case FORMAT_X16B16G16R16UI:
214 case FORMAT_A16B16G16R16:
215 case FORMAT_A16B16G16R16I:
216 case FORMAT_A16B16G16R16UI:
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:
232 case FORMAT_Q8W8V8U8:
233 case FORMAT_X8L8V8U8:
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);
246 c.x = Short4(0x0000);
247 c.y = Short4(0x0000);
248 c.z = Short4(0x0000);
254 c.w = Short4(0x1000);
262 c.y = Short4(0x1000);
264 c.z = Short4(0x1000);
265 case FORMAT_X32B32G32R32F:
266 c.w = Short4(0x1000);
267 case FORMAT_A32B32G32R32F:
270 case FORMAT_D32F_LOCKABLE:
271 case FORMAT_D32FS8_TEXTURE:
272 case FORMAT_D32FS8_SHADOW:
284 ((state.swizzleR != SWIZZLE_RED) ||
285 (state.swizzleG != SWIZZLE_GREEN) ||
286 (state.swizzleB != SWIZZLE_BLUE) ||
287 (state.swizzleA != SWIZZLE_ALPHA)))
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);
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)
300 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
302 if(state.compressedFormat)
304 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
308 if(state.textureType == TEXTURE_NULL)
317 if(hasFloatTexture()) // FIXME: Mostly identical to integer sampling
328 if(state.textureType == TEXTURE_CUBE)
330 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
337 Float lodBias = (function == Fetch) ? Float4(As<Int4>(q)).x : q.x;
339 if(state.textureType != TEXTURE_3D)
341 if(state.textureType != TEXTURE_CUBE)
343 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodBias, dsx, dsy, function);
347 computeLodCube(texture, lod, lodX, lodY, lodZ, lodBias, dsx, dsy, function);
352 computeLod3D(texture, lod, uuuu, vvvv, wwww, lodBias, dsx, dsy, function);
355 sampleFloatFilter(texture, c, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
361 sampleTexture(texture, cs, u, v, w, q, dsx, dsy, offset, function, false);
363 if(has16bitTextureFormat())
365 switch(state.textureFormat)
370 sRGBtoLinear16_5_12(cs.x);
371 sRGBtoLinear16_6_12(cs.y);
372 sRGBtoLinear16_5_12(cs.z);
374 convertSigned12(c.x, cs.x);
375 convertSigned12(c.y, cs.y);
376 convertSigned12(c.z, cs.z);
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);
391 for(int component = 0; component < textureComponentCount(); component++)
393 switch(state.textureFormat)
397 case FORMAT_X8B8G8R8I:
398 case FORMAT_A8B8G8R8I:
399 c[component] = As<Float4>(Int4(cs[component]) >> 8);
403 case FORMAT_X8B8G8R8UI:
404 case FORMAT_A8B8G8R8UI:
405 c[component] = As<Float4>(Int4(As<UShort4>(cs[component]) >> 8));
409 case FORMAT_X16B16G16R16I:
410 case FORMAT_A16B16G16R16I:
411 c[component] = As<Float4>(Int4(cs[component]));
414 case FORMAT_G16R16UI:
415 case FORMAT_X16B16G16R16UI:
416 case FORMAT_A16B16G16R16UI:
417 c[component] = As<Float4>(Int4(As<UShort4>(cs[component])));
420 // Normalized integer formats
421 if(state.sRGB && isRGBComponent(component))
423 sRGBtoLinear16_8_12(cs[component]); // FIXME: Perform linearization at surface level for read-only textures
424 convertSigned12(c[component], cs[component]);
428 if(hasUnsignedTextureComponent(component))
430 convertUnsigned16(c[component], cs[component]);
434 convertSigned15(c[component], cs[component]);
443 int componentCount = textureComponentCount();
445 if(state.textureFilter != FILTER_GATHER)
447 switch(state.textureFormat)
455 c.y = As<Float4>(UInt4(0));
459 case FORMAT_G16R16UI:
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:
477 case FORMAT_R8I_SNORM:
478 case FORMAT_G8R8I_SNORM:
479 case FORMAT_X8B8G8R8I_SNORM:
480 case FORMAT_A8B8G8R8I_SNORM:
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:
493 case FORMAT_Q8W8V8U8:
494 case FORMAT_X8L8V8U8:
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);
526 case FORMAT_X32B32G32R32F:
528 case FORMAT_A32B32G32R32F:
531 case FORMAT_D32F_LOCKABLE:
532 case FORMAT_D32FS8_TEXTURE:
533 case FORMAT_D32FS8_SHADOW:
544 if((state.swizzleR != SWIZZLE_RED) ||
545 (state.swizzleG != SWIZZLE_GREEN) ||
546 (state.swizzleB != SWIZZLE_BLUE) ||
547 (state.swizzleA != SWIZZLE_ALPHA))
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);
557 void SamplerCore::textureSize(Pointer<Byte> &texture, Vector4f &size, Float4 &lod)
559 for(int i = 0; i < 4; ++i)
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);
569 void SamplerCore::border(Short4 &mask, Float4 &coordinates)
571 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
572 mask = As<Short4>(Int2(As<Int4>(Pack(border, border))));
575 void SamplerCore::border(Int4 &mask, Float4 &coordinates)
577 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
580 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
582 Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
584 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
586 offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
588 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
590 offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
597 case -1: return uvw - offset;
599 case +1: return uvw + offset;
600 case 2: return uvw + offset + offset;
603 else // Clamp or mirror
607 case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset));
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));
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)
619 sampleAniso(texture, c, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
621 if(function == Fetch)
626 if(state.mipmapFilter > MIPMAP_POINT)
630 sampleAniso(texture, cc, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
632 lod *= Float(1 << 16);
634 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize
635 Short4 stri = utri >> 1; // FIXME: Optimize
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);
643 stri = Short4(0x7FFF) - stri;
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);
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;
663 if(state.addressingModeU == ADDRESSING_BORDER)
672 if(state.addressingModeV == ADDRESSING_BORDER)
678 if(state.addressingModeU == ADDRESSING_BORDER)
688 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
694 if(state.addressingModeU == ADDRESSING_BORDER ||
695 state.addressingModeV == ADDRESSING_BORDER)
705 if(state.addressingModeU == ADDRESSING_BORDER ||
706 state.addressingModeV == ADDRESSING_BORDER ||
707 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
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)));
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)
720 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
722 sampleQuad(texture, c, u, v, w, offset, lod, face, secondLOD, function);
726 Int a = RoundInt(anisotropy);
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);
743 Float4 u0 = u + B * du;
744 Float4 v0 = v + B * dv;
753 sampleQuad(texture, c, u0, v0, w, offset, lod, face, secondLOD, function);
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);
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);
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)
776 if(state.textureType != TEXTURE_3D)
778 sampleQuad2D(texture, c, u, v, w, offset, lod, face, secondLOD, function);
782 sample3D(texture, c, u, v, w, offset, lod, secondLOD, function);
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)
788 int componentCount = textureComponentCount();
789 bool gather = state.textureFilter == FILTER_GATHER;
791 Pointer<Byte> mipmap;
792 Pointer<Byte> buffer[4];
794 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
796 bool texelFetch = (function == Fetch);
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);
802 if(state.textureFilter == FILTER_POINT || texelFetch)
804 sampleTexel(c, uuuu, vvvv, wwww, offset, mipmap, buffer, function);
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);
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);
826 UShort4 f0u = As<UShort4>(uuuu0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
827 UShort4 f0v = As<UShort4>(vvvv0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
832 UShort4 f0u0v = MulHigh(f0u, f0v);
833 UShort4 f1u0v = MulHigh(f1u, f0v);
834 UShort4 f0u1v = MulHigh(f0u, f1v);
835 UShort4 f1u1v = MulHigh(f1u, f1v);
843 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
851 // Bilinear interpolation
852 if(componentCount >= 1)
854 if(has16bitTextureComponents() && hasUnsignedTextureComponent(0))
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);
862 if(hasUnsignedTextureComponent(0))
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);
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);
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
882 if(componentCount >= 2)
884 if(has16bitTextureComponents() && hasUnsignedTextureComponent(1))
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);
892 if(hasUnsignedTextureComponent(1))
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);
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);
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
912 if(componentCount >= 3)
914 if(has16bitTextureComponents() && hasUnsignedTextureComponent(2))
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);
922 if(hasUnsignedTextureComponent(2))
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);
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);
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
942 if(componentCount >= 4)
944 if(has16bitTextureComponents() && hasUnsignedTextureComponent(3))
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);
952 if(hasUnsignedTextureComponent(3))
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);
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);
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
982 void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4s &c_, Float4 &u_, Float4 &v_, Float4 &w_, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
984 int componentCount = textureComponentCount();
986 Pointer<Byte> mipmap;
987 Pointer<Byte> buffer[4];
990 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
992 bool texelFetch = (function == Fetch);
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);
998 if(state.textureFilter == FILTER_POINT || texelFetch)
1000 sampleTexel(c_, uuuu, vvvv, wwww, offset, mipmap, buffer, function);
1004 Vector4s c[2][2][2];
1010 for(int i = 0; i < 2; i++)
1012 for(int j = 0; j < 2; j++)
1014 for(int k = 0; k < 2; k++)
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);
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));
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);
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);
1054 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
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;
1066 for(int i = 0; i < 2; i++)
1068 for(int j = 0; j < 2; j++)
1070 for(int k = 0; k < 2; k++)
1072 sampleTexel(c[i][j][k], u[i][j][k], v[i][j][k], s[i][j][k], offset, mipmap, buffer, function);
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]); }
1079 if(i != 0 || j != 0 || k != 0)
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;
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;
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);
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)
1105 sampleFloatAniso(texture, c, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
1107 if(function == Fetch)
1112 if(state.mipmapFilter > MIPMAP_POINT)
1116 sampleFloatAniso(texture, cc, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
1118 Float4 lod4 = Float4(Frac(lod));
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;
1128 if(state.addressingModeU == ADDRESSING_BORDER)
1137 if(state.addressingModeV == ADDRESSING_BORDER)
1143 if(state.addressingModeU == ADDRESSING_BORDER)
1153 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
1159 if(state.addressingModeU == ADDRESSING_BORDER ||
1160 state.addressingModeV == ADDRESSING_BORDER)
1170 if(state.addressingModeU == ADDRESSING_BORDER ||
1171 state.addressingModeV == ADDRESSING_BORDER ||
1172 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
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]))));
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)
1185 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
1187 sampleFloat(texture, c, u, v, w, offset, lod, face, secondLOD, function);
1191 Int a = RoundInt(anisotropy);
1195 cSum.x = Float4(0.0f);
1196 cSum.y = Float4(0.0f);
1197 cSum.z = Float4(0.0f);
1198 cSum.w = Float4(0.0f);
1200 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
1201 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
1206 Float4 u0 = u + B * du;
1207 Float4 v0 = v + B * dv;
1216 sampleFloat(texture, c, u0, v0, w, offset, lod, face, secondLOD, function);
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)
1239 if(state.textureType != TEXTURE_3D)
1241 sampleFloat2D(texture, c, u, v, w, offset, lod, face, secondLOD, function);
1245 sampleFloat3D(texture, c, u, v, w, offset, lod, secondLOD, function);
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)
1251 int componentCount = textureComponentCount();
1252 bool gather = state.textureFilter == FILTER_GATHER;
1254 Pointer<Byte> mipmap;
1255 Pointer<Byte> buffer[4];
1257 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1259 bool texelFetch = (function == Fetch);
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);
1265 if(state.textureFilter == FILTER_POINT || texelFetch)
1267 sampleTexel(c, uuuu, vvvv, wwww, offset, w, mipmap, buffer, function);
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);
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);
1286 if(!gather) // Blend
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)));
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);
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);
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);
1317 void SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
1319 int componentCount = textureComponentCount();
1321 Pointer<Byte> mipmap;
1322 Pointer<Byte> buffer[4];
1325 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1327 bool texelFetch = (function == Fetch);
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);
1333 if(state.textureFilter == FILTER_POINT || texelFetch)
1335 sampleTexel(c, uuuu, vvvv, wwww, offset, w, mipmap, buffer, function);
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);
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);
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)));
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);
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);
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);
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);
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);
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);
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);
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)
1411 if(function != Lod && function != Fetch)
1415 if(function != Grad)
1417 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1421 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1422 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1424 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1427 // Scale by texture dimensions and LOD
1428 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1430 Float4 dUV2dxy = dUVdxy * dUVdxy;
1431 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1433 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1435 if(state.textureFilter == FILTER_ANISOTROPIC)
1437 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1439 Float4 dudx = duvdxy.xxxx;
1440 Float4 dudy = duvdxy.yyyy;
1441 Float4 dvdx = duvdxy.zzzz;
1442 Float4 dvdy = duvdxy.wwww;
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)));
1448 anisotropy = lod * Rcp_pp(det);
1449 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1451 lod *= Rcp_pp(anisotropy * anisotropy);
1455 lod = Float(As<Int>(lod));
1456 lod -= Float(0x3F800000);
1457 lod *= As<Float>(Int(0x33800000));
1459 if(function == Bias)
1466 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1469 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1470 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1473 void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1475 if(function != Lod && function != Fetch)
1477 if(function != Grad)
1479 Float4 dudxy = u.ywyw - u;
1480 Float4 dvdxy = v.ywyw - v;
1481 Float4 dsdxy = s.ywyw - s;
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));
1495 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1499 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1500 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1502 Float4 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1504 // Scale by texture dimensions and LOD
1505 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1507 Float4 dUV2dxy = dUVdxy * dUVdxy;
1508 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1510 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1514 lod = Float(As<Int>(lod));
1515 lod -= Float(0x3F800000);
1516 lod *= As<Float>(Int(0x33800000));
1518 if(function == Bias)
1525 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1528 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1529 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1532 void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1534 if(state.mipmapFilter == MIPMAP_NONE)
1537 else // Point and linear filter
1539 if(function != Lod && function != Fetch)
1545 if(function != Grad)
1547 dudxy = uuuu.ywyw - uuuu;
1548 dvdxy = vvvv.ywyw - vvvv;
1549 dsdxy = wwww.ywyw - wwww;
1557 dudxy = Float4(dudxy.xx, dsy.x.xx);
1558 dvdxy = Float4(dvdxy.xx, dsy.y.xx);
1559 dsdxy = Float4(dsdxy.xx, dsy.z.xx);
1561 dudxy = Float4(dudxy.xz, dudxy.xz);
1562 dvdxy = Float4(dvdxy.xz, dvdxy.xz);
1563 dsdxy = Float4(dsdxy.xz, dsdxy.xz);
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));
1578 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1581 lod = Float(As<Int>(lod));
1582 lod -= Float(0x3F800000);
1583 lod *= As<Float>(Int(0x33800000));
1585 if(function == Bias)
1592 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1595 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1596 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1600 void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z)
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
1606 Float4 absX = Abs(x);
1607 Float4 absY = Abs(y);
1608 Float4 absZ = Abs(z);
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)
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
1624 Int yAxis = SignMask(yMajor);
1625 Int zAxis = SignMask(zMajor);
1627 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
1628 Int negative = SignMask(n);
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;
1638 Float4 M = Max(Max(absX, absY), absZ);
1640 // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x)
1641 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
1643 // V = !yMajor ? -y : (n ^ z)
1644 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
1646 M = reciprocal(M) * Float4(0.5f);
1647 U = U * M + Float4(0.5f);
1648 V = V * M + Float4(0.5f);
1655 Short4 SamplerCore::applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode)
1657 Int4 tmp = Int4(As<UShort4>(uvw));
1658 tmp = tmp + As<Int4>(offset);
1662 case AddressingMode::ADDRESSING_WRAP:
1663 tmp = (tmp + whd * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % whd;
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));
1671 case ADDRESSING_TEXELFETCH:
1677 return As<Short4>(UShort4(tmp));
1680 void SamplerCore::computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function)
1682 bool texelFetch = (function == Fetch);
1683 bool hasOffset = (function.option == Offset);
1687 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width)));
1688 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height)));
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);
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))));
1703 if((state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY))
1705 if(state.textureType != TEXTURE_2D_ARRAY)
1709 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth)));
1713 wwww = applyOffset(wwww, offset.z, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeW);
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));
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);
1732 Int size = Int(*Pointer<Int>(mipmap + OFFSET(Mipmap, sliceP)));
1733 if((state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY))
1735 size *= Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)));
1738 UInt max = size - 1;
1740 for(int i = 0; i < 4; i++)
1742 index[i] = Min(Max(index[i], min), max);
1747 void SamplerCore::sampleTexel(Vector4s &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Vector4f &offset, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
1751 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
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;
1758 if(has16bitTextureFormat())
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);
1765 switch(state.textureFormat)
1768 c.z = (c.x & Short4(0x001Fu)) << 11;
1769 c.y = (c.x & Short4(0x07E0u)) << 5;
1770 c.x = (c.x & Short4(0xF800u));
1776 else if(has8bitTextureComponents())
1778 switch(textureComponentCount())
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);
1789 switch(state.textureFormat)
1791 case FORMAT_A8R8G8B8:
1793 c.z = As<Short4>(UnpackLow(c.z, c.y));
1794 c.x = As<Short4>(UnpackHigh(c.x, c.y));
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));
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:
1809 c.x = As<Short4>(UnpackLow(c.x, c.y));
1810 c.z = As<Short4>(UnpackHigh(c.z, c.y));
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));
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);
1832 switch(state.textureFormat)
1834 case FORMAT_X8R8G8B8:
1836 c.z = As<Short4>(UnpackLow(c.z, c.y));
1837 c.x = As<Short4>(UnpackHigh(c.x, c.y));
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));
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:
1850 c.x = As<Short4>(UnpackLow(c.x, c.y));
1851 c.z = As<Short4>(UnpackHigh(c.z, c.y));
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));
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);
1868 switch(state.textureFormat)
1873 case FORMAT_G8R8I_SNORM:
1876 c.y = (c.x & Short4(0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
1877 c.x = (c.x & Short4(0x00FFu)) | (c.x << 8);
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));
1897 else if(has16bitTextureComponents())
1899 switch(textureComponentCount())
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);
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])));
1914 c.x = UnpackLow(As<Int2>(c.x), As<Int2>(c.z));
1915 c.y = UnpackHigh(As<Int2>(c.y), As<Int2>(c.z));
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);
1927 else if(hasYuvFormat())
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
1936 int studioSwing = 1;
1938 switch(state.textureFormat)
1940 case FORMAT_YV12_BT601:
1945 case FORMAT_YV12_BT709:
1950 case FORMAT_YV12_JFIF:
1959 const float Kg = 1.0f - Kr - Kb;
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);
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;
1971 const float Rv = Vv * Rr;
1972 const float Gu = Uu * Gb;
1973 const float Gv = Vv * Gr;
1974 const float Bu = Uu * Bb;
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;
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)));
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)));
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)));
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));
2008 const UShort4 r0 = UShort4(iround(-R0 * 0x4000));
2009 const UShort4 g0 = UShort4(iround(G0 * 0x4000));
2010 const UShort4 b0 = UShort4(iround(-B0 * 0x4000));
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);
2017 c.x = Min(r, UShort4(0x3FFF)) << 2;
2018 c.y = Min(g, UShort4(0x3FFF)) << 2;
2019 c.z = Min(b, UShort4(0x3FFF)) << 2;
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)
2028 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
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;
2036 switch(textureComponentCount())
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);
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);
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);
2061 c.x = Float4(c.x.xz, c.z.xz);
2062 c.y = Float4(c.y.yw, c.z.yw);
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);
2071 if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER)
2073 Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f));
2075 c.x = As<Float4>(As<Int4>(CmpNLT(c.x, d)) & As<Int4>(Float4(1.0f))); // FIXME: Only less-equal?
2083 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
2085 if(state.mipmapFilter < MIPMAP_POINT)
2087 mipmap = texture + OFFSET(Texture,mipmap[0]);
2093 if(state.mipmapFilter == MIPMAP_POINT)
2095 ilod = RoundInt(lod);
2102 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
2105 if(state.textureType != TEXTURE_CUBE)
2107 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
2111 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1]));
2112 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2]));
2117 for(int i = 0; i < 4; i++)
2119 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
2124 Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap)
2126 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2128 return Short4(); // Unused
2130 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY)
2132 return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1));
2134 else if(addressingMode == ADDRESSING_CLAMP)
2136 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
2138 return Short4(Int4(clamp * Float4(1 << 16)));
2140 else if(addressingMode == ADDRESSING_MIRROR)
2142 Int4 convert = Int4(uw * Float4(1 << 16));
2143 Int4 mirror = (convert << 15) >> 31;
2147 return Short4(convert);
2149 else if(addressingMode == ADDRESSING_MIRRORONCE)
2152 Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
2155 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
2156 convert = As<Int4>(Pack(convert, convert));
2158 return As<Short4>(Int2(convert)) + Short4(0x8000u);
2160 else // Wrap (or border)
2162 return Short4(Int4(uw * Float4(1 << 16)));
2166 void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
2168 cs = RoundShort4(cf * Float4(0x1000));
2171 void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
2173 convertFixed12(cs.x, cf.x);
2174 convertFixed12(cs.y, cf.y);
2175 convertFixed12(cs.z, cf.z);
2176 convertFixed12(cs.w, cf.w);
2179 void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
2181 cf = Float4(cs) * Float4(1.0f / 0x0FFE);
2184 // void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
2186 // convertSigned12(cf.x, cs.x);
2187 // convertSigned12(cf.y, cs.y);
2188 // convertSigned12(cf.z, cs.z);
2189 // convertSigned12(cf.w, cs.w);
2192 void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
2194 cf = Float4(cs) * Float4(1.0f / 0x7FFF);
2197 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
2199 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
2202 void SamplerCore::sRGBtoLinear16_8_12(Short4 &c)
2204 c = As<UShort4>(c) >> 8;
2206 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_12));
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);
2214 void SamplerCore::sRGBtoLinear16_6_12(Short4 &c)
2216 c = As<UShort4>(c) >> 10;
2218 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_12));
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);
2226 void SamplerCore::sRGBtoLinear16_5_12(Short4 &c)
2228 c = As<UShort4>(c) >> 11;
2230 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_12));
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);
2238 bool SamplerCore::hasFloatTexture() const
2240 return Surface::isFloatFormat(state.textureFormat);
2243 bool SamplerCore::hasUnsignedTextureComponent(int component) const
2245 return Surface::isUnsignedComponent(state.textureFormat, component);
2248 int SamplerCore::textureComponentCount() const
2250 return Surface::componentCount(state.textureFormat);
2253 bool SamplerCore::has16bitTextureFormat() const
2255 switch(state.textureFormat)
2259 case FORMAT_R8I_SNORM:
2260 case FORMAT_G8R8I_SNORM:
2261 case FORMAT_X8B8G8R8I_SNORM:
2262 case FORMAT_A8B8G8R8I_SNORM:
2267 case FORMAT_X8B8G8R8I:
2268 case FORMAT_X8B8G8R8UI:
2269 case FORMAT_A8B8G8R8I:
2270 case FORMAT_A8B8G8R8UI:
2273 case FORMAT_G32R32I:
2274 case FORMAT_G32R32UI:
2275 case FORMAT_X32B32G32R32I:
2276 case FORMAT_X32B32G32R32UI:
2277 case FORMAT_A32B32G32R32I:
2278 case FORMAT_A32B32G32R32UI:
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:
2287 case FORMAT_Q8W8V8U8:
2288 case FORMAT_X8L8V8U8:
2290 case FORMAT_G32R32F:
2291 case FORMAT_X32B32G32R32F:
2292 case FORMAT_A32B32G32R32F:
2298 case FORMAT_D32F_LOCKABLE:
2299 case FORMAT_D32FS8_TEXTURE:
2300 case FORMAT_D32FS8_SHADOW:
2303 case FORMAT_A16B16G16R16:
2305 case FORMAT_A16W16V16U16:
2306 case FORMAT_Q16W16V16U16:
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:
2326 bool SamplerCore::has8bitTextureComponents() const
2328 switch(state.textureFormat)
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:
2338 case FORMAT_Q8W8V8U8:
2339 case FORMAT_X8L8V8U8:
2344 case FORMAT_R8I_SNORM:
2345 case FORMAT_G8R8I_SNORM:
2346 case FORMAT_X8B8G8R8I_SNORM:
2347 case FORMAT_A8B8G8R8I_SNORM:
2352 case FORMAT_X8B8G8R8I:
2353 case FORMAT_X8B8G8R8UI:
2354 case FORMAT_A8B8G8R8I:
2355 case FORMAT_A8B8G8R8UI:
2359 case FORMAT_G32R32F:
2360 case FORMAT_X32B32G32R32F:
2361 case FORMAT_A32B32G32R32F:
2363 case FORMAT_D32F_LOCKABLE:
2364 case FORMAT_D32FS8_TEXTURE:
2365 case FORMAT_D32FS8_SHADOW:
2368 case FORMAT_A16B16G16R16:
2370 case FORMAT_A16W16V16U16:
2371 case FORMAT_Q16W16V16U16:
2374 case FORMAT_G32R32I:
2375 case FORMAT_G32R32UI:
2376 case FORMAT_X32B32G32R32I:
2377 case FORMAT_X32B32G32R32UI:
2378 case FORMAT_A32B32G32R32I:
2379 case FORMAT_A32B32G32R32UI:
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:
2399 bool SamplerCore::has16bitTextureComponents() const
2401 switch(state.textureFormat)
2404 case FORMAT_R8I_SNORM:
2405 case FORMAT_G8R8I_SNORM:
2406 case FORMAT_X8B8G8R8I_SNORM:
2407 case FORMAT_A8B8G8R8I_SNORM:
2412 case FORMAT_X8B8G8R8I:
2413 case FORMAT_X8B8G8R8UI:
2414 case FORMAT_A8B8G8R8I:
2415 case FORMAT_A8B8G8R8UI:
2418 case FORMAT_G32R32I:
2419 case FORMAT_G32R32UI:
2420 case FORMAT_X32B32G32R32I:
2421 case FORMAT_X32B32G32R32UI:
2422 case FORMAT_A32B32G32R32I:
2423 case FORMAT_A32B32G32R32UI:
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:
2432 case FORMAT_Q8W8V8U8:
2433 case FORMAT_X8L8V8U8:
2435 case FORMAT_G32R32F:
2436 case FORMAT_X32B32G32R32F:
2437 case FORMAT_A32B32G32R32F:
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:
2452 case FORMAT_A16B16G16R16:
2455 case FORMAT_G16R16I:
2456 case FORMAT_G16R16UI:
2457 case FORMAT_X16B16G16R16I:
2458 case FORMAT_X16B16G16R16UI:
2459 case FORMAT_A16B16G16R16I:
2460 case FORMAT_A16B16G16R16UI:
2462 case FORMAT_A16W16V16U16:
2463 case FORMAT_Q16W16V16U16:
2472 bool SamplerCore::hasYuvFormat() const
2474 switch(state.textureFormat)
2476 case FORMAT_YV12_BT601:
2477 case FORMAT_YV12_BT709:
2478 case FORMAT_YV12_JFIF:
2481 case FORMAT_R8I_SNORM:
2482 case FORMAT_G8R8I_SNORM:
2483 case FORMAT_X8B8G8R8I_SNORM:
2484 case FORMAT_A8B8G8R8I_SNORM:
2489 case FORMAT_X8B8G8R8I:
2490 case FORMAT_X8B8G8R8UI:
2491 case FORMAT_A8B8G8R8I:
2492 case FORMAT_A8B8G8R8UI:
2495 case FORMAT_G32R32I:
2496 case FORMAT_G32R32UI:
2497 case FORMAT_X32B32G32R32I:
2498 case FORMAT_X32B32G32R32UI:
2499 case FORMAT_A32B32G32R32I:
2500 case FORMAT_A32B32G32R32UI:
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:
2509 case FORMAT_Q8W8V8U8:
2510 case FORMAT_X8L8V8U8:
2512 case FORMAT_G32R32F:
2513 case FORMAT_X32B32G32R32F:
2514 case FORMAT_A32B32G32R32F:
2520 case FORMAT_D32F_LOCKABLE:
2521 case FORMAT_D32FS8_TEXTURE:
2522 case FORMAT_D32FS8_SHADOW:
2525 case FORMAT_A16B16G16R16:
2528 case FORMAT_G16R16I:
2529 case FORMAT_G16R16UI:
2530 case FORMAT_X16B16G16R16I:
2531 case FORMAT_X16B16G16R16UI:
2532 case FORMAT_A16B16G16R16I:
2533 case FORMAT_A16B16G16R16UI:
2535 case FORMAT_A16W16V16U16:
2536 case FORMAT_Q16W16V16U16:
2545 bool SamplerCore::isRGBComponent(int component) const
2547 switch(state.textureFormat)
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;