blob: ff607d12a9a46d337e11a09f72c52929e991aa95 [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;
Nicolas Capens57642352018-02-27 13:29:26 -0500245 case FORMAT_D32F_LOCKABLE:
246 case FORMAT_D32FS8_TEXTURE:
247 case FORMAT_D32F_SHADOW:
248 case FORMAT_D32FS8_SHADOW:
249 c.y = c.x;
250 c.z = c.x;
251 c.w = c.x;
252 break;
253 default:
254 ASSERT(false);
255 }
256 }
257
258 if((state.swizzleR != SWIZZLE_RED) ||
259 (state.swizzleG != SWIZZLE_GREEN) ||
260 (state.swizzleB != SWIZZLE_BLUE) ||
261 (state.swizzleA != SWIZZLE_ALPHA))
262 {
263 const Vector4s col(c);
264 applySwizzle(state.swizzleR, c.x, col);
265 applySwizzle(state.swizzleG, c.y, col);
266 applySwizzle(state.swizzleB, c.z, col);
267 applySwizzle(state.swizzleA, c.w, col);
John Bauman89401822014-05-06 15:04:28 -0400268 }
269 }
270 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400271
Nicolas Capens89a218b2017-11-07 13:05:20 -0500272 return c;
John Bauman89401822014-05-06 15:04:28 -0400273 }
274
Nicolas Capensa0b57832017-11-07 13:07:53 -0500275 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 -0400276 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500277 Vector4f c;
278
John Bauman89401822014-05-06 15:04:28 -0400279 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -0400280 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -0400281
282 if(state.compressedFormat)
283 {
John Bauman66b8ab22014-05-06 15:57:45 -0400284 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -0400285 }
286 #endif
287
John Bauman89401822014-05-06 15:04:28 -0400288 if(state.textureType == TEXTURE_NULL)
289 {
John Bauman19bac1e2014-05-06 15:23:49 -0400290 c.x = Float4(0.0f);
291 c.y = Float4(0.0f);
292 c.z = Float4(0.0f);
293 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400294 }
295 else
296 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500297 // FIXME: YUV is not supported by the floating point path
298 bool forceFloatFiltering = state.highPrecisionFiltering && !hasYuvFormat() && (state.textureFilter != FILTER_POINT);
Nicolas Capensd0f5d392017-11-28 15:54:59 -0500299 bool seamlessCube = (state.addressingModeU == ADDRESSING_SEAMLESS);
Alexis Hetuc0632c92018-03-02 15:10:16 -0500300 bool rectangleTexture = (state.textureType == TEXTURE_RECTANGLE);
Alexis Hetu46768622018-01-16 22:09:28 -0500301 if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering || seamlessCube || rectangleTexture) // FIXME: Mostly identical to integer sampling
John Bauman89401822014-05-06 15:04:28 -0400302 {
303 Float4 uuuu = u;
304 Float4 vvvv = v;
305 Float4 wwww = w;
Nicolas Capensa0b57832017-11-07 13:07:53 -0500306 Float4 qqqq = q;
John Bauman89401822014-05-06 15:04:28 -0400307
308 Int face[4];
John Bauman89401822014-05-06 15:04:28 -0400309 Float lod;
310 Float anisotropy;
311 Float4 uDelta;
312 Float4 vDelta;
313
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500314 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400315 {
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500316 if(state.textureType != TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400317 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500318 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, bias.x, dsx, dsy, function);
John Bauman89401822014-05-06 15:04:28 -0400319 }
320 else
321 {
Nicolas Capens77f0b682017-11-07 13:25:09 -0500322 Float4 M;
323 cubeFace(face, uuuu, vvvv, u, v, w, M);
324 computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
John Bauman89401822014-05-06 15:04:28 -0400325 }
326 }
327 else
328 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500329 computeLod3D(texture, lod, uuuu, vvvv, wwww, bias.x, dsx, dsy, function);
John Bauman89401822014-05-06 15:04:28 -0400330 }
331
Nicolas Capensa0b57832017-11-07 13:07:53 -0500332 c = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
Alexis Hetufacada52017-07-20 16:56:30 -0400333
334 if(!hasFloatTexture() && !hasUnnormalizedIntegerTexture())
335 {
336 if(has16bitTextureFormat())
337 {
338 switch(state.textureFormat)
339 {
340 case FORMAT_R5G6B5:
341 c.x *= Float4(1.0f / 0xF800);
342 c.y *= Float4(1.0f / 0xFC00);
343 c.z *= Float4(1.0f / 0xF800);
344 break;
345 default:
346 ASSERT(false);
347 }
348 }
349 else
350 {
351 for(int component = 0; component < textureComponentCount(); component++)
352 {
353 c[component] *= Float4(hasUnsignedTextureComponent(component) ? 1.0f / 0xFFFF : 1.0f / 0x7FFF);
354 }
355 }
356 }
John Bauman89401822014-05-06 15:04:28 -0400357 }
358 else
359 {
Nicolas Capensa0b57832017-11-07 13:07:53 -0500360 Vector4s cs = sampleTexture(texture, u, v, w, q, bias, dsx, dsy, offset, function, false);
John Bauman89401822014-05-06 15:04:28 -0400361
Nicolas Capens5555af42017-12-14 13:14:03 -0500362 if(state.textureFormat == FORMAT_R5G6B5)
John Bauman89401822014-05-06 15:04:28 -0400363 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500364 c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
365 c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
366 c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
Alexis Hetuab849ae2017-07-14 10:44:10 -0400367 }
368 else
369 {
370 for(int component = 0; component < textureComponentCount(); component++)
John Bauman89401822014-05-06 15:04:28 -0400371 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500372 if(hasUnsignedTextureComponent(component))
John Bauman89401822014-05-06 15:04:28 -0400373 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500374 convertUnsigned16(c[component], cs[component]);
Alexis Hetu91dd1c42017-07-18 13:03:42 -0400375 }
376 else
377 {
Nicolas Capens5555af42017-12-14 13:14:03 -0500378 convertSigned15(c[component], cs[component]);
John Bauman89401822014-05-06 15:04:28 -0400379 }
380 }
381 }
382 }
383
384 int componentCount = textureComponentCount();
Alexis Hetu56f256e2017-07-21 11:41:13 -0400385 float defaultColorValue = colorsDefaultToZero ? 0.0f : 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400386
387 if(state.textureFilter != FILTER_GATHER)
388 {
389 switch(state.textureFormat)
390 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400391 case FORMAT_R8I:
392 case FORMAT_R8UI:
393 case FORMAT_R16I:
394 case FORMAT_R16UI:
395 case FORMAT_R32I:
396 case FORMAT_R32UI:
397 c.y = As<Float4>(UInt4(0));
398 case FORMAT_G8R8I:
399 case FORMAT_G8R8UI:
400 case FORMAT_G16R16I:
401 case FORMAT_G16R16UI:
402 case FORMAT_G32R32I:
403 case FORMAT_G32R32UI:
404 c.z = As<Float4>(UInt4(0));
405 case FORMAT_X8B8G8R8I:
406 case FORMAT_X8B8G8R8UI:
407 case FORMAT_X16B16G16R16I:
408 case FORMAT_X16B16G16R16UI:
409 case FORMAT_X32B32G32R32I:
410 case FORMAT_X32B32G32R32UI:
411 c.w = As<Float4>(UInt4(1));
412 case FORMAT_A8B8G8R8I:
413 case FORMAT_A8B8G8R8UI:
414 case FORMAT_A16B16G16R16I:
415 case FORMAT_A16B16G16R16UI:
416 case FORMAT_A32B32G32R32I:
417 case FORMAT_A32B32G32R32UI:
418 break;
Nicolas Capens975adb72017-12-19 15:34:20 -0500419 case FORMAT_R8_SNORM:
420 case FORMAT_G8R8_SNORM:
421 case FORMAT_X8B8G8R8_SNORM:
422 case FORMAT_A8B8G8R8_SNORM:
John Bauman89401822014-05-06 15:04:28 -0400423 case FORMAT_R8:
Nicolas Capens27496312015-05-12 15:16:06 -0400424 case FORMAT_R5G6B5:
Alexis Hetu3412d872015-10-26 16:40:26 -0400425 case FORMAT_G8R8:
426 case FORMAT_G16R16:
427 case FORMAT_A16B16G16R16:
John Bauman89401822014-05-06 15:04:28 -0400428 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400429 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -0400430 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400431 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400432 case FORMAT_SRGB8_X8:
433 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -0400434 case FORMAT_V8U8:
435 case FORMAT_Q8W8V8U8:
436 case FORMAT_X8L8V8U8:
437 case FORMAT_V16U16:
438 case FORMAT_A16W16V16U16:
439 case FORMAT_Q16W16V16U16:
Nicolas Capens9ada3092017-05-24 17:39:49 -0400440 case FORMAT_YV12_BT601:
441 case FORMAT_YV12_BT709:
442 case FORMAT_YV12_JFIF:
Alexis Hetu56f256e2017-07-21 11:41:13 -0400443 if(componentCount < 2) c.y = Float4(defaultColorValue);
444 if(componentCount < 3) c.z = Float4(defaultColorValue);
John Bauman19bac1e2014-05-06 15:23:49 -0400445 if(componentCount < 4) c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400446 break;
447 case FORMAT_A8:
John Bauman19bac1e2014-05-06 15:23:49 -0400448 c.w = c.x;
449 c.x = Float4(0.0f);
450 c.y = Float4(0.0f);
451 c.z = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -0400452 break;
453 case FORMAT_L8:
454 case FORMAT_L16:
John Bauman19bac1e2014-05-06 15:23:49 -0400455 c.y = c.x;
456 c.z = c.x;
457 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400458 break;
459 case FORMAT_A8L8:
John Bauman19bac1e2014-05-06 15:23:49 -0400460 c.w = c.y;
461 c.y = c.x;
462 c.z = c.x;
John Bauman89401822014-05-06 15:04:28 -0400463 break;
464 case FORMAT_R32F:
Alexis Hetu56f256e2017-07-21 11:41:13 -0400465 c.y = Float4(defaultColorValue);
John Bauman89401822014-05-06 15:04:28 -0400466 case FORMAT_G32R32F:
Alexis Hetu56f256e2017-07-21 11:41:13 -0400467 c.z = Float4(defaultColorValue);
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400468 case FORMAT_X32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -0500469 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman19bac1e2014-05-06 15:23:49 -0400470 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400471 case FORMAT_A32B32G32R32F:
472 break;
473 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400474 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -0500475 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -0400476 case FORMAT_D32FS8_SHADOW:
Alexis Hetuab2dd502017-11-16 15:35:59 -0500477 c.y = Float4(0.0f);
478 c.z = Float4(0.0f);
479 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400480 break;
481 default:
482 ASSERT(false);
483 }
484 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400485
Nicolas Capens57642352018-02-27 13:29:26 -0500486 if((state.swizzleR != SWIZZLE_RED) ||
487 (state.swizzleG != SWIZZLE_GREEN) ||
488 (state.swizzleB != SWIZZLE_BLUE) ||
489 (state.swizzleA != SWIZZLE_ALPHA))
490 {
491 const Vector4f col(c);
492 applySwizzle(state.swizzleR, c.x, col);
493 applySwizzle(state.swizzleG, c.y, col);
494 applySwizzle(state.swizzleB, c.z, col);
495 applySwizzle(state.swizzleA, c.w, col);
496 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400497 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500498
499 return c;
John Bauman89401822014-05-06 15:04:28 -0400500 }
501
Nicolas Capens89a218b2017-11-07 13:05:20 -0500502 Vector4f SamplerCore::textureSize(Pointer<Byte> &texture, Float4 &lod)
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400503 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500504 Vector4f size;
505
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400506 for(int i = 0; i < 4; ++i)
507 {
Alexis Hetu95ac1872016-06-06 13:26:52 -0400508 Int baseLevel = *Pointer<Int>(texture + OFFSET(Texture, baseLevel));
509 Pointer<Byte> mipmap = texture + OFFSET(Texture, mipmap) + (As<Int>(Extract(lod, i)) + baseLevel) * sizeof(Mipmap);
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400510 size.x = Insert(size.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
511 size.y = Insert(size.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
512 size.z = Insert(size.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
513 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500514
515 return size;
Alexis Hetu9f7d5622016-06-02 17:47:38 -0400516 }
517
John Bauman89401822014-05-06 15:04:28 -0400518 void SamplerCore::border(Short4 &mask, Float4 &coordinates)
519 {
520 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
Nicolas Capens33438a62017-09-27 11:47:35 -0400521 mask = As<Short4>(Int2(As<Int4>(PackSigned(border, border))));
John Bauman89401822014-05-06 15:04:28 -0400522 }
523
524 void SamplerCore::border(Int4 &mask, Float4 &coordinates)
525 {
526 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
527 }
528
Nicolas Capensb81efca2017-12-19 10:52:14 -0500529 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
John Bauman89401822014-05-06 15:04:28 -0400530 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500531 Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
532
533 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
534 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500535 offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
Nicolas Capens5989fab2016-02-15 10:31:49 -0500536 }
537 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
538 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500539 offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
Nicolas Capens5989fab2016-02-15 10:31:49 -0500540 }
541
John Bauman89401822014-05-06 15:04:28 -0400542 if(wrap)
543 {
544 switch(count)
545 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500546 case -1: return uvw - offset;
John Bauman89401822014-05-06 15:04:28 -0400547 case 0: return uvw;
Nicolas Capens5989fab2016-02-15 10:31:49 -0500548 case +1: return uvw + offset;
549 case 2: return uvw + offset + offset;
John Bauman89401822014-05-06 15:04:28 -0400550 }
551 }
552 else // Clamp or mirror
553 {
554 switch(count)
555 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500556 case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset));
John Bauman89401822014-05-06 15:04:28 -0400557 case 0: return uvw;
Nicolas Capens5989fab2016-02-15 10:31:49 -0500558 case +1: return AddSat(As<UShort4>(uvw), As<UShort4>(offset));
559 case 2: return AddSat(AddSat(As<UShort4>(uvw), As<UShort4>(offset)), As<UShort4>(offset));
John Bauman89401822014-05-06 15:04:28 -0400560 }
561 }
562
563 return uvw;
564 }
565
Nicolas Capens89a218b2017-11-07 13:05:20 -0500566 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 -0400567 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500568 Vector4s c = sampleAniso(texture, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400569
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400570 if(function == Fetch)
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400571 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500572 return c;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400573 }
John Bauman89401822014-05-06 15:04:28 -0400574
Nicolas Capense396a492018-01-02 14:22:23 -0500575 if(state.mipmapFilter == MIPMAP_LINEAR)
John Bauman89401822014-05-06 15:04:28 -0400576 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500577 Vector4s cc = sampleAniso(texture, u, v, w, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
John Bauman89401822014-05-06 15:04:28 -0400578
579 lod *= Float(1 << 16);
580
581 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize
582 Short4 stri = utri >> 1; // FIXME: Optimize
583
John Bauman19bac1e2014-05-06 15:23:49 -0400584 if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri);
585 if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri);
586 if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri);
587 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 -0400588
589 utri = ~utri;
Alexis Hetu90c7ad62016-06-27 11:50:40 -0400590 stri = Short4(0x7FFF) - stri;
John Bauman89401822014-05-06 15:04:28 -0400591
John Bauman19bac1e2014-05-06 15:23:49 -0400592 if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri);
593 if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri);
594 if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri);
595 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 -0500596
John Bauman19bac1e2014-05-06 15:23:49 -0400597 c.x += cc.x;
598 c.y += cc.y;
599 c.z += cc.z;
600 c.w += cc.w;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500601
John Bauman19bac1e2014-05-06 15:23:49 -0400602 if(!hasUnsignedTextureComponent(0)) c.x += c.x;
603 if(!hasUnsignedTextureComponent(1)) c.y += c.y;
604 if(!hasUnsignedTextureComponent(2)) c.z += c.z;
605 if(!hasUnsignedTextureComponent(3)) c.w += c.w;
John Bauman89401822014-05-06 15:04:28 -0400606 }
607
608 Short4 borderMask;
609
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400610 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400611 {
612 Short4 u0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500613
John Bauman89401822014-05-06 15:04:28 -0400614 border(u0, u);
615
616 borderMask = u0;
617 }
618
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400619 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400620 {
621 Short4 v0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500622
John Bauman89401822014-05-06 15:04:28 -0400623 border(v0, v);
624
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400625 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400626 {
627 borderMask &= v0;
628 }
629 else
630 {
631 borderMask = v0;
632 }
633 }
634
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500635 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400636 {
637 Short4 s0;
638
639 border(s0, w);
640
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400641 if(state.addressingModeU == ADDRESSING_BORDER ||
642 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400643 {
644 borderMask &= s0;
645 }
646 else
647 {
648 borderMask = s0;
649 }
650 }
651
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400652 if(state.addressingModeU == ADDRESSING_BORDER ||
653 state.addressingModeV == ADDRESSING_BORDER ||
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500654 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
John Bauman89401822014-05-06 15:04:28 -0400655 {
656 Short4 b;
657
Tom Anderson69bc6e82017-03-20 11:54:29 -0700658 c.x = (borderMask & c.x) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1)));
659 c.y = (borderMask & c.y) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1)));
660 c.z = (borderMask & c.z) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1)));
661 c.w = (borderMask & c.w) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1)));
John Bauman89401822014-05-06 15:04:28 -0400662 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500663
664 return c;
John Bauman89401822014-05-06 15:04:28 -0400665 }
666
Nicolas Capens89a218b2017-11-07 13:05:20 -0500667 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 -0400668 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500669 Vector4s c;
670
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400671 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
John Bauman89401822014-05-06 15:04:28 -0400672 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500673 c = sampleQuad(texture, u, v, w, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400674 }
675 else
676 {
677 Int a = RoundInt(anisotropy);
678
Alexis Hetu96517182015-04-15 10:30:23 -0400679 Vector4s cSum;
John Bauman89401822014-05-06 15:04:28 -0400680
Alexis Hetu90c7ad62016-06-27 11:50:40 -0400681 cSum.x = Short4(0);
682 cSum.y = Short4(0);
683 cSum.z = Short4(0);
684 cSum.w = Short4(0);
John Bauman89401822014-05-06 15:04:28 -0400685
686 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
687 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
688 UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a);
689 Short4 sw = Short4(cw >> 1);
690
691 Float4 du = uDelta;
692 Float4 dv = vDelta;
693
694 Float4 u0 = u + B * du;
695 Float4 v0 = v + B * dv;
696
697 du *= A;
698 dv *= A;
699
700 Int i = 0;
701
702 Do
703 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500704 c = sampleQuad(texture, u0, v0, w, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400705
706 u0 += du;
707 v0 += dv;
708
John Bauman19bac1e2014-05-06 15:23:49 -0400709 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw);
710 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw);
711 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw);
712 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 -0400713
714 i++;
715 }
716 Until(i >= a)
717
John Bauman19bac1e2014-05-06 15:23:49 -0400718 if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x);
719 if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y);
720 if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z);
721 if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w);
John Bauman89401822014-05-06 15:04:28 -0400722 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500723
724 return c;
John Bauman89401822014-05-06 15:04:28 -0400725 }
726
Nicolas Capens89a218b2017-11-07 13:05:20 -0500727 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 -0400728 {
Alexis Hetuc8b97852016-02-04 21:15:03 -0500729 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400730 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500731 return sampleQuad2D(texture, u, v, w, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400732 }
733 else
734 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500735 return sample3D(texture, u, v, w, offset, lod, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -0400736 }
737 }
738
Nicolas Capens89a218b2017-11-07 13:05:20 -0500739 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 -0400740 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500741 Vector4s c;
742
John Bauman89401822014-05-06 15:04:28 -0400743 int componentCount = textureComponentCount();
744 bool gather = state.textureFilter == FILTER_GATHER;
745
746 Pointer<Byte> mipmap;
747 Pointer<Byte> buffer[4];
748
749 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
750
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400751 bool texelFetch = (function == Fetch);
John Bauman89401822014-05-06 15:04:28 -0400752
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400753 Short4 uuuu = texelFetch ? Short4(As<Int4>(u)) : address(u, state.addressingModeU, mipmap);
754 Short4 vvvv = texelFetch ? Short4(As<Int4>(v)) : address(v, state.addressingModeV, mipmap);
755 Short4 wwww = texelFetch ? Short4(As<Int4>(w)) : address(w, state.addressingModeW, mipmap);
756
757 if(state.textureFilter == FILTER_POINT || texelFetch)
John Bauman89401822014-05-06 15:04:28 -0400758 {
Nicolas Capens5790c952017-08-01 17:00:36 -0400759 c = sampleTexel(uuuu, vvvv, wwww, offset, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -0400760 }
761 else
762 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500763 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
764 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
765 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
766 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
John Bauman89401822014-05-06 15:04:28 -0400767
Nicolas Capens5790c952017-08-01 17:00:36 -0400768 Vector4s c0 = sampleTexel(uuuu0, vvvv0, wwww, offset, mipmap, buffer, function);
769 Vector4s c1 = sampleTexel(uuuu1, vvvv0, wwww, offset, mipmap, buffer, function);
770 Vector4s c2 = sampleTexel(uuuu0, vvvv1, wwww, offset, mipmap, buffer, function);
771 Vector4s c3 = sampleTexel(uuuu1, vvvv1, wwww, offset, mipmap, buffer, function);
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500772
John Bauman89401822014-05-06 15:04:28 -0400773 if(!gather) // Blend
774 {
775 // Fractions
Nicolas Capens77980512016-12-02 14:22:32 -0500776 UShort4 f0u = As<UShort4>(uuuu0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
777 UShort4 f0v = As<UShort4>(vvvv0) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
John Bauman89401822014-05-06 15:04:28 -0400778
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400779 UShort4 f1u = ~f0u;
780 UShort4 f1v = ~f0v;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500781
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400782 UShort4 f0u0v = MulHigh(f0u, f0v);
783 UShort4 f1u0v = MulHigh(f1u, f0v);
784 UShort4 f0u1v = MulHigh(f0u, f1v);
785 UShort4 f1u1v = MulHigh(f1u, f1v);
John Bauman89401822014-05-06 15:04:28 -0400786
787 // Signed fractions
788 Short4 f1u1vs;
789 Short4 f0u1vs;
790 Short4 f1u0vs;
791 Short4 f0u0vs;
792
793 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
794 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400795 f1u1vs = f1u1v >> 1;
796 f0u1vs = f0u1v >> 1;
797 f1u0vs = f1u0v >> 1;
798 f0u0vs = f0u0v >> 1;
John Bauman89401822014-05-06 15:04:28 -0400799 }
800
801 // Bilinear interpolation
802 if(componentCount >= 1)
803 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400804 if(has16bitTextureComponents() && hasUnsignedTextureComponent(0))
John Bauman89401822014-05-06 15:04:28 -0400805 {
John Bauman19bac1e2014-05-06 15:23:49 -0400806 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u);
807 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u);
808 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 -0400809 }
810 else
811 {
812 if(hasUnsignedTextureComponent(0))
813 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400814 c0.x = MulHigh(As<UShort4>(c0.x), f1u1v);
815 c1.x = MulHigh(As<UShort4>(c1.x), f0u1v);
816 c2.x = MulHigh(As<UShort4>(c2.x), f1u0v);
817 c3.x = MulHigh(As<UShort4>(c3.x), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400818 }
819 else
820 {
John Bauman19bac1e2014-05-06 15:23:49 -0400821 c0.x = MulHigh(c0.x, f1u1vs);
822 c1.x = MulHigh(c1.x, f0u1vs);
823 c2.x = MulHigh(c2.x, f1u0vs);
824 c3.x = MulHigh(c3.x, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400825 }
826
John Bauman19bac1e2014-05-06 15:23:49 -0400827 c.x = (c0.x + c1.x) + (c2.x + c3.x);
828 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400829 }
830 }
831
832 if(componentCount >= 2)
833 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400834 if(has16bitTextureComponents() && hasUnsignedTextureComponent(1))
John Bauman89401822014-05-06 15:04:28 -0400835 {
John Bauman19bac1e2014-05-06 15:23:49 -0400836 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u);
837 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u);
838 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 -0400839 }
840 else
841 {
842 if(hasUnsignedTextureComponent(1))
843 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400844 c0.y = MulHigh(As<UShort4>(c0.y), f1u1v);
845 c1.y = MulHigh(As<UShort4>(c1.y), f0u1v);
846 c2.y = MulHigh(As<UShort4>(c2.y), f1u0v);
847 c3.y = MulHigh(As<UShort4>(c3.y), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400848 }
849 else
850 {
John Bauman19bac1e2014-05-06 15:23:49 -0400851 c0.y = MulHigh(c0.y, f1u1vs);
852 c1.y = MulHigh(c1.y, f0u1vs);
853 c2.y = MulHigh(c2.y, f1u0vs);
854 c3.y = MulHigh(c3.y, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400855 }
856
John Bauman19bac1e2014-05-06 15:23:49 -0400857 c.y = (c0.y + c1.y) + (c2.y + c3.y);
858 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400859 }
860 }
861
862 if(componentCount >= 3)
863 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400864 if(has16bitTextureComponents() && hasUnsignedTextureComponent(2))
John Bauman89401822014-05-06 15:04:28 -0400865 {
John Bauman19bac1e2014-05-06 15:23:49 -0400866 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u);
867 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u);
868 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 -0400869 }
870 else
871 {
872 if(hasUnsignedTextureComponent(2))
873 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400874 c0.z = MulHigh(As<UShort4>(c0.z), f1u1v);
875 c1.z = MulHigh(As<UShort4>(c1.z), f0u1v);
876 c2.z = MulHigh(As<UShort4>(c2.z), f1u0v);
877 c3.z = MulHigh(As<UShort4>(c3.z), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400878 }
879 else
880 {
John Bauman19bac1e2014-05-06 15:23:49 -0400881 c0.z = MulHigh(c0.z, f1u1vs);
882 c1.z = MulHigh(c1.z, f0u1vs);
883 c2.z = MulHigh(c2.z, f1u0vs);
884 c3.z = MulHigh(c3.z, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400885 }
886
John Bauman19bac1e2014-05-06 15:23:49 -0400887 c.z = (c0.z + c1.z) + (c2.z + c3.z);
888 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400889 }
890 }
891
892 if(componentCount >= 4)
893 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400894 if(has16bitTextureComponents() && hasUnsignedTextureComponent(3))
John Bauman89401822014-05-06 15:04:28 -0400895 {
John Bauman19bac1e2014-05-06 15:23:49 -0400896 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u);
897 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u);
898 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 -0400899 }
900 else
901 {
902 if(hasUnsignedTextureComponent(3))
903 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400904 c0.w = MulHigh(As<UShort4>(c0.w), f1u1v);
905 c1.w = MulHigh(As<UShort4>(c1.w), f0u1v);
906 c2.w = MulHigh(As<UShort4>(c2.w), f1u0v);
907 c3.w = MulHigh(As<UShort4>(c3.w), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400908 }
909 else
910 {
John Bauman19bac1e2014-05-06 15:23:49 -0400911 c0.w = MulHigh(c0.w, f1u1vs);
912 c1.w = MulHigh(c1.w, f0u1vs);
913 c2.w = MulHigh(c2.w, f1u0vs);
914 c3.w = MulHigh(c3.w, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400915 }
916
John Bauman19bac1e2014-05-06 15:23:49 -0400917 c.w = (c0.w + c1.w) + (c2.w + c3.w);
918 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400919 }
920 }
921 }
922 else
923 {
John Bauman19bac1e2014-05-06 15:23:49 -0400924 c.x = c1.x;
925 c.y = c2.x;
926 c.z = c3.x;
927 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -0400928 }
929 }
Nicolas Capens89a218b2017-11-07 13:05:20 -0500930
931 return c;
John Bauman89401822014-05-06 15:04:28 -0400932 }
933
Nicolas Capens89a218b2017-11-07 13:05:20 -0500934 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 -0400935 {
Nicolas Capens89a218b2017-11-07 13:05:20 -0500936 Vector4s c_;
937
John Bauman89401822014-05-06 15:04:28 -0400938 int componentCount = textureComponentCount();
939
940 Pointer<Byte> mipmap;
941 Pointer<Byte> buffer[4];
942 Int face[4];
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500943
John Bauman89401822014-05-06 15:04:28 -0400944 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
945
Nicolas Capensa3c16e42016-06-15 16:45:53 -0400946 bool texelFetch = (function == Fetch);
John Bauman89401822014-05-06 15:04:28 -0400947
Meng-Lin Wu2fce5822016-06-07 16:15:12 -0400948 Short4 uuuu = texelFetch ? Short4(As<Int4>(u_)) : address(u_, state.addressingModeU, mipmap);
949 Short4 vvvv = texelFetch ? Short4(As<Int4>(v_)) : address(v_, state.addressingModeV, mipmap);
950 Short4 wwww = texelFetch ? Short4(As<Int4>(w_)) : address(w_, state.addressingModeW, mipmap);
951
952 if(state.textureFilter == FILTER_POINT || texelFetch)
John Bauman89401822014-05-06 15:04:28 -0400953 {
Nicolas Capens5790c952017-08-01 17:00:36 -0400954 c_ = sampleTexel(uuuu, vvvv, wwww, offset, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -0400955 }
956 else
957 {
Alexis Hetu96517182015-04-15 10:30:23 -0400958 Vector4s c[2][2][2];
John Bauman89401822014-05-06 15:04:28 -0400959
960 Short4 u[2][2][2];
961 Short4 v[2][2][2];
962 Short4 s[2][2][2];
963
964 for(int i = 0; i < 2; i++)
965 {
966 for(int j = 0; j < 2; j++)
967 {
968 for(int k = 0; k < 2; k++)
969 {
Nicolas Capensb81efca2017-12-19 10:52:14 -0500970 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
971 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
972 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 -0400973 }
974 }
975 }
976
John Bauman89401822014-05-06 15:04:28 -0400977 // Fractions
Nicolas Capens77980512016-12-02 14:22:32 -0500978 UShort4 f0u = As<UShort4>(u[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
979 UShort4 f0v = As<UShort4>(v[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
980 UShort4 f0s = As<UShort4>(s[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth));
John Bauman89401822014-05-06 15:04:28 -0400981
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400982 UShort4 f1u = ~f0u;
983 UShort4 f1v = ~f0v;
984 UShort4 f1s = ~f0s;
John Bauman89401822014-05-06 15:04:28 -0400985
Nicolas Capens77980512016-12-02 14:22:32 -0500986 UShort4 f[2][2][2];
987 Short4 fs[2][2][2];
988
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400989 f[1][1][1] = MulHigh(f1u, f1v);
990 f[0][1][1] = MulHigh(f0u, f1v);
991 f[1][0][1] = MulHigh(f1u, f0v);
992 f[0][0][1] = MulHigh(f0u, f0v);
993 f[1][1][0] = MulHigh(f1u, f1v);
994 f[0][1][0] = MulHigh(f0u, f1v);
995 f[1][0][0] = MulHigh(f1u, f0v);
996 f[0][0][0] = MulHigh(f0u, f0v);
John Bauman89401822014-05-06 15:04:28 -0400997
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400998 f[1][1][1] = MulHigh(f[1][1][1], f1s);
999 f[0][1][1] = MulHigh(f[0][1][1], f1s);
1000 f[1][0][1] = MulHigh(f[1][0][1], f1s);
1001 f[0][0][1] = MulHigh(f[0][0][1], f1s);
1002 f[1][1][0] = MulHigh(f[1][1][0], f0s);
1003 f[0][1][0] = MulHigh(f[0][1][0], f0s);
1004 f[1][0][0] = MulHigh(f[1][0][0], f0s);
1005 f[0][0][0] = MulHigh(f[0][0][0], f0s);
John Bauman89401822014-05-06 15:04:28 -04001006
1007 // Signed fractions
1008 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
1009 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001010 fs[0][0][0] = f[0][0][0] >> 1;
1011 fs[0][0][1] = f[0][0][1] >> 1;
1012 fs[0][1][0] = f[0][1][0] >> 1;
1013 fs[0][1][1] = f[0][1][1] >> 1;
1014 fs[1][0][0] = f[1][0][0] >> 1;
1015 fs[1][0][1] = f[1][0][1] >> 1;
1016 fs[1][1][0] = f[1][1][0] >> 1;
1017 fs[1][1][1] = f[1][1][1] >> 1;
John Bauman89401822014-05-06 15:04:28 -04001018 }
1019
1020 for(int i = 0; i < 2; i++)
1021 {
1022 for(int j = 0; j < 2; j++)
1023 {
1024 for(int k = 0; k < 2; k++)
1025 {
Nicolas Capens5790c952017-08-01 17:00:36 -04001026 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 -04001027
Alexis Hetu0085c442015-06-12 15:19:20 -04001028 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]); }
1029 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]); }
1030 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]); }
1031 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 -04001032
1033 if(i != 0 || j != 0 || k != 0)
1034 {
John Bauman19bac1e2014-05-06 15:23:49 -04001035 if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x;
1036 if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y;
1037 if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z;
1038 if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w;
John Bauman89401822014-05-06 15:04:28 -04001039 }
1040 }
1041 }
1042 }
1043
John Bauman19bac1e2014-05-06 15:23:49 -04001044 if(componentCount >= 1) c_.x = c[0][0][0].x;
1045 if(componentCount >= 2) c_.y = c[0][0][0].y;
1046 if(componentCount >= 3) c_.z = c[0][0][0].z;
1047 if(componentCount >= 4) c_.w = c[0][0][0].w;
John Bauman89401822014-05-06 15:04:28 -04001048
1049 // Correct for signed fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001050 if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x);
1051 if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y);
1052 if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z);
1053 if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w);
John Bauman89401822014-05-06 15:04:28 -04001054 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001055
1056 return c_;
John Bauman89401822014-05-06 15:04:28 -04001057 }
1058
Nicolas Capensa0b57832017-11-07 13:07:53 -05001059 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 -04001060 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001061 Vector4f c = sampleFloatAniso(texture, u, v, w, q, offset, lod, anisotropy, uDelta, vDelta, face, false, function);
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001062
1063 if(function == Fetch)
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001064 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001065 return c;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001066 }
John Bauman89401822014-05-06 15:04:28 -04001067
Nicolas Capense396a492018-01-02 14:22:23 -05001068 if(state.mipmapFilter == MIPMAP_LINEAR)
John Bauman89401822014-05-06 15:04:28 -04001069 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001070 Vector4f cc = sampleFloatAniso(texture, u, v, w, q, offset, lod, anisotropy, uDelta, vDelta, face, true, function);
John Bauman89401822014-05-06 15:04:28 -04001071
John Bauman19bac1e2014-05-06 15:23:49 -04001072 Float4 lod4 = Float4(Frac(lod));
John Bauman89401822014-05-06 15:04:28 -04001073
John Bauman19bac1e2014-05-06 15:23:49 -04001074 c.x = (cc.x - c.x) * lod4 + c.x;
1075 c.y = (cc.y - c.y) * lod4 + c.y;
1076 c.z = (cc.z - c.z) * lod4 + c.z;
1077 c.w = (cc.w - c.w) * lod4 + c.w;
John Bauman89401822014-05-06 15:04:28 -04001078 }
1079
1080 Int4 borderMask;
1081
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001082 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001083 {
1084 Int4 u0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001085
John Bauman89401822014-05-06 15:04:28 -04001086 border(u0, u);
1087
1088 borderMask = u0;
1089 }
1090
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001091 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001092 {
1093 Int4 v0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001094
John Bauman89401822014-05-06 15:04:28 -04001095 border(v0, v);
1096
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001097 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001098 {
1099 borderMask &= v0;
1100 }
1101 else
1102 {
1103 borderMask = v0;
1104 }
1105 }
1106
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001107 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -04001108 {
1109 Int4 s0;
1110
1111 border(s0, w);
1112
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001113 if(state.addressingModeU == ADDRESSING_BORDER ||
1114 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001115 {
1116 borderMask &= s0;
1117 }
1118 else
1119 {
1120 borderMask = s0;
1121 }
1122 }
1123
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001124 if(state.addressingModeU == ADDRESSING_BORDER ||
1125 state.addressingModeV == ADDRESSING_BORDER ||
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001126 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
John Bauman89401822014-05-06 15:04:28 -04001127 {
1128 Int4 b;
1129
Tom Anderson69bc6e82017-03-20 11:54:29 -07001130 c.x = As<Float4>((borderMask & As<Int4>(c.x)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0]))));
1131 c.y = As<Float4>((borderMask & As<Int4>(c.y)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1]))));
1132 c.z = As<Float4>((borderMask & As<Int4>(c.z)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2]))));
1133 c.w = As<Float4>((borderMask & As<Int4>(c.w)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3]))));
John Bauman89401822014-05-06 15:04:28 -04001134 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001135
1136 return c;
John Bauman89401822014-05-06 15:04:28 -04001137 }
1138
Nicolas Capensa0b57832017-11-07 13:07:53 -05001139 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 -04001140 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001141 Vector4f c;
1142
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001143 if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
John Bauman89401822014-05-06 15:04:28 -04001144 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001145 c = sampleFloat(texture, u, v, w, q, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001146 }
1147 else
1148 {
1149 Int a = RoundInt(anisotropy);
1150
John Bauman19bac1e2014-05-06 15:23:49 -04001151 Vector4f cSum;
John Bauman89401822014-05-06 15:04:28 -04001152
John Bauman19bac1e2014-05-06 15:23:49 -04001153 cSum.x = Float4(0.0f);
1154 cSum.y = Float4(0.0f);
1155 cSum.z = Float4(0.0f);
1156 cSum.w = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -04001157
1158 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
1159 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
1160
1161 Float4 du = uDelta;
1162 Float4 dv = vDelta;
1163
1164 Float4 u0 = u + B * du;
1165 Float4 v0 = v + B * dv;
1166
1167 du *= A;
1168 dv *= A;
1169
1170 Int i = 0;
1171
1172 Do
1173 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001174 c = sampleFloat(texture, u0, v0, w, q, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001175
1176 u0 += du;
1177 v0 += dv;
1178
John Bauman19bac1e2014-05-06 15:23:49 -04001179 cSum.x += c.x * A;
1180 cSum.y += c.y * A;
1181 cSum.z += c.z * A;
1182 cSum.w += c.w * A;
John Bauman89401822014-05-06 15:04:28 -04001183
1184 i++;
1185 }
1186 Until(i >= a)
1187
John Bauman19bac1e2014-05-06 15:23:49 -04001188 c.x = cSum.x;
1189 c.y = cSum.y;
1190 c.z = cSum.z;
1191 c.w = cSum.w;
John Bauman89401822014-05-06 15:04:28 -04001192 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001193
1194 return c;
John Bauman89401822014-05-06 15:04:28 -04001195 }
1196
Nicolas Capensa0b57832017-11-07 13:07:53 -05001197 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 -04001198 {
Alexis Hetuc8b97852016-02-04 21:15:03 -05001199 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -04001200 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001201 return sampleFloat2D(texture, u, v, w, q, offset, lod, face, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001202 }
1203 else
1204 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001205 return sampleFloat3D(texture, u, v, w, offset, lod, secondLOD, function);
John Bauman89401822014-05-06 15:04:28 -04001206 }
1207 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001208
Nicolas Capensa0b57832017-11-07 13:07:53 -05001209 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 -04001210 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001211 Vector4f c;
1212
John Bauman89401822014-05-06 15:04:28 -04001213 int componentCount = textureComponentCount();
1214 bool gather = state.textureFilter == FILTER_GATHER;
1215
1216 Pointer<Byte> mipmap;
1217 Pointer<Byte> buffer[4];
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001218
John Bauman89401822014-05-06 15:04:28 -04001219 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1220
Alexis Hetu75a61852017-07-14 14:17:14 -04001221 Int4 x0, x1, y0, y1, z0;
1222 Float4 fu, fv;
Nicolas Capensb81efca2017-12-19 10:52:14 -05001223 Int4 filter = computeFilterOffset(lod);
Alexis Hetu75a61852017-07-14 14:17:14 -04001224 address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
Nicolas Capensf8b827e2017-11-27 15:25:05 -05001225 address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
1226 address(w, z0, z0, fv, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
John Bauman89401822014-05-06 15:04:28 -04001227
Alexis Hetu75a61852017-07-14 14:17:14 -04001228 Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16);
1229 y0 *= pitchP;
1230 if(hasThirdCoordinate())
John Bauman89401822014-05-06 15:04:28 -04001231 {
Alexis Hetu75a61852017-07-14 14:17:14 -04001232 Int4 sliceP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, sliceP), 16);
1233 z0 *= sliceP;
1234 }
1235
1236 if(state.textureFilter == FILTER_POINT || (function == Fetch))
1237 {
Nicolas Capensa0b57832017-11-07 13:07:53 -05001238 c = sampleTexel(x0, y0, z0, q, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001239 }
1240 else
1241 {
Alexis Hetu75a61852017-07-14 14:17:14 -04001242 y1 *= pitchP;
John Bauman89401822014-05-06 15:04:28 -04001243
Nicolas Capensa0b57832017-11-07 13:07:53 -05001244 Vector4f c0 = sampleTexel(x0, y0, z0, q, mipmap, buffer, function);
1245 Vector4f c1 = sampleTexel(x1, y0, z0, q, mipmap, buffer, function);
1246 Vector4f c2 = sampleTexel(x0, y1, z0, q, mipmap, buffer, function);
1247 Vector4f c3 = sampleTexel(x1, y1, z0, q, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001248
1249 if(!gather) // Blend
1250 {
John Bauman19bac1e2014-05-06 15:23:49 -04001251 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1252 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1253 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1254 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001255
John Bauman19bac1e2014-05-06 15:23:49 -04001256 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1257 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1258 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1259 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001260
John Bauman19bac1e2014-05-06 15:23:49 -04001261 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x);
1262 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y);
1263 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z);
1264 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001265 }
1266 else
1267 {
John Bauman19bac1e2014-05-06 15:23:49 -04001268 c.x = c1.x;
1269 c.y = c2.x;
1270 c.z = c3.x;
1271 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -04001272 }
1273 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001274
1275 return c;
John Bauman89401822014-05-06 15:04:28 -04001276 }
1277
Nicolas Capens89a218b2017-11-07 13:05:20 -05001278 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 -04001279 {
Nicolas Capens89a218b2017-11-07 13:05:20 -05001280 Vector4f c;
1281
John Bauman89401822014-05-06 15:04:28 -04001282 int componentCount = textureComponentCount();
1283
1284 Pointer<Byte> mipmap;
1285 Pointer<Byte> buffer[4];
1286 Int face[4];
1287
1288 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1289
Alexis Hetu75a61852017-07-14 14:17:14 -04001290 Int4 x0, x1, y0, y1, z0, z1;
1291 Float4 fu, fv, fw;
Nicolas Capensb81efca2017-12-19 10:52:14 -05001292 Int4 filter = computeFilterOffset(lod);
Alexis Hetu75a61852017-07-14 14:17:14 -04001293 address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
1294 address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
1295 address(w, z0, z1, fw, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
John Bauman89401822014-05-06 15:04:28 -04001296
Alexis Hetu75a61852017-07-14 14:17:14 -04001297 Int4 pitchP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, pitchP), 16);
1298 Int4 sliceP = *Pointer<Int4>(mipmap + OFFSET(Mipmap, sliceP), 16);
1299 y0 *= pitchP;
1300 z0 *= sliceP;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001301
Alexis Hetu75a61852017-07-14 14:17:14 -04001302 if(state.textureFilter == FILTER_POINT || (function == Fetch))
John Bauman89401822014-05-06 15:04:28 -04001303 {
Nicolas Capens5790c952017-08-01 17:00:36 -04001304 c = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001305 }
1306 else
1307 {
Alexis Hetu75a61852017-07-14 14:17:14 -04001308 y1 *= pitchP;
1309 z1 *= sliceP;
John Bauman89401822014-05-06 15:04:28 -04001310
Nicolas Capens5790c952017-08-01 17:00:36 -04001311 Vector4f c0 = sampleTexel(x0, y0, z0, w, mipmap, buffer, function);
1312 Vector4f c1 = sampleTexel(x1, y0, z0, w, mipmap, buffer, function);
1313 Vector4f c2 = sampleTexel(x0, y1, z0, w, mipmap, buffer, function);
1314 Vector4f c3 = sampleTexel(x1, y1, z0, w, mipmap, buffer, function);
1315 Vector4f c4 = sampleTexel(x0, y0, z1, w, mipmap, buffer, function);
1316 Vector4f c5 = sampleTexel(x1, y0, z1, w, mipmap, buffer, function);
1317 Vector4f c6 = sampleTexel(x0, y1, z1, w, mipmap, buffer, function);
1318 Vector4f c7 = sampleTexel(x1, y1, z1, w, mipmap, buffer, function);
John Bauman89401822014-05-06 15:04:28 -04001319
1320 // Blend first slice
John Bauman19bac1e2014-05-06 15:23:49 -04001321 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1322 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1323 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1324 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001325
John Bauman19bac1e2014-05-06 15:23:49 -04001326 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1327 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1328 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1329 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001330
John Bauman19bac1e2014-05-06 15:23:49 -04001331 if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x);
1332 if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y);
1333 if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z);
1334 if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001335
1336 // Blend second slice
John Bauman19bac1e2014-05-06 15:23:49 -04001337 if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x);
1338 if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y);
1339 if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z);
1340 if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001341
John Bauman19bac1e2014-05-06 15:23:49 -04001342 if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x);
1343 if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y);
1344 if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z);
1345 if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w);
John Bauman89401822014-05-06 15:04:28 -04001346
John Bauman19bac1e2014-05-06 15:23:49 -04001347 if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x);
1348 if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y);
1349 if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z);
1350 if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001351
1352 // Blend slices
Nicolas Capens5790c952017-08-01 17:00:36 -04001353 if(componentCount >= 1) c.x = c0.x + fw * (c4.x - c0.x);
1354 if(componentCount >= 2) c.y = c0.y + fw * (c4.y - c0.y);
1355 if(componentCount >= 3) c.z = c0.z + fw * (c4.z - c0.z);
1356 if(componentCount >= 4) c.w = c0.w + fw * (c4.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001357 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001358
1359 return c;
John Bauman89401822014-05-06 15:04:28 -04001360 }
1361
Nicolas Capens6e744262017-07-07 12:46:21 -04001362 Float SamplerCore::log2sqrt(Float lod)
1363 {
1364 // log2(sqrt(lod)) // Equals 0.25 * log2(lod^2).
1365 lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
1366 lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
1367 lod *= As<Float>(Int(0x33000000)); // Scale by 0.25 * 2^-23 (mantissa length).
1368
1369 return lod;
1370 }
1371
Nicolas Capens823c1c12017-11-22 15:06:58 -05001372 Float SamplerCore::log2(Float lod)
1373 {
1374 lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
1375 lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
1376 lod *= As<Float>(Int(0x33800000)); // Scale by 0.5 * 2^-23 (mantissa length).
1377
1378 return lod;
1379 }
1380
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001381 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 -04001382 {
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001383 if(function != Lod && function != Fetch)
John Bauman89401822014-05-06 15:04:28 -04001384 {
1385 Float4 duvdxy;
1386
Nicolas Capens161a76e2017-11-24 10:10:22 -05001387 if(function != Grad) // Implicit
John Bauman89401822014-05-06 15:04:28 -04001388 {
1389 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1390 }
1391 else
1392 {
1393 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1394 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001395
John Bauman89401822014-05-06 15:04:28 -04001396 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1397 }
1398
Nicolas Capens823c1c12017-11-22 15:06:58 -05001399 // Scale by texture dimensions and global LOD.
John Bauman89401822014-05-06 15:04:28 -04001400 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1401
1402 Float4 dUV2dxy = dUVdxy * dUVdxy;
1403 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1404
1405 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1406
1407 if(state.textureFilter == FILTER_ANISOTROPIC)
1408 {
1409 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1410
1411 Float4 dudx = duvdxy.xxxx;
1412 Float4 dudy = duvdxy.yyyy;
1413 Float4 dvdx = duvdxy.zzzz;
1414 Float4 dvdy = duvdxy.wwww;
1415
1416 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
Tom Anderson69bc6e82017-03-20 11:54:29 -07001417 uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
1418 vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
John Bauman89401822014-05-06 15:04:28 -04001419
1420 anisotropy = lod * Rcp_pp(det);
1421 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1422
1423 lod *= Rcp_pp(anisotropy * anisotropy);
1424 }
1425
Nicolas Capens6e744262017-07-07 12:46:21 -04001426 lod = log2sqrt(lod); // log2(sqrt(lod))
John Bauman89401822014-05-06 15:04:28 -04001427
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001428 if(function == Bias)
John Bauman89401822014-05-06 15:04:28 -04001429 {
1430 lod += lodBias;
1431 }
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001432 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001433 else if(function == Lod)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001434 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001435 lod = lodBias;
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001436 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001437 else if(function == Fetch)
1438 {
1439 // TODO: Eliminate int-float-int conversion.
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001440 lod = Float(As<Int>(lodBias));
Nicolas Capensa0b57832017-11-07 13:07:53 -05001441 }
1442 else if(function == Base)
1443 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001444 lod = Float(0);
Nicolas Capensa0b57832017-11-07 13:07:53 -05001445 }
1446 else assert(false);
John Bauman89401822014-05-06 15:04:28 -04001447
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001448 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1449 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001450 }
1451
Nicolas Capens77f0b682017-11-07 13:25:09 -05001452 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 -04001453 {
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001454 if(function != Lod && function != Fetch)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001455 {
Nicolas Capens77f0b682017-11-07 13:25:09 -05001456 Float4 dudxy, dvdxy, dsdxy;
1457
Nicolas Capens161a76e2017-11-24 10:10:22 -05001458 if(function != Grad) // Implicit
John Bauman89401822014-05-06 15:04:28 -04001459 {
Nicolas Capens77f0b682017-11-07 13:25:09 -05001460 Float4 U = u * M;
1461 Float4 V = v * M;
1462 Float4 W = w * M;
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001463
Nicolas Capens823c1c12017-11-22 15:06:58 -05001464 dudxy = Abs(U - U.xxxx);
1465 dvdxy = Abs(V - V.xxxx);
1466 dsdxy = Abs(W - W.xxxx);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001467 }
1468 else
1469 {
Nicolas Capens77f0b682017-11-07 13:25:09 -05001470 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1471 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1472 dsdxy = Float4(dsx.z.xx, dsy.z.xx);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001473
Nicolas Capens823c1c12017-11-22 15:06:58 -05001474 dudxy = Abs(dudxy * Float4(M.x));
1475 dvdxy = Abs(dvdxy * Float4(M.x));
1476 dsdxy = Abs(dsdxy * Float4(M.x));
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001477 }
1478
Nicolas Capens823c1c12017-11-22 15:06:58 -05001479 // Compute the largest Manhattan distance in two dimensions.
1480 // This takes the footprint across adjacent faces into account.
1481 Float4 duvdxy = dudxy + dvdxy;
1482 Float4 dusdxy = dudxy + dsdxy;
1483 Float4 dvsdxy = dvdxy + dsdxy;
Nicolas Capens77f0b682017-11-07 13:25:09 -05001484
Nicolas Capens823c1c12017-11-22 15:06:58 -05001485 dudxy = Max(Max(duvdxy, dusdxy), dvsdxy);
Nicolas Capens77f0b682017-11-07 13:25:09 -05001486
Nicolas Capens161a76e2017-11-24 10:10:22 -05001487 lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z);
Nicolas Capens77f0b682017-11-07 13:25:09 -05001488
Nicolas Capens823c1c12017-11-22 15:06:58 -05001489 // Scale by texture dimension and global LOD.
1490 lod *= *Pointer<Float>(texture + OFFSET(Texture,widthLOD));
1491
1492 lod = log2(lod);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001493
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001494 if(function == Bias)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001495 {
1496 lod += lodBias;
John Bauman89401822014-05-06 15:04:28 -04001497 }
1498 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001499 else if(function == Lod)
John Bauman89401822014-05-06 15:04:28 -04001500 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001501 lod = lodBias;
John Bauman89401822014-05-06 15:04:28 -04001502 }
Nicolas Capensa0b57832017-11-07 13:07:53 -05001503 else if(function == Fetch)
1504 {
1505 // TODO: Eliminate int-float-int conversion.
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001506 lod = Float(As<Int>(lodBias));
Nicolas Capensa0b57832017-11-07 13:07:53 -05001507 }
1508 else if(function == Base)
1509 {
Nicolas Capens467ce5a2017-12-19 13:46:29 -05001510 lod = Float(0);
Nicolas Capensa0b57832017-11-07 13:07:53 -05001511 }
1512 else assert(false);
John Bauman89401822014-05-06 15:04:28 -04001513
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001514 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1515 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
John Bauman89401822014-05-06 15:04:28 -04001516 }
1517
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001518 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 -04001519 {
Nicolas Capense396a492018-01-02 14:22:23 -05001520 if(function != Lod && function != Fetch)
John Bauman89401822014-05-06 15:04:28 -04001521 {
Nicolas Capense396a492018-01-02 14:22:23 -05001522 Float4 dudxy, dvdxy, dsdxy;
1523
1524 if(function != Grad) // Implicit
1525 {
1526 dudxy = uuuu - uuuu.xxxx;
1527 dvdxy = vvvv - vvvv.xxxx;
1528 dsdxy = wwww - wwww.xxxx;
1529 }
1530 else
1531 {
1532 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1533 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1534 dsdxy = Float4(dsx.z.xx, dsy.z.xx);
1535 }
1536
1537 // Scale by texture dimensions and global LOD.
1538 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1539 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
1540 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
1541
1542 dudxy *= dudxy;
1543 dvdxy *= dvdxy;
1544 dsdxy *= dsdxy;
1545
1546 dudxy += dvdxy;
1547 dudxy += dsdxy;
1548
1549 lod = Max(Float(dudxy.y), Float(dudxy.z)); // FIXME: Max(dudxy.y, dudxy.z);
1550
1551 lod = log2sqrt(lod); // log2(sqrt(lod))
1552
1553 if(function == Bias)
1554 {
1555 lod += lodBias;
1556 }
John Bauman89401822014-05-06 15:04:28 -04001557 }
Nicolas Capense396a492018-01-02 14:22:23 -05001558 else if(function == Lod)
John Bauman89401822014-05-06 15:04:28 -04001559 {
Nicolas Capense396a492018-01-02 14:22:23 -05001560 lod = lodBias;
John Bauman89401822014-05-06 15:04:28 -04001561 }
Nicolas Capense396a492018-01-02 14:22:23 -05001562 else if(function == Fetch)
1563 {
1564 // TODO: Eliminate int-float-int conversion.
1565 lod = Float(As<Int>(lodBias));
1566 }
1567 else if(function == Base)
1568 {
1569 lod = Float(0);
1570 }
1571 else assert(false);
1572
1573 lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
1574 lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
John Bauman89401822014-05-06 15:04:28 -04001575 }
1576
Nicolas Capens77f0b682017-11-07 13:25:09 -05001577 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 -04001578 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001579 Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0
1580 Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0
1581 Int4 zn = CmpLT(z, Float4(0.0f)); // z < 0
John Bauman89401822014-05-06 15:04:28 -04001582
1583 Float4 absX = Abs(x);
1584 Float4 absY = Abs(y);
1585 Float4 absZ = Abs(z);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001586
John Bauman89401822014-05-06 15:04:28 -04001587 Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y)
1588 Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z)
1589 Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001590 Int4 xMajor = xy & ~zx; // abs(x) > abs(y) && abs(x) > abs(z)
1591 Int4 yMajor = yz & ~xy; // abs(y) > abs(z) && abs(y) > abs(x)
1592 Int4 zMajor = zx & ~yz; // abs(z) > abs(x) && abs(z) > abs(y)
John Bauman89401822014-05-06 15:04:28 -04001593
1594 // FACE_POSITIVE_X = 000b
1595 // FACE_NEGATIVE_X = 001b
1596 // FACE_POSITIVE_Y = 010b
1597 // FACE_NEGATIVE_Y = 011b
1598 // FACE_POSITIVE_Z = 100b
1599 // FACE_NEGATIVE_Z = 101b
1600
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001601 Int yAxis = SignMask(yMajor);
1602 Int zAxis = SignMask(zMajor);
John Bauman89401822014-05-06 15:04:28 -04001603
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001604 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
John Bauman89401822014-05-06 15:04:28 -04001605 Int negative = SignMask(n);
1606
1607 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
1608 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4);
1609 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4);
1610 face[1] = (face[0] >> 4) & 0x7;
1611 face[2] = (face[0] >> 8) & 0x7;
1612 face[3] = (face[0] >> 12) & 0x7;
1613 face[0] &= 0x7;
1614
Nicolas Capens77f0b682017-11-07 13:25:09 -05001615 M = Max(Max(absX, absY), absZ);
John Bauman89401822014-05-06 15:04:28 -04001616
Nicolas Capensd0f5d392017-11-28 15:54:59 -05001617 // U = xMajor ? (neg ^ -z) : ((zMajor & neg) ^ x)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001618 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
John Bauman89401822014-05-06 15:04:28 -04001619
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001620 // V = !yMajor ? -y : (n ^ z)
1621 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001622
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001623 M = reciprocal(M) * Float4(0.5f);
1624 U = U * M + Float4(0.5f);
1625 V = V * M + Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -04001626 }
1627
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001628 Short4 SamplerCore::applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode)
1629 {
1630 Int4 tmp = Int4(As<UShort4>(uvw));
1631 tmp = tmp + As<Int4>(offset);
1632
Nicolas Capens89a218b2017-11-07 13:05:20 -05001633 switch(mode)
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001634 {
1635 case AddressingMode::ADDRESSING_WRAP:
1636 tmp = (tmp + whd * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % whd;
1637 break;
1638 case AddressingMode::ADDRESSING_CLAMP:
1639 case AddressingMode::ADDRESSING_MIRROR:
1640 case AddressingMode::ADDRESSING_MIRRORONCE:
1641 case AddressingMode::ADDRESSING_BORDER: // FIXME: Implement and test ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, ADDRESSING_BORDER
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001642 tmp = Min(Max(tmp, Int4(0)), whd - Int4(1));
1643 break;
1644 case ADDRESSING_TEXELFETCH:
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001645 break;
Nicolas Capensd0f5d392017-11-28 15:54:59 -05001646 case AddressingMode::ADDRESSING_SEAMLESS:
1647 ASSERT(false); // Cube sampling doesn't support offset.
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001648 default:
1649 ASSERT(false);
1650 }
1651
1652 return As<Short4>(UShort4(tmp));
1653 }
1654
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001655 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 -04001656 {
Nicolas Capensa3c16e42016-06-15 16:45:53 -04001657 bool texelFetch = (function == Fetch);
1658 bool hasOffset = (function.option == Offset);
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001659
Nicolas Capens77980512016-12-02 14:22:32 -05001660 if(!texelFetch)
John Bauman89401822014-05-06 15:04:28 -04001661 {
Nicolas Capens77980512016-12-02 14:22:32 -05001662 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width)));
1663 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height)));
John Bauman89401822014-05-06 15:04:28 -04001664 }
Nicolas Capens77980512016-12-02 14:22:32 -05001665
1666 if(hasOffset)
John Bauman89401822014-05-06 15:04:28 -04001667 {
Nicolas Capens2a3932c2017-11-07 14:35:38 -05001668 UShort4 w = *Pointer<UShort4>(mipmap + OFFSET(Mipmap, width));
1669 uuuu = applyOffset(uuuu, offset.x, Int4(w), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeU);
1670 UShort4 h = *Pointer<UShort4>(mipmap + OFFSET(Mipmap, height));
1671 vvvv = applyOffset(vvvv, offset.y, Int4(h), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeV);
Alexis Hetuf15e8942015-12-01 15:13:23 -05001672 }
Nicolas Capens411273e2017-01-26 15:13:36 -08001673
Nicolas Capens77980512016-12-02 14:22:32 -05001674 Short4 uuu2 = uuuu;
1675 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1676 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1677 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1678 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
John Bauman89401822014-05-06 15:04:28 -04001679
Alexis Hetu75a61852017-07-14 14:17:14 -04001680 if(hasThirdCoordinate())
Alexis Hetuf15e8942015-12-01 15:13:23 -05001681 {
1682 if(state.textureType != TEXTURE_2D_ARRAY)
John Bauman89401822014-05-06 15:04:28 -04001683 {
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001684 if(!texelFetch)
1685 {
1686 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth)));
1687 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001688
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001689 if(hasOffset)
1690 {
Nicolas Capens2a3932c2017-11-07 14:35:38 -05001691 UShort4 d = *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth));
1692 wwww = applyOffset(wwww, offset.z, Int4(d), texelFetch ? ADDRESSING_TEXELFETCH : state.addressingModeW);
Meng-Lin Wu2337a192016-06-01 13:54:07 -04001693 }
John Bauman89401822014-05-06 15:04:28 -04001694 }
Nicolas Capens89a218b2017-11-07 13:05:20 -05001695
Alexis Hetu42e53032017-10-03 13:56:07 -04001696 UInt4 uv(As<UInt2>(uuuu), As<UInt2>(uuu2));
1697 uv += As<UInt4>(Int4(As<UShort4>(wwww))) * *Pointer<UInt4>(mipmap + OFFSET(Mipmap, sliceP));
Nicolas Capens89a218b2017-11-07 13:05:20 -05001698
Alexis Hetu42e53032017-10-03 13:56:07 -04001699 index[0] = Extract(As<Int4>(uv), 0);
1700 index[1] = Extract(As<Int4>(uv), 1);
1701 index[2] = Extract(As<Int4>(uv), 2);
1702 index[3] = Extract(As<Int4>(uv), 3);
John Bauman89401822014-05-06 15:04:28 -04001703 }
Alexis Hetu42e53032017-10-03 13:56:07 -04001704 else
1705 {
1706 index[0] = Extract(As<Int2>(uuuu), 0);
1707 index[1] = Extract(As<Int2>(uuuu), 1);
1708 index[2] = Extract(As<Int2>(uuu2), 0);
1709 index[3] = Extract(As<Int2>(uuu2), 1);
1710 }
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001711
1712 if(texelFetch)
1713 {
1714 Int size = Int(*Pointer<Int>(mipmap + OFFSET(Mipmap, sliceP)));
Alexis Hetu75a61852017-07-14 14:17:14 -04001715 if(hasThirdCoordinate())
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001716 {
1717 size *= Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)));
1718 }
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001719 UInt min = 0;
1720 UInt max = size - 1;
Meng-Lin Wu2fce5822016-06-07 16:15:12 -04001721
1722 for(int i = 0; i < 4; i++)
1723 {
1724 index[i] = Min(Max(index[i], min), max);
1725 }
1726 }
John Bauman89401822014-05-06 15:04:28 -04001727 }
1728
Alexis Hetu75a61852017-07-14 14:17:14 -04001729 void SamplerCore::computeIndices(UInt index[4], Int4& uuuu, Int4& vvvv, Int4& wwww, const Pointer<Byte> &mipmap, SamplerFunction function)
1730 {
1731 UInt4 indices = uuuu + vvvv;
1732
1733 if(hasThirdCoordinate())
1734 {
1735 indices += As<UInt4>(wwww);
1736 }
1737
1738 for(int i = 0; i < 4; i++)
1739 {
1740 index[i] = Extract(As<Int4>(indices), i);
1741 }
1742 }
1743
Nicolas Capens5790c952017-08-01 17:00:36 -04001744 Vector4s SamplerCore::sampleTexel(UInt index[4], Pointer<Byte> buffer[4])
John Bauman89401822014-05-06 15:04:28 -04001745 {
Nicolas Capens5790c952017-08-01 17:00:36 -04001746 Vector4s c;
1747
John Bauman89401822014-05-06 15:04:28 -04001748 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1749 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1750 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1751 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1752
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001753 if(has16bitTextureFormat())
John Bauman89401822014-05-06 15:04:28 -04001754 {
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001755 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1756 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1757 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1758 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
Nicolas Capens27496312015-05-12 15:16:06 -04001759
1760 switch(state.textureFormat)
1761 {
1762 case FORMAT_R5G6B5:
1763 c.z = (c.x & Short4(0x001Fu)) << 11;
1764 c.y = (c.x & Short4(0x07E0u)) << 5;
1765 c.x = (c.x & Short4(0xF800u));
1766 break;
1767 default:
1768 ASSERT(false);
1769 }
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001770 }
Nicolas Capens21bda852015-09-01 10:23:33 -04001771 else if(has8bitTextureComponents())
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001772 {
John Bauman89401822014-05-06 15:04:28 -04001773 switch(textureComponentCount())
1774 {
1775 case 4:
1776 {
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001777 Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1778 Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1779 Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1780 Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
Nicolas Capens411273e2017-01-26 15:13:36 -08001781 c.x = Unpack(c0, c1);
1782 c.y = Unpack(c2, c3);
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001783
John Bauman89401822014-05-06 15:04:28 -04001784 switch(state.textureFormat)
1785 {
1786 case FORMAT_A8R8G8B8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001787 c.z = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001788 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1789 c.y = c.z;
1790 c.w = c.x;
1791 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1792 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1793 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1794 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
John Bauman89401822014-05-06 15:04:28 -04001795 break;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001796 case FORMAT_A8B8G8R8:
Alexis Hetu3412d872015-10-26 16:40:26 -04001797 case FORMAT_A8B8G8R8I:
Nicolas Capens975adb72017-12-19 15:34:20 -05001798 case FORMAT_A8B8G8R8_SNORM:
John Bauman89401822014-05-06 15:04:28 -04001799 case FORMAT_Q8W8V8U8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001800 case FORMAT_SRGB8_A8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001801 c.z = As<Short4>(UnpackHigh(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001802 c.x = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001803 c.y = c.x;
1804 c.w = c.z;
1805 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1806 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1807 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1808 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001809 // Propagate sign bit
1810 if(state.textureFormat == FORMAT_A8B8G8R8I)
1811 {
1812 c.x >>= 8;
1813 c.y >>= 8;
1814 c.z >>= 8;
1815 c.w >>= 8;
1816 }
1817 break;
1818 case FORMAT_A8B8G8R8UI:
1819 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1820 c.x = As<Short4>(UnpackLow(c.x, c.y));
1821 c.y = c.x;
1822 c.w = c.z;
1823 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0)));
1824 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0)));
1825 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(Short4(0)));
1826 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(Short4(0)));
John Bauman89401822014-05-06 15:04:28 -04001827 break;
1828 default:
1829 ASSERT(false);
1830 }
1831 }
1832 break;
1833 case 3:
1834 {
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001835 Byte4 c0 = Pointer<Byte4>(buffer[f0])[index[0]];
1836 Byte4 c1 = Pointer<Byte4>(buffer[f1])[index[1]];
1837 Byte4 c2 = Pointer<Byte4>(buffer[f2])[index[2]];
1838 Byte4 c3 = Pointer<Byte4>(buffer[f3])[index[3]];
Nicolas Capens411273e2017-01-26 15:13:36 -08001839 c.x = Unpack(c0, c1);
1840 c.y = Unpack(c2, c3);
John Bauman89401822014-05-06 15:04:28 -04001841
1842 switch(state.textureFormat)
1843 {
1844 case FORMAT_X8R8G8B8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001845 c.z = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001846 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1847 c.y = c.z;
1848 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1849 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1850 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
John Bauman89401822014-05-06 15:04:28 -04001851 break;
Nicolas Capens975adb72017-12-19 15:34:20 -05001852 case FORMAT_X8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04001853 case FORMAT_X8B8G8R8I:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001854 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04001855 case FORMAT_X8L8V8U8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001856 case FORMAT_SRGB8_X8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001857 c.z = As<Short4>(UnpackHigh(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001858 c.x = As<Short4>(UnpackLow(c.x, c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001859 c.y = c.x;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001860 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1861 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001862 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001863 // Propagate sign bit
1864 if(state.textureFormat == FORMAT_X8B8G8R8I)
1865 {
1866 c.x >>= 8;
1867 c.y >>= 8;
1868 c.z >>= 8;
1869 }
1870 break;
1871 case FORMAT_X8B8G8R8UI:
1872 c.z = As<Short4>(UnpackHigh(c.x, c.y));
1873 c.x = As<Short4>(UnpackLow(c.x, c.y));
1874 c.y = c.x;
1875 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0)));
1876 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0)));
1877 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(Short4(0)));
John Bauman89401822014-05-06 15:04:28 -04001878 break;
1879 default:
1880 ASSERT(false);
1881 }
1882 }
1883 break;
1884 case 2:
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001885 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1886 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1887 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1888 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
John Bauman89401822014-05-06 15:04:28 -04001889
1890 switch(state.textureFormat)
1891 {
1892 case FORMAT_G8R8:
Nicolas Capens975adb72017-12-19 15:34:20 -05001893 case FORMAT_G8R8_SNORM:
John Bauman89401822014-05-06 15:04:28 -04001894 case FORMAT_V8U8:
1895 case FORMAT_A8L8:
Alexis Hetu90c7ad62016-06-27 11:50:40 -04001896 c.y = (c.x & Short4(0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
1897 c.x = (c.x & Short4(0x00FFu)) | (c.x << 8);
John Bauman89401822014-05-06 15:04:28 -04001898 break;
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001899 case FORMAT_G8R8I:
1900 c.y = c.x >> 8;
1901 c.x = (c.x << 8) >> 8; // Propagate sign bit
1902 break;
1903 case FORMAT_G8R8UI:
1904 c.y = As<Short4>(As<UShort4>(c.x) >> 8);
1905 c.x &= Short4(0x00FFu);
1906 break;
John Bauman89401822014-05-06 15:04:28 -04001907 default:
1908 ASSERT(false);
1909 }
1910 break;
1911 case 1:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001912 {
1913 Int c0 = Int(*Pointer<Byte>(buffer[f0] + index[0]));
1914 Int c1 = Int(*Pointer<Byte>(buffer[f1] + index[1]));
1915 Int c2 = Int(*Pointer<Byte>(buffer[f2] + index[2]));
1916 Int c3 = Int(*Pointer<Byte>(buffer[f3] + index[3]));
1917 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001918
1919 switch(state.textureFormat)
1920 {
1921 case FORMAT_R8I:
1922 case FORMAT_R8UI:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001923 {
Nicolas Capens2d8c3702017-07-25 13:56:46 -04001924 Int zero(0);
1925 c.x = Unpack(As<Byte4>(c0), As<Byte4>(zero));
1926 // Propagate sign bit
1927 if(state.textureFormat == FORMAT_R8I)
1928 {
1929 c.x = (c.x << 8) >> 8;
1930 }
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001931 }
Nicolas Capens2d8c3702017-07-25 13:56:46 -04001932 break;
Alexis Hetu91dd1c42017-07-18 13:03:42 -04001933 default:
1934 c.x = Unpack(As<Byte4>(c0));
1935 break;
1936 }
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001937 }
John Bauman89401822014-05-06 15:04:28 -04001938 break;
1939 default:
1940 ASSERT(false);
1941 }
1942 }
Nicolas Capens21bda852015-09-01 10:23:33 -04001943 else if(has16bitTextureComponents())
John Bauman89401822014-05-06 15:04:28 -04001944 {
1945 switch(textureComponentCount())
1946 {
1947 case 4:
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001948 c.x = Pointer<Short4>(buffer[f0])[index[0]];
1949 c.y = Pointer<Short4>(buffer[f1])[index[1]];
1950 c.z = Pointer<Short4>(buffer[f2])[index[2]];
1951 c.w = Pointer<Short4>(buffer[f3])[index[3]];
John Bauman19bac1e2014-05-06 15:23:49 -04001952 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman89401822014-05-06 15:04:28 -04001953 break;
Nicolas Capense4a88b92017-11-30 00:14:57 -05001954 case 3:
1955 c.x = Pointer<Short4>(buffer[f0])[index[0]];
1956 c.y = Pointer<Short4>(buffer[f1])[index[1]];
1957 c.z = Pointer<Short4>(buffer[f2])[index[2]];
1958 c.w = Pointer<Short4>(buffer[f3])[index[3]];
1959 transpose4x3(c.x, c.y, c.z, c.w);
1960 break;
John Bauman89401822014-05-06 15:04:28 -04001961 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -04001962 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]);
1963 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1])));
1964 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]);
1965 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3])));
1966 c.y = c.x;
Nicolas Capens45f187a2016-12-02 15:30:56 -05001967 c.x = UnpackLow(As<Int2>(c.x), As<Int2>(c.z));
1968 c.y = UnpackHigh(As<Int2>(c.y), As<Int2>(c.z));
John Bauman89401822014-05-06 15:04:28 -04001969 break;
1970 case 1:
Nicolas Capens9b0e6552017-01-26 21:49:04 -08001971 c.x = Insert(c.x, Pointer<Short>(buffer[f0])[index[0]], 0);
1972 c.x = Insert(c.x, Pointer<Short>(buffer[f1])[index[1]], 1);
1973 c.x = Insert(c.x, Pointer<Short>(buffer[f2])[index[2]], 2);
1974 c.x = Insert(c.x, Pointer<Short>(buffer[f3])[index[3]], 3);
John Bauman89401822014-05-06 15:04:28 -04001975 break;
1976 default:
1977 ASSERT(false);
1978 }
1979 }
Alexis Hetu5de90b22017-07-17 11:19:12 -04001980 else ASSERT(false);
Nicolas Capens5790c952017-08-01 17:00:36 -04001981
Nicolas Capens5555af42017-12-14 13:14:03 -05001982 if(state.sRGB)
1983 {
1984 if(state.textureFormat == FORMAT_R5G6B5)
1985 {
1986 sRGBtoLinear16_5_16(c.x);
1987 sRGBtoLinear16_6_16(c.y);
1988 sRGBtoLinear16_5_16(c.z);
1989 }
1990 else
1991 {
1992 for(int i = 0; i < textureComponentCount(); i++)
1993 {
1994 if(isRGBComponent(i))
1995 {
1996 sRGBtoLinear16_8_16(c[i]);
1997 }
1998 }
1999 }
2000 }
2001
Nicolas Capens5790c952017-08-01 17:00:36 -04002002 return c;
Alexis Hetu5de90b22017-07-17 11:19:12 -04002003 }
2004
Nicolas Capens5790c952017-08-01 17:00:36 -04002005 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 -04002006 {
Nicolas Capens5790c952017-08-01 17:00:36 -04002007 Vector4s c;
Alexis Hetu5de90b22017-07-17 11:19:12 -04002008
Nicolas Capens5790c952017-08-01 17:00:36 -04002009 UInt index[4];
Alexis Hetu5de90b22017-07-17 11:19:12 -04002010 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap, function);
2011
2012 if(hasYuvFormat())
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002013 {
2014 // Generic YPbPr to RGB transformation
2015 // R = Y + 2 * (1 - Kr) * Pr
2016 // G = Y - 2 * Kb * (1 - Kb) / Kg * Pb - 2 * Kr * (1 - Kr) / Kg * Pr
2017 // B = Y + 2 * (1 - Kb) * Pb
2018
2019 float Kb = 0.114f;
2020 float Kr = 0.299f;
2021 int studioSwing = 1;
2022
2023 switch(state.textureFormat)
2024 {
2025 case FORMAT_YV12_BT601:
2026 Kb = 0.114f;
2027 Kr = 0.299f;
2028 studioSwing = 1;
2029 break;
2030 case FORMAT_YV12_BT709:
2031 Kb = 0.0722f;
2032 Kr = 0.2126f;
2033 studioSwing = 1;
2034 break;
2035 case FORMAT_YV12_JFIF:
2036 Kb = 0.114f;
2037 Kr = 0.299f;
2038 studioSwing = 0;
2039 break;
2040 default:
2041 ASSERT(false);
2042 }
2043
2044 const float Kg = 1.0f - Kr - Kb;
2045
2046 const float Rr = 2 * (1 - Kr);
2047 const float Gb = -2 * Kb * (1 - Kb) / Kg;
2048 const float Gr = -2 * Kr * (1 - Kr) / Kg;
2049 const float Bb = 2 * (1 - Kb);
2050
2051 // Scaling and bias for studio-swing range: Y = [16 .. 235], U/V = [16 .. 240]
2052 const float Yy = studioSwing ? 255.0f / (235 - 16) : 1.0f;
2053 const float Uu = studioSwing ? 255.0f / (240 - 16) : 1.0f;
2054 const float Vv = studioSwing ? 255.0f / (240 - 16) : 1.0f;
2055
2056 const float Rv = Vv * Rr;
2057 const float Gu = Uu * Gb;
2058 const float Gv = Vv * Gr;
2059 const float Bu = Uu * Bb;
2060
2061 const float R0 = (studioSwing * -16 * Yy - 128 * Rv) / 255;
2062 const float G0 = (studioSwing * -16 * Yy - 128 * Gu - 128 * Gv) / 255;
2063 const float B0 = (studioSwing * -16 * Yy - 128 * Bu) / 255;
2064
Nicolas Capens9b0e6552017-01-26 21:49:04 -08002065 Int c0 = Int(buffer[0][index[0]]);
2066 Int c1 = Int(buffer[0][index[1]]);
2067 Int c2 = Int(buffer[0][index[2]]);
2068 Int c3 = Int(buffer[0][index[3]]);
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002069 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2070 UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0)));
2071
Nicolas Capensa3c16e42016-06-15 16:45:53 -04002072 computeIndices(index, uuuu, vvvv, wwww, offset, mipmap + sizeof(Mipmap), function);
Nicolas Capens9b0e6552017-01-26 21:49:04 -08002073 c0 = Int(buffer[1][index[0]]);
2074 c1 = Int(buffer[1][index[1]]);
2075 c2 = Int(buffer[1][index[2]]);
2076 c3 = Int(buffer[1][index[3]]);
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002077 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2078 UShort4 V = As<UShort4>(Unpack(As<Byte4>(c0)));
2079
Nicolas Capens9b0e6552017-01-26 21:49:04 -08002080 c0 = Int(buffer[2][index[0]]);
2081 c1 = Int(buffer[2][index[1]]);
2082 c2 = Int(buffer[2][index[2]]);
2083 c3 = Int(buffer[2][index[3]]);
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002084 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
2085 UShort4 U = As<UShort4>(Unpack(As<Byte4>(c0)));
2086
2087 const UShort4 yY = UShort4(iround(Yy * 0x4000));
2088 const UShort4 rV = UShort4(iround(Rv * 0x4000));
2089 const UShort4 gU = UShort4(iround(-Gu * 0x4000));
2090 const UShort4 gV = UShort4(iround(-Gv * 0x4000));
2091 const UShort4 bU = UShort4(iround(Bu * 0x4000));
2092
2093 const UShort4 r0 = UShort4(iround(-R0 * 0x4000));
2094 const UShort4 g0 = UShort4(iround(G0 * 0x4000));
2095 const UShort4 b0 = UShort4(iround(-B0 * 0x4000));
2096
2097 UShort4 y = MulHigh(Y, yY);
2098 UShort4 r = SubSat(y + MulHigh(V, rV), r0);
2099 UShort4 g = SubSat(y + g0, MulHigh(U, gU) + MulHigh(V, gV));
2100 UShort4 b = SubSat(y + MulHigh(U, bU), b0);
2101
2102 c.x = Min(r, UShort4(0x3FFF)) << 2;
2103 c.y = Min(g, UShort4(0x3FFF)) << 2;
2104 c.z = Min(b, UShort4(0x3FFF)) << 2;
2105 }
Alexis Hetu5de90b22017-07-17 11:19:12 -04002106 else
2107 {
Nicolas Capens5790c952017-08-01 17:00:36 -04002108 return sampleTexel(index, buffer);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002109 }
Nicolas Capens5790c952017-08-01 17:00:36 -04002110
2111 return c;
John Bauman89401822014-05-06 15:04:28 -04002112 }
2113
Nicolas Capens5790c952017-08-01 17:00:36 -04002114 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 -04002115 {
Nicolas Capens5790c952017-08-01 17:00:36 -04002116 Vector4f c;
John Bauman89401822014-05-06 15:04:28 -04002117
Nicolas Capens5790c952017-08-01 17:00:36 -04002118 UInt index[4];
Alexis Hetu75a61852017-07-14 14:17:14 -04002119 computeIndices(index, uuuu, vvvv, wwww, mipmap, function);
John Bauman89401822014-05-06 15:04:28 -04002120
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002121 if(hasFloatTexture() || has32bitIntegerTextureComponents())
John Bauman89401822014-05-06 15:04:28 -04002122 {
Alexis Hetu5de90b22017-07-17 11:19:12 -04002123 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
2124 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
2125 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
2126 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
John Bauman89401822014-05-06 15:04:28 -04002127
Alexis Hetu5de90b22017-07-17 11:19:12 -04002128 // Read texels
2129 switch(textureComponentCount())
John Bauman89401822014-05-06 15:04:28 -04002130 {
Alexis Hetu5de90b22017-07-17 11:19:12 -04002131 case 4:
2132 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2133 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2134 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2135 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2136 transpose4x4(c.x, c.y, c.z, c.w);
2137 break;
2138 case 3:
Alexis Hetu5de90b22017-07-17 11:19:12 -04002139 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
2140 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
2141 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
2142 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
2143 transpose4x3(c.x, c.y, c.z, c.w);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002144 break;
2145 case 2:
2146 // FIXME: Optimal shuffling?
2147 c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8);
2148 c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8);
2149 c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8);
2150 c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8);
2151 c.y = c.x;
2152 c.x = Float4(c.x.xz, c.z.xz);
2153 c.y = Float4(c.y.yw, c.z.yw);
2154 break;
2155 case 1:
2156 // FIXME: Optimal shuffling?
2157 c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4);
2158 c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4);
2159 c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4);
2160 c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002161 break;
2162 default:
2163 ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04002164 }
Nicolas Capens185c18b2017-11-07 13:51:50 -05002165
2166 if(state.compare != COMPARE_BYPASS)
2167 {
2168 Float4 ref = z;
2169
2170 if(!hasFloatTexture())
2171 {
2172 ref = Min(Max(ref, Float4(0.0f)), Float4(1.0f));
2173 }
2174
2175 Int4 boolean;
2176
2177 switch(state.compare)
2178 {
2179 case COMPARE_LESSEQUAL: boolean = CmpLE(ref, c.x); break;
2180 case COMPARE_GREATEREQUAL: boolean = CmpNLT(ref, c.x); break;
2181 case COMPARE_LESS: boolean = CmpLT(ref, c.x); break;
2182 case COMPARE_GREATER: boolean = CmpNLE(ref, c.x); break;
2183 case COMPARE_EQUAL: boolean = CmpEQ(ref, c.x); break;
2184 case COMPARE_NOTEQUAL: boolean = CmpNEQ(ref, c.x); break;
2185 case COMPARE_ALWAYS: boolean = Int4(-1); break;
2186 case COMPARE_NEVER: boolean = Int4(0); break;
2187 default: ASSERT(false);
2188 }
2189
2190 c.x = As<Float4>(boolean & As<Int4>(Float4(1.0f)));
2191 c.y = Float4(0.0f);
2192 c.z = Float4(0.0f);
2193 c.w = Float4(1.0f);
2194 }
Alexis Hetu5de90b22017-07-17 11:19:12 -04002195 }
2196 else
2197 {
2198 ASSERT(!hasYuvFormat());
2199
Nicolas Capens5790c952017-08-01 17:00:36 -04002200 Vector4s cs = sampleTexel(index, buffer);
Alexis Hetu5de90b22017-07-17 11:19:12 -04002201
2202 bool isInteger = Surface::isNonNormalizedInteger(state.textureFormat);
2203 int componentCount = textureComponentCount();
Nicolas Capens5555af42017-12-14 13:14:03 -05002204 for(int n = 0; n < componentCount; n++)
Alexis Hetu5de90b22017-07-17 11:19:12 -04002205 {
2206 if(hasUnsignedTextureComponent(n))
2207 {
2208 if(isInteger)
2209 {
2210 c[n] = As<Float4>(Int4(As<UShort4>(cs[n])));
2211 }
2212 else
2213 {
2214 c[n] = Float4(As<UShort4>(cs[n]));
2215 }
2216 }
2217 else
2218 {
2219 if(isInteger)
2220 {
2221 c[n] = As<Float4>(Int4(cs[n]));
2222 }
2223 else
2224 {
2225 c[n] = Float4(cs[n]);
2226 }
2227 }
2228 }
John Bauman89401822014-05-06 15:04:28 -04002229 }
Nicolas Capens5790c952017-08-01 17:00:36 -04002230
2231 return c;
John Bauman89401822014-05-06 15:04:28 -04002232 }
2233
2234 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
2235 {
Nicolas Capense396a492018-01-02 14:22:23 -05002236 if(state.mipmapFilter == MIPMAP_NONE)
John Bauman89401822014-05-06 15:04:28 -04002237 {
2238 mipmap = texture + OFFSET(Texture,mipmap[0]);
2239 }
2240 else
2241 {
2242 Int ilod;
2243
2244 if(state.mipmapFilter == MIPMAP_POINT)
2245 {
2246 ilod = RoundInt(lod);
2247 }
Nicolas Capense396a492018-01-02 14:22:23 -05002248 else // MIPMAP_LINEAR
John Bauman89401822014-05-06 15:04:28 -04002249 {
2250 ilod = Int(lod);
2251 }
2252
2253 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
2254 }
2255
2256 if(state.textureType != TEXTURE_CUBE)
2257 {
John Bauman66b8ab22014-05-06 15:57:45 -04002258 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002259
2260 if(hasYuvFormat())
2261 {
2262 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1]));
2263 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2]));
2264 }
John Bauman89401822014-05-06 15:04:28 -04002265 }
2266 else
2267 {
2268 for(int i = 0; i < 4; i++)
2269 {
John Bauman66b8ab22014-05-06 15:57:45 -04002270 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -04002271 }
2272 }
2273 }
2274
Nicolas Capensb81efca2017-12-19 10:52:14 -05002275 Int4 SamplerCore::computeFilterOffset(Float &lod)
Alexis Hetu75a61852017-07-14 14:17:14 -04002276 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002277 Int4 filter = -1;
2278
2279 if(state.textureFilter == FILTER_POINT)
Alexis Hetu75a61852017-07-14 14:17:14 -04002280 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002281 filter = 0;
2282 }
2283 else if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
2284 {
Nicolas Capensb81efca2017-12-19 10:52:14 -05002285 filter = CmpNLE(Float4(lod), Float4(0.0f));
Alexis Hetu75a61852017-07-14 14:17:14 -04002286 }
2287 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
2288 {
Nicolas Capensb81efca2017-12-19 10:52:14 -05002289 filter = CmpLE(Float4(lod), Float4(0.0f));
Alexis Hetu75a61852017-07-14 14:17:14 -04002290 }
2291
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002292 return filter;
Alexis Hetu75a61852017-07-14 14:17:14 -04002293 }
2294
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002295 Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte> &mipmap)
John Bauman89401822014-05-06 15:04:28 -04002296 {
Nicolas Capens7bb62682016-02-08 11:30:56 -05002297 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2298 {
2299 return Short4(); // Unused
2300 }
2301 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY)
2302 {
2303 return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1));
2304 }
Nicolas Capensc4b1bfa2017-11-28 15:52:52 -05002305 else if(addressingMode == ADDRESSING_CLAMP || addressingMode == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04002306 {
2307 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
2308
Nicolas Capens7bb62682016-02-08 11:30:56 -05002309 return Short4(Int4(clamp * Float4(1 << 16)));
John Bauman89401822014-05-06 15:04:28 -04002310 }
2311 else if(addressingMode == ADDRESSING_MIRROR)
2312 {
2313 Int4 convert = Int4(uw * Float4(1 << 16));
2314 Int4 mirror = (convert << 15) >> 31;
2315
2316 convert ^= mirror;
2317
Nicolas Capens7bb62682016-02-08 11:30:56 -05002318 return Short4(convert);
John Bauman89401822014-05-06 15:04:28 -04002319 }
2320 else if(addressingMode == ADDRESSING_MIRRORONCE)
2321 {
2322 // Absolute value
2323 Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
2324
2325 // Clamp
2326 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
Nicolas Capens33438a62017-09-27 11:47:35 -04002327 convert = As<Int4>(PackSigned(convert, convert));
John Bauman89401822014-05-06 15:04:28 -04002328
Alexis Hetu90c7ad62016-06-27 11:50:40 -04002329 return As<Short4>(Int2(convert)) + Short4(0x8000u);
John Bauman89401822014-05-06 15:04:28 -04002330 }
Nicolas Capensc4b1bfa2017-11-28 15:52:52 -05002331 else // Wrap
John Bauman89401822014-05-06 15:04:28 -04002332 {
Nicolas Capens7bb62682016-02-08 11:30:56 -05002333 return Short4(Int4(uw * Float4(1 << 16)));
Alexis Hetuf15e8942015-12-01 15:13:23 -05002334 }
2335 }
2336
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002337 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 -04002338 {
2339 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2340 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002341 return; // Unused
Alexis Hetu75a61852017-07-14 14:17:14 -04002342 }
2343
2344 Int4 dim = Int4(*Pointer<Short4>(mipmap + whd, 16));
2345 Int4 maxXYZ = dim - Int4(1);
2346
2347 if(function == Fetch)
2348 {
2349 xyz0 = Min(Max(((function.option == Offset) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ);
2350 }
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002351 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 -04002352 {
2353 xyz0 = Min(Max(RoundInt(uvw), Int4(0)), maxXYZ);
2354 }
2355 else
2356 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002357 const int halfBits = 0x3EFFFFFF; // Value just under 0.5f
2358 const int oneBits = 0x3F7FFFFF; // Value just under 1.0f
2359 const int twoBits = 0x3FFFFFFF; // Value just under 2.0f
Alexis Hetu75a61852017-07-14 14:17:14 -04002360
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002361 Float4 coord = uvw;
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002362
Alexis Hetuc0632c92018-03-02 15:10:16 -05002363 if(state.textureType == TEXTURE_RECTANGLE)
Alexis Hetu75a61852017-07-14 14:17:14 -04002364 {
Alexis Hetu0641aeb2018-05-08 14:25:40 -04002365 // According to https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_rectangle.txt
2366 // "CLAMP_TO_EDGE causes the s coordinate to be clamped to the range[0.5, wt - 0.5].
2367 // CLAMP_TO_EDGE causes the t coordinate to be clamped to the range[0.5, ht - 0.5]."
2368 // Unless SwiftShader implements support for ADDRESSING_BORDER, other modes should be equivalent
2369 // to CLAMP_TO_EDGE. Rectangle textures have no support for any MIRROR or REPEAT modes.
2370 coord = Min(Max(coord, Float4(0.5f)), Float4(dim) - Float4(0.5f));
Alexis Hetu46768622018-01-16 22:09:28 -05002371 }
2372 else
2373 {
2374 switch(addressingMode)
Alexis Hetu75a61852017-07-14 14:17:14 -04002375 {
Alexis Hetu46768622018-01-16 22:09:28 -05002376 case ADDRESSING_CLAMP:
2377 case ADDRESSING_BORDER:
2378 case ADDRESSING_SEAMLESS:
Ben Claytona63e5f92019-02-14 19:31:30 +00002379 {
2380 // While cube face coordinates are nominally already in the
2381 // [0, 1] range due to the projection, and numerical
2382 // imprecision is tolerated due to the border of pixels for
2383 // seamless filtering, this isn't true for inf and NaN
2384 // values. So we always clamp.
2385 Float4 one = As<Float4>(Int4(oneBits));
2386 coord = Min(Max(coord, Float4(0.0f)), one);
2387 }
2388 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002389 case ADDRESSING_MIRROR:
Alexis Hetu75a61852017-07-14 14:17:14 -04002390 {
2391 Float4 half = As<Float4>(Int4(halfBits));
2392 Float4 one = As<Float4>(Int4(oneBits));
2393 Float4 two = As<Float4>(Int4(twoBits));
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002394 coord = one - Abs(two * Frac(coord * half) - one);
Alexis Hetu75a61852017-07-14 14:17:14 -04002395 }
2396 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002397 case ADDRESSING_MIRRORONCE:
Alexis Hetu75a61852017-07-14 14:17:14 -04002398 {
2399 Float4 half = As<Float4>(Int4(halfBits));
2400 Float4 one = As<Float4>(Int4(oneBits));
2401 Float4 two = As<Float4>(Int4(twoBits));
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002402 coord = one - Abs(two * Frac(Min(Max(coord, -one), two) * half) - one);
Alexis Hetu75a61852017-07-14 14:17:14 -04002403 }
2404 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002405 default: // Wrap
2406 coord = Frac(coord);
2407 break;
2408 }
2409
2410 coord = coord * Float4(dim);
Alexis Hetu75a61852017-07-14 14:17:14 -04002411 }
2412
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002413 if(state.textureFilter == FILTER_POINT ||
Alexis Hetu46768622018-01-16 22:09:28 -05002414 state.textureFilter == FILTER_GATHER)
2415 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002416 xyz0 = Int4(coord);
2417 }
2418 else
2419 {
2420 if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR ||
Alexis Hetu46768622018-01-16 22:09:28 -05002421 state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002422 {
2423 coord -= As<Float4>(As<Int4>(Float4(0.5f)) & filter);
2424 }
2425 else
2426 {
2427 coord -= Float4(0.5f);
2428 }
2429
2430 Float4 floor = Floor(coord);
2431 xyz0 = Int4(floor);
2432 f = coord - floor;
2433 }
Alexis Hetu75a61852017-07-14 14:17:14 -04002434
2435 if(function.option == Offset)
2436 {
2437 xyz0 += As<Int4>(texOffset);
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002438 }
2439
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002440 if(addressingMode == ADDRESSING_SEAMLESS)
2441 {
2442 xyz0 += Int4(1);
2443 }
2444
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002445 xyz1 = xyz0 - filter; // Increment
2446
2447 if(function.option == Offset)
2448 {
Alexis Hetu75a61852017-07-14 14:17:14 -04002449 switch(addressingMode)
2450 {
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002451 case ADDRESSING_SEAMLESS:
2452 ASSERT(false); // Cube sampling doesn't support offset.
Alexis Hetu75a61852017-07-14 14:17:14 -04002453 case ADDRESSING_MIRROR:
2454 case ADDRESSING_MIRRORONCE:
2455 case ADDRESSING_BORDER:
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002456 // FIXME: Implement ADDRESSING_MIRROR, ADDRESSING_MIRRORONCE, and ADDRESSING_BORDER.
2457 // Fall through to Clamp.
Alexis Hetu75a61852017-07-14 14:17:14 -04002458 case ADDRESSING_CLAMP:
2459 xyz0 = Min(Max(xyz0, Int4(0)), maxXYZ);
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002460 xyz1 = Min(Max(xyz1, Int4(0)), maxXYZ);
Alexis Hetu75a61852017-07-14 14:17:14 -04002461 break;
2462 default: // Wrap
2463 xyz0 = (xyz0 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim;
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002464 xyz1 = (xyz1 + dim * Int4(-MIN_PROGRAM_TEXEL_OFFSET)) % dim;
Alexis Hetu75a61852017-07-14 14:17:14 -04002465 break;
2466 }
2467 }
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002468 else if(state.textureFilter != FILTER_POINT)
Alexis Hetu75a61852017-07-14 14:17:14 -04002469 {
Alexis Hetu75a61852017-07-14 14:17:14 -04002470 switch(addressingMode)
2471 {
Nicolas Capensd0f5d392017-11-28 15:54:59 -05002472 case ADDRESSING_SEAMLESS:
2473 break;
Alexis Hetu75a61852017-07-14 14:17:14 -04002474 case ADDRESSING_MIRROR:
2475 case ADDRESSING_MIRRORONCE:
2476 case ADDRESSING_BORDER:
Alexis Hetu75a61852017-07-14 14:17:14 -04002477 case ADDRESSING_CLAMP:
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002478 xyz0 = Max(xyz0, Int4(0));
2479 xyz1 = Min(xyz1, maxXYZ);
Alexis Hetu75a61852017-07-14 14:17:14 -04002480 break;
2481 default: // Wrap
2482 {
Nicolas Capensf8b827e2017-11-27 15:25:05 -05002483 Int4 under = CmpLT(xyz0, Int4(0));
2484 xyz0 = (under & maxXYZ) | (~under & xyz0); // xyz < 0 ? dim - 1 : xyz // FIXME: IfThenElse()
2485
2486 Int4 nover = CmpLT(xyz1, dim);
2487 xyz1 = nover & xyz1; // xyz >= dim ? 0 : xyz
Alexis Hetu75a61852017-07-14 14:17:14 -04002488 }
2489 break;
2490 }
2491 }
2492 }
2493 }
2494
Alexis Hetu96517182015-04-15 10:30:23 -04002495 void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
John Bauman89401822014-05-06 15:04:28 -04002496 {
Alexis Hetu96517182015-04-15 10:30:23 -04002497 cs = RoundShort4(cf * Float4(0x1000));
John Bauman89401822014-05-06 15:04:28 -04002498 }
2499
Alexis Hetu96517182015-04-15 10:30:23 -04002500 void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
John Bauman89401822014-05-06 15:04:28 -04002501 {
Alexis Hetu96517182015-04-15 10:30:23 -04002502 convertFixed12(cs.x, cf.x);
2503 convertFixed12(cs.y, cf.y);
2504 convertFixed12(cs.z, cf.z);
2505 convertFixed12(cs.w, cf.w);
John Bauman89401822014-05-06 15:04:28 -04002506 }
2507
Alexis Hetu96517182015-04-15 10:30:23 -04002508 void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002509 {
Alexis Hetu96517182015-04-15 10:30:23 -04002510 cf = Float4(cs) * Float4(1.0f / 0x0FFE);
John Bauman89401822014-05-06 15:04:28 -04002511 }
2512
Alexis Hetu96517182015-04-15 10:30:23 -04002513// void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
John Bauman89401822014-05-06 15:04:28 -04002514// {
Alexis Hetu96517182015-04-15 10:30:23 -04002515// convertSigned12(cf.x, cs.x);
2516// convertSigned12(cf.y, cs.y);
2517// convertSigned12(cf.z, cs.z);
2518// convertSigned12(cf.w, cs.w);
John Bauman89401822014-05-06 15:04:28 -04002519// }
2520
Alexis Hetu96517182015-04-15 10:30:23 -04002521 void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002522 {
Alexis Hetu96517182015-04-15 10:30:23 -04002523 cf = Float4(cs) * Float4(1.0f / 0x7FFF);
John Bauman89401822014-05-06 15:04:28 -04002524 }
2525
Alexis Hetu96517182015-04-15 10:30:23 -04002526 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002527 {
Alexis Hetu96517182015-04-15 10:30:23 -04002528 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
John Bauman89401822014-05-06 15:04:28 -04002529 }
2530
Nicolas Capens5555af42017-12-14 13:14:03 -05002531 void SamplerCore::sRGBtoLinear16_8_16(Short4 &c)
John Bauman89401822014-05-06 15:04:28 -04002532 {
2533 c = As<UShort4>(c) >> 8;
2534
Nicolas Capens5555af42017-12-14 13:14:03 -05002535 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_16));
Nicolas Capense1a50af2015-05-13 16:48:18 -04002536
2537 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2538 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2539 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2540 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2541 }
2542
Nicolas Capens5555af42017-12-14 13:14:03 -05002543 void SamplerCore::sRGBtoLinear16_6_16(Short4 &c)
Nicolas Capense1a50af2015-05-13 16:48:18 -04002544 {
2545 c = As<UShort4>(c) >> 10;
2546
Nicolas Capens5555af42017-12-14 13:14:03 -05002547 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_16));
Nicolas Capense1a50af2015-05-13 16:48:18 -04002548
2549 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2550 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2551 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2552 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2553 }
2554
Nicolas Capens5555af42017-12-14 13:14:03 -05002555 void SamplerCore::sRGBtoLinear16_5_16(Short4 &c)
Nicolas Capense1a50af2015-05-13 16:48:18 -04002556 {
2557 c = As<UShort4>(c) >> 11;
2558
Nicolas Capens5555af42017-12-14 13:14:03 -05002559 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_16));
John Bauman89401822014-05-06 15:04:28 -04002560
2561 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2562 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2563 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2564 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2565 }
2566
2567 bool SamplerCore::hasFloatTexture() const
2568 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002569 return Surface::isFloatFormat(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04002570 }
2571
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002572 bool SamplerCore::hasUnnormalizedIntegerTexture() const
2573 {
2574 return Surface::isNonNormalizedInteger(state.textureFormat);
2575 }
2576
John Bauman89401822014-05-06 15:04:28 -04002577 bool SamplerCore::hasUnsignedTextureComponent(int component) const
2578 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002579 return Surface::isUnsignedComponent(state.textureFormat, component);
John Bauman89401822014-05-06 15:04:28 -04002580 }
2581
2582 int SamplerCore::textureComponentCount() const
2583 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002584 return Surface::componentCount(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04002585 }
2586
Alexis Hetu75a61852017-07-14 14:17:14 -04002587 bool SamplerCore::hasThirdCoordinate() const
2588 {
2589 return (state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY);
2590 }
2591
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002592 bool SamplerCore::has16bitTextureFormat() const
John Bauman89401822014-05-06 15:04:28 -04002593 {
2594 switch(state.textureFormat)
2595 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002596 case FORMAT_R5G6B5:
2597 return true;
Nicolas Capens975adb72017-12-19 15:34:20 -05002598 case FORMAT_R8_SNORM:
2599 case FORMAT_G8R8_SNORM:
2600 case FORMAT_X8B8G8R8_SNORM:
2601 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002602 case FORMAT_R8I:
2603 case FORMAT_R8UI:
2604 case FORMAT_G8R8I:
2605 case FORMAT_G8R8UI:
2606 case FORMAT_X8B8G8R8I:
2607 case FORMAT_X8B8G8R8UI:
2608 case FORMAT_A8B8G8R8I:
2609 case FORMAT_A8B8G8R8UI:
2610 case FORMAT_R32I:
2611 case FORMAT_R32UI:
2612 case FORMAT_G32R32I:
2613 case FORMAT_G32R32UI:
2614 case FORMAT_X32B32G32R32I:
2615 case FORMAT_X32B32G32R32UI:
2616 case FORMAT_A32B32G32R32I:
2617 case FORMAT_A32B32G32R32UI:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002618 case FORMAT_G8R8:
2619 case FORMAT_X8R8G8B8:
2620 case FORMAT_X8B8G8R8:
2621 case FORMAT_A8R8G8B8:
2622 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002623 case FORMAT_SRGB8_X8:
2624 case FORMAT_SRGB8_A8:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002625 case FORMAT_V8U8:
2626 case FORMAT_Q8W8V8U8:
2627 case FORMAT_X8L8V8U8:
2628 case FORMAT_R32F:
2629 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002630 case FORMAT_X32B32G32R32F:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002631 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002632 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002633 case FORMAT_A8:
2634 case FORMAT_R8:
2635 case FORMAT_L8:
2636 case FORMAT_A8L8:
2637 case FORMAT_D32F_LOCKABLE:
2638 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002639 case FORMAT_D32F_SHADOW:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002640 case FORMAT_D32FS8_SHADOW:
2641 case FORMAT_L16:
2642 case FORMAT_G16R16:
2643 case FORMAT_A16B16G16R16:
2644 case FORMAT_V16U16:
2645 case FORMAT_A16W16V16U16:
2646 case FORMAT_Q16W16V16U16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002647 case FORMAT_R16I:
2648 case FORMAT_R16UI:
2649 case FORMAT_G16R16I:
2650 case FORMAT_G16R16UI:
2651 case FORMAT_X16B16G16R16I:
2652 case FORMAT_X16B16G16R16UI:
2653 case FORMAT_A16B16G16R16I:
2654 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002655 case FORMAT_YV12_BT601:
2656 case FORMAT_YV12_BT709:
2657 case FORMAT_YV12_JFIF:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002658 return false;
2659 default:
2660 ASSERT(false);
2661 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002662
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002663 return false;
2664 }
2665
Nicolas Capens21bda852015-09-01 10:23:33 -04002666 bool SamplerCore::has8bitTextureComponents() const
2667 {
2668 switch(state.textureFormat)
2669 {
Nicolas Capens21bda852015-09-01 10:23:33 -04002670 case FORMAT_G8R8:
2671 case FORMAT_X8R8G8B8:
2672 case FORMAT_X8B8G8R8:
2673 case FORMAT_A8R8G8B8:
2674 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002675 case FORMAT_SRGB8_X8:
2676 case FORMAT_SRGB8_A8:
Nicolas Capens21bda852015-09-01 10:23:33 -04002677 case FORMAT_V8U8:
2678 case FORMAT_Q8W8V8U8:
2679 case FORMAT_X8L8V8U8:
2680 case FORMAT_A8:
2681 case FORMAT_R8:
2682 case FORMAT_L8:
2683 case FORMAT_A8L8:
Nicolas Capens975adb72017-12-19 15:34:20 -05002684 case FORMAT_R8_SNORM:
2685 case FORMAT_G8R8_SNORM:
2686 case FORMAT_X8B8G8R8_SNORM:
2687 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002688 case FORMAT_R8I:
2689 case FORMAT_R8UI:
2690 case FORMAT_G8R8I:
2691 case FORMAT_G8R8UI:
2692 case FORMAT_X8B8G8R8I:
2693 case FORMAT_X8B8G8R8UI:
2694 case FORMAT_A8B8G8R8I:
2695 case FORMAT_A8B8G8R8UI:
Nicolas Capens21bda852015-09-01 10:23:33 -04002696 return true;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002697 case FORMAT_R5G6B5:
Nicolas Capens21bda852015-09-01 10:23:33 -04002698 case FORMAT_R32F:
2699 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002700 case FORMAT_X32B32G32R32F:
Nicolas Capens21bda852015-09-01 10:23:33 -04002701 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002702 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capens21bda852015-09-01 10:23:33 -04002703 case FORMAT_D32F_LOCKABLE:
2704 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002705 case FORMAT_D32F_SHADOW:
Nicolas Capens21bda852015-09-01 10:23:33 -04002706 case FORMAT_D32FS8_SHADOW:
2707 case FORMAT_L16:
2708 case FORMAT_G16R16:
2709 case FORMAT_A16B16G16R16:
2710 case FORMAT_V16U16:
2711 case FORMAT_A16W16V16U16:
2712 case FORMAT_Q16W16V16U16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002713 case FORMAT_R32I:
2714 case FORMAT_R32UI:
2715 case FORMAT_G32R32I:
2716 case FORMAT_G32R32UI:
2717 case FORMAT_X32B32G32R32I:
2718 case FORMAT_X32B32G32R32UI:
2719 case FORMAT_A32B32G32R32I:
2720 case FORMAT_A32B32G32R32UI:
2721 case FORMAT_R16I:
2722 case FORMAT_R16UI:
2723 case FORMAT_G16R16I:
2724 case FORMAT_G16R16UI:
2725 case FORMAT_X16B16G16R16I:
2726 case FORMAT_X16B16G16R16UI:
2727 case FORMAT_A16B16G16R16I:
2728 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002729 case FORMAT_YV12_BT601:
2730 case FORMAT_YV12_BT709:
2731 case FORMAT_YV12_JFIF:
Nicolas Capens21bda852015-09-01 10:23:33 -04002732 return false;
2733 default:
2734 ASSERT(false);
2735 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002736
Nicolas Capens21bda852015-09-01 10:23:33 -04002737 return false;
2738 }
2739
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002740 bool SamplerCore::has16bitTextureComponents() const
2741 {
2742 switch(state.textureFormat)
2743 {
2744 case FORMAT_R5G6B5:
Nicolas Capens975adb72017-12-19 15:34:20 -05002745 case FORMAT_R8_SNORM:
2746 case FORMAT_G8R8_SNORM:
2747 case FORMAT_X8B8G8R8_SNORM:
2748 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002749 case FORMAT_R8I:
2750 case FORMAT_R8UI:
2751 case FORMAT_G8R8I:
2752 case FORMAT_G8R8UI:
2753 case FORMAT_X8B8G8R8I:
2754 case FORMAT_X8B8G8R8UI:
2755 case FORMAT_A8B8G8R8I:
2756 case FORMAT_A8B8G8R8UI:
2757 case FORMAT_R32I:
2758 case FORMAT_R32UI:
2759 case FORMAT_G32R32I:
2760 case FORMAT_G32R32UI:
2761 case FORMAT_X32B32G32R32I:
2762 case FORMAT_X32B32G32R32UI:
2763 case FORMAT_A32B32G32R32I:
2764 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002765 case FORMAT_G8R8:
2766 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002767 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002768 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002769 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002770 case FORMAT_SRGB8_X8:
2771 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002772 case FORMAT_V8U8:
2773 case FORMAT_Q8W8V8U8:
2774 case FORMAT_X8L8V8U8:
2775 case FORMAT_R32F:
2776 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002777 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002778 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002779 case FORMAT_X32B32G32R32F_UNSIGNED:
John Bauman89401822014-05-06 15:04:28 -04002780 case FORMAT_A8:
2781 case FORMAT_R8:
2782 case FORMAT_L8:
2783 case FORMAT_A8L8:
2784 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002785 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002786 case FORMAT_D32F_SHADOW:
John Bauman66b8ab22014-05-06 15:57:45 -04002787 case FORMAT_D32FS8_SHADOW:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002788 case FORMAT_YV12_BT601:
2789 case FORMAT_YV12_BT709:
2790 case FORMAT_YV12_JFIF:
John Bauman89401822014-05-06 15:04:28 -04002791 return false;
2792 case FORMAT_L16:
2793 case FORMAT_G16R16:
2794 case FORMAT_A16B16G16R16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002795 case FORMAT_R16I:
2796 case FORMAT_R16UI:
2797 case FORMAT_G16R16I:
2798 case FORMAT_G16R16UI:
2799 case FORMAT_X16B16G16R16I:
2800 case FORMAT_X16B16G16R16UI:
2801 case FORMAT_A16B16G16R16I:
2802 case FORMAT_A16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002803 case FORMAT_V16U16:
2804 case FORMAT_A16W16V16U16:
2805 case FORMAT_Q16W16V16U16:
2806 return true;
2807 default:
2808 ASSERT(false);
2809 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002810
John Bauman89401822014-05-06 15:04:28 -04002811 return false;
2812 }
2813
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002814 bool SamplerCore::has32bitIntegerTextureComponents() const
2815 {
2816 switch(state.textureFormat)
2817 {
2818 case FORMAT_R5G6B5:
Nicolas Capens975adb72017-12-19 15:34:20 -05002819 case FORMAT_R8_SNORM:
2820 case FORMAT_G8R8_SNORM:
2821 case FORMAT_X8B8G8R8_SNORM:
2822 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002823 case FORMAT_R8I:
2824 case FORMAT_R8UI:
2825 case FORMAT_G8R8I:
2826 case FORMAT_G8R8UI:
2827 case FORMAT_X8B8G8R8I:
2828 case FORMAT_X8B8G8R8UI:
2829 case FORMAT_A8B8G8R8I:
2830 case FORMAT_A8B8G8R8UI:
2831 case FORMAT_G8R8:
2832 case FORMAT_X8R8G8B8:
2833 case FORMAT_X8B8G8R8:
2834 case FORMAT_A8R8G8B8:
2835 case FORMAT_A8B8G8R8:
2836 case FORMAT_SRGB8_X8:
2837 case FORMAT_SRGB8_A8:
2838 case FORMAT_V8U8:
2839 case FORMAT_Q8W8V8U8:
2840 case FORMAT_X8L8V8U8:
2841 case FORMAT_L16:
2842 case FORMAT_G16R16:
2843 case FORMAT_A16B16G16R16:
2844 case FORMAT_R16I:
2845 case FORMAT_R16UI:
2846 case FORMAT_G16R16I:
2847 case FORMAT_G16R16UI:
2848 case FORMAT_X16B16G16R16I:
2849 case FORMAT_X16B16G16R16UI:
2850 case FORMAT_A16B16G16R16I:
2851 case FORMAT_A16B16G16R16UI:
2852 case FORMAT_V16U16:
2853 case FORMAT_A16W16V16U16:
2854 case FORMAT_Q16W16V16U16:
2855 case FORMAT_R32F:
2856 case FORMAT_G32R32F:
2857 case FORMAT_X32B32G32R32F:
2858 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002859 case FORMAT_X32B32G32R32F_UNSIGNED:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002860 case FORMAT_A8:
2861 case FORMAT_R8:
2862 case FORMAT_L8:
2863 case FORMAT_A8L8:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002864 case FORMAT_D32F_LOCKABLE:
2865 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002866 case FORMAT_D32F_SHADOW:
Alexis Hetu91dd1c42017-07-18 13:03:42 -04002867 case FORMAT_D32FS8_SHADOW:
2868 case FORMAT_YV12_BT601:
2869 case FORMAT_YV12_BT709:
2870 case FORMAT_YV12_JFIF:
2871 return false;
2872 case FORMAT_R32I:
2873 case FORMAT_R32UI:
2874 case FORMAT_G32R32I:
2875 case FORMAT_G32R32UI:
2876 case FORMAT_X32B32G32R32I:
2877 case FORMAT_X32B32G32R32UI:
2878 case FORMAT_A32B32G32R32I:
2879 case FORMAT_A32B32G32R32UI:
2880 return true;
2881 default:
2882 ASSERT(false);
2883 }
2884
2885 return false;
2886 }
2887
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002888 bool SamplerCore::hasYuvFormat() const
2889 {
2890 switch(state.textureFormat)
2891 {
2892 case FORMAT_YV12_BT601:
2893 case FORMAT_YV12_BT709:
2894 case FORMAT_YV12_JFIF:
2895 return true;
2896 case FORMAT_R5G6B5:
Nicolas Capens975adb72017-12-19 15:34:20 -05002897 case FORMAT_R8_SNORM:
2898 case FORMAT_G8R8_SNORM:
2899 case FORMAT_X8B8G8R8_SNORM:
2900 case FORMAT_A8B8G8R8_SNORM:
Alexis Hetu3412d872015-10-26 16:40:26 -04002901 case FORMAT_R8I:
2902 case FORMAT_R8UI:
2903 case FORMAT_G8R8I:
2904 case FORMAT_G8R8UI:
2905 case FORMAT_X8B8G8R8I:
2906 case FORMAT_X8B8G8R8UI:
2907 case FORMAT_A8B8G8R8I:
2908 case FORMAT_A8B8G8R8UI:
2909 case FORMAT_R32I:
2910 case FORMAT_R32UI:
2911 case FORMAT_G32R32I:
2912 case FORMAT_G32R32UI:
2913 case FORMAT_X32B32G32R32I:
2914 case FORMAT_X32B32G32R32UI:
2915 case FORMAT_A32B32G32R32I:
2916 case FORMAT_A32B32G32R32UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002917 case FORMAT_G8R8:
2918 case FORMAT_X8R8G8B8:
2919 case FORMAT_X8B8G8R8:
2920 case FORMAT_A8R8G8B8:
2921 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002922 case FORMAT_SRGB8_X8:
2923 case FORMAT_SRGB8_A8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002924 case FORMAT_V8U8:
2925 case FORMAT_Q8W8V8U8:
2926 case FORMAT_X8L8V8U8:
2927 case FORMAT_R32F:
2928 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002929 case FORMAT_X32B32G32R32F:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002930 case FORMAT_A32B32G32R32F:
Nicolas Capens67fdd832017-12-21 11:20:54 -05002931 case FORMAT_X32B32G32R32F_UNSIGNED:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002932 case FORMAT_A8:
2933 case FORMAT_R8:
2934 case FORMAT_L8:
2935 case FORMAT_A8L8:
2936 case FORMAT_D32F_LOCKABLE:
2937 case FORMAT_D32FS8_TEXTURE:
Nicolas Capens57e7cea2017-12-13 22:25:04 -05002938 case FORMAT_D32F_SHADOW:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002939 case FORMAT_D32FS8_SHADOW:
2940 case FORMAT_L16:
2941 case FORMAT_G16R16:
2942 case FORMAT_A16B16G16R16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002943 case FORMAT_R16I:
2944 case FORMAT_R16UI:
2945 case FORMAT_G16R16I:
2946 case FORMAT_G16R16UI:
2947 case FORMAT_X16B16G16R16I:
2948 case FORMAT_X16B16G16R16UI:
2949 case FORMAT_A16B16G16R16I:
2950 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002951 case FORMAT_V16U16:
2952 case FORMAT_A16W16V16U16:
2953 case FORMAT_Q16W16V16U16:
2954 return false;
2955 default:
2956 ASSERT(false);
2957 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002958
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002959 return false;
2960 }
2961
John Bauman89401822014-05-06 15:04:28 -04002962 bool SamplerCore::isRGBComponent(int component) const
2963 {
2964 switch(state.textureFormat)
2965 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002966 case FORMAT_R5G6B5: return component < 3;
Nicolas Capens975adb72017-12-19 15:34:20 -05002967 case FORMAT_R8_SNORM: return component < 1;
2968 case FORMAT_G8R8_SNORM: return component < 2;
2969 case FORMAT_X8B8G8R8_SNORM: return component < 3;
2970 case FORMAT_A8B8G8R8_SNORM: return component < 3;
Alexis Hetu3412d872015-10-26 16:40:26 -04002971 case FORMAT_R8I: return component < 1;
2972 case FORMAT_R8UI: return component < 1;
2973 case FORMAT_G8R8I: return component < 2;
2974 case FORMAT_G8R8UI: return component < 2;
2975 case FORMAT_X8B8G8R8I: return component < 3;
2976 case FORMAT_X8B8G8R8UI: return component < 3;
2977 case FORMAT_A8B8G8R8I: return component < 3;
2978 case FORMAT_A8B8G8R8UI: return component < 3;
2979 case FORMAT_R32I: return component < 1;
2980 case FORMAT_R32UI: return component < 1;
2981 case FORMAT_G32R32I: return component < 2;
2982 case FORMAT_G32R32UI: return component < 2;
2983 case FORMAT_X32B32G32R32I: return component < 3;
2984 case FORMAT_X32B32G32R32UI: return component < 3;
2985 case FORMAT_A32B32G32R32I: return component < 3;
2986 case FORMAT_A32B32G32R32UI: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002987 case FORMAT_G8R8: return component < 2;
2988 case FORMAT_X8R8G8B8: return component < 3;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002989 case FORMAT_X8B8G8R8: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002990 case FORMAT_A8R8G8B8: return component < 3;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002991 case FORMAT_A8B8G8R8: return component < 3;
Alexis Hetu049a1872016-04-25 16:59:58 -04002992 case FORMAT_SRGB8_X8: return component < 3;
2993 case FORMAT_SRGB8_A8: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002994 case FORMAT_V8U8: return false;
2995 case FORMAT_Q8W8V8U8: return false;
2996 case FORMAT_X8L8V8U8: return false;
2997 case FORMAT_R32F: return component < 1;
2998 case FORMAT_G32R32F: return component < 2;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002999 case FORMAT_X32B32G32R32F: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003000 case FORMAT_A32B32G32R32F: return component < 3;
Nicolas Capens67fdd832017-12-21 11:20:54 -05003001 case FORMAT_X32B32G32R32F_UNSIGNED: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003002 case FORMAT_A8: return false;
3003 case FORMAT_R8: return component < 1;
3004 case FORMAT_L8: return component < 1;
3005 case FORMAT_A8L8: return component < 1;
3006 case FORMAT_D32F_LOCKABLE: return false;
3007 case FORMAT_D32FS8_TEXTURE: return false;
Nicolas Capens57e7cea2017-12-13 22:25:04 -05003008 case FORMAT_D32F_SHADOW: return false;
John Bauman66b8ab22014-05-06 15:57:45 -04003009 case FORMAT_D32FS8_SHADOW: return false;
3010 case FORMAT_L16: return component < 1;
3011 case FORMAT_G16R16: return component < 2;
3012 case FORMAT_A16B16G16R16: return component < 3;
Alexis Hetu3412d872015-10-26 16:40:26 -04003013 case FORMAT_R16I: return component < 1;
3014 case FORMAT_R16UI: return component < 1;
3015 case FORMAT_G16R16I: return component < 2;
3016 case FORMAT_G16R16UI: return component < 2;
3017 case FORMAT_X16B16G16R16I: return component < 3;
3018 case FORMAT_X16B16G16R16UI: return component < 3;
3019 case FORMAT_A16B16G16R16I: return component < 3;
3020 case FORMAT_A16B16G16R16UI: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04003021 case FORMAT_V16U16: return false;
3022 case FORMAT_A16W16V16U16: return false;
3023 case FORMAT_Q16W16V16U16: return false;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04003024 case FORMAT_YV12_BT601: return component < 3;
3025 case FORMAT_YV12_BT709: return component < 3;
3026 case FORMAT_YV12_JFIF: return component < 3;
John Bauman89401822014-05-06 15:04:28 -04003027 default:
3028 ASSERT(false);
3029 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05003030
John Bauman89401822014-05-06 15:04:28 -04003031 return false;
3032 }
3033}