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 extern bool colorsDefaultToZero;
55 SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
59 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy)
61 sampleTexture(texture, c, u, v, w, q, dsx, dsy, dsx, Implicit, true);
64 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)
67 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
69 if(state.compressedFormat)
71 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
79 if(state.textureType == TEXTURE_NULL)
85 if(fixed12) // FIXME: Convert to fixed12 at higher level, when required
91 c.w = Short4(0xFFFFu); // FIXME
101 if(state.textureType == TEXTURE_CUBE)
103 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
110 Float lodBias = (function == Fetch) ? Float4(As<Int4>(q)).x : q.x;
112 if(state.textureType != TEXTURE_3D)
114 if(state.textureType != TEXTURE_CUBE)
116 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodBias, dsx, dsy, function);
120 computeLodCube(texture, lod, lodX, lodY, lodZ, lodBias, dsx, dsy, function);
125 computeLod3D(texture, lod, uuuu, vvvv, wwww, lodBias, dsx, dsy, function);
128 if(!hasFloatTexture())
130 sampleFilter(texture, c, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
136 sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
138 convertFixed12(c, cf);
141 if(fixed12 && !hasFloatTexture())
143 if(has16bitTextureFormat())
145 switch(state.textureFormat)
150 sRGBtoLinear16_5_12(c.x);
151 sRGBtoLinear16_6_12(c.y);
152 sRGBtoLinear16_5_12(c.z);
156 c.x = MulHigh(As<UShort4>(c.x), UShort4(0x10000000 / 0xF800));
157 c.y = MulHigh(As<UShort4>(c.y), UShort4(0x10000000 / 0xFC00));
158 c.z = MulHigh(As<UShort4>(c.z), UShort4(0x10000000 / 0xF800));
167 for(int component = 0; component < textureComponentCount(); component++)
169 if(state.sRGB && isRGBComponent(component))
171 sRGBtoLinear16_8_12(c[component]); // FIXME: Perform linearization at surface level for read-only textures
175 if(hasUnsignedTextureComponent(component))
177 c[component] = As<UShort4>(c[component]) >> 4;
181 c[component] = c[component] >> 3;
188 if(fixed12 && state.textureFilter != FILTER_GATHER)
190 int componentCount = textureComponentCount();
191 short defaultColorValue = colorsDefaultToZero ? 0x0000 : 0x1000;
193 switch(state.textureFormat)
195 case FORMAT_R8I_SNORM:
196 case FORMAT_G8R8I_SNORM:
197 case FORMAT_X8B8G8R8I_SNORM:
198 case FORMAT_A8B8G8R8I_SNORM:
206 case FORMAT_X8B8G8R8I:
207 case FORMAT_X8B8G8R8UI:
208 case FORMAT_A8B8G8R8I:
209 case FORMAT_A8B8G8R8UI:
214 case FORMAT_G16R16UI:
215 case FORMAT_X16B16G16R16I:
216 case FORMAT_X16B16G16R16UI:
217 case FORMAT_A16B16G16R16:
218 case FORMAT_A16B16G16R16I:
219 case FORMAT_A16B16G16R16UI:
223 case FORMAT_G32R32UI:
224 case FORMAT_X32B32G32R32I:
225 case FORMAT_X32B32G32R32UI:
226 case FORMAT_A32B32G32R32I:
227 case FORMAT_A32B32G32R32UI:
228 case FORMAT_X8R8G8B8:
229 case FORMAT_X8B8G8R8:
230 case FORMAT_A8R8G8B8:
231 case FORMAT_A8B8G8R8:
232 case FORMAT_SRGB8_X8:
233 case FORMAT_SRGB8_A8:
235 case FORMAT_Q8W8V8U8:
236 case FORMAT_X8L8V8U8:
238 case FORMAT_A16W16V16U16:
239 case FORMAT_Q16W16V16U16:
240 case FORMAT_YV12_BT601:
241 case FORMAT_YV12_BT709:
242 case FORMAT_YV12_JFIF:
243 if(componentCount < 2) c.y = Short4(defaultColorValue);
244 if(componentCount < 3) c.z = Short4(defaultColorValue);
245 if(componentCount < 4) c.w = Short4(0x1000);
249 c.x = Short4(0x0000);
250 c.y = Short4(0x0000);
251 c.z = Short4(0x0000);
257 c.w = Short4(0x1000);
265 c.y = Short4(defaultColorValue);
267 c.z = Short4(defaultColorValue);
268 case FORMAT_X32B32G32R32F:
269 c.w = Short4(0x1000);
270 case FORMAT_A32B32G32R32F:
273 case FORMAT_D32F_LOCKABLE:
274 case FORMAT_D32FS8_TEXTURE:
275 case FORMAT_D32FS8_SHADOW:
287 ((state.swizzleR != SWIZZLE_RED) ||
288 (state.swizzleG != SWIZZLE_GREEN) ||
289 (state.swizzleB != SWIZZLE_BLUE) ||
290 (state.swizzleA != SWIZZLE_ALPHA)))
292 const Vector4s col(c);
293 applySwizzle(state.swizzleR, c.x, col);
294 applySwizzle(state.swizzleG, c.y, col);
295 applySwizzle(state.swizzleB, c.z, col);
296 applySwizzle(state.swizzleA, c.w, col);
300 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
303 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
305 if(state.compressedFormat)
307 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
311 if(state.textureType == TEXTURE_NULL)
320 // FIXME: YUV and sRGB are not supported by the floating point path
321 bool forceFloatFiltering = state.highPrecisionFiltering && !state.sRGB && !hasYuvFormat() && (state.textureFilter != FILTER_POINT);
322 if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering) // FIXME: Mostly identical to integer sampling
333 if(state.textureType == TEXTURE_CUBE)
335 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
342 Float lodBias = (function == Fetch) ? Float4(As<Int4>(q)).x : q.x;
344 if(state.textureType != TEXTURE_3D)
346 if(state.textureType != TEXTURE_CUBE)
348 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodBias, dsx, dsy, function);
352 computeLodCube(texture, lod, lodX, lodY, lodZ, lodBias, dsx, dsy, function);
357 computeLod3D(texture, lod, uuuu, vvvv, wwww, lodBias, dsx, dsy, function);
360 sampleFloatFilter(texture, c, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
362 if(!hasFloatTexture() && !hasUnnormalizedIntegerTexture())
364 if(has16bitTextureFormat())
366 switch(state.textureFormat)
369 c.x *= Float4(1.0f / 0xF800);
370 c.y *= Float4(1.0f / 0xFC00);
371 c.z *= Float4(1.0f / 0xF800);
379 for(int component = 0; component < textureComponentCount(); component++)
381 c[component] *= Float4(hasUnsignedTextureComponent(component) ? 1.0f / 0xFFFF : 1.0f / 0x7FFF);
390 sampleTexture(texture, cs, u, v, w, q, dsx, dsy, offset, function, false);
392 if(has16bitTextureFormat())
394 switch(state.textureFormat)
399 sRGBtoLinear16_5_12(cs.x);
400 sRGBtoLinear16_6_12(cs.y);
401 sRGBtoLinear16_5_12(cs.z);
403 convertSigned12(c.x, cs.x);
404 convertSigned12(c.y, cs.y);
405 convertSigned12(c.z, cs.z);
409 c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
410 c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
411 c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
420 for(int component = 0; component < textureComponentCount(); component++)
422 // Normalized integer formats
423 if(state.sRGB && isRGBComponent(component))
425 sRGBtoLinear16_8_12(cs[component]); // FIXME: Perform linearization at surface level for read-only textures
426 convertSigned12(c[component], cs[component]);
430 if(hasUnsignedTextureComponent(component))
432 convertUnsigned16(c[component], cs[component]);
436 convertSigned15(c[component], cs[component]);
443 int componentCount = textureComponentCount();
444 float defaultColorValue = colorsDefaultToZero ? 0.0f : 1.0f;
446 if(state.textureFilter != FILTER_GATHER)
448 switch(state.textureFormat)
456 c.y = As<Float4>(UInt4(0));
460 case FORMAT_G16R16UI:
462 case FORMAT_G32R32UI:
463 c.z = As<Float4>(UInt4(0));
464 case FORMAT_X8B8G8R8I:
465 case FORMAT_X8B8G8R8UI:
466 case FORMAT_X16B16G16R16I:
467 case FORMAT_X16B16G16R16UI:
468 case FORMAT_X32B32G32R32I:
469 case FORMAT_X32B32G32R32UI:
470 c.w = As<Float4>(UInt4(1));
471 case FORMAT_A8B8G8R8I:
472 case FORMAT_A8B8G8R8UI:
473 case FORMAT_A16B16G16R16I:
474 case FORMAT_A16B16G16R16UI:
475 case FORMAT_A32B32G32R32I:
476 case FORMAT_A32B32G32R32UI:
478 case FORMAT_R8I_SNORM:
479 case FORMAT_G8R8I_SNORM:
480 case FORMAT_X8B8G8R8I_SNORM:
481 case FORMAT_A8B8G8R8I_SNORM:
486 case FORMAT_A16B16G16R16:
487 case FORMAT_X8R8G8B8:
488 case FORMAT_X8B8G8R8:
489 case FORMAT_A8R8G8B8:
490 case FORMAT_A8B8G8R8:
491 case FORMAT_SRGB8_X8:
492 case FORMAT_SRGB8_A8:
494 case FORMAT_Q8W8V8U8:
495 case FORMAT_X8L8V8U8:
497 case FORMAT_A16W16V16U16:
498 case FORMAT_Q16W16V16U16:
499 case FORMAT_YV12_BT601:
500 case FORMAT_YV12_BT709:
501 case FORMAT_YV12_JFIF:
502 if(componentCount < 2) c.y = Float4(defaultColorValue);
503 if(componentCount < 3) c.z = Float4(defaultColorValue);
504 if(componentCount < 4) c.w = Float4(1.0f);
524 c.y = Float4(defaultColorValue);
526 c.z = Float4(defaultColorValue);
527 case FORMAT_X32B32G32R32F:
529 case FORMAT_A32B32G32R32F:
532 case FORMAT_D32F_LOCKABLE:
533 case FORMAT_D32FS8_TEXTURE:
534 case FORMAT_D32FS8_SHADOW:
545 if((state.swizzleR != SWIZZLE_RED) ||
546 (state.swizzleG != SWIZZLE_GREEN) ||
547 (state.swizzleB != SWIZZLE_BLUE) ||
548 (state.swizzleA != SWIZZLE_ALPHA))
550 const Vector4f col(c);
551 applySwizzle(state.swizzleR, c.x, col);
552 applySwizzle(state.swizzleG, c.y, col);
553 applySwizzle(state.swizzleB, c.z, col);
554 applySwizzle(state.swizzleA, c.w, col);
558 void SamplerCore::textureSize(Pointer<Byte> &texture, Vector4f &size, Float4 &lod)
560 for(int i = 0; i < 4; ++i)
562 Int baseLevel = *Pointer<Int>(texture + OFFSET(Texture, baseLevel));
563 Pointer<Byte> mipmap = texture + OFFSET(Texture, mipmap) + (As<Int>(Extract(lod, i)) + baseLevel) * sizeof(Mipmap);
564 size.x = Insert(size.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
565 size.y = Insert(size.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
566 size.z = Insert(size.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
570 void SamplerCore::border(Short4 &mask, Float4 &coordinates)
572 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
573 mask = As<Short4>(Int2(As<Int4>(PackSigned(border, border))));
576 void SamplerCore::border(Int4 &mask, Float4 &coordinates)
578 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
581 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
583 Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
585 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
587 offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
589 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
591 offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
598 case -1: return uvw - offset;
600 case +1: return uvw + offset;
601 case 2: return uvw + offset + offset;
604 else // Clamp or mirror
608 case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset));
610 case +1: return AddSat(As<UShort4>(uvw), As<UShort4>(offset));
611 case 2: return AddSat(AddSat(As<UShort4>(uvw), As<UShort4>(offset)), As<UShort4>(offset));
618 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)
620 sampleAniso(texture, c, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
622 if(function == Fetch)
627 if(state.mipmapFilter > MIPMAP_POINT)
631 sampleAniso(texture, cc, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
633 lod *= Float(1 << 16);
635 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize
636 Short4 stri = utri >> 1; // FIXME: Optimize
638 if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri);
639 if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri);
640 if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri);
641 if(hasUnsignedTextureComponent(3)) cc.w = MulHigh(As<UShort4>(cc.w), utri); else cc.w = MulHigh(cc.w, stri);
644 stri = Short4(0x7FFF) - stri;
646 if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri);
647 if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri);
648 if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri);
649 if(hasUnsignedTextureComponent(3)) c.w = MulHigh(As<UShort4>(c.w), utri); else c.w = MulHigh(c.w, stri);
656 if(!hasUnsignedTextureComponent(0)) c.x += c.x;
657 if(!hasUnsignedTextureComponent(1)) c.y += c.y;
658 if(!hasUnsignedTextureComponent(2)) c.z += c.z;
659 if(!hasUnsignedTextureComponent(3)) c.w += c.w;
664 if(state.addressingModeU == ADDRESSING_BORDER)
673 if(state.addressingModeV == ADDRESSING_BORDER)
679 if(state.addressingModeU == ADDRESSING_BORDER)
689 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
695 if(state.addressingModeU == ADDRESSING_BORDER ||
696 state.addressingModeV == ADDRESSING_BORDER)
706 if(state.addressingModeU == ADDRESSING_BORDER ||
707 state.addressingModeV == ADDRESSING_BORDER ||
708 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
712 c.x = (borderMask & c.x) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1)));
713 c.y = (borderMask & c.y) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1)));
714 c.z = (borderMask & c.z) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1)));
715 c.w = (borderMask & c.w) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1)));
719 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)
721 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
723 sampleQuad(texture, c, u, v, w, offset, lod, face, secondLOD, function);
727 Int a = RoundInt(anisotropy);
736 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
737 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
738 UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a);
739 Short4 sw = Short4(cw >> 1);
744 Float4 u0 = u + B * du;
745 Float4 v0 = v + B * dv;
754 sampleQuad(texture, c, u0, v0, w, offset, lod, face, secondLOD, function);
759 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw);
760 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw);
761 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw);
762 if(hasUnsignedTextureComponent(3)) cSum.w += As<Short4>(MulHigh(As<UShort4>(c.w), cw)); else cSum.w += MulHigh(c.w, sw);
768 if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x);
769 if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y);
770 if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z);
771 if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w);
775 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)
777 if(state.textureType != TEXTURE_3D)
779 sampleQuad2D(texture, c, u, v, w, offset, lod, face, secondLOD, function);
783 sample3D(texture, c, u, v, w, offset, lod, secondLOD, function);
787 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)
789 int componentCount = textureComponentCount();
790 bool gather = state.textureFilter == FILTER_GATHER;
792 Pointer<Byte> mipmap;
793 Pointer<Byte> buffer[4];
795 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
797 bool texelFetch = (function == Fetch);
799 Short4 uuuu = texelFetch ? Short4(As<Int4>(u)) : address(u, state.addressingModeU, mipmap);
800 Short4 vvvv = texelFetch ? Short4(As<Int4>(v)) : address(v, state.addressingModeV, mipmap);
801 Short4 wwww = texelFetch ? Short4(As<Int4>(w)) : address(w, state.addressingModeW, mipmap);
803 if(state.textureFilter == FILTER_POINT || texelFetch)
805 c = sampleTexel(uuuu, vvvv, wwww, offset, mipmap, buffer, function);
809 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
810 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
811 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
812 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
814 Vector4s c0 = sampleTexel(uuuu0, vvvv0, wwww, offset, mipmap, buffer, function);
815 Vector4s c1 = sampleTexel(uuuu1, vvvv0, wwww, offset, mipmap, buffer, function);
816 Vector4s c2 = sampleTexel(uuuu0, vvvv1, wwww, offset, mipmap, buffer, function);
817 Vector4s c3 = sampleTexel(uuuu1, vvvv1, wwww, offset, mipmap, buffer, function);
822 UShort4 f0u = As<UShort4>(uuuu0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
823 UShort4 f0v = As<UShort4>(vvvv0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
828 UShort4 f0u0v = MulHigh(f0u, f0v);
829 UShort4 f1u0v = MulHigh(f1u, f0v);
830 UShort4 f0u1v = MulHigh(f0u, f1v);
831 UShort4 f1u1v = MulHigh(f1u, f1v);
839 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
847 // Bilinear interpolation
848 if(componentCount >= 1)
850 if(has16bitTextureComponents() && hasUnsignedTextureComponent(0))
852 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u);
853 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u);
854 c.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0v) + MulHigh(As<UShort4>(c2.x), f0v);
858 if(hasUnsignedTextureComponent(0))
860 c0.x = MulHigh(As<UShort4>(c0.x), f1u1v);
861 c1.x = MulHigh(As<UShort4>(c1.x), f0u1v);
862 c2.x = MulHigh(As<UShort4>(c2.x), f1u0v);
863 c3.x = MulHigh(As<UShort4>(c3.x), f0u0v);
867 c0.x = MulHigh(c0.x, f1u1vs);
868 c1.x = MulHigh(c1.x, f0u1vs);
869 c2.x = MulHigh(c2.x, f1u0vs);
870 c3.x = MulHigh(c3.x, f0u0vs);
873 c.x = (c0.x + c1.x) + (c2.x + c3.x);
874 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x); // Correct for signed fractions
878 if(componentCount >= 2)
880 if(has16bitTextureComponents() && hasUnsignedTextureComponent(1))
882 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u);
883 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u);
884 c.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0v) + MulHigh(As<UShort4>(c2.y), f0v);
888 if(hasUnsignedTextureComponent(1))
890 c0.y = MulHigh(As<UShort4>(c0.y), f1u1v);
891 c1.y = MulHigh(As<UShort4>(c1.y), f0u1v);
892 c2.y = MulHigh(As<UShort4>(c2.y), f1u0v);
893 c3.y = MulHigh(As<UShort4>(c3.y), f0u0v);
897 c0.y = MulHigh(c0.y, f1u1vs);
898 c1.y = MulHigh(c1.y, f0u1vs);
899 c2.y = MulHigh(c2.y, f1u0vs);
900 c3.y = MulHigh(c3.y, f0u0vs);
903 c.y = (c0.y + c1.y) + (c2.y + c3.y);
904 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y); // Correct for signed fractions
908 if(componentCount >= 3)
910 if(has16bitTextureComponents() && hasUnsignedTextureComponent(2))
912 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u);
913 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u);
914 c.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0v) + MulHigh(As<UShort4>(c2.z), f0v);
918 if(hasUnsignedTextureComponent(2))
920 c0.z = MulHigh(As<UShort4>(c0.z), f1u1v);
921 c1.z = MulHigh(As<UShort4>(c1.z), f0u1v);
922 c2.z = MulHigh(As<UShort4>(c2.z), f1u0v);
923 c3.z = MulHigh(As<UShort4>(c3.z), f0u0v);
927 c0.z = MulHigh(c0.z, f1u1vs);
928 c1.z = MulHigh(c1.z, f0u1vs);
929 c2.z = MulHigh(c2.z, f1u0vs);
930 c3.z = MulHigh(c3.z, f0u0vs);
933 c.z = (c0.z + c1.z) + (c2.z + c3.z);
934 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z); // Correct for signed fractions
938 if(componentCount >= 4)
940 if(has16bitTextureComponents() && hasUnsignedTextureComponent(3))
942 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u);
943 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u);
944 c.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0v) + MulHigh(As<UShort4>(c2.w), f0v);
948 if(hasUnsignedTextureComponent(3))
950 c0.w = MulHigh(As<UShort4>(c0.w), f1u1v);
951 c1.w = MulHigh(As<UShort4>(c1.w), f0u1v);
952 c2.w = MulHigh(As<UShort4>(c2.w), f1u0v);
953 c3.w = MulHigh(As<UShort4>(c3.w), f0u0v);
957 c0.w = MulHigh(c0.w, f1u1vs);
958 c1.w = MulHigh(c1.w, f0u1vs);
959 c2.w = MulHigh(c2.w, f1u0vs);
960 c3.w = MulHigh(c3.w, f0u0vs);
963 c.w = (c0.w + c1.w) + (c2.w + c3.w);
964 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w); // Correct for signed fractions
978 void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4s &c_, Float4 &u_, Float4 &v_, Float4 &w_, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
980 int componentCount = textureComponentCount();
982 Pointer<Byte> mipmap;
983 Pointer<Byte> buffer[4];
986 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
988 bool texelFetch = (function == Fetch);
990 Short4 uuuu = texelFetch ? Short4(As<Int4>(u_)) : address(u_, state.addressingModeU, mipmap);
991 Short4 vvvv = texelFetch ? Short4(As<Int4>(v_)) : address(v_, state.addressingModeV, mipmap);
992 Short4 wwww = texelFetch ? Short4(As<Int4>(w_)) : address(w_, state.addressingModeW, mipmap);
994 if(state.textureFilter == FILTER_POINT || texelFetch)
996 c_ = sampleTexel(uuuu, vvvv, wwww, offset, mipmap, buffer, function);
1000 Vector4s c[2][2][2];
1006 for(int i = 0; i < 2; i++)
1008 for(int j = 0; j < 2; j++)
1010 for(int k = 0; k < 2; k++)
1012 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
1013 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
1014 s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
1020 UShort4 f0u = As<UShort4>(u[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
1021 UShort4 f0v = As<UShort4>(v[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
1022 UShort4 f0s = As<UShort4>(s[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth));
1031 f[1][1][1] = MulHigh(f1u, f1v);
1032 f[0][1][1] = MulHigh(f0u, f1v);
1033 f[1][0][1] = MulHigh(f1u, f0v);
1034 f[0][0][1] = MulHigh(f0u, f0v);
1035 f[1][1][0] = MulHigh(f1u, f1v);
1036 f[0][1][0] = MulHigh(f0u, f1v);
1037 f[1][0][0] = MulHigh(f1u, f0v);
1038 f[0][0][0] = MulHigh(f0u, f0v);
1040 f[1][1][1] = MulHigh(f[1][1][1], f1s);
1041 f[0][1][1] = MulHigh(f[0][1][1], f1s);
1042 f[1][0][1] = MulHigh(f[1][0][1], f1s);
1043 f[0][0][1] = MulHigh(f[0][0][1], f1s);
1044 f[1][1][0] = MulHigh(f[1][1][0], f0s);
1045 f[0][1][0] = MulHigh(f[0][1][0], f0s);
1046 f[1][0][0] = MulHigh(f[1][0][0], f0s);
1047 f[0][0][0] = MulHigh(f[0][0][0], f0s);
1050 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
1052 fs[0][0][0] = f[0][0][0] >> 1;
1053 fs[0][0][1] = f[0][0][1] >> 1;
1054 fs[0][1][0] = f[0][1][0] >> 1;
1055 fs[0][1][1] = f[0][1][1] >> 1;
1056 fs[1][0][0] = f[1][0][0] >> 1;
1057 fs[1][0][1] = f[1][0][1] >> 1;
1058 fs[1][1][0] = f[1][1][0] >> 1;
1059 fs[1][1][1] = f[1][1][1] >> 1;
1062 for(int i = 0; i < 2; i++)
1064 for(int j = 0; j < 2; j++)
1066 for(int k = 0; k < 2; k++)
1068 c[i][j][k] = sampleTexel(u[i][j][k], v[i][j][k], s[i][j][k], offset, mipmap, buffer, function);
1070 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]); }
1071 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]); }
1072 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]); }
1073 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]); }
1075 if(i != 0 || j != 0 || k != 0)
1077 if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x;
1078 if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y;
1079 if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z;
1080 if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w;
1086 if(componentCount >= 1) c_.x = c[0][0][0].x;
1087 if(componentCount >= 2) c_.y = c[0][0][0].y;
1088 if(componentCount >= 3) c_.z = c[0][0][0].z;
1089 if(componentCount >= 4) c_.w = c[0][0][0].w;
1091 // Correct for signed fractions
1092 if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x);
1093 if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y);
1094 if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z);
1095 if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w);
1099 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)
1101 sampleFloatAniso(texture, c, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
1103 if(function == Fetch)
1108 if(state.mipmapFilter > MIPMAP_POINT)
1112 sampleFloatAniso(texture, cc, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
1114 Float4 lod4 = Float4(Frac(lod));
1116 c.x = (cc.x - c.x) * lod4 + c.x;
1117 c.y = (cc.y - c.y) * lod4 + c.y;
1118 c.z = (cc.z - c.z) * lod4 + c.z;
1119 c.w = (cc.w - c.w) * lod4 + c.w;
1124 if(state.addressingModeU == ADDRESSING_BORDER)
1133 if(state.addressingModeV == ADDRESSING_BORDER)
1139 if(state.addressingModeU == ADDRESSING_BORDER)
1149 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
1155 if(state.addressingModeU == ADDRESSING_BORDER ||
1156 state.addressingModeV == ADDRESSING_BORDER)
1166 if(state.addressingModeU == ADDRESSING_BORDER ||
1167 state.addressingModeV == ADDRESSING_BORDER ||
1168 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
1172 c.x = As<Float4>((borderMask & As<Int4>(c.x)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0]))));
1173 c.y = As<Float4>((borderMask & As<Int4>(c.y)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1]))));
1174 c.z = As<Float4>((borderMask & As<Int4>(c.z)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2]))));
1175 c.w = As<Float4>((borderMask & As<Int4>(c.w)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3]))));
1179 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)
1181 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
1183 sampleFloat(texture, c, u, v, w, offset, lod, face, secondLOD, function);
1187 Int a = RoundInt(anisotropy);
1191 cSum.x = Float4(0.0f);
1192 cSum.y = Float4(0.0f);
1193 cSum.z = Float4(0.0f);
1194 cSum.w = Float4(0.0f);
1196 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
1197 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
1202 Float4 u0 = u + B * du;
1203 Float4 v0 = v + B * dv;
1212 sampleFloat(texture, c, u0, v0, w, offset, lod, face, secondLOD, function);
1233 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)
1235 if(state.textureType != TEXTURE_3D)
1237 sampleFloat2D(texture, c, u, v, w, offset, lod, face, secondLOD, function);
1241 sampleFloat3D(texture, c, u, v, w, offset, lod, secondLOD, function);
1245 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)
1247 int componentCount = textureComponentCount();
1248 bool gather = state.textureFilter == FILTER_GATHER;
1250 Pointer<Byte> mipmap;
1251 Pointer<Byte> buffer[4];
1253 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1255 Int4 x0, x1, y0, y1, z0;
1257 Int4 filter = computeFilterOffset(lod);
1258 address(w, z0, z0, fv, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
1259 address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
1260 address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
1262 Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16);
1264 if(hasThirdCoordinate())
1266 Int4 sliceP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, sliceP), 16);
1270 if(state.textureFilter == FILTER_POINT || (function == Fetch))
1272 c = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
1278 Vector4f c0 = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
1279 Vector4f c1 = sampleTexel(x1, y0, z0, w, mipmap, buffer, function);
1280 Vector4f c2 = sampleTexel(x0, y1, z0, w, mipmap, buffer, function);
1281 Vector4f c3 = sampleTexel(x1, y1, z0, w, mipmap, buffer, function);
1283 if(!gather) // Blend
1285 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1286 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1287 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1288 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
1290 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1291 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1292 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1293 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
1295 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x);
1296 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y);
1297 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z);
1298 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w);
1310 void SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
1312 int componentCount = textureComponentCount();
1314 Pointer<Byte> mipmap;
1315 Pointer<Byte> buffer[4];
1318 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1320 Int4 x0, x1, y0, y1, z0, z1;
1322 Int4 filter = computeFilterOffset(lod);
1323 address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
1324 address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
1325 address(w, z0, z1, fw, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
1327 Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16);
1328 Int4 sliceP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, sliceP), 16);
1332 if(state.textureFilter == FILTER_POINT || (function == Fetch))
1334 c = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
1341 Vector4f c0 = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
1342 Vector4f c1 = sampleTexel(x1, y0, z0, w, mipmap, buffer, function);
1343 Vector4f c2 = sampleTexel(x0, y1, z0, w, mipmap, buffer, function);
1344 Vector4f c3 = sampleTexel(x1, y1, z0, w, mipmap, buffer, function);
1345 Vector4f c4 = sampleTexel(x0, y0, z1, w, mipmap, buffer, function);
1346 Vector4f c5 = sampleTexel(x1, y0, z1, w, mipmap, buffer, function);
1347 Vector4f c6 = sampleTexel(x0, y1, z1, w, mipmap, buffer, function);
1348 Vector4f c7 = sampleTexel(x1, y1, z1, w, mipmap, buffer, function);
1350 // Blend first slice
1351 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1352 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1353 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1354 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
1356 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1357 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1358 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1359 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
1361 if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x);
1362 if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y);
1363 if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z);
1364 if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w);
1366 // Blend second slice
1367 if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x);
1368 if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y);
1369 if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z);
1370 if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w);
1372 if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x);
1373 if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y);
1374 if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z);
1375 if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w);
1377 if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x);
1378 if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y);
1379 if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z);
1380 if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w);
1383 if(componentCount >= 1) c.x = c0.x + fw * (c4.x - c0.x);
1384 if(componentCount >= 2) c.y = c0.y + fw * (c4.y - c0.y);
1385 if(componentCount >= 3) c.z = c0.z + fw * (c4.z - c0.z);
1386 if(componentCount >= 4) c.w = c0.w + fw * (c4.w - c0.w);
1390 Float SamplerCore::log2sqrt(Float lod)
1392 // log2(sqrt(lod)) // Equals 0.25 * log2(lod^2).
1393 lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
1394 lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
1395 lod *= As<Float>(Int(0x33000000)); // Scale by 0.25 * 2^-23 (mantissa length).
1400 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)
1402 if(function != Lod && function != Fetch)
1406 if(function != Grad)
1408 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1412 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1413 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1415 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1418 // Scale by texture dimensions and LOD
1419 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1421 Float4 dUV2dxy = dUVdxy * dUVdxy;
1422 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1424 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1426 if(state.textureFilter == FILTER_ANISOTROPIC)
1428 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1430 Float4 dudx = duvdxy.xxxx;
1431 Float4 dudy = duvdxy.yyyy;
1432 Float4 dvdx = duvdxy.zzzz;
1433 Float4 dvdy = duvdxy.wwww;
1435 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
1436 uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
1437 vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
1439 anisotropy = lod * Rcp_pp(det);
1440 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1442 lod *= Rcp_pp(anisotropy * anisotropy);
1445 lod = log2sqrt(lod); // log2(sqrt(lod))
1447 if(function == Bias)
1454 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1457 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1458 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1461 void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1463 if(function != Lod && function != Fetch)
1465 if(function != Grad)
1467 Float4 dudxy = u.ywyw - u;
1468 Float4 dvdxy = v.ywyw - v;
1469 Float4 dsdxy = s.ywyw - s;
1471 // Scale by texture dimensions and LOD
1472 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1473 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1474 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1483 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1487 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1488 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1490 Float4 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1492 // Scale by texture dimensions and LOD
1493 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1495 Float4 dUV2dxy = dUVdxy * dUVdxy;
1496 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1498 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1501 lod = log2sqrt(lod); // log2(sqrt(lod))
1503 if(function == Bias)
1510 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1513 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1514 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1517 void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
1519 if(state.mipmapFilter == MIPMAP_NONE)
1522 else // Point and linear filter
1524 if(function != Lod && function != Fetch)
1530 if(function != Grad)
1532 dudxy = uuuu.ywyw - uuuu;
1533 dvdxy = vvvv.ywyw - vvvv;
1534 dsdxy = wwww.ywyw - wwww;
1542 dudxy = Float4(dudxy.xx, dsy.x.xx);
1543 dvdxy = Float4(dvdxy.xx, dsy.y.xx);
1544 dsdxy = Float4(dsdxy.xx, dsy.z.xx);
1546 dudxy = Float4(dudxy.xz, dudxy.xz);
1547 dvdxy = Float4(dvdxy.xz, dvdxy.xz);
1548 dsdxy = Float4(dsdxy.xz, dsdxy.xz);
1551 // Scale by texture dimensions and LOD
1552 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1553 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
1554 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
1563 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1565 lod = log2sqrt(lod); // log2(sqrt(lod))
1567 if(function == Bias)
1574 lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
1577 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1578 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
1582 void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z)
1584 Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0
1585 Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0
1586 Int4 zn = CmpLT(z, Float4(0.0f)); // z < 0
1588 Float4 absX = Abs(x);
1589 Float4 absY = Abs(y);
1590 Float4 absZ = Abs(z);
1592 Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y)
1593 Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z)
1594 Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x)
1595 Int4 xMajor = xy & ~zx; // abs(x) > abs(y) && abs(x) > abs(z)
1596 Int4 yMajor = yz & ~xy; // abs(y) > abs(z) && abs(y) > abs(x)
1597 Int4 zMajor = zx & ~yz; // abs(z) > abs(x) && abs(z) > abs(y)
1599 // FACE_POSITIVE_X = 000b
1600 // FACE_NEGATIVE_X = 001b
1601 // FACE_POSITIVE_Y = 010b
1602 // FACE_NEGATIVE_Y = 011b
1603 // FACE_POSITIVE_Z = 100b
1604 // FACE_NEGATIVE_Z = 101b
1606 Int yAxis = SignMask(yMajor);
1607 Int zAxis = SignMask(zMajor);
1609 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
1610 Int negative = SignMask(n);
1612 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
1613 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4);
1614 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4);
1615 face[1] = (face[0] >> 4) & 0x7;
1616 face[2] = (face[0] >> 8) & 0x7;
1617 face[3] = (face[0] >> 12) & 0x7;
1620 Float4 M = Max(Max(absX, absY), absZ);
1622 // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x)
1623 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
1625 // V = !yMajor ? -y : (n ^ z)
1626 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
1628 M = reciprocal(M) * Float4(0.5f);
1629 U = U * M + Float4(0.5f);
1630 V = V * M + Float4(0.5f);
1637 Short4 SamplerCore::applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode)
1639 Int4 tmp = Int4(As<UShort4>(uvw));
1640 tmp = tmp + As<Int4>(offset);
1644 case AddressingMode::ADDRESSING_WRAP:
1645 tmp = (tmp + whd * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % whd;
1647 case AddressingMode::ADDRESSING_CLAMP:
1648 case AddressingMode::ADDRESSING_MIRROR:
1649 case AddressingMode::ADDRESSING_MIRRORONCE:
1650 case AddressingMode::ADDRESSING_BORDER: // FIXME: Implement and test ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, ADDRESSING_BORDER
1651 tmp = Min(Max(tmp, Int4(0)), whd - Int4(1));
1653 case ADDRESSING_TEXELFETCH:
1659 return As<Short4>(UShort4(tmp));
1662 void SamplerCore::computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function)
1664 bool texelFetch = (function == Fetch);
1665 bool hasOffset = (function.option == Offset);
1669 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width)));
1670 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height)));
1675 uuuu = applyOffset(uuuu, offset.x, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, width))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeU);
1676 vvvv = applyOffset(vvvv, offset.y, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, height))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeV);
1680 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1681 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1682 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1683 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1685 if(hasThirdCoordinate())
1687 if(state.textureType != TEXTURE_2D_ARRAY)
1691 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth)));
1695 wwww = applyOffset(wwww, offset.z, Int4(*Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth))), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeW);
1698 UInt4 uv(As<UInt2>(uuuu), As<UInt2>(uuu2));
1699 uv += As<UInt4>(Int4(As<UShort4>(wwww))) * *Pointer<UInt4>(mipmap + OFFSET(Mipmap, sliceP));
1700 index[0] = Extract(As<Int4>(uv), 0);
1701 index[1] = Extract(As<Int4>(uv), 1);
1702 index[2] = Extract(As<Int4>(uv), 2);
1703 index[3] = Extract(As<Int4>(uv), 3);
1707 index[0] = Extract(As<Int2>(uuuu), 0);
1708 index[1] = Extract(As<Int2>(uuuu), 1);
1709 index[2] = Extract(As<Int2>(uuu2), 0);
1710 index[3] = Extract(As<Int2>(uuu2), 1);
1715 Int size = Int(*Pointer<Int>(mipmap + OFFSET(Mipmap, sliceP)));
1716 if(hasThirdCoordinate())
1718 size *= Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)));
1721 UInt max = size - 1;
1723 for(int i = 0; i < 4; i++)
1725 index[i] = Min(Max(index[i], min), max);
1730 void SamplerCore::computeIndices(UInt index[4], Int4& uuuu, Int4& vvvv, Int4& wwww, const Pointer<Byte> &mipmap, SamplerFunction function)
1732 UInt4 indices = uuuu + vvvv;
1734 if(hasThirdCoordinate())
1736 indices += As<UInt4>(wwww);
1739 for(int i = 0; i < 4; i++)
1741 index[i] = Extract(As<Int4>(indices), i);
1745 Vector4s SamplerCore::sampleTexel(UInt index[4], Pointer<Byte> buffer[4])
1749 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1750 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1751 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1752 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1754 if(has16bitTextureFormat())
1756 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1757 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1758 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1759 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
1761 switch(state.textureFormat)
1764 c.z = (c.x & Short4(0x001Fu)) << 11;
1765 c.y = (c.x & Short4(0x07E0u)) << 5;
1766 c.x = (c.x & Short4(0xF800u));
1772 else if(has8bitTextureComponents())
1774 switch(textureComponentCount())
1778 Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1779 Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1780 Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1781 Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
1782 c.x = Unpack(c0, c1);
1783 c.y = Unpack(c2, c3);
1785 switch(state.textureFormat)
1787 case FORMAT_A8R8G8B8:
1788 c.z = As<Short4>(UnpackLow(c.x, c.y));
1789 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1792 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1793 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1794 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1795 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
1797 case FORMAT_A8B8G8R8:
1798 case FORMAT_A8B8G8R8I:
1799 case FORMAT_A8B8G8R8I_SNORM:
1800 case FORMAT_Q8W8V8U8:
1801 case FORMAT_SRGB8_A8:
1802 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1803 c.x = As<Short4>(UnpackLow(c.x, c.y));
1806 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1807 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1808 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1809 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
1810 // Propagate sign bit
1811 if(state.textureFormat == FORMAT_A8B8G8R8I)
1819 case FORMAT_A8B8G8R8UI:
1820 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1821 c.x = As<Short4>(UnpackLow(c.x, c.y));
1824 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0)));
1825 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0)));
1826 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(Short4(0)));
1827 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(Short4(0)));
1836 Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1837 Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1838 Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1839 Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
1840 c.x = Unpack(c0, c1);
1841 c.y = Unpack(c2, c3);
1843 switch(state.textureFormat)
1845 case FORMAT_X8R8G8B8:
1846 c.z = As<Short4>(UnpackLow(c.x, c.y));
1847 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1849 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1850 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1851 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1853 case FORMAT_X8B8G8R8I_SNORM:
1854 case FORMAT_X8B8G8R8I:
1855 case FORMAT_X8B8G8R8:
1856 case FORMAT_X8L8V8U8:
1857 case FORMAT_SRGB8_X8:
1858 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1859 c.x = As<Short4>(UnpackLow(c.x, c.y));
1861 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1862 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1863 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1864 // Propagate sign bit
1865 if(state.textureFormat == FORMAT_X8B8G8R8I)
1872 case FORMAT_X8B8G8R8UI:
1873 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1874 c.x = As<Short4>(UnpackLow(c.x, c.y));
1876 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0)));
1877 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0)));
1878 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(Short4(0)));
1886 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1887 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1888 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1889 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
1891 switch(state.textureFormat)
1894 case FORMAT_G8R8I_SNORM:
1897 c.y = (c.x & Short4(0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
1898 c.x = (c.x & Short4(0x00FFu)) | (c.x << 8);
1902 c.x = (c.x << 8) >> 8; // Propagate sign bit
1905 c.y = As<Short4>(As<UShort4>(c.x) >> 8);
1906 c.x &= Short4(0x00FFu);
1914 Int c0 = Int(*Pointer<Byte>(buffer[f0] + index[0]));
1915 Int c1 = Int(*Pointer<Byte>(buffer[f1] + index[1]));
1916 Int c2 = Int(*Pointer<Byte>(buffer[f2] + index[2]));
1917 Int c3 = Int(*Pointer<Byte>(buffer[f3] + index[3]));
1918 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1920 switch(state.textureFormat)
1926 c.x = Unpack(As<Byte4>(c0), As<Byte4>(zero));
1927 // Propagate sign bit
1928 if(state.textureFormat == FORMAT_R8I)
1930 c.x = (c.x << 8) >> 8;
1935 c.x = Unpack(As<Byte4>(c0));
1944 else if(has16bitTextureComponents())
1946 switch(textureComponentCount())
1949 c.x = Pointer<Short4>(buffer[f0])[index[0]];
1950 c.y = Pointer<Short4>(buffer[f1])[index[1]];
1951 c.z = Pointer<Short4>(buffer[f2])[index[2]];
1952 c.w = Pointer<Short4>(buffer[f3])[index[3]];
1953 transpose4x4(c.x, c.y, c.z, c.w);
1956 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]);
1957 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1])));
1958 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]);
1959 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3])));
1961 c.x = UnpackLow(As<Int2>(c.x), As<Int2>(c.z));
1962 c.y = UnpackHigh(As<Int2>(c.y), As<Int2>(c.z));
1965 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1966 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1967 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1968 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
1979 Vector4s SamplerCore::sampleTexel(Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Vector4f &offset, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
1984 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
1988 // Generic YPbPr to RGB transformation
1989 // R = Y + 2 * (1 - Kr) * Pr
1990 // G = Y - 2 * Kb * (1 - Kb) / Kg * Pb - 2 * Kr * (1 - Kr) / Kg * Pr
1991 // B = Y + 2 * (1 - Kb) * Pb
1995 int studioSwing = 1;
1997 switch(state.textureFormat)
1999 case FORMAT_YV12_BT601:
2004 case FORMAT_YV12_BT709:
2009 case FORMAT_YV12_JFIF:
2018 const float Kg = 1.0f - Kr - Kb;
2020 const float Rr = 2 * (1 - Kr);
2021 const float Gb = -2 * Kb * (1 - Kb) / Kg;
2022 const float Gr = -2 * Kr * (1 - Kr) / Kg;
2023 const float Bb = 2 * (1 - Kb);
2025 // Scaling and bias for studio-swing range: Y = [16 .. 235], U/V = [16 .. 240]
2026 const float Yy = studioSwing ? 255.0f / (235 - 16) : 1.0f;
2027 const float Uu = studioSwing ? 255.0f / (240 - 16) : 1.0f;
2028 const float Vv = studioSwing ? 255.0f / (240 - 16) : 1.0f;
2030 const float Rv = Vv * Rr;
2031 const float Gu = Uu * Gb;
2032 const float Gv = Vv * Gr;
2033 const float Bu = Uu * Bb;
2035 const float R0 = (studioSwing * -16 * Yy - 128 * Rv) / 255;
2036 const float G0 = (studioSwing * -16 * Yy - 128 * Gu - 128 * Gv) / 255;
2037 const float B0 = (studioSwing * -16 * Yy - 128 * Bu) / 255;
2039 Int c0 = Int(buffer[0][index[0]]);
2040 Int c1 = Int(buffer[0][index[1]]);
2041 Int c2 = Int(buffer[0][index[2]]);
2042 Int c3 = Int(buffer[0][index[3]]);
2043 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2044 UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0)));
2046 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap + sizeof(Mipmap), function);
2047 c0 = Int(buffer[1][index[0]]);
2048 c1 = Int(buffer[1][index[1]]);
2049 c2 = Int(buffer[1][index[2]]);
2050 c3 = Int(buffer[1][index[3]]);
2051 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2052 UShort4 V = As<UShort4>(Unpack(As<Byte4>(c0)));
2054 c0 = Int(buffer[2][index[0]]);
2055 c1 = Int(buffer[2][index[1]]);
2056 c2 = Int(buffer[2][index[2]]);
2057 c3 = Int(buffer[2][index[3]]);
2058 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2059 UShort4 U = As<UShort4>(Unpack(As<Byte4>(c0)));
2061 const UShort4 yY = UShort4(iround(Yy * 0x4000));
2062 const UShort4 rV = UShort4(iround(Rv * 0x4000));
2063 const UShort4 gU = UShort4(iround(-Gu * 0x4000));
2064 const UShort4 gV = UShort4(iround(-Gv * 0x4000));
2065 const UShort4 bU = UShort4(iround(Bu * 0x4000));
2067 const UShort4 r0 = UShort4(iround(-R0 * 0x4000));
2068 const UShort4 g0 = UShort4(iround(G0 * 0x4000));
2069 const UShort4 b0 = UShort4(iround(-B0 * 0x4000));
2071 UShort4 y = MulHigh(Y, yY);
2072 UShort4 r = SubSat(y + MulHigh(V, rV), r0);
2073 UShort4 g = SubSat(y + g0, MulHigh(U, gU) + MulHigh(V, gV));
2074 UShort4 b = SubSat(y + MulHigh(U, bU), b0);
2076 c.x = Min(r, UShort4(0x3FFF)) << 2;
2077 c.y = Min(g, UShort4(0x3FFF)) << 2;
2078 c.z = Min(b, UShort4(0x3FFF)) << 2;
2082 return sampleTexel(index, buffer);
2088 Vector4f SamplerCore::sampleTexel(Int4 &uuuu, Int4 &vvvv, Int4 &wwww, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
2093 computeIndices(index, uuuu, vvvv, wwww, mipmap, function);
2095 if(hasFloatTexture() || has32bitIntegerTextureComponents())
2097 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
2098 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
2099 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
2100 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
2103 switch(textureComponentCount())
2106 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2107 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2108 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2109 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2110 transpose4x4(c.x, c.y, c.z, c.w);
2113 ASSERT(state.textureFormat == FORMAT_X32B32G32R32F);
2114 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2115 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2116 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2117 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2118 transpose4x3(c.x, c.y, c.z, c.w);
2122 // FIXME: Optimal shuffling?
2123 c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8);
2124 c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8);
2125 c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8);
2126 c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8);
2128 c.x = Float4(c.x.xz, c.z.xz);
2129 c.y = Float4(c.y.yw, c.z.yw);
2132 // FIXME: Optimal shuffling?
2133 c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4);
2134 c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4);
2135 c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4);
2136 c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4);
2138 if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER)
2140 Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f));
2142 c.x = As<Float4>(As<Int4>(CmpNLT(c.x, d)) & As<Int4>(Float4(1.0f))); // FIXME: Only less-equal?
2151 ASSERT(!hasYuvFormat());
2153 Vector4s cs = sampleTexel(index, buffer);
2155 bool isInteger = Surface::isNonNormalizedInteger(state.textureFormat);
2156 int componentCount = textureComponentCount();
2157 for(int n = 0; n < componentCount; ++n)
2159 if(hasUnsignedTextureComponent(n))
2163 c[n] = As<Float4>(Int4(As<UShort4>(cs[n])));
2167 c[n] = Float4(As<UShort4>(cs[n]));
2174 c[n] = As<Float4>(Int4(cs[n]));
2178 c[n] = Float4(cs[n]);
2187 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
2189 if(state.mipmapFilter < MIPMAP_POINT)
2191 mipmap = texture + OFFSET(Texture,mipmap[0]);
2197 if(state.mipmapFilter == MIPMAP_POINT)
2199 ilod = RoundInt(lod);
2206 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
2209 if(state.textureType != TEXTURE_CUBE)
2211 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
2215 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1]));
2216 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2]));
2221 for(int i = 0; i < 4; i++)
2223 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
2228 Int4 SamplerCore::computeFilterOffset(Float &lod)
2230 Int4 filtering((state.textureFilter == FILTER_POINT) ? 0 : 1);
2231 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
2233 filtering &= CmpNLE(Float4(lod), Float4(0.0f));
2235 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
2237 filtering &= CmpLE(Float4(lod), Float4(0.0f));
2243 Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap)
2245 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2247 return Short4(); // Unused
2249 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY)
2251 return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1));
2253 else if(addressingMode == ADDRESSING_CLAMP)
2255 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
2257 return Short4(Int4(clamp * Float4(1 << 16)));
2259 else if(addressingMode == ADDRESSING_MIRROR)
2261 Int4 convert = Int4(uw * Float4(1 << 16));
2262 Int4 mirror = (convert << 15) >> 31;
2266 return Short4(convert);
2268 else if(addressingMode == ADDRESSING_MIRRORONCE)
2271 Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
2274 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
2275 convert = As<Int4>(PackSigned(convert, convert));
2277 return As<Short4>(Int2(convert)) + Short4(0x8000u);
2279 else // Wrap (or border)
2281 return Short4(Int4(uw * Float4(1 << 16)));
2285 void SamplerCore::address(Float4 &uvw, Int4& xyz0, Int4& xyz1, Float4& f, Pointer<Byte>& mipmap, Float4 &texOffset, Int4 &filter, int whd, AddressingMode addressingMode, SamplerFunction function)
2287 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2292 Int4 dim = Int4(*Pointer<Short4>(mipmap + whd, 16));
2293 Int4 maxXYZ = dim - Int4(1);
2295 if(function == Fetch)
2297 xyz0 = Min(Max(((function.option == Offset) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ);
2299 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY) // Note: Offset does not apply to array layers
2301 xyz0 = Min(Max(RoundInt(uvw), Int4(0)), maxXYZ);
2305 const int halfBits = 0x3effffff; // Value just under 0.5f
2306 const int oneBits = 0x3f7fffff; // Value just under 1.0f
2307 const int twoBits = 0x3fffffff; // Value just under 2.0f
2309 Float4 coord = Float4(dim);
2310 switch(addressingMode)
2312 case ADDRESSING_CLAMP:
2314 Float4 one = As<Float4>(Int4(oneBits));
2315 coord *= Min(Max(uvw, Float4(0.0f)), one);
2318 case ADDRESSING_MIRROR:
2320 Float4 half = As<Float4>(Int4(halfBits));
2321 Float4 one = As<Float4>(Int4(oneBits));
2322 Float4 two = As<Float4>(Int4(twoBits));
2323 coord *= one - Abs(two * Frac(uvw * half) - one);
2326 case ADDRESSING_MIRRORONCE:
2328 Float4 half = As<Float4>(Int4(halfBits));
2329 Float4 one = As<Float4>(Int4(oneBits));
2330 Float4 two = As<Float4>(Int4(twoBits));
2331 coord *= one - Abs(two * Frac(Min(Max(uvw, -one), two) * half) - one);
2334 default: // Wrap (or border)
2341 if(function.option == Offset)
2343 xyz0 += As<Int4>(texOffset);
2344 switch(addressingMode)
2346 case ADDRESSING_MIRROR:
2347 case ADDRESSING_MIRRORONCE:
2348 case ADDRESSING_BORDER:
2349 // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE and ADDRESSING_BORDER. Fall through to Clamp.
2350 case ADDRESSING_CLAMP:
2351 xyz0 = Min(Max(xyz0, Int4(0)), maxXYZ);
2354 xyz0 = (xyz0 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim;
2359 if(state.textureFilter != FILTER_POINT) // Compute 2nd coordinate, if needed
2361 bool gather = state.textureFilter == FILTER_GATHER;
2363 xyz1 = xyz0 + filter; // Increment
2367 Float4 frac = Frac(coord);
2368 f = Abs(frac - Float4(0.5f));
2369 xyz1 -= CmpLT(frac, Float4(0.5f)) & (filter + filter); // Decrement xyz if necessary
2372 switch(addressingMode)
2374 case ADDRESSING_MIRROR:
2375 case ADDRESSING_MIRRORONCE:
2376 case ADDRESSING_BORDER:
2377 // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE and ADDRESSING_BORDER. Fall through to Clamp.
2378 case ADDRESSING_CLAMP:
2379 xyz1 = gather ? Min(xyz1, maxXYZ) : Min(Max(xyz1, Int4(0)), maxXYZ);
2383 // The coordinates overflow or underflow by at most 1
2384 Int4 over = CmpNLT(xyz1, dim);
2385 xyz1 = (over & Int4(0)) | (~over & xyz1); // xyz >= dim ? 0 : xyz
2388 Int4 under = CmpLT(xyz1, Int4(0));
2389 xyz1 = (under & maxXYZ) | (~under & xyz1); // xyz < 0 ? dim - 1 : xyz
2398 void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
2400 cs = RoundShort4(cf * Float4(0x1000));
2403 void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
2405 convertFixed12(cs.x, cf.x);
2406 convertFixed12(cs.y, cf.y);
2407 convertFixed12(cs.z, cf.z);
2408 convertFixed12(cs.w, cf.w);
2411 void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
2413 cf = Float4(cs) * Float4(1.0f / 0x0FFE);
2416 // void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
2418 // convertSigned12(cf.x, cs.x);
2419 // convertSigned12(cf.y, cs.y);
2420 // convertSigned12(cf.z, cs.z);
2421 // convertSigned12(cf.w, cs.w);
2424 void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
2426 cf = Float4(cs) * Float4(1.0f / 0x7FFF);
2429 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
2431 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
2434 void SamplerCore::sRGBtoLinear16_8_12(Short4 &c)
2436 c = As<UShort4>(c) >> 8;
2438 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_12));
2440 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2441 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2442 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2443 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2446 void SamplerCore::sRGBtoLinear16_6_12(Short4 &c)
2448 c = As<UShort4>(c) >> 10;
2450 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_12));
2452 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2453 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2454 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2455 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2458 void SamplerCore::sRGBtoLinear16_5_12(Short4 &c)
2460 c = As<UShort4>(c) >> 11;
2462 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_12));
2464 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2465 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2466 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2467 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2470 bool SamplerCore::hasFloatTexture() const
2472 return Surface::isFloatFormat(state.textureFormat);
2475 bool SamplerCore::hasUnnormalizedIntegerTexture() const
2477 return Surface::isNonNormalizedInteger(state.textureFormat);
2480 bool SamplerCore::hasUnsignedTextureComponent(int component) const
2482 return Surface::isUnsignedComponent(state.textureFormat, component);
2485 int SamplerCore::textureComponentCount() const
2487 return Surface::componentCount(state.textureFormat);
2490 bool SamplerCore::hasThirdCoordinate() const
2492 return (state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY);
2495 bool SamplerCore::has16bitTextureFormat() const
2497 switch(state.textureFormat)
2501 case FORMAT_R8I_SNORM:
2502 case FORMAT_G8R8I_SNORM:
2503 case FORMAT_X8B8G8R8I_SNORM:
2504 case FORMAT_A8B8G8R8I_SNORM:
2509 case FORMAT_X8B8G8R8I:
2510 case FORMAT_X8B8G8R8UI:
2511 case FORMAT_A8B8G8R8I:
2512 case FORMAT_A8B8G8R8UI:
2515 case FORMAT_G32R32I:
2516 case FORMAT_G32R32UI:
2517 case FORMAT_X32B32G32R32I:
2518 case FORMAT_X32B32G32R32UI:
2519 case FORMAT_A32B32G32R32I:
2520 case FORMAT_A32B32G32R32UI:
2522 case FORMAT_X8R8G8B8:
2523 case FORMAT_X8B8G8R8:
2524 case FORMAT_A8R8G8B8:
2525 case FORMAT_A8B8G8R8:
2526 case FORMAT_SRGB8_X8:
2527 case FORMAT_SRGB8_A8:
2529 case FORMAT_Q8W8V8U8:
2530 case FORMAT_X8L8V8U8:
2532 case FORMAT_G32R32F:
2533 case FORMAT_X32B32G32R32F:
2534 case FORMAT_A32B32G32R32F:
2540 case FORMAT_D32F_LOCKABLE:
2541 case FORMAT_D32FS8_TEXTURE:
2542 case FORMAT_D32FS8_SHADOW:
2545 case FORMAT_A16B16G16R16:
2547 case FORMAT_A16W16V16U16:
2548 case FORMAT_Q16W16V16U16:
2551 case FORMAT_G16R16I:
2552 case FORMAT_G16R16UI:
2553 case FORMAT_X16B16G16R16I:
2554 case FORMAT_X16B16G16R16UI:
2555 case FORMAT_A16B16G16R16I:
2556 case FORMAT_A16B16G16R16UI:
2557 case FORMAT_YV12_BT601:
2558 case FORMAT_YV12_BT709:
2559 case FORMAT_YV12_JFIF:
2568 bool SamplerCore::has8bitTextureComponents() const
2570 switch(state.textureFormat)
2573 case FORMAT_X8R8G8B8:
2574 case FORMAT_X8B8G8R8:
2575 case FORMAT_A8R8G8B8:
2576 case FORMAT_A8B8G8R8:
2577 case FORMAT_SRGB8_X8:
2578 case FORMAT_SRGB8_A8:
2580 case FORMAT_Q8W8V8U8:
2581 case FORMAT_X8L8V8U8:
2586 case FORMAT_R8I_SNORM:
2587 case FORMAT_G8R8I_SNORM:
2588 case FORMAT_X8B8G8R8I_SNORM:
2589 case FORMAT_A8B8G8R8I_SNORM:
2594 case FORMAT_X8B8G8R8I:
2595 case FORMAT_X8B8G8R8UI:
2596 case FORMAT_A8B8G8R8I:
2597 case FORMAT_A8B8G8R8UI:
2601 case FORMAT_G32R32F:
2602 case FORMAT_X32B32G32R32F:
2603 case FORMAT_A32B32G32R32F:
2605 case FORMAT_D32F_LOCKABLE:
2606 case FORMAT_D32FS8_TEXTURE:
2607 case FORMAT_D32FS8_SHADOW:
2610 case FORMAT_A16B16G16R16:
2612 case FORMAT_A16W16V16U16:
2613 case FORMAT_Q16W16V16U16:
2616 case FORMAT_G32R32I:
2617 case FORMAT_G32R32UI:
2618 case FORMAT_X32B32G32R32I:
2619 case FORMAT_X32B32G32R32UI:
2620 case FORMAT_A32B32G32R32I:
2621 case FORMAT_A32B32G32R32UI:
2624 case FORMAT_G16R16I:
2625 case FORMAT_G16R16UI:
2626 case FORMAT_X16B16G16R16I:
2627 case FORMAT_X16B16G16R16UI:
2628 case FORMAT_A16B16G16R16I:
2629 case FORMAT_A16B16G16R16UI:
2630 case FORMAT_YV12_BT601:
2631 case FORMAT_YV12_BT709:
2632 case FORMAT_YV12_JFIF:
2641 bool SamplerCore::has16bitTextureComponents() const
2643 switch(state.textureFormat)
2646 case FORMAT_R8I_SNORM:
2647 case FORMAT_G8R8I_SNORM:
2648 case FORMAT_X8B8G8R8I_SNORM:
2649 case FORMAT_A8B8G8R8I_SNORM:
2654 case FORMAT_X8B8G8R8I:
2655 case FORMAT_X8B8G8R8UI:
2656 case FORMAT_A8B8G8R8I:
2657 case FORMAT_A8B8G8R8UI:
2660 case FORMAT_G32R32I:
2661 case FORMAT_G32R32UI:
2662 case FORMAT_X32B32G32R32I:
2663 case FORMAT_X32B32G32R32UI:
2664 case FORMAT_A32B32G32R32I:
2665 case FORMAT_A32B32G32R32UI:
2667 case FORMAT_X8R8G8B8:
2668 case FORMAT_X8B8G8R8:
2669 case FORMAT_A8R8G8B8:
2670 case FORMAT_A8B8G8R8:
2671 case FORMAT_SRGB8_X8:
2672 case FORMAT_SRGB8_A8:
2674 case FORMAT_Q8W8V8U8:
2675 case FORMAT_X8L8V8U8:
2677 case FORMAT_G32R32F:
2678 case FORMAT_X32B32G32R32F:
2679 case FORMAT_A32B32G32R32F:
2685 case FORMAT_D32F_LOCKABLE:
2686 case FORMAT_D32FS8_TEXTURE:
2687 case FORMAT_D32FS8_SHADOW:
2688 case FORMAT_YV12_BT601:
2689 case FORMAT_YV12_BT709:
2690 case FORMAT_YV12_JFIF:
2694 case FORMAT_A16B16G16R16:
2697 case FORMAT_G16R16I:
2698 case FORMAT_G16R16UI:
2699 case FORMAT_X16B16G16R16I:
2700 case FORMAT_X16B16G16R16UI:
2701 case FORMAT_A16B16G16R16I:
2702 case FORMAT_A16B16G16R16UI:
2704 case FORMAT_A16W16V16U16:
2705 case FORMAT_Q16W16V16U16:
2714 bool SamplerCore::has32bitIntegerTextureComponents() const
2716 switch(state.textureFormat)
2719 case FORMAT_R8I_SNORM:
2720 case FORMAT_G8R8I_SNORM:
2721 case FORMAT_X8B8G8R8I_SNORM:
2722 case FORMAT_A8B8G8R8I_SNORM:
2727 case FORMAT_X8B8G8R8I:
2728 case FORMAT_X8B8G8R8UI:
2729 case FORMAT_A8B8G8R8I:
2730 case FORMAT_A8B8G8R8UI:
2732 case FORMAT_X8R8G8B8:
2733 case FORMAT_X8B8G8R8:
2734 case FORMAT_A8R8G8B8:
2735 case FORMAT_A8B8G8R8:
2736 case FORMAT_SRGB8_X8:
2737 case FORMAT_SRGB8_A8:
2739 case FORMAT_Q8W8V8U8:
2740 case FORMAT_X8L8V8U8:
2743 case FORMAT_A16B16G16R16:
2746 case FORMAT_G16R16I:
2747 case FORMAT_G16R16UI:
2748 case FORMAT_X16B16G16R16I:
2749 case FORMAT_X16B16G16R16UI:
2750 case FORMAT_A16B16G16R16I:
2751 case FORMAT_A16B16G16R16UI:
2753 case FORMAT_A16W16V16U16:
2754 case FORMAT_Q16W16V16U16:
2756 case FORMAT_G32R32F:
2757 case FORMAT_X32B32G32R32F:
2758 case FORMAT_A32B32G32R32F:
2764 case FORMAT_D32F_LOCKABLE:
2765 case FORMAT_D32FS8_TEXTURE:
2766 case FORMAT_D32FS8_SHADOW:
2767 case FORMAT_YV12_BT601:
2768 case FORMAT_YV12_BT709:
2769 case FORMAT_YV12_JFIF:
2773 case FORMAT_G32R32I:
2774 case FORMAT_G32R32UI:
2775 case FORMAT_X32B32G32R32I:
2776 case FORMAT_X32B32G32R32UI:
2777 case FORMAT_A32B32G32R32I:
2778 case FORMAT_A32B32G32R32UI:
2787 bool SamplerCore::hasYuvFormat() const
2789 switch(state.textureFormat)
2791 case FORMAT_YV12_BT601:
2792 case FORMAT_YV12_BT709:
2793 case FORMAT_YV12_JFIF:
2796 case FORMAT_R8I_SNORM:
2797 case FORMAT_G8R8I_SNORM:
2798 case FORMAT_X8B8G8R8I_SNORM:
2799 case FORMAT_A8B8G8R8I_SNORM:
2804 case FORMAT_X8B8G8R8I:
2805 case FORMAT_X8B8G8R8UI:
2806 case FORMAT_A8B8G8R8I:
2807 case FORMAT_A8B8G8R8UI:
2810 case FORMAT_G32R32I:
2811 case FORMAT_G32R32UI:
2812 case FORMAT_X32B32G32R32I:
2813 case FORMAT_X32B32G32R32UI:
2814 case FORMAT_A32B32G32R32I:
2815 case FORMAT_A32B32G32R32UI:
2817 case FORMAT_X8R8G8B8:
2818 case FORMAT_X8B8G8R8:
2819 case FORMAT_A8R8G8B8:
2820 case FORMAT_A8B8G8R8:
2821 case FORMAT_SRGB8_X8:
2822 case FORMAT_SRGB8_A8:
2824 case FORMAT_Q8W8V8U8:
2825 case FORMAT_X8L8V8U8:
2827 case FORMAT_G32R32F:
2828 case FORMAT_X32B32G32R32F:
2829 case FORMAT_A32B32G32R32F:
2835 case FORMAT_D32F_LOCKABLE:
2836 case FORMAT_D32FS8_TEXTURE:
2837 case FORMAT_D32FS8_SHADOW:
2840 case FORMAT_A16B16G16R16:
2843 case FORMAT_G16R16I:
2844 case FORMAT_G16R16UI:
2845 case FORMAT_X16B16G16R16I:
2846 case FORMAT_X16B16G16R16UI:
2847 case FORMAT_A16B16G16R16I:
2848 case FORMAT_A16B16G16R16UI:
2850 case FORMAT_A16W16V16U16:
2851 case FORMAT_Q16W16V16U16:
2860 bool SamplerCore::isRGBComponent(int component) const
2862 switch(state.textureFormat)
2864 case FORMAT_R5G6B5: return component < 3;
2865 case FORMAT_R8I_SNORM: return component < 1;
2866 case FORMAT_G8R8I_SNORM: return component < 2;
2867 case FORMAT_X8B8G8R8I_SNORM: return component < 3;
2868 case FORMAT_A8B8G8R8I_SNORM: return component < 3;
2869 case FORMAT_R8I: return component < 1;
2870 case FORMAT_R8UI: return component < 1;
2871 case FORMAT_G8R8I: return component < 2;
2872 case FORMAT_G8R8UI: return component < 2;
2873 case FORMAT_X8B8G8R8I: return component < 3;
2874 case FORMAT_X8B8G8R8UI: return component < 3;
2875 case FORMAT_A8B8G8R8I: return component < 3;
2876 case FORMAT_A8B8G8R8UI: return component < 3;
2877 case FORMAT_R32I: return component < 1;
2878 case FORMAT_R32UI: return component < 1;
2879 case FORMAT_G32R32I: return component < 2;
2880 case FORMAT_G32R32UI: return component < 2;
2881 case FORMAT_X32B32G32R32I: return component < 3;
2882 case FORMAT_X32B32G32R32UI: return component < 3;
2883 case FORMAT_A32B32G32R32I: return component < 3;
2884 case FORMAT_A32B32G32R32UI: return component < 3;
2885 case FORMAT_G8R8: return component < 2;
2886 case FORMAT_X8R8G8B8: return component < 3;
2887 case FORMAT_X8B8G8R8: return component < 3;
2888 case FORMAT_A8R8G8B8: return component < 3;
2889 case FORMAT_A8B8G8R8: return component < 3;
2890 case FORMAT_SRGB8_X8: return component < 3;
2891 case FORMAT_SRGB8_A8: return component < 3;
2892 case FORMAT_V8U8: return false;
2893 case FORMAT_Q8W8V8U8: return false;
2894 case FORMAT_X8L8V8U8: return false;
2895 case FORMAT_R32F: return component < 1;
2896 case FORMAT_G32R32F: return component < 2;
2897 case FORMAT_X32B32G32R32F: return component < 3;
2898 case FORMAT_A32B32G32R32F: return component < 3;
2899 case FORMAT_A8: return false;
2900 case FORMAT_R8: return component < 1;
2901 case FORMAT_L8: return component < 1;
2902 case FORMAT_A8L8: return component < 1;
2903 case FORMAT_D32F: return false;
2904 case FORMAT_D32F_LOCKABLE: return false;
2905 case FORMAT_D32FS8_TEXTURE: return false;
2906 case FORMAT_D32FS8_SHADOW: return false;
2907 case FORMAT_L16: return component < 1;
2908 case FORMAT_G16R16: return component < 2;
2909 case FORMAT_A16B16G16R16: return component < 3;
2910 case FORMAT_R16I: return component < 1;
2911 case FORMAT_R16UI: return component < 1;
2912 case FORMAT_G16R16I: return component < 2;
2913 case FORMAT_G16R16UI: return component < 2;
2914 case FORMAT_X16B16G16R16I: return component < 3;
2915 case FORMAT_X16B16G16R16UI: return component < 3;
2916 case FORMAT_A16B16G16R16I: return component < 3;
2917 case FORMAT_A16B16G16R16UI: return component < 3;
2918 case FORMAT_V16U16: return false;
2919 case FORMAT_A16W16V16U16: return false;
2920 case FORMAT_Q16W16V16U16: return false;
2921 case FORMAT_YV12_BT601: return component < 3;
2922 case FORMAT_YV12_BT709: return component < 3;
2923 case FORMAT_YV12_JFIF: return component < 3;