blob: 6ede6f12480ce2f6b80348a7eefbd0150be7154d [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "SamplerCore.hpp"
16
17#include "Constants.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040018#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040019
Alexis Hetu1d01aa32015-09-29 11:50:05 -040020namespace
21{
22 void applySwizzle(sw::SwizzleType swizzle, sw::Short4& s, const sw::Vector4s& c)
23 {
24 switch(swizzle)
25 {
26 case sw::SWIZZLE_RED: s = c.x; break;
27 case sw::SWIZZLE_GREEN: s = c.y; break;
28 case sw::SWIZZLE_BLUE: s = c.z; break;
29 case sw::SWIZZLE_ALPHA: s = c.w; break;
Alexis Hetu90c7ad62016-06-27 11:50:40 -040030 case sw::SWIZZLE_ZERO: s = sw::Short4(0x0000); break;
31 case sw::SWIZZLE_ONE: s = sw::Short4(0x1000); break;
Alexis Hetu1d01aa32015-09-29 11:50:05 -040032 default: ASSERT(false);
33 }
34 }
35
36 void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c)
37 {
38 switch(swizzle)
39 {
40 case sw::SWIZZLE_RED: f = c.x; break;
41 case sw::SWIZZLE_GREEN: f = c.y; break;
42 case sw::SWIZZLE_BLUE: f = c.z; break;
43 case sw::SWIZZLE_ALPHA: f = c.w; break;
44 case sw::SWIZZLE_ZERO: f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break;
45 case sw::SWIZZLE_ONE: f = sw::Float4(1.0f, 1.0f, 1.0f, 1.0f); break;
46 default: ASSERT(false);
47 }
48 }
49}
50
John Bauman89401822014-05-06 15:04:28 -040051namespace sw
52{
Alexis Hetu56f256e2017-07-21 11:41:13 -040053 extern bool colorsDefaultToZero;
54
John Bauman89401822014-05-06 15:04:28 -040055 SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
56 {
57 }
58
Nicolas Capensa0b57832017-11-07 13:07:53 -050059 Vector4s SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy)
Nicolas Capensc2534f42016-04-04 11:13:24 -040060 {
Nicolas Capensa0b57832017-11-07 13:07:53 -050061 return sampleTexture(texture, u, v, w, q, q, dsx, dsy, (dsx), Implicit, true);
Nicolas Capensc2534f42016-04-04 11:13:24 -040062 }
63
Nicolas Capensa0b57832017-11-07 13:07:53 -050064 Vector4s SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function, bool fixed12)
John Bauman89401822014-05-06 15:04:28 -040065 {
Nicolas Capens89a218b2017-11-07 13:05:20 -050066 Vector4s c;
67
John Bauman89401822014-05-06 15:04:28 -040068 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -040069 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -040070
71 if(state.compressedFormat)
72 {
John Bauman66b8ab22014-05-06 15:57:45 -040073 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -040074 }
75 #endif
76
John Bauman89401822014-05-06 15:04:28 -040077 if(state.textureType == TEXTURE_NULL)
78 {
Alexis Hetu90c7ad62016-06-27 11:50:40 -040079 c.x = Short4(0x0000);
80 c.y = Short4(0x0000);
81 c.z = Short4(0x0000);
John Bauman89401822014-05-06 15:04:28 -040082
83 if(fixed12) // FIXME: Convert to fixed12 at higher level, when required
84 {
Alexis Hetu90c7ad62016-06-27 11:50:40 -040085 c.w = Short4(0x1000);
John Bauman89401822014-05-06 15:04:28 -040086 }
87 else
88 {
Alexis Hetu90c7ad62016-06-27 11:50:40 -040089 c.w = Short4(0xFFFFu); // FIXME
John Bauman89401822014-05-06 15:04:28 -040090 }
91 }
92 else
93 {
Nicolas Capens77f0b682017-11-07 13:25:09 -050094 Float4 uuuu = u;
95 Float4 vvvv = v;
96 Float4 wwww = w;
97 Float4 qqqq = q;
98
John Bauman89401822014-05-06 15:04:28 -040099 Int face[4];
John Bauman89401822014-05-06 15:04:28 -0400100 Float lod;
101 Float anisotropy;
102 Float4 uDelta;
103 Float4 vDelta;
104
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500105 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400106 {
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500107 if(state.textureType != TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400108 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500109 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, bias.x, dsx, dsy, function);
John Bauman89401822014-05-06 15:04:28 -0400110 }
111 else
112 {
Nicolas Capens77f0b682017-11-07 13:25:09 -0500113 Float4 M;
114 cubeFace(face, uuuu, vvvv, u, v, w, M);
115 computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
John Bauman89401822014-05-06 15:04:28 -0400116 }
117 }
118 else
119 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500120 computeLod3D(texture, lod, uuuu, vvvv, wwww, bias.x, dsx, dsy, function);
John Bauman89401822014-05-06 15:04:28 -0400121 }
122
John Bauman89401822014-05-06 15:04:28 -0400123 if(!hasFloatTexture())
124 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500125 c = sampleFilter(texture, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
John Bauman89401822014-05-06 15:04:28 -0400126 }
127 else
128 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500129 Vector4f cf = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
John Bauman89401822014-05-06 15:04:28 -0400130
131 convertFixed12(c, cf);
132 }
133
Nicolas Capens57642352018-02-27 13:29:26 -0500134 if(fixed12)
John Bauman89401822014-05-06 15:04:28 -0400135 {
Nicolas Capens57642352018-02-27 13:29:26 -0500136 if(!hasFloatTexture())
John Bauman89401822014-05-06 15:04:28 -0400137 {
Nicolas Capens57642352018-02-27 13:29:26 -0500138 if(state.textureFormat == FORMAT_R5G6B5)
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400139 {
Nicolas Capens57642352018-02-27 13:29:26 -0500140 c.x = MulHigh(As<UShort4>(c.x), UShort4(0x10000000 / 0xF800));
141 c.y = MulHigh(As<UShort4>(c.y), UShort4(0x10000000 / 0xFC00));
142 c.z = MulHigh(As<UShort4>(c.z), UShort4(0x10000000 / 0xF800));
143 }
144 else
145 {
146 for(int component = 0; component < textureComponentCount(); component++)
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400147 {
Nicolas Capens57642352018-02-27 13:29:26 -0500148 if(hasUnsignedTextureComponent(component))
149 {
150 c[component] = As<UShort4>(c[component]) >> 4;
151 }
152 else
153 {
154 c[component] = c[component] >> 3;
155 }
John Bauman89401822014-05-06 15:04:28 -0400156 }
157 }
158 }
John Bauman89401822014-05-06 15:04:28 -0400159
Nicolas Capens57642352018-02-27 13:29:26 -0500160 if(state.textureFilter != FILTER_GATHER)
John Bauman89401822014-05-06 15:04:28 -0400161 {
Nicolas Capens57642352018-02-27 13:29:26 -0500162 int componentCount = textureComponentCount();
163 short defaultColorValue = colorsDefaultToZero ? 0x0000 : 0x1000;
164
165 switch(state.textureFormat)
166 {
167 case FORMAT_R8_SNORM:
168 case FORMAT_G8R8_SNORM:
169 case FORMAT_X8B8G8R8_SNORM:
170 case FORMAT_A8B8G8R8_SNORM:
171 case FORMAT_R8:
172 case FORMAT_R5G6B5:
173 case FORMAT_G8R8:
174 case FORMAT_R8I:
175 case FORMAT_R8UI:
176 case FORMAT_G8R8I:
177 case FORMAT_G8R8UI:
178 case FORMAT_X8B8G8R8I:
179 case FORMAT_X8B8G8R8UI:
180 case FORMAT_A8B8G8R8I:
181 case FORMAT_A8B8G8R8UI:
182 case FORMAT_R16I:
183 case FORMAT_R16UI:
184 case FORMAT_G16R16:
185 case FORMAT_G16R16I:
186 case FORMAT_G16R16UI:
187 case FORMAT_X16B16G16R16I:
188 case FORMAT_X16B16G16R16UI:
189 case FORMAT_A16B16G16R16:
190 case FORMAT_A16B16G16R16I:
191 case FORMAT_A16B16G16R16UI:
192 case FORMAT_R32I:
193 case FORMAT_R32UI:
194 case FORMAT_G32R32I:
195 case FORMAT_G32R32UI:
196 case FORMAT_X32B32G32R32I:
197 case FORMAT_X32B32G32R32UI:
198 case FORMAT_A32B32G32R32I:
199 case FORMAT_A32B32G32R32UI:
200 case FORMAT_X8R8G8B8:
201 case FORMAT_X8B8G8R8:
202 case FORMAT_A8R8G8B8:
203 case FORMAT_A8B8G8R8:
204 case FORMAT_SRGB8_X8:
205 case FORMAT_SRGB8_A8:
206 case FORMAT_V8U8:
207 case FORMAT_Q8W8V8U8:
208 case FORMAT_X8L8V8U8:
209 case FORMAT_V16U16:
210 case FORMAT_A16W16V16U16:
211 case FORMAT_Q16W16V16U16:
212 case FORMAT_YV12_BT601:
213 case FORMAT_YV12_BT709:
214 case FORMAT_YV12_JFIF:
215 if(componentCount < 2) c.y = Short4(defaultColorValue);
216 if(componentCount < 3) c.z = Short4(defaultColorValue);
217 if(componentCount < 4) c.w = Short4(0x1000);
218 break;
219 case FORMAT_A8:
220 c.w = c.x;
221 c.x = Short4(0x0000);
222 c.y = Short4(0x0000);
223 c.z = Short4(0x0000);
224 break;
225 case FORMAT_L8:
226 case FORMAT_L16:
227 c.y = c.x;
228 c.z = c.x;
229 c.w = Short4(0x1000);
230 break;
231 case FORMAT_A8L8:
232 c.w = c.y;
233 c.y = c.x;
234 c.z = c.x;
235 break;
236 case FORMAT_R32F:
237 c.y = Short4(defaultColorValue);
238 case FORMAT_G32R32F:
239 c.z = Short4(defaultColorValue);
240 case FORMAT_X32B32G32R32F:
241 case FORMAT_X32B32G32R32F_UNSIGNED:
242 c.w = Short4(0x1000);
243 case FORMAT_A32B32G32R32F:
244 break;
245 case FORMAT_D32F:
246 case FORMAT_D32FS8:
247 case FORMAT_D32F_LOCKABLE:
248 case FORMAT_D32FS8_TEXTURE:
249 case FORMAT_D32F_SHADOW:
250 case FORMAT_D32FS8_SHADOW:
251 c.y = c.x;
252 c.z = c.x;
253 c.w = c.x;
254 break;
255 default:
256 ASSERT(false);
257 }
258 }
259
260 if((state.swizzleR != SWIZZLE_RED) ||
261 (state.swizzleG != SWIZZLE_GREEN) ||
262 (state.swizzleB != SWIZZLE_BLUE) ||
263 (state.swizzleA != SWIZZLE_ALPHA))
264 {
265 const Vector4s col(c);
266 applySwizzle(state.swizzleR, c.x, col);
267 applySwizzle(state.swizzleG, c.y, col);
268 applySwizzle(state.swizzleB, c.z, col);
269 applySwizzle(state.swizzleA, c.w, col);
John Bauman89401822014-05-06 15:04:28 -0400270 }
271 }
272 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400273
Nicolas Capens89a218b2017-11-07 13:05:20 -0500274 return c;
John Bauman89401822014-05-06 15:04:28 -0400275 }
276
Nicolas Capensa0b57832017-11-07 13:07:53 -0500277 Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -0400278 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500279 Vector4f c;
280
John Bauman89401822014-05-06 15:04:28 -0400281 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -0400282 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -0400283
284 if(state.compressedFormat)
285 {
John Bauman66b8ab22014-05-06 15:57:45 -0400286 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -0400287 }
288 #endif
289
John Bauman89401822014-05-06 15:04:28 -0400290 if(state.textureType == TEXTURE_NULL)
291 {
John Bauman19bac1e2014-05-06 15:23:49 -0400292 c.x = Float4(0.0f);
293 c.y = Float4(0.0f);
294 c.z = Float4(0.0f);
295 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400296 }
297 else
298 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500299 // FIXME: YUV is not supported by the floating point path
300 bool forceFloatFiltering = state.highPrecisionFiltering && !hasYuvFormat() && (state.textureFilter != FILTER_POINT);
Nicolas Capensd0f5d392017-11-28 15:54:59 -0500301 bool seamlessCube = (state.addressingModeU == ADDRESSING_SEAMLESS);
Alexis Hetuc0632c92018-03-02 15:10:16 -0500302 bool rectangleTexture = (state.textureType == TEXTURE_RECTANGLE);
Alexis Hetu46768622018-01-16 22:09:28 -0500303 if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering || seamlessCube || rectangleTexture) // FIXME: Mostly identical to integer sampling
John Bauman89401822014-05-06 15:04:28 -0400304 {
305 Float4 uuuu = u;
306 Float4 vvvv = v;
307 Float4 wwww = w;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500308 Float4 qqqq = q;
John Bauman89401822014-05-06 15:04:28 -0400309
310 Int face[4];
John Bauman89401822014-05-06 15:04:28 -0400311 Float lod;
312 Float anisotropy;
313 Float4 uDelta;
314 Float4 vDelta;
315
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500316 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400317 {
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500318 if(state.textureType != TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400319 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500320 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, bias.x, dsx, dsy, function);
John Bauman89401822014-05-06 15:04:28 -0400321 }
322 else
323 {
Nicolas Capens77f0b682017-11-07 13:25:09 -0500324 Float4 M;
325 cubeFace(face, uuuu, vvvv, u, v, w, M);
326 computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
John Bauman89401822014-05-06 15:04:28 -0400327 }
328 }
329 else
330 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500331 computeLod3D(texture, lod, uuuu, vvvv, wwww, bias.x, dsx, dsy, function);
John Bauman89401822014-05-06 15:04:28 -0400332 }
333
Nicolas Capensa0b57832017-11-07 13:07:53 -0500334 c = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
Alexis Hetufacada52017-07-20 16:56:30 -0400335
336 if(!hasFloatTexture() && !hasUnnormalizedIntegerTexture())
337 {
338 if(has16bitTextureFormat())
339 {
340 switch(state.textureFormat)
341 {
342 case FORMAT_R5G6B5:
343 c.x *= Float4(1.0f / 0xF800);
344 c.y *= Float4(1.0f / 0xFC00);
345 c.z *= Float4(1.0f / 0xF800);
346 break;
347 default:
348 ASSERT(false);
349 }
350 }
351 else
352 {
353 for(int component = 0; component < textureComponentCount(); component++)
354 {
355 c[component] *= Float4(hasUnsignedTextureComponent(component) ? 1.0f / 0xFFFF : 1.0f / 0x7FFF);
356 }
357 }
358 }
John Bauman89401822014-05-06 15:04:28 -0400359 }
360 else
361 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500362 Vector4s cs = sampleTexture(texture, u, v, w, q, bias, dsx, dsy, offset, function, false);
John Bauman89401822014-05-06 15:04:28 -0400363
Nicolas Capens5555af42017-12-14 13:14:03 -0500364 if(state.textureFormat == FORMAT_R5G6B5)
John Bauman89401822014-05-06 15:04:28 -0400365 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500366 c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
367 c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
368 c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
Alexis Hetuab849ae2017-07-14 10:44:10 -0400369 }
370 else
371 {
372 for(int component = 0; component < textureComponentCount(); component++)
John Bauman89401822014-05-06 15:04:28 -0400373 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500374 if(hasUnsignedTextureComponent(component))
John Bauman89401822014-05-06 15:04:28 -0400375 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500376 convertUnsigned16(c[component], cs[component]);
Alexis Hetu91dd1c42017-07-18 13:03:42 -0400377 }
378 else
379 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500380 convertSigned15(c[component], cs[component]);
John Bauman89401822014-05-06 15:04:28 -0400381 }
382 }
383 }
384 }
385
386 int componentCount = textureComponentCount();
Alexis Hetu56f256e2017-07-21 11:41:13 -0400387 float defaultColorValue = colorsDefaultToZero ? 0.0f : 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400388
389 if(state.textureFilter != FILTER_GATHER)
390 {
391 switch(state.textureFormat)
392 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400393 case FORMAT_R8I:
394 case FORMAT_R8UI:
395 case FORMAT_R16I:
396 case FORMAT_R16UI:
397 case FORMAT_R32I:
398 case FORMAT_R32UI:
399 c.y = As<Float4>(UInt4(0));
400 case FORMAT_G8R8I:
401 case FORMAT_G8R8UI:
402 case FORMAT_G16R16I:
403 case FORMAT_G16R16UI:
404 case FORMAT_G32R32I:
405 case FORMAT_G32R32UI:
406 c.z = As<Float4>(UInt4(0));
407 case FORMAT_X8B8G8R8I:
408 case FORMAT_X8B8G8R8UI:
409 case FORMAT_X16B16G16R16I:
410 case FORMAT_X16B16G16R16UI:
411 case FORMAT_X32B32G32R32I:
412 case FORMAT_X32B32G32R32UI:
413 c.w = As<Float4>(UInt4(1));
414 case FORMAT_A8B8G8R8I:
415 case FORMAT_A8B8G8R8UI:
416 case FORMAT_A16B16G16R16I:
417 case FORMAT_A16B16G16R16UI:
418 case FORMAT_A32B32G32R32I:
419 case FORMAT_A32B32G32R32UI:
420 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500421 case FORMAT_R8_SNORM:
422 case FORMAT_G8R8_SNORM:
423 case FORMAT_X8B8G8R8_SNORM:
424 case FORMAT_A8B8G8R8_SNORM:
John Bauman89401822014-05-06 15:04:28 -0400425 case FORMAT_R8:
Nicolas Capens27496312015-05-12 15:16:06 -0400426 case FORMAT_R5G6B5:
Alexis Hetu3412d872015-10-26 16:40:26 -0400427 case FORMAT_G8R8:
428 case FORMAT_G16R16:
429 case FORMAT_A16B16G16R16:
John Bauman89401822014-05-06 15:04:28 -0400430 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400431 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -0400432 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400433 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400434 case FORMAT_SRGB8_X8:
435 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -0400436 case FORMAT_V8U8:
437 case FORMAT_Q8W8V8U8:
438 case FORMAT_X8L8V8U8:
439 case FORMAT_V16U16:
440 case FORMAT_A16W16V16U16:
441 case FORMAT_Q16W16V16U16:
Nicolas Capens9ada3092017-05-24 17:39:49 -0400442 case FORMAT_YV12_BT601:
443 case FORMAT_YV12_BT709:
444 case FORMAT_YV12_JFIF:
Alexis Hetu56f256e2017-07-21 11:41:13 -0400445 if(componentCount < 2) c.y = Float4(defaultColorValue);
446 if(componentCount < 3) c.z = Float4(defaultColorValue);
John Bauman19bac1e2014-05-06 15:23:49 -0400447 if(componentCount < 4) c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400448 break;
449 case FORMAT_A8:
John Bauman19bac1e2014-05-06 15:23:49 -0400450 c.w = c.x;
451 c.x = Float4(0.0f);
452 c.y = Float4(0.0f);
453 c.z = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -0400454 break;
455 case FORMAT_L8:
456 case FORMAT_L16:
John Bauman19bac1e2014-05-06 15:23:49 -0400457 c.y = c.x;
458 c.z = c.x;
459 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400460 break;
461 case FORMAT_A8L8:
John Bauman19bac1e2014-05-06 15:23:49 -0400462 c.w = c.y;
463 c.y = c.x;
464 c.z = c.x;
John Bauman89401822014-05-06 15:04:28 -0400465 break;
466 case FORMAT_R32F:
Alexis Hetu56f256e2017-07-21 11:41:13 -0400467 c.y = Float4(defaultColorValue);
John Bauman89401822014-05-06 15:04:28 -0400468 case FORMAT_G32R32F:
Alexis Hetu56f256e2017-07-21 11:41:13 -0400469 c.z = Float4(defaultColorValue);
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400470 case FORMAT_X32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -0500471 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman19bac1e2014-05-06 15:23:49 -0400472 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400473 case FORMAT_A32B32G32R32F:
474 break;
Alexis Hetu3412d872015-10-26 16:40:26 -0400475 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500476 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -0400477 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400478 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500479 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -0400480 case FORMAT_D32FS8_SHADOW:
Alexis Hetuab2dd502017-11-16 15:35:59 -0500481 c.y = Float4(0.0f);
482 c.z = Float4(0.0f);
483 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400484 break;
485 default:
486 ASSERT(false);
487 }
488 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400489
Nicolas Capens57642352018-02-27 13:29:26 -0500490 if((state.swizzleR != SWIZZLE_RED) ||
491 (state.swizzleG != SWIZZLE_GREEN) ||
492 (state.swizzleB != SWIZZLE_BLUE) ||
493 (state.swizzleA != SWIZZLE_ALPHA))
494 {
495 const Vector4f col(c);
496 applySwizzle(state.swizzleR, c.x, col);
497 applySwizzle(state.swizzleG, c.y, col);
498 applySwizzle(state.swizzleB, c.z, col);
499 applySwizzle(state.swizzleA, c.w, col);
500 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400501 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500502
503 return c;
John Bauman89401822014-05-06 15:04:28 -0400504 }
505
Nicolas Capens89a218b2017-11-07 13:05:20 -0500506 Vector4f SamplerCore::textureSize(Pointer<Byte> &texture, Float4 &lod)
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400507 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500508 Vector4f size;
509
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400510 for(int i = 0; i < 4; ++i)
511 {
Alexis Hetu95ac1872016-06-06 13:26:52 -0400512 Int baseLevel = *Pointer<Int>(texture + OFFSET(Texture, baseLevel));
513 Pointer<Byte> mipmap = texture + OFFSET(Texture, mipmap) + (As<Int>(Extract(lod, i)) + baseLevel) * sizeof(Mipmap);
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400514 size.x = Insert(size.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
515 size.y = Insert(size.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
516 size.z = Insert(size.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
517 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500518
519 return size;
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400520 }
521
John Bauman89401822014-05-06 15:04:28 -0400522 void SamplerCore::border(Short4 &mask, Float4 &coordinates)
523 {
524 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
Nicolas Capens33438a62017-09-27 11:47:35 -0400525 mask = As<Short4>(Int2(As<Int4>(PackSigned(border, border))));
John Bauman89401822014-05-06 15:04:28 -0400526 }
527
528 void SamplerCore::border(Int4 &mask, Float4 &coordinates)
529 {
530 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
531 }
532
Nicolas Capensb81efca2017-12-19 10:52:14 -0500533 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
John Bauman89401822014-05-06 15:04:28 -0400534 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500535 Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
536
537 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
538 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500539 offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
Nicolas Capens5989fab2016-02-15 10:31:49 -0500540 }
541 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
542 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500543 offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
Nicolas Capens5989fab2016-02-15 10:31:49 -0500544 }
545
John Bauman89401822014-05-06 15:04:28 -0400546 if(wrap)
547 {
548 switch(count)
549 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500550 case -1: return uvw - offset;
John Bauman89401822014-05-06 15:04:28 -0400551 case 0: return uvw;
Nicolas Capens5989fab2016-02-15 10:31:49 -0500552 case +1: return uvw + offset;
553 case 2: return uvw + offset + offset;
John Bauman89401822014-05-06 15:04:28 -0400554 }
555 }
556 else // Clamp or mirror
557 {
558 switch(count)
559 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500560 case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset));
John Bauman89401822014-05-06 15:04:28 -0400561 case 0: return uvw;
Nicolas Capens5989fab2016-02-15 10:31:49 -0500562 case +1: return AddSat(As<UShort4>(uvw), As<UShort4>(offset));
563 case 2: return AddSat(AddSat(As<UShort4>(uvw), As<UShort4>(offset)), As<UShort4>(offset));
John Bauman89401822014-05-06 15:04:28 -0400564 }
565 }
566
567 return uvw;
568 }
569
Nicolas Capens89a218b2017-11-07 13:05:20 -0500570 Vector4s SamplerCore::sampleFilter(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -0400571 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500572 Vector4s c = sampleAniso(texture, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400573
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400574 if(function == Fetch)
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400575 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500576 return c;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400577 }
John Bauman89401822014-05-06 15:04:28 -0400578
Nicolas Capense396a492018-01-02 14:22:23 -0500579 if(state.mipmapFilter == MIPMAP_LINEAR)
John Bauman89401822014-05-06 15:04:28 -0400580 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500581 Vector4s cc = sampleAniso(texture, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
John Bauman89401822014-05-06 15:04:28 -0400582
583 lod *= Float(1 << 16);
584
585 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize
586 Short4 stri = utri >> 1; // FIXME: Optimize
587
John Bauman19bac1e2014-05-06 15:23:49 -0400588 if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri);
589 if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri);
590 if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri);
591 if(hasUnsignedTextureComponent(3)) cc.w = MulHigh(As<UShort4>(cc.w), utri); else cc.w = MulHigh(cc.w, stri);
John Bauman89401822014-05-06 15:04:28 -0400592
593 utri = ~utri;
Alexis Hetu90c7ad62016-06-27 11:50:40 -0400594 stri = Short4(0x7FFF) - stri;
John Bauman89401822014-05-06 15:04:28 -0400595
John Bauman19bac1e2014-05-06 15:23:49 -0400596 if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri);
597 if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri);
598 if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri);
599 if(hasUnsignedTextureComponent(3)) c.w = MulHigh(As<UShort4>(c.w), utri); else c.w = MulHigh(c.w, stri);
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500600
John Bauman19bac1e2014-05-06 15:23:49 -0400601 c.x += cc.x;
602 c.y += cc.y;
603 c.z += cc.z;
604 c.w += cc.w;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500605
John Bauman19bac1e2014-05-06 15:23:49 -0400606 if(!hasUnsignedTextureComponent(0)) c.x += c.x;
607 if(!hasUnsignedTextureComponent(1)) c.y += c.y;
608 if(!hasUnsignedTextureComponent(2)) c.z += c.z;
609 if(!hasUnsignedTextureComponent(3)) c.w += c.w;
John Bauman89401822014-05-06 15:04:28 -0400610 }
611
612 Short4 borderMask;
613
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400614 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400615 {
616 Short4 u0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500617
John Bauman89401822014-05-06 15:04:28 -0400618 border(u0, u);
619
620 borderMask = u0;
621 }
622
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400623 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400624 {
625 Short4 v0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500626
John Bauman89401822014-05-06 15:04:28 -0400627 border(v0, v);
628
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400629 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400630 {
631 borderMask &= v0;
632 }
633 else
634 {
635 borderMask = v0;
636 }
637 }
638
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500639 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400640 {
641 Short4 s0;
642
643 border(s0, w);
644
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400645 if(state.addressingModeU == ADDRESSING_BORDER ||
646 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400647 {
648 borderMask &= s0;
649 }
650 else
651 {
652 borderMask = s0;
653 }
654 }
655
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400656 if(state.addressingModeU == ADDRESSING_BORDER ||
657 state.addressingModeV == ADDRESSING_BORDER ||
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500658 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
John Bauman89401822014-05-06 15:04:28 -0400659 {
660 Short4 b;
661
Tom Anderson69bc6e82017-03-20 11:54:29 -0700662 c.x = (borderMask & c.x) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1)));
663 c.y = (borderMask & c.y) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1)));
664 c.z = (borderMask & c.z) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1)));
665 c.w = (borderMask & c.w) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1)));
John Bauman89401822014-05-06 15:04:28 -0400666 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500667
668 return c;
John Bauman89401822014-05-06 15:04:28 -0400669 }
670
Nicolas Capens89a218b2017-11-07 13:05:20 -0500671 Vector4s SamplerCore::sampleAniso(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -0400672 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500673 Vector4s c;
674
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400675 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
John Bauman89401822014-05-06 15:04:28 -0400676 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500677 c = sampleQuad(texture, u, v, w, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400678 }
679 else
680 {
681 Int a = RoundInt(anisotropy);
682
Alexis Hetu96517182015-04-15 10:30:23 -0400683 Vector4s cSum;
John Bauman89401822014-05-06 15:04:28 -0400684
Alexis Hetu90c7ad62016-06-27 11:50:40 -0400685 cSum.x = Short4(0);
686 cSum.y = Short4(0);
687 cSum.z = Short4(0);
688 cSum.w = Short4(0);
John Bauman89401822014-05-06 15:04:28 -0400689
690 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
691 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
692 UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a);
693 Short4 sw = Short4(cw >> 1);
694
695 Float4 du = uDelta;
696 Float4 dv = vDelta;
697
698 Float4 u0 = u + B * du;
699 Float4 v0 = v + B * dv;
700
701 du *= A;
702 dv *= A;
703
704 Int i = 0;
705
706 Do
707 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500708 c = sampleQuad(texture, u0, v0, w, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400709
710 u0 += du;
711 v0 += dv;
712
John Bauman19bac1e2014-05-06 15:23:49 -0400713 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw);
714 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw);
715 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw);
716 if(hasUnsignedTextureComponent(3)) cSum.w += As<Short4>(MulHigh(As<UShort4>(c.w), cw)); else cSum.w += MulHigh(c.w, sw);
John Bauman89401822014-05-06 15:04:28 -0400717
718 i++;
719 }
720 Until(i >= a)
721
John Bauman19bac1e2014-05-06 15:23:49 -0400722 if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x);
723 if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y);
724 if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z);
725 if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w);
John Bauman89401822014-05-06 15:04:28 -0400726 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500727
728 return c;
John Bauman89401822014-05-06 15:04:28 -0400729 }
730
Nicolas Capens89a218b2017-11-07 13:05:20 -0500731 Vector4s SamplerCore::sampleQuad(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -0400732 {
Alexis Hetuc8b97852016-02-04 21:15:03 -0500733 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400734 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500735 return sampleQuad2D(texture, u, v, w, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400736 }
737 else
738 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500739 return sample3D(texture, u, v, w, offset, lod, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400740 }
741 }
742
Nicolas Capens89a218b2017-11-07 13:05:20 -0500743 Vector4s SamplerCore::sampleQuad2D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -0400744 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500745 Vector4s c;
746
John Bauman89401822014-05-06 15:04:28 -0400747 int componentCount = textureComponentCount();
748 bool gather = state.textureFilter == FILTER_GATHER;
749
750 Pointer<Byte> mipmap;
751 Pointer<Byte> buffer[4];
752
753 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
754
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400755 bool texelFetch = (function == Fetch);
John Bauman89401822014-05-06 15:04:28 -0400756
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400757 Short4 uuuu = texelFetch ? Short4(As<Int4>(u)) : address(u, state.addressingModeU, mipmap);
758 Short4 vvvv = texelFetch ? Short4(As<Int4>(v)) : address(v, state.addressingModeV, mipmap);
759 Short4 wwww = texelFetch ? Short4(As<Int4>(w)) : address(w, state.addressingModeW, mipmap);
760
761 if(state.textureFilter == FILTER_POINT || texelFetch)
John Bauman89401822014-05-06 15:04:28 -0400762 {
Nicolas Capens5790c952017-08-01 17:00:36 -0400763 c = sampleTexel(uuuu, vvvv, wwww, offset, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -0400764 }
765 else
766 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500767 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
768 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
769 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
770 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
John Bauman89401822014-05-06 15:04:28 -0400771
Nicolas Capens5790c952017-08-01 17:00:36 -0400772 Vector4s c0 = sampleTexel(uuuu0, vvvv0, wwww, offset, mipmap, buffer, function);
773 Vector4s c1 = sampleTexel(uuuu1, vvvv0, wwww, offset, mipmap, buffer, function);
774 Vector4s c2 = sampleTexel(uuuu0, vvvv1, wwww, offset, mipmap, buffer, function);
775 Vector4s c3 = sampleTexel(uuuu1, vvvv1, wwww, offset, mipmap, buffer, function);
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500776
John Bauman89401822014-05-06 15:04:28 -0400777 if(!gather) // Blend
778 {
779 // Fractions
Nicolas Capens77980512016-12-02 14:22:32 -0500780 UShort4 f0u = As<UShort4>(uuuu0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
781 UShort4 f0v = As<UShort4>(vvvv0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
John Bauman89401822014-05-06 15:04:28 -0400782
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400783 UShort4 f1u = ~f0u;
784 UShort4 f1v = ~f0v;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500785
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400786 UShort4 f0u0v = MulHigh(f0u, f0v);
787 UShort4 f1u0v = MulHigh(f1u, f0v);
788 UShort4 f0u1v = MulHigh(f0u, f1v);
789 UShort4 f1u1v = MulHigh(f1u, f1v);
John Bauman89401822014-05-06 15:04:28 -0400790
791 // Signed fractions
792 Short4 f1u1vs;
793 Short4 f0u1vs;
794 Short4 f1u0vs;
795 Short4 f0u0vs;
796
797 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
798 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400799 f1u1vs = f1u1v >> 1;
800 f0u1vs = f0u1v >> 1;
801 f1u0vs = f1u0v >> 1;
802 f0u0vs = f0u0v >> 1;
John Bauman89401822014-05-06 15:04:28 -0400803 }
804
805 // Bilinear interpolation
806 if(componentCount >= 1)
807 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400808 if(has16bitTextureComponents() && hasUnsignedTextureComponent(0))
John Bauman89401822014-05-06 15:04:28 -0400809 {
John Bauman19bac1e2014-05-06 15:23:49 -0400810 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u);
811 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u);
812 c.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0v) + MulHigh(As<UShort4>(c2.x), f0v);
John Bauman89401822014-05-06 15:04:28 -0400813 }
814 else
815 {
816 if(hasUnsignedTextureComponent(0))
817 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400818 c0.x = MulHigh(As<UShort4>(c0.x), f1u1v);
819 c1.x = MulHigh(As<UShort4>(c1.x), f0u1v);
820 c2.x = MulHigh(As<UShort4>(c2.x), f1u0v);
821 c3.x = MulHigh(As<UShort4>(c3.x), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400822 }
823 else
824 {
John Bauman19bac1e2014-05-06 15:23:49 -0400825 c0.x = MulHigh(c0.x, f1u1vs);
826 c1.x = MulHigh(c1.x, f0u1vs);
827 c2.x = MulHigh(c2.x, f1u0vs);
828 c3.x = MulHigh(c3.x, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400829 }
830
John Bauman19bac1e2014-05-06 15:23:49 -0400831 c.x = (c0.x + c1.x) + (c2.x + c3.x);
832 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400833 }
834 }
835
836 if(componentCount >= 2)
837 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400838 if(has16bitTextureComponents() && hasUnsignedTextureComponent(1))
John Bauman89401822014-05-06 15:04:28 -0400839 {
John Bauman19bac1e2014-05-06 15:23:49 -0400840 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u);
841 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u);
842 c.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0v) + MulHigh(As<UShort4>(c2.y), f0v);
John Bauman89401822014-05-06 15:04:28 -0400843 }
844 else
845 {
846 if(hasUnsignedTextureComponent(1))
847 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400848 c0.y = MulHigh(As<UShort4>(c0.y), f1u1v);
849 c1.y = MulHigh(As<UShort4>(c1.y), f0u1v);
850 c2.y = MulHigh(As<UShort4>(c2.y), f1u0v);
851 c3.y = MulHigh(As<UShort4>(c3.y), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400852 }
853 else
854 {
John Bauman19bac1e2014-05-06 15:23:49 -0400855 c0.y = MulHigh(c0.y, f1u1vs);
856 c1.y = MulHigh(c1.y, f0u1vs);
857 c2.y = MulHigh(c2.y, f1u0vs);
858 c3.y = MulHigh(c3.y, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400859 }
860
John Bauman19bac1e2014-05-06 15:23:49 -0400861 c.y = (c0.y + c1.y) + (c2.y + c3.y);
862 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400863 }
864 }
865
866 if(componentCount >= 3)
867 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400868 if(has16bitTextureComponents() && hasUnsignedTextureComponent(2))
John Bauman89401822014-05-06 15:04:28 -0400869 {
John Bauman19bac1e2014-05-06 15:23:49 -0400870 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u);
871 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u);
872 c.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0v) + MulHigh(As<UShort4>(c2.z), f0v);
John Bauman89401822014-05-06 15:04:28 -0400873 }
874 else
875 {
876 if(hasUnsignedTextureComponent(2))
877 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400878 c0.z = MulHigh(As<UShort4>(c0.z), f1u1v);
879 c1.z = MulHigh(As<UShort4>(c1.z), f0u1v);
880 c2.z = MulHigh(As<UShort4>(c2.z), f1u0v);
881 c3.z = MulHigh(As<UShort4>(c3.z), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400882 }
883 else
884 {
John Bauman19bac1e2014-05-06 15:23:49 -0400885 c0.z = MulHigh(c0.z, f1u1vs);
886 c1.z = MulHigh(c1.z, f0u1vs);
887 c2.z = MulHigh(c2.z, f1u0vs);
888 c3.z = MulHigh(c3.z, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400889 }
890
John Bauman19bac1e2014-05-06 15:23:49 -0400891 c.z = (c0.z + c1.z) + (c2.z + c3.z);
892 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400893 }
894 }
895
896 if(componentCount >= 4)
897 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400898 if(has16bitTextureComponents() && hasUnsignedTextureComponent(3))
John Bauman89401822014-05-06 15:04:28 -0400899 {
John Bauman19bac1e2014-05-06 15:23:49 -0400900 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u);
901 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u);
902 c.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0v) + MulHigh(As<UShort4>(c2.w), f0v);
John Bauman89401822014-05-06 15:04:28 -0400903 }
904 else
905 {
906 if(hasUnsignedTextureComponent(3))
907 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400908 c0.w = MulHigh(As<UShort4>(c0.w), f1u1v);
909 c1.w = MulHigh(As<UShort4>(c1.w), f0u1v);
910 c2.w = MulHigh(As<UShort4>(c2.w), f1u0v);
911 c3.w = MulHigh(As<UShort4>(c3.w), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400912 }
913 else
914 {
John Bauman19bac1e2014-05-06 15:23:49 -0400915 c0.w = MulHigh(c0.w, f1u1vs);
916 c1.w = MulHigh(c1.w, f0u1vs);
917 c2.w = MulHigh(c2.w, f1u0vs);
918 c3.w = MulHigh(c3.w, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400919 }
920
John Bauman19bac1e2014-05-06 15:23:49 -0400921 c.w = (c0.w + c1.w) + (c2.w + c3.w);
922 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400923 }
924 }
925 }
926 else
927 {
John Bauman19bac1e2014-05-06 15:23:49 -0400928 c.x = c1.x;
929 c.y = c2.x;
930 c.z = c3.x;
931 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -0400932 }
933 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500934
935 return c;
John Bauman89401822014-05-06 15:04:28 -0400936 }
937
Nicolas Capens89a218b2017-11-07 13:05:20 -0500938 Vector4s SamplerCore::sample3D(Pointer<Byte> &texture, Float4 &u_, Float4 &v_, Float4 &w_, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -0400939 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500940 Vector4s c_;
941
John Bauman89401822014-05-06 15:04:28 -0400942 int componentCount = textureComponentCount();
943
944 Pointer<Byte> mipmap;
945 Pointer<Byte> buffer[4];
946 Int face[4];
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500947
John Bauman89401822014-05-06 15:04:28 -0400948 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
949
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400950 bool texelFetch = (function == Fetch);
John Bauman89401822014-05-06 15:04:28 -0400951
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400952 Short4 uuuu = texelFetch ? Short4(As<Int4>(u_)) : address(u_, state.addressingModeU, mipmap);
953 Short4 vvvv = texelFetch ? Short4(As<Int4>(v_)) : address(v_, state.addressingModeV, mipmap);
954 Short4 wwww = texelFetch ? Short4(As<Int4>(w_)) : address(w_, state.addressingModeW, mipmap);
955
956 if(state.textureFilter == FILTER_POINT || texelFetch)
John Bauman89401822014-05-06 15:04:28 -0400957 {
Nicolas Capens5790c952017-08-01 17:00:36 -0400958 c_ = sampleTexel(uuuu, vvvv, wwww, offset, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -0400959 }
960 else
961 {
Alexis Hetu96517182015-04-15 10:30:23 -0400962 Vector4s c[2][2][2];
John Bauman89401822014-05-06 15:04:28 -0400963
964 Short4 u[2][2][2];
965 Short4 v[2][2][2];
966 Short4 s[2][2][2];
967
968 for(int i = 0; i < 2; i++)
969 {
970 for(int j = 0; j < 2; j++)
971 {
972 for(int k = 0; k < 2; k++)
973 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500974 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
975 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
976 s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
John Bauman89401822014-05-06 15:04:28 -0400977 }
978 }
979 }
980
John Bauman89401822014-05-06 15:04:28 -0400981 // Fractions
Nicolas Capens77980512016-12-02 14:22:32 -0500982 UShort4 f0u = As<UShort4>(u[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
983 UShort4 f0v = As<UShort4>(v[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
984 UShort4 f0s = As<UShort4>(s[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth));
John Bauman89401822014-05-06 15:04:28 -0400985
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400986 UShort4 f1u = ~f0u;
987 UShort4 f1v = ~f0v;
988 UShort4 f1s = ~f0s;
John Bauman89401822014-05-06 15:04:28 -0400989
Nicolas Capens77980512016-12-02 14:22:32 -0500990 UShort4 f[2][2][2];
991 Short4 fs[2][2][2];
992
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400993 f[1][1][1] = MulHigh(f1u, f1v);
994 f[0][1][1] = MulHigh(f0u, f1v);
995 f[1][0][1] = MulHigh(f1u, f0v);
996 f[0][0][1] = MulHigh(f0u, f0v);
997 f[1][1][0] = MulHigh(f1u, f1v);
998 f[0][1][0] = MulHigh(f0u, f1v);
999 f[1][0][0] = MulHigh(f1u, f0v);
1000 f[0][0][0] = MulHigh(f0u, f0v);
John Bauman89401822014-05-06 15:04:28 -04001001
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001002 f[1][1][1] = MulHigh(f[1][1][1], f1s);
1003 f[0][1][1] = MulHigh(f[0][1][1], f1s);
1004 f[1][0][1] = MulHigh(f[1][0][1], f1s);
1005 f[0][0][1] = MulHigh(f[0][0][1], f1s);
1006 f[1][1][0] = MulHigh(f[1][1][0], f0s);
1007 f[0][1][0] = MulHigh(f[0][1][0], f0s);
1008 f[1][0][0] = MulHigh(f[1][0][0], f0s);
1009 f[0][0][0] = MulHigh(f[0][0][0], f0s);
John Bauman89401822014-05-06 15:04:28 -04001010
1011 // Signed fractions
1012 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
1013 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001014 fs[0][0][0] = f[0][0][0] >> 1;
1015 fs[0][0][1] = f[0][0][1] >> 1;
1016 fs[0][1][0] = f[0][1][0] >> 1;
1017 fs[0][1][1] = f[0][1][1] >> 1;
1018 fs[1][0][0] = f[1][0][0] >> 1;
1019 fs[1][0][1] = f[1][0][1] >> 1;
1020 fs[1][1][0] = f[1][1][0] >> 1;
1021 fs[1][1][1] = f[1][1][1] >> 1;
John Bauman89401822014-05-06 15:04:28 -04001022 }
1023
1024 for(int i = 0; i < 2; i++)
1025 {
1026 for(int j = 0; j < 2; j++)
1027 {
1028 for(int k = 0; k < 2; k++)
1029 {
Nicolas Capens5790c952017-08-01 17:00:36 -04001030 c[i][j][k] = sampleTexel(u[i][j][k], v[i][j][k], s[i][j][k], offset, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001031
Alexis Hetu0085c442015-06-12 15:19:20 -04001032 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]); }
1033 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]); }
1034 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]); }
1035 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]); }
John Bauman89401822014-05-06 15:04:28 -04001036
1037 if(i != 0 || j != 0 || k != 0)
1038 {
John Bauman19bac1e2014-05-06 15:23:49 -04001039 if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x;
1040 if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y;
1041 if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z;
1042 if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w;
John Bauman89401822014-05-06 15:04:28 -04001043 }
1044 }
1045 }
1046 }
1047
John Bauman19bac1e2014-05-06 15:23:49 -04001048 if(componentCount >= 1) c_.x = c[0][0][0].x;
1049 if(componentCount >= 2) c_.y = c[0][0][0].y;
1050 if(componentCount >= 3) c_.z = c[0][0][0].z;
1051 if(componentCount >= 4) c_.w = c[0][0][0].w;
John Bauman89401822014-05-06 15:04:28 -04001052
1053 // Correct for signed fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001054 if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x);
1055 if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y);
1056 if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z);
1057 if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w);
John Bauman89401822014-05-06 15:04:28 -04001058 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001059
1060 return c_;
John Bauman89401822014-05-06 15:04:28 -04001061 }
1062
Nicolas Capensa0b57832017-11-07 13:07:53 -05001063 Vector4f SamplerCore::sampleFloatFilter(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001064 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001065 Vector4f c = sampleFloatAniso(texture, u, v, w, q, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001066
1067 if(function == Fetch)
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001068 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001069 return c;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001070 }
John Bauman89401822014-05-06 15:04:28 -04001071
Nicolas Capense396a492018-01-02 14:22:23 -05001072 if(state.mipmapFilter == MIPMAP_LINEAR)
John Bauman89401822014-05-06 15:04:28 -04001073 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001074 Vector4f cc = sampleFloatAniso(texture, u, v, w, q, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
John Bauman89401822014-05-06 15:04:28 -04001075
John Bauman19bac1e2014-05-06 15:23:49 -04001076 Float4 lod4 = Float4(Frac(lod));
John Bauman89401822014-05-06 15:04:28 -04001077
John Bauman19bac1e2014-05-06 15:23:49 -04001078 c.x = (cc.x - c.x) * lod4 + c.x;
1079 c.y = (cc.y - c.y) * lod4 + c.y;
1080 c.z = (cc.z - c.z) * lod4 + c.z;
1081 c.w = (cc.w - c.w) * lod4 + c.w;
John Bauman89401822014-05-06 15:04:28 -04001082 }
1083
1084 Int4 borderMask;
1085
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001086 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001087 {
1088 Int4 u0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001089
John Bauman89401822014-05-06 15:04:28 -04001090 border(u0, u);
1091
1092 borderMask = u0;
1093 }
1094
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001095 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001096 {
1097 Int4 v0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001098
John Bauman89401822014-05-06 15:04:28 -04001099 border(v0, v);
1100
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001101 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001102 {
1103 borderMask &= v0;
1104 }
1105 else
1106 {
1107 borderMask = v0;
1108 }
1109 }
1110
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001111 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -04001112 {
1113 Int4 s0;
1114
1115 border(s0, w);
1116
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001117 if(state.addressingModeU == ADDRESSING_BORDER ||
1118 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001119 {
1120 borderMask &= s0;
1121 }
1122 else
1123 {
1124 borderMask = s0;
1125 }
1126 }
1127
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001128 if(state.addressingModeU == ADDRESSING_BORDER ||
1129 state.addressingModeV == ADDRESSING_BORDER ||
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001130 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
John Bauman89401822014-05-06 15:04:28 -04001131 {
1132 Int4 b;
1133
Tom Anderson69bc6e82017-03-20 11:54:29 -07001134 c.x = As<Float4>((borderMask & As<Int4>(c.x)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0]))));
1135 c.y = As<Float4>((borderMask & As<Int4>(c.y)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1]))));
1136 c.z = As<Float4>((borderMask & As<Int4>(c.z)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2]))));
1137 c.w = As<Float4>((borderMask & As<Int4>(c.w)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3]))));
John Bauman89401822014-05-06 15:04:28 -04001138 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001139
1140 return c;
John Bauman89401822014-05-06 15:04:28 -04001141 }
1142
Nicolas Capensa0b57832017-11-07 13:07:53 -05001143 Vector4f SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &offset, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001144 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001145 Vector4f c;
1146
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001147 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
John Bauman89401822014-05-06 15:04:28 -04001148 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001149 c = sampleFloat(texture, u, v, w, q, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001150 }
1151 else
1152 {
1153 Int a = RoundInt(anisotropy);
1154
John Bauman19bac1e2014-05-06 15:23:49 -04001155 Vector4f cSum;
John Bauman89401822014-05-06 15:04:28 -04001156
John Bauman19bac1e2014-05-06 15:23:49 -04001157 cSum.x = Float4(0.0f);
1158 cSum.y = Float4(0.0f);
1159 cSum.z = Float4(0.0f);
1160 cSum.w = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -04001161
1162 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
1163 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
1164
1165 Float4 du = uDelta;
1166 Float4 dv = vDelta;
1167
1168 Float4 u0 = u + B * du;
1169 Float4 v0 = v + B * dv;
1170
1171 du *= A;
1172 dv *= A;
1173
1174 Int i = 0;
1175
1176 Do
1177 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001178 c = sampleFloat(texture, u0, v0, w, q, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001179
1180 u0 += du;
1181 v0 += dv;
1182
John Bauman19bac1e2014-05-06 15:23:49 -04001183 cSum.x += c.x * A;
1184 cSum.y += c.y * A;
1185 cSum.z += c.z * A;
1186 cSum.w += c.w * A;
John Bauman89401822014-05-06 15:04:28 -04001187
1188 i++;
1189 }
1190 Until(i >= a)
1191
John Bauman19bac1e2014-05-06 15:23:49 -04001192 c.x = cSum.x;
1193 c.y = cSum.y;
1194 c.z = cSum.z;
1195 c.w = cSum.w;
John Bauman89401822014-05-06 15:04:28 -04001196 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001197
1198 return c;
John Bauman89401822014-05-06 15:04:28 -04001199 }
1200
Nicolas Capensa0b57832017-11-07 13:07:53 -05001201 Vector4f SamplerCore::sampleFloat(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001202 {
Alexis Hetuc8b97852016-02-04 21:15:03 -05001203 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -04001204 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001205 return sampleFloat2D(texture, u, v, w, q, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001206 }
1207 else
1208 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001209 return sampleFloat3D(texture, u, v, w, offset, lod, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001210 }
1211 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001212
Nicolas Capensa0b57832017-11-07 13:07:53 -05001213 Vector4f SamplerCore::sampleFloat2D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &offset, Float &lod, Int face[4], bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001214 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001215 Vector4f c;
1216
John Bauman89401822014-05-06 15:04:28 -04001217 int componentCount = textureComponentCount();
1218 bool gather = state.textureFilter == FILTER_GATHER;
1219
1220 Pointer<Byte> mipmap;
1221 Pointer<Byte> buffer[4];
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001222
John Bauman89401822014-05-06 15:04:28 -04001223 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1224
Alexis Hetu75a61852017-07-14 14:17:14 -04001225 Int4 x0, x1, y0, y1, z0;
1226 Float4 fu, fv;
Nicolas Capensb81efca2017-12-19 10:52:14 -05001227 Int4 filter = computeFilterOffset(lod);
Alexis Hetu75a61852017-07-14 14:17:14 -04001228 address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
Nicolas Capensf8b827e2017-11-27 15:25:05 -05001229 address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
1230 address(w, z0, z0, fv, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
John Bauman89401822014-05-06 15:04:28 -04001231
Alexis Hetu75a61852017-07-14 14:17:14 -04001232 Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16);
1233 y0 *= pitchP;
1234 if(hasThirdCoordinate())
John Bauman89401822014-05-06 15:04:28 -04001235 {
Alexis Hetu75a61852017-07-14 14:17:14 -04001236 Int4 sliceP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, sliceP), 16);
1237 z0 *= sliceP;
1238 }
1239
1240 if(state.textureFilter == FILTER_POINT || (function == Fetch))
1241 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001242 c = sampleTexel(x0, y0, z0, q, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001243 }
1244 else
1245 {
Alexis Hetu75a61852017-07-14 14:17:14 -04001246 y1 *= pitchP;
John Bauman89401822014-05-06 15:04:28 -04001247
Nicolas Capensa0b57832017-11-07 13:07:53 -05001248 Vector4f c0 = sampleTexel(x0, y0, z0, q, mipmap, buffer, function);
1249 Vector4f c1 = sampleTexel(x1, y0, z0, q, mipmap, buffer, function);
1250 Vector4f c2 = sampleTexel(x0, y1, z0, q, mipmap, buffer, function);
1251 Vector4f c3 = sampleTexel(x1, y1, z0, q, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001252
1253 if(!gather) // Blend
1254 {
John Bauman19bac1e2014-05-06 15:23:49 -04001255 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1256 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1257 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1258 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001259
John Bauman19bac1e2014-05-06 15:23:49 -04001260 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1261 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1262 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1263 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001264
John Bauman19bac1e2014-05-06 15:23:49 -04001265 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x);
1266 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y);
1267 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z);
1268 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001269 }
1270 else
1271 {
John Bauman19bac1e2014-05-06 15:23:49 -04001272 c.x = c1.x;
1273 c.y = c2.x;
1274 c.z = c3.x;
1275 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -04001276 }
1277 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001278
1279 return c;
John Bauman89401822014-05-06 15:04:28 -04001280 }
1281
Nicolas Capens89a218b2017-11-07 13:05:20 -05001282 Vector4f SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001283 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001284 Vector4f c;
1285
John Bauman89401822014-05-06 15:04:28 -04001286 int componentCount = textureComponentCount();
1287
1288 Pointer<Byte> mipmap;
1289 Pointer<Byte> buffer[4];
1290 Int face[4];
1291
1292 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1293
Alexis Hetu75a61852017-07-14 14:17:14 -04001294 Int4 x0, x1, y0, y1, z0, z1;
1295 Float4 fu, fv, fw;
Nicolas Capensb81efca2017-12-19 10:52:14 -05001296 Int4 filter = computeFilterOffset(lod);
Alexis Hetu75a61852017-07-14 14:17:14 -04001297 address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
1298 address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
1299 address(w, z0, z1, fw, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
John Bauman89401822014-05-06 15:04:28 -04001300
Alexis Hetu75a61852017-07-14 14:17:14 -04001301 Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16);
1302 Int4 sliceP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, sliceP), 16);
1303 y0 *= pitchP;
1304 z0 *= sliceP;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001305
Alexis Hetu75a61852017-07-14 14:17:14 -04001306 if(state.textureFilter == FILTER_POINT || (function == Fetch))
John Bauman89401822014-05-06 15:04:28 -04001307 {
Nicolas Capens5790c952017-08-01 17:00:36 -04001308 c = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001309 }
1310 else
1311 {
Alexis Hetu75a61852017-07-14 14:17:14 -04001312 y1 *= pitchP;
1313 z1 *= sliceP;
John Bauman89401822014-05-06 15:04:28 -04001314
Nicolas Capens5790c952017-08-01 17:00:36 -04001315 Vector4f c0 = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
1316 Vector4f c1 = sampleTexel(x1, y0, z0, w, mipmap, buffer, function);
1317 Vector4f c2 = sampleTexel(x0, y1, z0, w, mipmap, buffer, function);
1318 Vector4f c3 = sampleTexel(x1, y1, z0, w, mipmap, buffer, function);
1319 Vector4f c4 = sampleTexel(x0, y0, z1, w, mipmap, buffer, function);
1320 Vector4f c5 = sampleTexel(x1, y0, z1, w, mipmap, buffer, function);
1321 Vector4f c6 = sampleTexel(x0, y1, z1, w, mipmap, buffer, function);
1322 Vector4f c7 = sampleTexel(x1, y1, z1, w, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001323
1324 // Blend first slice
John Bauman19bac1e2014-05-06 15:23:49 -04001325 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1326 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1327 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1328 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001329
John Bauman19bac1e2014-05-06 15:23:49 -04001330 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1331 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1332 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1333 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001334
John Bauman19bac1e2014-05-06 15:23:49 -04001335 if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x);
1336 if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y);
1337 if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z);
1338 if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001339
1340 // Blend second slice
John Bauman19bac1e2014-05-06 15:23:49 -04001341 if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x);
1342 if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y);
1343 if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z);
1344 if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001345
John Bauman19bac1e2014-05-06 15:23:49 -04001346 if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x);
1347 if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y);
1348 if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z);
1349 if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w);
John Bauman89401822014-05-06 15:04:28 -04001350
John Bauman19bac1e2014-05-06 15:23:49 -04001351 if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x);
1352 if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y);
1353 if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z);
1354 if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001355
1356 // Blend slices
Nicolas Capens5790c952017-08-01 17:00:36 -04001357 if(componentCount >= 1) c.x = c0.x + fw * (c4.x - c0.x);
1358 if(componentCount >= 2) c.y = c0.y + fw * (c4.y - c0.y);
1359 if(componentCount >= 3) c.z = c0.z + fw * (c4.z - c0.z);
1360 if(componentCount >= 4) c.w = c0.w + fw * (c4.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001361 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001362
1363 return c;
John Bauman89401822014-05-06 15:04:28 -04001364 }
1365
Nicolas Capens6e744262017-07-07 12:46:21 -04001366 Float SamplerCore::log2sqrt(Float lod)
1367 {
1368 // log2(sqrt(lod)) // Equals 0.25 * log2(lod^2).
1369 lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
1370 lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
1371 lod *= As<Float>(Int(0x33000000)); // Scale by 0.25 * 2^-23 (mantissa length).
1372
1373 return lod;
1374 }
1375
Nicolas Capens823c1c12017-11-22 15:06:58 -05001376 Float SamplerCore::log2(Float lod)
1377 {
1378 lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
1379 lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
1380 lod *= As<Float>(Int(0x33800000)); // Scale by 0.5 * 2^-23 (mantissa length).
1381
1382 return lod;
1383 }
1384
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001385 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)
John Bauman89401822014-05-06 15:04:28 -04001386 {
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001387 if(function != Lod && function != Fetch)
John Bauman89401822014-05-06 15:04:28 -04001388 {
1389 Float4 duvdxy;
1390
Nicolas Capens161a76e2017-11-24 10:10:22 -05001391 if(function != Grad) // Implicit
John Bauman89401822014-05-06 15:04:28 -04001392 {
1393 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1394 }
1395 else
1396 {
1397 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1398 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001399
John Bauman89401822014-05-06 15:04:28 -04001400 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1401 }
1402
Nicolas Capens823c1c12017-11-22 15:06:58 -05001403 // Scale by texture dimensions and global LOD.
John Bauman89401822014-05-06 15:04:28 -04001404 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1405
1406 Float4 dUV2dxy = dUVdxy * dUVdxy;
1407 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1408
1409 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1410
1411 if(state.textureFilter == FILTER_ANISOTROPIC)
1412 {
1413 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1414
1415 Float4 dudx = duvdxy.xxxx;
1416 Float4 dudy = duvdxy.yyyy;
1417 Float4 dvdx = duvdxy.zzzz;
1418 Float4 dvdy = duvdxy.wwww;
1419
1420 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
Tom Anderson69bc6e82017-03-20 11:54:29 -07001421 uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
1422 vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
John Bauman89401822014-05-06 15:04:28 -04001423
1424 anisotropy = lod * Rcp_pp(det);
1425 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1426
1427 lod *= Rcp_pp(anisotropy * anisotropy);
1428 }
1429
Nicolas Capens6e744262017-07-07 12:46:21 -04001430 lod = log2sqrt(lod); // log2(sqrt(lod))
John Bauman89401822014-05-06 15:04:28 -04001431
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001432 if(function == Bias)
John Bauman89401822014-05-06 15:04:28 -04001433 {
1434 lod += lodBias;
1435 }
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001436 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001437 else if(function == Lod)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001438 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001439 lod = lodBias;
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001440 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001441 else if(function == Fetch)
1442 {
1443 // TODO: Eliminate int-float-int conversion.
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001444 lod = Float(As<Int>(lodBias));
Nicolas Capensa0b57832017-11-07 13:07:53 -05001445 }
1446 else if(function == Base)
1447 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001448 lod = Float(0);
Nicolas Capensa0b57832017-11-07 13:07:53 -05001449 }
1450 else assert(false);
John Bauman89401822014-05-06 15:04:28 -04001451
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001452 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1453 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001454 }
1455
Nicolas Capens77f0b682017-11-07 13:25:09 -05001456 void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001457 {
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001458 if(function != Lod && function != Fetch)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001459 {
Nicolas Capens77f0b682017-11-07 13:25:09 -05001460 Float4 dudxy, dvdxy, dsdxy;
1461
Nicolas Capens161a76e2017-11-24 10:10:22 -05001462 if(function != Grad) // Implicit
John Bauman89401822014-05-06 15:04:28 -04001463 {
Nicolas Capens77f0b682017-11-07 13:25:09 -05001464 Float4 U = u * M;
1465 Float4 V = v * M;
1466 Float4 W = w * M;
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001467
Nicolas Capens823c1c12017-11-22 15:06:58 -05001468 dudxy = Abs(U - U.xxxx);
1469 dvdxy = Abs(V - V.xxxx);
1470 dsdxy = Abs(W - W.xxxx);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001471 }
1472 else
1473 {
Nicolas Capens77f0b682017-11-07 13:25:09 -05001474 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1475 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1476 dsdxy = Float4(dsx.z.xx, dsy.z.xx);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001477
Nicolas Capens823c1c12017-11-22 15:06:58 -05001478 dudxy = Abs(dudxy * Float4(M.x));
1479 dvdxy = Abs(dvdxy * Float4(M.x));
1480 dsdxy = Abs(dsdxy * Float4(M.x));
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001481 }
1482
Nicolas Capens823c1c12017-11-22 15:06:58 -05001483 // Compute the largest Manhattan distance in two dimensions.
1484 // This takes the footprint across adjacent faces into account.
1485 Float4 duvdxy = dudxy + dvdxy;
1486 Float4 dusdxy = dudxy + dsdxy;
1487 Float4 dvsdxy = dvdxy + dsdxy;
Nicolas Capens77f0b682017-11-07 13:25:09 -05001488
Nicolas Capens823c1c12017-11-22 15:06:58 -05001489 dudxy = Max(Max(duvdxy, dusdxy), dvsdxy);
Nicolas Capens77f0b682017-11-07 13:25:09 -05001490
Nicolas Capens161a76e2017-11-24 10:10:22 -05001491 lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z);
Nicolas Capens77f0b682017-11-07 13:25:09 -05001492
Nicolas Capens823c1c12017-11-22 15:06:58 -05001493 // Scale by texture dimension and global LOD.
1494 lod *= *Pointer<Float>(texture + OFFSET(Texture,widthLOD));
1495
1496 lod = log2(lod);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001497
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001498 if(function == Bias)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001499 {
1500 lod += lodBias;
John Bauman89401822014-05-06 15:04:28 -04001501 }
1502 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001503 else if(function == Lod)
John Bauman89401822014-05-06 15:04:28 -04001504 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001505 lod = lodBias;
John Bauman89401822014-05-06 15:04:28 -04001506 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001507 else if(function == Fetch)
1508 {
1509 // TODO: Eliminate int-float-int conversion.
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001510 lod = Float(As<Int>(lodBias));
Nicolas Capensa0b57832017-11-07 13:07:53 -05001511 }
1512 else if(function == Base)
1513 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001514 lod = Float(0);
Nicolas Capensa0b57832017-11-07 13:07:53 -05001515 }
1516 else assert(false);
John Bauman89401822014-05-06 15:04:28 -04001517
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001518 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1519 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
John Bauman89401822014-05-06 15:04:28 -04001520 }
1521
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001522 void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001523 {
Nicolas Capense396a492018-01-02 14:22:23 -05001524 if(function != Lod && function != Fetch)
John Bauman89401822014-05-06 15:04:28 -04001525 {
Nicolas Capense396a492018-01-02 14:22:23 -05001526 Float4 dudxy, dvdxy, dsdxy;
1527
1528 if(function != Grad) // Implicit
1529 {
1530 dudxy = uuuu - uuuu.xxxx;
1531 dvdxy = vvvv - vvvv.xxxx;
1532 dsdxy = wwww - wwww.xxxx;
1533 }
1534 else
1535 {
1536 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1537 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1538 dsdxy = Float4(dsx.z.xx, dsy.z.xx);
1539 }
1540
1541 // Scale by texture dimensions and global LOD.
1542 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1543 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
1544 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
1545
1546 dudxy *= dudxy;
1547 dvdxy *= dvdxy;
1548 dsdxy *= dsdxy;
1549
1550 dudxy += dvdxy;
1551 dudxy += dsdxy;
1552
1553 lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z);
1554
1555 lod = log2sqrt(lod); // log2(sqrt(lod))
1556
1557 if(function == Bias)
1558 {
1559 lod += lodBias;
1560 }
John Bauman89401822014-05-06 15:04:28 -04001561 }
Nicolas Capense396a492018-01-02 14:22:23 -05001562 else if(function == Lod)
John Bauman89401822014-05-06 15:04:28 -04001563 {
Nicolas Capense396a492018-01-02 14:22:23 -05001564 lod = lodBias;
John Bauman89401822014-05-06 15:04:28 -04001565 }
Nicolas Capense396a492018-01-02 14:22:23 -05001566 else if(function == Fetch)
1567 {
1568 // TODO: Eliminate int-float-int conversion.
1569 lod = Float(As<Int>(lodBias));
1570 }
1571 else if(function == Base)
1572 {
1573 lod = Float(0);
1574 }
1575 else assert(false);
1576
1577 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1578 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
John Bauman89401822014-05-06 15:04:28 -04001579 }
1580
Nicolas Capens77f0b682017-11-07 13:25:09 -05001581 void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M)
John Bauman89401822014-05-06 15:04:28 -04001582 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001583 Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0
1584 Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0
1585 Int4 zn = CmpLT(z, Float4(0.0f)); // z < 0
John Bauman89401822014-05-06 15:04:28 -04001586
1587 Float4 absX = Abs(x);
1588 Float4 absY = Abs(y);
1589 Float4 absZ = Abs(z);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001590
John Bauman89401822014-05-06 15:04:28 -04001591 Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y)
1592 Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z)
1593 Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001594 Int4 xMajor = xy & ~zx; // abs(x) > abs(y) && abs(x) > abs(z)
1595 Int4 yMajor = yz & ~xy; // abs(y) > abs(z) && abs(y) > abs(x)
1596 Int4 zMajor = zx & ~yz; // abs(z) > abs(x) && abs(z) > abs(y)
John Bauman89401822014-05-06 15:04:28 -04001597
1598 // FACE_POSITIVE_X = 000b
1599 // FACE_NEGATIVE_X = 001b
1600 // FACE_POSITIVE_Y = 010b
1601 // FACE_NEGATIVE_Y = 011b
1602 // FACE_POSITIVE_Z = 100b
1603 // FACE_NEGATIVE_Z = 101b
1604
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001605 Int yAxis = SignMask(yMajor);
1606 Int zAxis = SignMask(zMajor);
John Bauman89401822014-05-06 15:04:28 -04001607
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001608 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
John Bauman89401822014-05-06 15:04:28 -04001609 Int negative = SignMask(n);
1610
1611 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
1612 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4);
1613 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4);
1614 face[1] = (face[0] >> 4) & 0x7;
1615 face[2] = (face[0] >> 8) & 0x7;
1616 face[3] = (face[0] >> 12) & 0x7;
1617 face[0] &= 0x7;
1618
Nicolas Capens77f0b682017-11-07 13:25:09 -05001619 M = Max(Max(absX, absY), absZ);
John Bauman89401822014-05-06 15:04:28 -04001620
Nicolas Capensd0f5d392017-11-28 15:54:59 -05001621 // U = xMajor ? (neg ^ -z) : ((zMajor & neg) ^ x)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001622 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
John Bauman89401822014-05-06 15:04:28 -04001623
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001624 // V = !yMajor ? -y : (n ^ z)
1625 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001626
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001627 M = reciprocal(M) * Float4(0.5f);
1628 U = U * M + Float4(0.5f);
1629 V = V * M + Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -04001630 }
1631
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001632 Short4 SamplerCore::applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode)
1633 {
1634 Int4 tmp = Int4(As<UShort4>(uvw));
1635 tmp = tmp + As<Int4>(offset);
1636
Nicolas Capens89a218b2017-11-07 13:05:20 -05001637 switch(mode)
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001638 {
1639 case AddressingMode::ADDRESSING_WRAP:
1640 tmp = (tmp + whd * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % whd;
1641 break;
1642 case AddressingMode::ADDRESSING_CLAMP:
1643 case AddressingMode::ADDRESSING_MIRROR:
1644 case AddressingMode::ADDRESSING_MIRRORONCE:
1645 case AddressingMode::ADDRESSING_BORDER: // FIXME: Implement and test ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, ADDRESSING_BORDER
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001646 tmp = Min(Max(tmp, Int4(0)), whd - Int4(1));
1647 break;
1648 case ADDRESSING_TEXELFETCH:
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001649 break;
Nicolas Capensd0f5d392017-11-28 15:54:59 -05001650 case AddressingMode::ADDRESSING_SEAMLESS:
1651 ASSERT(false); // Cube sampling doesn't support offset.
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001652 default:
1653 ASSERT(false);
1654 }
1655
1656 return As<Short4>(UShort4(tmp));
1657 }
1658
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001659 void SamplerCore::computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04001660 {
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001661 bool texelFetch = (function == Fetch);
1662 bool hasOffset = (function.option == Offset);
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001663
Nicolas Capens77980512016-12-02 14:22:32 -05001664 if(!texelFetch)
John Bauman89401822014-05-06 15:04:28 -04001665 {
Nicolas Capens77980512016-12-02 14:22:32 -05001666 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width)));
1667 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height)));
John Bauman89401822014-05-06 15:04:28 -04001668 }
Nicolas Capens77980512016-12-02 14:22:32 -05001669
1670 if(hasOffset)
John Bauman89401822014-05-06 15:04:28 -04001671 {
Nicolas Capens2a3932c2017-11-07 14:35:38 -05001672 UShort4 w = *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width));
1673 uuuu = applyOffset(uuuu, offset.x, Int4(w), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeU);
1674 UShort4 h = *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height));
1675 vvvv = applyOffset(vvvv, offset.y, Int4(h), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeV);
Alexis Hetuf15e8942015-12-01 15:13:23 -05001676 }
Nicolas Capens411273e2017-01-26 15:13:36 -08001677
Nicolas Capens77980512016-12-02 14:22:32 -05001678 Short4 uuu2 = uuuu;
1679 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1680 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1681 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1682 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
John Bauman89401822014-05-06 15:04:28 -04001683
Alexis Hetu75a61852017-07-14 14:17:14 -04001684 if(hasThirdCoordinate())
Alexis Hetuf15e8942015-12-01 15:13:23 -05001685 {
1686 if(state.textureType != TEXTURE_2D_ARRAY)
John Bauman89401822014-05-06 15:04:28 -04001687 {
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001688 if(!texelFetch)
1689 {
1690 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth)));
1691 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001692
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001693 if(hasOffset)
1694 {
Nicolas Capens2a3932c2017-11-07 14:35:38 -05001695 UShort4 d = *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth));
1696 wwww = applyOffset(wwww, offset.z, Int4(d), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeW);
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001697 }
John Bauman89401822014-05-06 15:04:28 -04001698 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001699
Alexis Hetu42e53032017-10-03 13:56:07 -04001700 UInt4 uv(As<UInt2>(uuuu), As<UInt2>(uuu2));
1701 uv += As<UInt4>(Int4(As<UShort4>(wwww))) * *Pointer<UInt4>(mipmap + OFFSET(Mipmap, sliceP));
Nicolas Capens89a218b2017-11-07 13:05:20 -05001702
Alexis Hetu42e53032017-10-03 13:56:07 -04001703 index[0] = Extract(As<Int4>(uv), 0);
1704 index[1] = Extract(As<Int4>(uv), 1);
1705 index[2] = Extract(As<Int4>(uv), 2);
1706 index[3] = Extract(As<Int4>(uv), 3);
John Bauman89401822014-05-06 15:04:28 -04001707 }
Alexis Hetu42e53032017-10-03 13:56:07 -04001708 else
1709 {
1710 index[0] = Extract(As<Int2>(uuuu), 0);
1711 index[1] = Extract(As<Int2>(uuuu), 1);
1712 index[2] = Extract(As<Int2>(uuu2), 0);
1713 index[3] = Extract(As<Int2>(uuu2), 1);
1714 }
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001715
1716 if(texelFetch)
1717 {
1718 Int size = Int(*Pointer<Int>(mipmap + OFFSET(Mipmap, sliceP)));
Alexis Hetu75a61852017-07-14 14:17:14 -04001719 if(hasThirdCoordinate())
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001720 {
1721 size *= Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)));
1722 }
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001723 UInt min = 0;
1724 UInt max = size - 1;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001725
1726 for(int i = 0; i < 4; i++)
1727 {
1728 index[i] = Min(Max(index[i], min), max);
1729 }
1730 }
John Bauman89401822014-05-06 15:04:28 -04001731 }
1732
Alexis Hetu75a61852017-07-14 14:17:14 -04001733 void SamplerCore::computeIndices(UInt index[4], Int4& uuuu, Int4& vvvv, Int4& wwww, const Pointer<Byte> &mipmap, SamplerFunction function)
1734 {
1735 UInt4 indices = uuuu + vvvv;
1736
1737 if(hasThirdCoordinate())
1738 {
1739 indices += As<UInt4>(wwww);
1740 }
1741
1742 for(int i = 0; i < 4; i++)
1743 {
1744 index[i] = Extract(As<Int4>(indices), i);
1745 }
1746 }
1747
Nicolas Capens5790c952017-08-01 17:00:36 -04001748 Vector4s SamplerCore::sampleTexel(UInt index[4], Pointer<Byte> buffer[4])
John Bauman89401822014-05-06 15:04:28 -04001749 {
Nicolas Capens5790c952017-08-01 17:00:36 -04001750 Vector4s c;
1751
John Bauman89401822014-05-06 15:04:28 -04001752 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1753 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1754 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1755 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1756
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001757 if(has16bitTextureFormat())
John Bauman89401822014-05-06 15:04:28 -04001758 {
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001759 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1760 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1761 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1762 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
Nicolas Capens27496312015-05-12 15:16:06 -04001763
1764 switch(state.textureFormat)
1765 {
1766 case FORMAT_R5G6B5:
1767 c.z = (c.x & Short4(0x001Fu)) << 11;
1768 c.y = (c.x & Short4(0x07E0u)) << 5;
1769 c.x = (c.x & Short4(0xF800u));
1770 break;
1771 default:
1772 ASSERT(false);
1773 }
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001774 }
Nicolas Capens21bda852015-09-01 10:23:33 -04001775 else if(has8bitTextureComponents())
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001776 {
John Bauman89401822014-05-06 15:04:28 -04001777 switch(textureComponentCount())
1778 {
1779 case 4:
1780 {
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001781 Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1782 Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1783 Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1784 Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
Nicolas Capens411273e2017-01-26 15:13:36 -08001785 c.x = Unpack(c0, c1);
1786 c.y = Unpack(c2, c3);
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001787
John Bauman89401822014-05-06 15:04:28 -04001788 switch(state.textureFormat)
1789 {
1790 case FORMAT_A8R8G8B8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001791 c.z = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001792 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1793 c.y = c.z;
1794 c.w = c.x;
1795 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1796 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1797 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1798 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
John Bauman89401822014-05-06 15:04:28 -04001799 break;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001800 case FORMAT_A8B8G8R8:
Alexis Hetu3412d872015-10-26 16:40:26 -04001801 case FORMAT_A8B8G8R8I:
Nicolas Capens975adb72017-12-19 15:34:20 -05001802 case FORMAT_A8B8G8R8_SNORM:
John Bauman89401822014-05-06 15:04:28 -04001803 case FORMAT_Q8W8V8U8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001804 case FORMAT_SRGB8_A8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001805 c.z = As<Short4>(UnpackHigh(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001806 c.x = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001807 c.y = c.x;
1808 c.w = c.z;
1809 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1810 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1811 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1812 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001813 // Propagate sign bit
1814 if(state.textureFormat == FORMAT_A8B8G8R8I)
1815 {
1816 c.x >>= 8;
1817 c.y >>= 8;
1818 c.z >>= 8;
1819 c.w >>= 8;
1820 }
1821 break;
1822 case FORMAT_A8B8G8R8UI:
1823 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1824 c.x = As<Short4>(UnpackLow(c.x, c.y));
1825 c.y = c.x;
1826 c.w = c.z;
1827 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0)));
1828 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0)));
1829 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(Short4(0)));
1830 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(Short4(0)));
John Bauman89401822014-05-06 15:04:28 -04001831 break;
1832 default:
1833 ASSERT(false);
1834 }
1835 }
1836 break;
1837 case 3:
1838 {
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001839 Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1840 Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1841 Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1842 Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
Nicolas Capens411273e2017-01-26 15:13:36 -08001843 c.x = Unpack(c0, c1);
1844 c.y = Unpack(c2, c3);
John Bauman89401822014-05-06 15:04:28 -04001845
1846 switch(state.textureFormat)
1847 {
1848 case FORMAT_X8R8G8B8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001849 c.z = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001850 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1851 c.y = c.z;
1852 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1853 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1854 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
John Bauman89401822014-05-06 15:04:28 -04001855 break;
Nicolas Capens975adb72017-12-19 15:34:20 -05001856 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04001857 case FORMAT_X8B8G8R8I:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001858 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04001859 case FORMAT_X8L8V8U8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001860 case FORMAT_SRGB8_X8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001861 c.z = As<Short4>(UnpackHigh(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001862 c.x = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001863 c.y = c.x;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001864 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1865 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001866 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001867 // Propagate sign bit
1868 if(state.textureFormat == FORMAT_X8B8G8R8I)
1869 {
1870 c.x >>= 8;
1871 c.y >>= 8;
1872 c.z >>= 8;
1873 }
1874 break;
1875 case FORMAT_X8B8G8R8UI:
1876 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1877 c.x = As<Short4>(UnpackLow(c.x, c.y));
1878 c.y = c.x;
1879 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0)));
1880 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0)));
1881 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(Short4(0)));
John Bauman89401822014-05-06 15:04:28 -04001882 break;
1883 default:
1884 ASSERT(false);
1885 }
1886 }
1887 break;
1888 case 2:
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001889 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1890 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1891 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1892 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
John Bauman89401822014-05-06 15:04:28 -04001893
1894 switch(state.textureFormat)
1895 {
1896 case FORMAT_G8R8:
Nicolas Capens975adb72017-12-19 15:34:20 -05001897 case FORMAT_G8R8_SNORM:
John Bauman89401822014-05-06 15:04:28 -04001898 case FORMAT_V8U8:
1899 case FORMAT_A8L8:
Alexis Hetu90c7ad62016-06-27 11:50:40 -04001900 c.y = (c.x & Short4(0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
1901 c.x = (c.x & Short4(0x00FFu)) | (c.x << 8);
John Bauman89401822014-05-06 15:04:28 -04001902 break;
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001903 case FORMAT_G8R8I:
1904 c.y = c.x >> 8;
1905 c.x = (c.x << 8) >> 8; // Propagate sign bit
1906 break;
1907 case FORMAT_G8R8UI:
1908 c.y = As<Short4>(As<UShort4>(c.x) >> 8);
1909 c.x &= Short4(0x00FFu);
1910 break;
John Bauman89401822014-05-06 15:04:28 -04001911 default:
1912 ASSERT(false);
1913 }
1914 break;
1915 case 1:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001916 {
1917 Int c0 = Int(*Pointer<Byte>(buffer[f0] + index[0]));
1918 Int c1 = Int(*Pointer<Byte>(buffer[f1] + index[1]));
1919 Int c2 = Int(*Pointer<Byte>(buffer[f2] + index[2]));
1920 Int c3 = Int(*Pointer<Byte>(buffer[f3] + index[3]));
1921 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001922
1923 switch(state.textureFormat)
1924 {
1925 case FORMAT_R8I:
1926 case FORMAT_R8UI:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001927 {
Nicolas Capens2d8c3702017-07-25 13:56:46 -04001928 Int zero(0);
1929 c.x = Unpack(As<Byte4>(c0), As<Byte4>(zero));
1930 // Propagate sign bit
1931 if(state.textureFormat == FORMAT_R8I)
1932 {
1933 c.x = (c.x << 8) >> 8;
1934 }
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001935 }
Nicolas Capens2d8c3702017-07-25 13:56:46 -04001936 break;
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001937 default:
1938 c.x = Unpack(As<Byte4>(c0));
1939 break;
1940 }
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001941 }
John Bauman89401822014-05-06 15:04:28 -04001942 break;
1943 default:
1944 ASSERT(false);
1945 }
1946 }
Nicolas Capens21bda852015-09-01 10:23:33 -04001947 else if(has16bitTextureComponents())
John Bauman89401822014-05-06 15:04:28 -04001948 {
1949 switch(textureComponentCount())
1950 {
1951 case 4:
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001952 c.x = Pointer<Short4>(buffer[f0])[index[0]];
1953 c.y = Pointer<Short4>(buffer[f1])[index[1]];
1954 c.z = Pointer<Short4>(buffer[f2])[index[2]];
1955 c.w = Pointer<Short4>(buffer[f3])[index[3]];
John Bauman19bac1e2014-05-06 15:23:49 -04001956 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman89401822014-05-06 15:04:28 -04001957 break;
Nicolas Capense4a88b92017-11-30 00:14:57 -05001958 case 3:
1959 c.x = Pointer<Short4>(buffer[f0])[index[0]];
1960 c.y = Pointer<Short4>(buffer[f1])[index[1]];
1961 c.z = Pointer<Short4>(buffer[f2])[index[2]];
1962 c.w = Pointer<Short4>(buffer[f3])[index[3]];
1963 transpose4x3(c.x, c.y, c.z, c.w);
1964 break;
John Bauman89401822014-05-06 15:04:28 -04001965 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -04001966 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]);
1967 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1])));
1968 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]);
1969 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3])));
1970 c.y = c.x;
Nicolas Capens45f187a2016-12-02 15:30:56 -05001971 c.x = UnpackLow(As<Int2>(c.x), As<Int2>(c.z));
1972 c.y = UnpackHigh(As<Int2>(c.y), As<Int2>(c.z));
John Bauman89401822014-05-06 15:04:28 -04001973 break;
1974 case 1:
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001975 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1976 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1977 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1978 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
John Bauman89401822014-05-06 15:04:28 -04001979 break;
1980 default:
1981 ASSERT(false);
1982 }
1983 }
Alexis Hetu5de90b22017-07-17 11:19:12 -04001984 else ASSERT(false);
Nicolas Capens5790c952017-08-01 17:00:36 -04001985
Nicolas Capens5555af42017-12-14 13:14:03 -05001986 if(state.sRGB)
1987 {
1988 if(state.textureFormat == FORMAT_R5G6B5)
1989 {
1990 sRGBtoLinear16_5_16(c.x);
1991 sRGBtoLinear16_6_16(c.y);
1992 sRGBtoLinear16_5_16(c.z);
1993 }
1994 else
1995 {
1996 for(int i = 0; i < textureComponentCount(); i++)
1997 {
1998 if(isRGBComponent(i))
1999 {
2000 sRGBtoLinear16_8_16(c[i]);
2001 }
2002 }
2003 }
2004 }
2005
Nicolas Capens5790c952017-08-01 17:00:36 -04002006 return c;
Alexis Hetu5de90b22017-07-17 11:19:12 -04002007 }
2008
Nicolas Capens5790c952017-08-01 17:00:36 -04002009 Vector4s SamplerCore::sampleTexel(Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Vector4f &offset, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
Alexis Hetu5de90b22017-07-17 11:19:12 -04002010 {
Nicolas Capens5790c952017-08-01 17:00:36 -04002011 Vector4s c;
Alexis Hetu5de90b22017-07-17 11:19:12 -04002012
Nicolas Capens5790c952017-08-01 17:00:36 -04002013 UInt index[4];
Alexis Hetu5de90b22017-07-17 11:19:12 -04002014 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
2015
2016 if(hasYuvFormat())
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002017 {
2018 // Generic YPbPr to RGB transformation
2019 // R = Y + 2 * (1 - Kr) * Pr
2020 // G = Y - 2 * Kb * (1 - Kb) / Kg * Pb - 2 * Kr * (1 - Kr) / Kg * Pr
2021 // B = Y + 2 * (1 - Kb) * Pb
2022
2023 float Kb = 0.114f;
2024 float Kr = 0.299f;
2025 int studioSwing = 1;
2026
2027 switch(state.textureFormat)
2028 {
2029 case FORMAT_YV12_BT601:
2030 Kb = 0.114f;
2031 Kr = 0.299f;
2032 studioSwing = 1;
2033 break;
2034 case FORMAT_YV12_BT709:
2035 Kb = 0.0722f;
2036 Kr = 0.2126f;
2037 studioSwing = 1;
2038 break;
2039 case FORMAT_YV12_JFIF:
2040 Kb = 0.114f;
2041 Kr = 0.299f;
2042 studioSwing = 0;
2043 break;
2044 default:
2045 ASSERT(false);
2046 }
2047
2048 const float Kg = 1.0f - Kr - Kb;
2049
2050 const float Rr = 2 * (1 - Kr);
2051 const float Gb = -2 * Kb * (1 - Kb) / Kg;
2052 const float Gr = -2 * Kr * (1 - Kr) / Kg;
2053 const float Bb = 2 * (1 - Kb);
2054
2055 // Scaling and bias for studio-swing range: Y = [16 .. 235], U/V = [16 .. 240]
2056 const float Yy = studioSwing ? 255.0f / (235 - 16) : 1.0f;
2057 const float Uu = studioSwing ? 255.0f / (240 - 16) : 1.0f;
2058 const float Vv = studioSwing ? 255.0f / (240 - 16) : 1.0f;
2059
2060 const float Rv = Vv * Rr;
2061 const float Gu = Uu * Gb;
2062 const float Gv = Vv * Gr;
2063 const float Bu = Uu * Bb;
2064
2065 const float R0 = (studioSwing * -16 * Yy - 128 * Rv) / 255;
2066 const float G0 = (studioSwing * -16 * Yy - 128 * Gu - 128 * Gv) / 255;
2067 const float B0 = (studioSwing * -16 * Yy - 128 * Bu) / 255;
2068
Nicolas Capens9b0e6552017-01-26 21:49:04 -08002069 Int c0 = Int(buffer[0][index[0]]);
2070 Int c1 = Int(buffer[0][index[1]]);
2071 Int c2 = Int(buffer[0][index[2]]);
2072 Int c3 = Int(buffer[0][index[3]]);
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002073 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2074 UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0)));
2075
Nicolas Capensa3c16e42016-06-15 16:45:53 -04002076 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap + sizeof(Mipmap), function);
Nicolas Capens9b0e6552017-01-26 21:49:04 -08002077 c0 = Int(buffer[1][index[0]]);
2078 c1 = Int(buffer[1][index[1]]);
2079 c2 = Int(buffer[1][index[2]]);
2080 c3 = Int(buffer[1][index[3]]);
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002081 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2082 UShort4 V = As<UShort4>(Unpack(As<Byte4>(c0)));
2083
Nicolas Capens9b0e6552017-01-26 21:49:04 -08002084 c0 = Int(buffer[2][index[0]]);
2085 c1 = Int(buffer[2][index[1]]);
2086 c2 = Int(buffer[2][index[2]]);
2087 c3 = Int(buffer[2][index[3]]);
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002088 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2089 UShort4 U = As<UShort4>(Unpack(As<Byte4>(c0)));
2090
2091 const UShort4 yY = UShort4(iround(Yy * 0x4000));
2092 const UShort4 rV = UShort4(iround(Rv * 0x4000));
2093 const UShort4 gU = UShort4(iround(-Gu * 0x4000));
2094 const UShort4 gV = UShort4(iround(-Gv * 0x4000));
2095 const UShort4 bU = UShort4(iround(Bu * 0x4000));
2096
2097 const UShort4 r0 = UShort4(iround(-R0 * 0x4000));
2098 const UShort4 g0 = UShort4(iround(G0 * 0x4000));
2099 const UShort4 b0 = UShort4(iround(-B0 * 0x4000));
2100
2101 UShort4 y = MulHigh(Y, yY);
2102 UShort4 r = SubSat(y + MulHigh(V, rV), r0);
2103 UShort4 g = SubSat(y + g0, MulHigh(U, gU) + MulHigh(V, gV));
2104 UShort4 b = SubSat(y + MulHigh(U, bU), b0);
2105
2106 c.x = Min(r, UShort4(0x3FFF)) << 2;
2107 c.y = Min(g, UShort4(0x3FFF)) << 2;
2108 c.z = Min(b, UShort4(0x3FFF)) << 2;
2109 }
Alexis Hetu5de90b22017-07-17 11:19:12 -04002110 else
2111 {
Nicolas Capens5790c952017-08-01 17:00:36 -04002112 return sampleTexel(index, buffer);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002113 }
Nicolas Capens5790c952017-08-01 17:00:36 -04002114
2115 return c;
John Bauman89401822014-05-06 15:04:28 -04002116 }
2117
Nicolas Capens5790c952017-08-01 17:00:36 -04002118 Vector4f SamplerCore::sampleTexel(Int4 &uuuu, Int4 &vvvv, Int4 &wwww, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4], SamplerFunction function)
John Bauman89401822014-05-06 15:04:28 -04002119 {
Nicolas Capens5790c952017-08-01 17:00:36 -04002120 Vector4f c;
John Bauman89401822014-05-06 15:04:28 -04002121
Nicolas Capens5790c952017-08-01 17:00:36 -04002122 UInt index[4];
Alexis Hetu75a61852017-07-14 14:17:14 -04002123 computeIndices(index, uuuu, vvvv, wwww, mipmap, function);
John Bauman89401822014-05-06 15:04:28 -04002124
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002125 if(hasFloatTexture() || has32bitIntegerTextureComponents())
John Bauman89401822014-05-06 15:04:28 -04002126 {
Alexis Hetu5de90b22017-07-17 11:19:12 -04002127 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
2128 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
2129 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
2130 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
John Bauman89401822014-05-06 15:04:28 -04002131
Alexis Hetu5de90b22017-07-17 11:19:12 -04002132 // Read texels
2133 switch(textureComponentCount())
John Bauman89401822014-05-06 15:04:28 -04002134 {
Alexis Hetu5de90b22017-07-17 11:19:12 -04002135 case 4:
2136 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2137 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2138 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2139 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2140 transpose4x4(c.x, c.y, c.z, c.w);
2141 break;
2142 case 3:
Alexis Hetu5de90b22017-07-17 11:19:12 -04002143 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2144 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2145 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2146 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2147 transpose4x3(c.x, c.y, c.z, c.w);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002148 break;
2149 case 2:
2150 // FIXME: Optimal shuffling?
2151 c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8);
2152 c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8);
2153 c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8);
2154 c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8);
2155 c.y = c.x;
2156 c.x = Float4(c.x.xz, c.z.xz);
2157 c.y = Float4(c.y.yw, c.z.yw);
2158 break;
2159 case 1:
2160 // FIXME: Optimal shuffling?
2161 c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4);
2162 c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4);
2163 c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4);
2164 c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002165 break;
2166 default:
2167 ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04002168 }
Nicolas Capens185c18b2017-11-07 13:51:50 -05002169
2170 if(state.compare != COMPARE_BYPASS)
2171 {
2172 Float4 ref = z;
2173
2174 if(!hasFloatTexture())
2175 {
2176 ref = Min(Max(ref, Float4(0.0f)), Float4(1.0f));
2177 }
2178
2179 Int4 boolean;
2180
2181 switch(state.compare)
2182 {
2183 case COMPARE_LESSEQUAL: boolean = CmpLE(ref, c.x); break;
2184 case COMPARE_GREATEREQUAL: boolean = CmpNLT(ref, c.x); break;
2185 case COMPARE_LESS: boolean = CmpLT(ref, c.x); break;
2186 case COMPARE_GREATER: boolean = CmpNLE(ref, c.x); break;
2187 case COMPARE_EQUAL: boolean = CmpEQ(ref, c.x); break;
2188 case COMPARE_NOTEQUAL: boolean = CmpNEQ(ref, c.x); break;
2189 case COMPARE_ALWAYS: boolean = Int4(-1); break;
2190 case COMPARE_NEVER: boolean = Int4(0); break;
2191 default: ASSERT(false);
2192 }
2193
2194 c.x = As<Float4>(boolean & As<Int4>(Float4(1.0f)));
2195 c.y = Float4(0.0f);
2196 c.z = Float4(0.0f);
2197 c.w = Float4(1.0f);
2198 }
Alexis Hetu5de90b22017-07-17 11:19:12 -04002199 }
2200 else
2201 {
2202 ASSERT(!hasYuvFormat());
2203
Nicolas Capens5790c952017-08-01 17:00:36 -04002204 Vector4s cs = sampleTexel(index, buffer);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002205
2206 bool isInteger = Surface::isNonNormalizedInteger(state.textureFormat);
2207 int componentCount = textureComponentCount();
Nicolas Capens5555af42017-12-14 13:14:03 -05002208 for(int n = 0; n < componentCount; n++)
Alexis Hetu5de90b22017-07-17 11:19:12 -04002209 {
2210 if(hasUnsignedTextureComponent(n))
2211 {
2212 if(isInteger)
2213 {
2214 c[n] = As<Float4>(Int4(As<UShort4>(cs[n])));
2215 }
2216 else
2217 {
2218 c[n] = Float4(As<UShort4>(cs[n]));
2219 }
2220 }
2221 else
2222 {
2223 if(isInteger)
2224 {
2225 c[n] = As<Float4>(Int4(cs[n]));
2226 }
2227 else
2228 {
2229 c[n] = Float4(cs[n]);
2230 }
2231 }
2232 }
John Bauman89401822014-05-06 15:04:28 -04002233 }
Nicolas Capens5790c952017-08-01 17:00:36 -04002234
2235 return c;
John Bauman89401822014-05-06 15:04:28 -04002236 }
2237
2238 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
2239 {
Nicolas Capense396a492018-01-02 14:22:23 -05002240 if(state.mipmapFilter == MIPMAP_NONE)
John Bauman89401822014-05-06 15:04:28 -04002241 {
2242 mipmap = texture + OFFSET(Texture,mipmap[0]);
2243 }
2244 else
2245 {
2246 Int ilod;
2247
2248 if(state.mipmapFilter == MIPMAP_POINT)
2249 {
2250 ilod = RoundInt(lod);
2251 }
Nicolas Capense396a492018-01-02 14:22:23 -05002252 else // MIPMAP_LINEAR
John Bauman89401822014-05-06 15:04:28 -04002253 {
2254 ilod = Int(lod);
2255 }
2256
2257 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
2258 }
2259
2260 if(state.textureType != TEXTURE_CUBE)
2261 {
John Bauman66b8ab22014-05-06 15:57:45 -04002262 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002263
2264 if(hasYuvFormat())
2265 {
2266 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1]));
2267 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2]));
2268 }
John Bauman89401822014-05-06 15:04:28 -04002269 }
2270 else
2271 {
2272 for(int i = 0; i < 4; i++)
2273 {
John Bauman66b8ab22014-05-06 15:57:45 -04002274 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -04002275 }
2276 }
2277 }
2278
Nicolas Capensb81efca2017-12-19 10:52:14 -05002279 Int4 SamplerCore::computeFilterOffset(Float &lod)
Alexis Hetu75a61852017-07-14 14:17:14 -04002280 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002281 Int4 filter = -1;
2282
2283 if(state.textureFilter == FILTER_POINT)
Alexis Hetu75a61852017-07-14 14:17:14 -04002284 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002285 filter = 0;
2286 }
2287 else if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
2288 {
Nicolas Capensb81efca2017-12-19 10:52:14 -05002289 filter = CmpNLE(Float4(lod), Float4(0.0f));
Alexis Hetu75a61852017-07-14 14:17:14 -04002290 }
2291 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
2292 {
Nicolas Capensb81efca2017-12-19 10:52:14 -05002293 filter = CmpLE(Float4(lod), Float4(0.0f));
Alexis Hetu75a61852017-07-14 14:17:14 -04002294 }
2295
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002296 return filter;
Alexis Hetu75a61852017-07-14 14:17:14 -04002297 }
2298
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002299 Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte> &mipmap)
John Bauman89401822014-05-06 15:04:28 -04002300 {
Nicolas Capens7bb62682016-02-08 11:30:56 -05002301 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2302 {
2303 return Short4(); // Unused
2304 }
2305 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY)
2306 {
2307 return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1));
2308 }
Nicolas Capensc4b1bfa2017-11-28 15:52:52 -05002309 else if(addressingMode == ADDRESSING_CLAMP || addressingMode == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04002310 {
2311 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
2312
Nicolas Capens7bb62682016-02-08 11:30:56 -05002313 return Short4(Int4(clamp * Float4(1 << 16)));
John Bauman89401822014-05-06 15:04:28 -04002314 }
2315 else if(addressingMode == ADDRESSING_MIRROR)
2316 {
2317 Int4 convert = Int4(uw * Float4(1 << 16));
2318 Int4 mirror = (convert << 15) >> 31;
2319
2320 convert ^= mirror;
2321
Nicolas Capens7bb62682016-02-08 11:30:56 -05002322 return Short4(convert);
John Bauman89401822014-05-06 15:04:28 -04002323 }
2324 else if(addressingMode == ADDRESSING_MIRRORONCE)
2325 {
2326 // Absolute value
2327 Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
2328
2329 // Clamp
2330 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
Nicolas Capens33438a62017-09-27 11:47:35 -04002331 convert = As<Int4>(PackSigned(convert, convert));
John Bauman89401822014-05-06 15:04:28 -04002332
Alexis Hetu90c7ad62016-06-27 11:50:40 -04002333 return As<Short4>(Int2(convert)) + Short4(0x8000u);
John Bauman89401822014-05-06 15:04:28 -04002334 }
Nicolas Capensc4b1bfa2017-11-28 15:52:52 -05002335 else // Wrap
John Bauman89401822014-05-06 15:04:28 -04002336 {
Nicolas Capens7bb62682016-02-08 11:30:56 -05002337 return Short4(Int4(uw * Float4(1 << 16)));
Alexis Hetuf15e8942015-12-01 15:13:23 -05002338 }
2339 }
2340
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002341 void SamplerCore::address(Float4 &uvw, Int4 &xyz0, Int4 &xyz1, Float4 &f, Pointer<Byte> &mipmap, Float4 &texOffset, Int4 &filter, int whd, AddressingMode addressingMode, SamplerFunction function)
Alexis Hetu75a61852017-07-14 14:17:14 -04002342 {
2343 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2344 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002345 return; // Unused
Alexis Hetu75a61852017-07-14 14:17:14 -04002346 }
2347
2348 Int4 dim = Int4(*Pointer<Short4>(mipmap + whd, 16));
2349 Int4 maxXYZ = dim - Int4(1);
2350
2351 if(function == Fetch)
2352 {
2353 xyz0 = Min(Max(((function.option == Offset) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ);
2354 }
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002355 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY) // Note: Offset does not apply to array layers
Alexis Hetu75a61852017-07-14 14:17:14 -04002356 {
2357 xyz0 = Min(Max(RoundInt(uvw), Int4(0)), maxXYZ);
2358 }
2359 else
2360 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002361 const int halfBits = 0x3EFFFFFF; // Value just under 0.5f
2362 const int oneBits = 0x3F7FFFFF; // Value just under 1.0f
2363 const int twoBits = 0x3FFFFFFF; // Value just under 2.0f
Alexis Hetu75a61852017-07-14 14:17:14 -04002364
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002365 bool pointFilter = state.textureFilter == FILTER_POINT ||
2366 state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR ||
2367 state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT;
2368
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002369 Float4 coord = uvw;
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002370
Alexis Hetuc0632c92018-03-02 15:10:16 -05002371 if(state.textureType == TEXTURE_RECTANGLE)
Alexis Hetu75a61852017-07-14 14:17:14 -04002372 {
Alexis Hetu0641aeb2018-05-08 14:25:40 -04002373 // According to https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_rectangle.txt
2374 // "CLAMP_TO_EDGE causes the s coordinate to be clamped to the range[0.5, wt - 0.5].
2375 // CLAMP_TO_EDGE causes the t coordinate to be clamped to the range[0.5, ht - 0.5]."
2376 // Unless SwiftShader implements support for ADDRESSING_BORDER, other modes should be equivalent
2377 // to CLAMP_TO_EDGE. Rectangle textures have no support for any MIRROR or REPEAT modes.
2378 coord = Min(Max(coord, Float4(0.5f)), Float4(dim) - Float4(0.5f));
Alexis Hetu46768622018-01-16 22:09:28 -05002379 }
2380 else
2381 {
2382 switch(addressingMode)
Alexis Hetu75a61852017-07-14 14:17:14 -04002383 {
Alexis Hetu46768622018-01-16 22:09:28 -05002384 case ADDRESSING_CLAMP:
2385 case ADDRESSING_BORDER:
2386 case ADDRESSING_SEAMLESS:
2387 // Linear filtering of cube doesn't require clamping because the coordinates
2388 // are already in [0, 1] range and numerical imprecision is tolerated.
2389 if(addressingMode != ADDRESSING_SEAMLESS || pointFilter)
2390 {
2391 Float4 one = As<Float4>(Int4(oneBits));
2392 coord = Min(Max(coord, Float4(0.0f)), one);
2393 }
2394 break;
2395 case ADDRESSING_MIRROR:
Alexis Hetu75a61852017-07-14 14:17:14 -04002396 {
2397 Float4 half = As<Float4>(Int4(halfBits));
2398 Float4 one = As<Float4>(Int4(oneBits));
2399 Float4 two = As<Float4>(Int4(twoBits));
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002400 coord = one - Abs(two * Frac(coord * half) - one);
Alexis Hetu75a61852017-07-14 14:17:14 -04002401 }
2402 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002403 case ADDRESSING_MIRRORONCE:
Alexis Hetu75a61852017-07-14 14:17:14 -04002404 {
2405 Float4 half = As<Float4>(Int4(halfBits));
2406 Float4 one = As<Float4>(Int4(oneBits));
2407 Float4 two = As<Float4>(Int4(twoBits));
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002408 coord = one - Abs(two * Frac(Min(Max(coord, -one), two) * half) - one);
Alexis Hetu75a61852017-07-14 14:17:14 -04002409 }
2410 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002411 default: // Wrap
2412 coord = Frac(coord);
2413 break;
2414 }
2415
2416 coord = coord * Float4(dim);
Alexis Hetu75a61852017-07-14 14:17:14 -04002417 }
2418
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002419 if(state.textureFilter == FILTER_POINT ||
Alexis Hetu46768622018-01-16 22:09:28 -05002420 state.textureFilter == FILTER_GATHER)
2421 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002422 xyz0 = Int4(coord);
2423 }
2424 else
2425 {
2426 if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR ||
Alexis Hetu46768622018-01-16 22:09:28 -05002427 state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002428 {
2429 coord -= As<Float4>(As<Int4>(Float4(0.5f)) & filter);
2430 }
2431 else
2432 {
2433 coord -= Float4(0.5f);
2434 }
2435
2436 Float4 floor = Floor(coord);
2437 xyz0 = Int4(floor);
2438 f = coord - floor;
2439 }
Alexis Hetu75a61852017-07-14 14:17:14 -04002440
2441 if(function.option == Offset)
2442 {
2443 xyz0 += As<Int4>(texOffset);
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002444 }
2445
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002446 if(addressingMode == ADDRESSING_SEAMLESS)
2447 {
2448 xyz0 += Int4(1);
2449 }
2450
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002451 xyz1 = xyz0 - filter; // Increment
2452
2453 if(function.option == Offset)
2454 {
Alexis Hetu75a61852017-07-14 14:17:14 -04002455 switch(addressingMode)
2456 {
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002457 case ADDRESSING_SEAMLESS:
2458 ASSERT(false); // Cube sampling doesn't support offset.
Alexis Hetu75a61852017-07-14 14:17:14 -04002459 case ADDRESSING_MIRROR:
2460 case ADDRESSING_MIRRORONCE:
2461 case ADDRESSING_BORDER:
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002462 // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, and ADDRESSING_BORDER.
2463 // Fall through to Clamp.
Alexis Hetu75a61852017-07-14 14:17:14 -04002464 case ADDRESSING_CLAMP:
2465 xyz0 = Min(Max(xyz0, Int4(0)), maxXYZ);
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002466 xyz1 = Min(Max(xyz1, Int4(0)), maxXYZ);
Alexis Hetu75a61852017-07-14 14:17:14 -04002467 break;
2468 default: // Wrap
2469 xyz0 = (xyz0 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim;
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002470 xyz1 = (xyz1 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim;
Alexis Hetu75a61852017-07-14 14:17:14 -04002471 break;
2472 }
2473 }
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002474 else if(state.textureFilter != FILTER_POINT)
Alexis Hetu75a61852017-07-14 14:17:14 -04002475 {
Alexis Hetu75a61852017-07-14 14:17:14 -04002476 switch(addressingMode)
2477 {
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002478 case ADDRESSING_SEAMLESS:
2479 break;
Alexis Hetu75a61852017-07-14 14:17:14 -04002480 case ADDRESSING_MIRROR:
2481 case ADDRESSING_MIRRORONCE:
2482 case ADDRESSING_BORDER:
Alexis Hetu75a61852017-07-14 14:17:14 -04002483 case ADDRESSING_CLAMP:
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002484 xyz0 = Max(xyz0, Int4(0));
2485 xyz1 = Min(xyz1, maxXYZ);
Alexis Hetu75a61852017-07-14 14:17:14 -04002486 break;
2487 default: // Wrap
2488 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002489 Int4 under = CmpLT(xyz0, Int4(0));
2490 xyz0 = (under & maxXYZ) | (~under & xyz0); // xyz < 0 ? dim - 1 : xyz // FIXME: IfThenElse()
2491
2492 Int4 nover = CmpLT(xyz1, dim);
2493 xyz1 = nover & xyz1; // xyz >= dim ? 0 : xyz
Alexis Hetu75a61852017-07-14 14:17:14 -04002494 }
2495 break;
2496 }
2497 }
2498 }
2499 }
2500
Alexis Hetu96517182015-04-15 10:30:23 -04002501 void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
John Bauman89401822014-05-06 15:04:28 -04002502 {
Alexis Hetu96517182015-04-15 10:30:23 -04002503 cs = RoundShort4(cf * Float4(0x1000));
John Bauman89401822014-05-06 15:04:28 -04002504 }
2505
Alexis Hetu96517182015-04-15 10:30:23 -04002506 void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
John Bauman89401822014-05-06 15:04:28 -04002507 {
Alexis Hetu96517182015-04-15 10:30:23 -04002508 convertFixed12(cs.x, cf.x);
2509 convertFixed12(cs.y, cf.y);
2510 convertFixed12(cs.z, cf.z);
2511 convertFixed12(cs.w, cf.w);
John Bauman89401822014-05-06 15:04:28 -04002512 }
2513
Alexis Hetu96517182015-04-15 10:30:23 -04002514 void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002515 {
Alexis Hetu96517182015-04-15 10:30:23 -04002516 cf = Float4(cs) * Float4(1.0f / 0x0FFE);
John Bauman89401822014-05-06 15:04:28 -04002517 }
2518
Alexis Hetu96517182015-04-15 10:30:23 -04002519// void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
John Bauman89401822014-05-06 15:04:28 -04002520// {
Alexis Hetu96517182015-04-15 10:30:23 -04002521// convertSigned12(cf.x, cs.x);
2522// convertSigned12(cf.y, cs.y);
2523// convertSigned12(cf.z, cs.z);
2524// convertSigned12(cf.w, cs.w);
John Bauman89401822014-05-06 15:04:28 -04002525// }
2526
Alexis Hetu96517182015-04-15 10:30:23 -04002527 void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002528 {
Alexis Hetu96517182015-04-15 10:30:23 -04002529 cf = Float4(cs) * Float4(1.0f / 0x7FFF);
John Bauman89401822014-05-06 15:04:28 -04002530 }
2531
Alexis Hetu96517182015-04-15 10:30:23 -04002532 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002533 {
Alexis Hetu96517182015-04-15 10:30:23 -04002534 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
John Bauman89401822014-05-06 15:04:28 -04002535 }
2536
Nicolas Capens5555af42017-12-14 13:14:03 -05002537 void SamplerCore::sRGBtoLinear16_8_16(Short4 &c)
John Bauman89401822014-05-06 15:04:28 -04002538 {
2539 c = As<UShort4>(c) >> 8;
2540
Nicolas Capens5555af42017-12-14 13:14:03 -05002541 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_16));
Nicolas Capense1a50af2015-05-13 16:48:18 -04002542
2543 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2544 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2545 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2546 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2547 }
2548
Nicolas Capens5555af42017-12-14 13:14:03 -05002549 void SamplerCore::sRGBtoLinear16_6_16(Short4 &c)
Nicolas Capense1a50af2015-05-13 16:48:18 -04002550 {
2551 c = As<UShort4>(c) >> 10;
2552
Nicolas Capens5555af42017-12-14 13:14:03 -05002553 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_16));
Nicolas Capense1a50af2015-05-13 16:48:18 -04002554
2555 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2556 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2557 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2558 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2559 }
2560
Nicolas Capens5555af42017-12-14 13:14:03 -05002561 void SamplerCore::sRGBtoLinear16_5_16(Short4 &c)
Nicolas Capense1a50af2015-05-13 16:48:18 -04002562 {
2563 c = As<UShort4>(c) >> 11;
2564
Nicolas Capens5555af42017-12-14 13:14:03 -05002565 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_16));
John Bauman89401822014-05-06 15:04:28 -04002566
2567 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2568 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2569 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2570 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2571 }
2572
2573 bool SamplerCore::hasFloatTexture() const
2574 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002575 return Surface::isFloatFormat(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04002576 }
2577
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002578 bool SamplerCore::hasUnnormalizedIntegerTexture() const
2579 {
2580 return Surface::isNonNormalizedInteger(state.textureFormat);
2581 }
2582
John Bauman89401822014-05-06 15:04:28 -04002583 bool SamplerCore::hasUnsignedTextureComponent(int component) const
2584 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002585 return Surface::isUnsignedComponent(state.textureFormat, component);
John Bauman89401822014-05-06 15:04:28 -04002586 }
2587
2588 int SamplerCore::textureComponentCount() const
2589 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002590 return Surface::componentCount(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04002591 }
2592
Alexis Hetu75a61852017-07-14 14:17:14 -04002593 bool SamplerCore::hasThirdCoordinate() const
2594 {
2595 return (state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY);
2596 }
2597
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002598 bool SamplerCore::has16bitTextureFormat() const
John Bauman89401822014-05-06 15:04:28 -04002599 {
2600 switch(state.textureFormat)
2601 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002602 case FORMAT_R5G6B5:
2603 return true;
Nicolas Capens975adb72017-12-19 15:34:20 -05002604 case FORMAT_R8_SNORM:
2605 case FORMAT_G8R8_SNORM:
2606 case FORMAT_X8B8G8R8_SNORM:
2607 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002608 case FORMAT_R8I:
2609 case FORMAT_R8UI:
2610 case FORMAT_G8R8I:
2611 case FORMAT_G8R8UI:
2612 case FORMAT_X8B8G8R8I:
2613 case FORMAT_X8B8G8R8UI:
2614 case FORMAT_A8B8G8R8I:
2615 case FORMAT_A8B8G8R8UI:
2616 case FORMAT_R32I:
2617 case FORMAT_R32UI:
2618 case FORMAT_G32R32I:
2619 case FORMAT_G32R32UI:
2620 case FORMAT_X32B32G32R32I:
2621 case FORMAT_X32B32G32R32UI:
2622 case FORMAT_A32B32G32R32I:
2623 case FORMAT_A32B32G32R32UI:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002624 case FORMAT_G8R8:
2625 case FORMAT_X8R8G8B8:
2626 case FORMAT_X8B8G8R8:
2627 case FORMAT_A8R8G8B8:
2628 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002629 case FORMAT_SRGB8_X8:
2630 case FORMAT_SRGB8_A8:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002631 case FORMAT_V8U8:
2632 case FORMAT_Q8W8V8U8:
2633 case FORMAT_X8L8V8U8:
2634 case FORMAT_R32F:
2635 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002636 case FORMAT_X32B32G32R32F:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002637 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002638 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002639 case FORMAT_A8:
2640 case FORMAT_R8:
2641 case FORMAT_L8:
2642 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002643 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002644 case FORMAT_D32FS8:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002645 case FORMAT_D32F_LOCKABLE:
2646 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002647 case FORMAT_D32F_SHADOW:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002648 case FORMAT_D32FS8_SHADOW:
2649 case FORMAT_L16:
2650 case FORMAT_G16R16:
2651 case FORMAT_A16B16G16R16:
2652 case FORMAT_V16U16:
2653 case FORMAT_A16W16V16U16:
2654 case FORMAT_Q16W16V16U16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002655 case FORMAT_R16I:
2656 case FORMAT_R16UI:
2657 case FORMAT_G16R16I:
2658 case FORMAT_G16R16UI:
2659 case FORMAT_X16B16G16R16I:
2660 case FORMAT_X16B16G16R16UI:
2661 case FORMAT_A16B16G16R16I:
2662 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002663 case FORMAT_YV12_BT601:
2664 case FORMAT_YV12_BT709:
2665 case FORMAT_YV12_JFIF:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002666 return false;
2667 default:
2668 ASSERT(false);
2669 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002670
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002671 return false;
2672 }
2673
Nicolas Capens21bda852015-09-01 10:23:33 -04002674 bool SamplerCore::has8bitTextureComponents() const
2675 {
2676 switch(state.textureFormat)
2677 {
Nicolas Capens21bda852015-09-01 10:23:33 -04002678 case FORMAT_G8R8:
2679 case FORMAT_X8R8G8B8:
2680 case FORMAT_X8B8G8R8:
2681 case FORMAT_A8R8G8B8:
2682 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002683 case FORMAT_SRGB8_X8:
2684 case FORMAT_SRGB8_A8:
Nicolas Capens21bda852015-09-01 10:23:33 -04002685 case FORMAT_V8U8:
2686 case FORMAT_Q8W8V8U8:
2687 case FORMAT_X8L8V8U8:
2688 case FORMAT_A8:
2689 case FORMAT_R8:
2690 case FORMAT_L8:
2691 case FORMAT_A8L8:
Nicolas Capens975adb72017-12-19 15:34:20 -05002692 case FORMAT_R8_SNORM:
2693 case FORMAT_G8R8_SNORM:
2694 case FORMAT_X8B8G8R8_SNORM:
2695 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002696 case FORMAT_R8I:
2697 case FORMAT_R8UI:
2698 case FORMAT_G8R8I:
2699 case FORMAT_G8R8UI:
2700 case FORMAT_X8B8G8R8I:
2701 case FORMAT_X8B8G8R8UI:
2702 case FORMAT_A8B8G8R8I:
2703 case FORMAT_A8B8G8R8UI:
Nicolas Capens21bda852015-09-01 10:23:33 -04002704 return true;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002705 case FORMAT_R5G6B5:
Nicolas Capens21bda852015-09-01 10:23:33 -04002706 case FORMAT_R32F:
2707 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002708 case FORMAT_X32B32G32R32F:
Nicolas Capens21bda852015-09-01 10:23:33 -04002709 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002710 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetu3412d872015-10-26 16:40:26 -04002711 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002712 case FORMAT_D32FS8:
Nicolas Capens21bda852015-09-01 10:23:33 -04002713 case FORMAT_D32F_LOCKABLE:
2714 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002715 case FORMAT_D32F_SHADOW:
Nicolas Capens21bda852015-09-01 10:23:33 -04002716 case FORMAT_D32FS8_SHADOW:
2717 case FORMAT_L16:
2718 case FORMAT_G16R16:
2719 case FORMAT_A16B16G16R16:
2720 case FORMAT_V16U16:
2721 case FORMAT_A16W16V16U16:
2722 case FORMAT_Q16W16V16U16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002723 case FORMAT_R32I:
2724 case FORMAT_R32UI:
2725 case FORMAT_G32R32I:
2726 case FORMAT_G32R32UI:
2727 case FORMAT_X32B32G32R32I:
2728 case FORMAT_X32B32G32R32UI:
2729 case FORMAT_A32B32G32R32I:
2730 case FORMAT_A32B32G32R32UI:
2731 case FORMAT_R16I:
2732 case FORMAT_R16UI:
2733 case FORMAT_G16R16I:
2734 case FORMAT_G16R16UI:
2735 case FORMAT_X16B16G16R16I:
2736 case FORMAT_X16B16G16R16UI:
2737 case FORMAT_A16B16G16R16I:
2738 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002739 case FORMAT_YV12_BT601:
2740 case FORMAT_YV12_BT709:
2741 case FORMAT_YV12_JFIF:
Nicolas Capens21bda852015-09-01 10:23:33 -04002742 return false;
2743 default:
2744 ASSERT(false);
2745 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002746
Nicolas Capens21bda852015-09-01 10:23:33 -04002747 return false;
2748 }
2749
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002750 bool SamplerCore::has16bitTextureComponents() const
2751 {
2752 switch(state.textureFormat)
2753 {
2754 case FORMAT_R5G6B5:
Nicolas Capens975adb72017-12-19 15:34:20 -05002755 case FORMAT_R8_SNORM:
2756 case FORMAT_G8R8_SNORM:
2757 case FORMAT_X8B8G8R8_SNORM:
2758 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002759 case FORMAT_R8I:
2760 case FORMAT_R8UI:
2761 case FORMAT_G8R8I:
2762 case FORMAT_G8R8UI:
2763 case FORMAT_X8B8G8R8I:
2764 case FORMAT_X8B8G8R8UI:
2765 case FORMAT_A8B8G8R8I:
2766 case FORMAT_A8B8G8R8UI:
2767 case FORMAT_R32I:
2768 case FORMAT_R32UI:
2769 case FORMAT_G32R32I:
2770 case FORMAT_G32R32UI:
2771 case FORMAT_X32B32G32R32I:
2772 case FORMAT_X32B32G32R32UI:
2773 case FORMAT_A32B32G32R32I:
2774 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002775 case FORMAT_G8R8:
2776 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002777 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002778 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002779 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002780 case FORMAT_SRGB8_X8:
2781 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002782 case FORMAT_V8U8:
2783 case FORMAT_Q8W8V8U8:
2784 case FORMAT_X8L8V8U8:
2785 case FORMAT_R32F:
2786 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002787 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002788 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002789 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002790 case FORMAT_A8:
2791 case FORMAT_R8:
2792 case FORMAT_L8:
2793 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002794 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002795 case FORMAT_D32FS8:
John Bauman89401822014-05-06 15:04:28 -04002796 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002797 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002798 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002799 case FORMAT_D32FS8_SHADOW:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002800 case FORMAT_YV12_BT601:
2801 case FORMAT_YV12_BT709:
2802 case FORMAT_YV12_JFIF:
John Bauman89401822014-05-06 15:04:28 -04002803 return false;
2804 case FORMAT_L16:
2805 case FORMAT_G16R16:
2806 case FORMAT_A16B16G16R16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002807 case FORMAT_R16I:
2808 case FORMAT_R16UI:
2809 case FORMAT_G16R16I:
2810 case FORMAT_G16R16UI:
2811 case FORMAT_X16B16G16R16I:
2812 case FORMAT_X16B16G16R16UI:
2813 case FORMAT_A16B16G16R16I:
2814 case FORMAT_A16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002815 case FORMAT_V16U16:
2816 case FORMAT_A16W16V16U16:
2817 case FORMAT_Q16W16V16U16:
2818 return true;
2819 default:
2820 ASSERT(false);
2821 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002822
John Bauman89401822014-05-06 15:04:28 -04002823 return false;
2824 }
2825
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002826 bool SamplerCore::has32bitIntegerTextureComponents() const
2827 {
2828 switch(state.textureFormat)
2829 {
2830 case FORMAT_R5G6B5:
Nicolas Capens975adb72017-12-19 15:34:20 -05002831 case FORMAT_R8_SNORM:
2832 case FORMAT_G8R8_SNORM:
2833 case FORMAT_X8B8G8R8_SNORM:
2834 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002835 case FORMAT_R8I:
2836 case FORMAT_R8UI:
2837 case FORMAT_G8R8I:
2838 case FORMAT_G8R8UI:
2839 case FORMAT_X8B8G8R8I:
2840 case FORMAT_X8B8G8R8UI:
2841 case FORMAT_A8B8G8R8I:
2842 case FORMAT_A8B8G8R8UI:
2843 case FORMAT_G8R8:
2844 case FORMAT_X8R8G8B8:
2845 case FORMAT_X8B8G8R8:
2846 case FORMAT_A8R8G8B8:
2847 case FORMAT_A8B8G8R8:
2848 case FORMAT_SRGB8_X8:
2849 case FORMAT_SRGB8_A8:
2850 case FORMAT_V8U8:
2851 case FORMAT_Q8W8V8U8:
2852 case FORMAT_X8L8V8U8:
2853 case FORMAT_L16:
2854 case FORMAT_G16R16:
2855 case FORMAT_A16B16G16R16:
2856 case FORMAT_R16I:
2857 case FORMAT_R16UI:
2858 case FORMAT_G16R16I:
2859 case FORMAT_G16R16UI:
2860 case FORMAT_X16B16G16R16I:
2861 case FORMAT_X16B16G16R16UI:
2862 case FORMAT_A16B16G16R16I:
2863 case FORMAT_A16B16G16R16UI:
2864 case FORMAT_V16U16:
2865 case FORMAT_A16W16V16U16:
2866 case FORMAT_Q16W16V16U16:
2867 case FORMAT_R32F:
2868 case FORMAT_G32R32F:
2869 case FORMAT_X32B32G32R32F:
2870 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002871 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002872 case FORMAT_A8:
2873 case FORMAT_R8:
2874 case FORMAT_L8:
2875 case FORMAT_A8L8:
2876 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002877 case FORMAT_D32FS8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002878 case FORMAT_D32F_LOCKABLE:
2879 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002880 case FORMAT_D32F_SHADOW:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002881 case FORMAT_D32FS8_SHADOW:
2882 case FORMAT_YV12_BT601:
2883 case FORMAT_YV12_BT709:
2884 case FORMAT_YV12_JFIF:
2885 return false;
2886 case FORMAT_R32I:
2887 case FORMAT_R32UI:
2888 case FORMAT_G32R32I:
2889 case FORMAT_G32R32UI:
2890 case FORMAT_X32B32G32R32I:
2891 case FORMAT_X32B32G32R32UI:
2892 case FORMAT_A32B32G32R32I:
2893 case FORMAT_A32B32G32R32UI:
2894 return true;
2895 default:
2896 ASSERT(false);
2897 }
2898
2899 return false;
2900 }
2901
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002902 bool SamplerCore::hasYuvFormat() const
2903 {
2904 switch(state.textureFormat)
2905 {
2906 case FORMAT_YV12_BT601:
2907 case FORMAT_YV12_BT709:
2908 case FORMAT_YV12_JFIF:
2909 return true;
2910 case FORMAT_R5G6B5:
Nicolas Capens975adb72017-12-19 15:34:20 -05002911 case FORMAT_R8_SNORM:
2912 case FORMAT_G8R8_SNORM:
2913 case FORMAT_X8B8G8R8_SNORM:
2914 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002915 case FORMAT_R8I:
2916 case FORMAT_R8UI:
2917 case FORMAT_G8R8I:
2918 case FORMAT_G8R8UI:
2919 case FORMAT_X8B8G8R8I:
2920 case FORMAT_X8B8G8R8UI:
2921 case FORMAT_A8B8G8R8I:
2922 case FORMAT_A8B8G8R8UI:
2923 case FORMAT_R32I:
2924 case FORMAT_R32UI:
2925 case FORMAT_G32R32I:
2926 case FORMAT_G32R32UI:
2927 case FORMAT_X32B32G32R32I:
2928 case FORMAT_X32B32G32R32UI:
2929 case FORMAT_A32B32G32R32I:
2930 case FORMAT_A32B32G32R32UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002931 case FORMAT_G8R8:
2932 case FORMAT_X8R8G8B8:
2933 case FORMAT_X8B8G8R8:
2934 case FORMAT_A8R8G8B8:
2935 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002936 case FORMAT_SRGB8_X8:
2937 case FORMAT_SRGB8_A8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002938 case FORMAT_V8U8:
2939 case FORMAT_Q8W8V8U8:
2940 case FORMAT_X8L8V8U8:
2941 case FORMAT_R32F:
2942 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002943 case FORMAT_X32B32G32R32F:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002944 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002945 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002946 case FORMAT_A8:
2947 case FORMAT_R8:
2948 case FORMAT_L8:
2949 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002950 case FORMAT_D32F:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002951 case FORMAT_D32FS8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002952 case FORMAT_D32F_LOCKABLE:
2953 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002954 case FORMAT_D32F_SHADOW:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002955 case FORMAT_D32FS8_SHADOW:
2956 case FORMAT_L16:
2957 case FORMAT_G16R16:
2958 case FORMAT_A16B16G16R16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002959 case FORMAT_R16I:
2960 case FORMAT_R16UI:
2961 case FORMAT_G16R16I:
2962 case FORMAT_G16R16UI:
2963 case FORMAT_X16B16G16R16I:
2964 case FORMAT_X16B16G16R16UI:
2965 case FORMAT_A16B16G16R16I:
2966 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002967 case FORMAT_V16U16:
2968 case FORMAT_A16W16V16U16:
2969 case FORMAT_Q16W16V16U16:
2970 return false;
2971 default:
2972 ASSERT(false);
2973 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002974
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002975 return false;
2976 }
2977
John Bauman89401822014-05-06 15:04:28 -04002978 bool SamplerCore::isRGBComponent(int component) const
2979 {
2980 switch(state.textureFormat)
2981 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002982 case FORMAT_R5G6B5: return component < 3;
Nicolas Capens975adb72017-12-19 15:34:20 -05002983 case FORMAT_R8_SNORM: return component < 1;
2984 case FORMAT_G8R8_SNORM: return component < 2;
2985 case FORMAT_X8B8G8R8_SNORM: return component < 3;
2986 case FORMAT_A8B8G8R8_SNORM: return component < 3;
Alexis Hetu3412d872015-10-26 16:40:26 -04002987 case FORMAT_R8I: return component < 1;
2988 case FORMAT_R8UI: return component < 1;
2989 case FORMAT_G8R8I: return component < 2;
2990 case FORMAT_G8R8UI: return component < 2;
2991 case FORMAT_X8B8G8R8I: return component < 3;
2992 case FORMAT_X8B8G8R8UI: return component < 3;
2993 case FORMAT_A8B8G8R8I: return component < 3;
2994 case FORMAT_A8B8G8R8UI: return component < 3;
2995 case FORMAT_R32I: return component < 1;
2996 case FORMAT_R32UI: return component < 1;
2997 case FORMAT_G32R32I: return component < 2;
2998 case FORMAT_G32R32UI: return component < 2;
2999 case FORMAT_X32B32G32R32I: return component < 3;
3000 case FORMAT_X32B32G32R32UI: return component < 3;
3001 case FORMAT_A32B32G32R32I: return component < 3;
3002 case FORMAT_A32B32G32R32UI: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003003 case FORMAT_G8R8: return component < 2;
3004 case FORMAT_X8R8G8B8: return component < 3;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04003005 case FORMAT_X8B8G8R8: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003006 case FORMAT_A8R8G8B8: return component < 3;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04003007 case FORMAT_A8B8G8R8: return component < 3;
Alexis Hetu049a1872016-04-25 16:59:58 -04003008 case FORMAT_SRGB8_X8: return component < 3;
3009 case FORMAT_SRGB8_A8: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003010 case FORMAT_V8U8: return false;
3011 case FORMAT_Q8W8V8U8: return false;
3012 case FORMAT_X8L8V8U8: return false;
3013 case FORMAT_R32F: return component < 1;
3014 case FORMAT_G32R32F: return component < 2;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04003015 case FORMAT_X32B32G32R32F: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003016 case FORMAT_A32B32G32R32F: return component < 3;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003017 case FORMAT_X32B32G32R32F_UNSIGNED: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003018 case FORMAT_A8: return false;
3019 case FORMAT_R8: return component < 1;
3020 case FORMAT_L8: return component < 1;
3021 case FORMAT_A8L8: return component < 1;
Alexis Hetu3412d872015-10-26 16:40:26 -04003022 case FORMAT_D32F: return false;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003023 case FORMAT_D32FS8: return false;
John Bauman66b8ab22014-05-06 15:57:45 -04003024 case FORMAT_D32F_LOCKABLE: return false;
3025 case FORMAT_D32FS8_TEXTURE: return false;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003026 case FORMAT_D32F_SHADOW: return false;
John Bauman66b8ab22014-05-06 15:57:45 -04003027 case FORMAT_D32FS8_SHADOW: return false;
3028 case FORMAT_L16: return component < 1;
3029 case FORMAT_G16R16: return component < 2;
3030 case FORMAT_A16B16G16R16: return component < 3;
Alexis Hetu3412d872015-10-26 16:40:26 -04003031 case FORMAT_R16I: return component < 1;
3032 case FORMAT_R16UI: return component < 1;
3033 case FORMAT_G16R16I: return component < 2;
3034 case FORMAT_G16R16UI: return component < 2;
3035 case FORMAT_X16B16G16R16I: return component < 3;
3036 case FORMAT_X16B16G16R16UI: return component < 3;
3037 case FORMAT_A16B16G16R16I: return component < 3;
3038 case FORMAT_A16B16G16R16UI: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003039 case FORMAT_V16U16: return false;
3040 case FORMAT_A16W16V16U16: return false;
3041 case FORMAT_Q16W16V16U16: return false;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04003042 case FORMAT_YV12_BT601: return component < 3;
3043 case FORMAT_YV12_BT709: return component < 3;
3044 case FORMAT_YV12_JFIF: return component < 3;
John Bauman89401822014-05-06 15:04:28 -04003045 default:
3046 ASSERT(false);
3047 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05003048
John Bauman89401822014-05-06 15:04:28 -04003049 return false;
3050 }
3051}