blob: a4de5f59ed60af1c89b77dd10b035d634d67e63d [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"
18#include "Debug.hpp"
19
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;
30 case sw::SWIZZLE_ZERO: s = sw::Short4(0x0000, 0x0000, 0x0000, 0x0000); break;
31 case sw::SWIZZLE_ONE: s = sw::Short4(0x1000, 0x1000, 0x1000, 0x1000); break;
32 default: ASSERT(false);
33 }
34 }
35
36 void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c)
37 {
38 switch(swizzle)
39 {
40 case sw::SWIZZLE_RED: f = c.x; break;
41 case sw::SWIZZLE_GREEN: f = c.y; break;
42 case sw::SWIZZLE_BLUE: f = c.z; break;
43 case sw::SWIZZLE_ALPHA: f = c.w; break;
44 case sw::SWIZZLE_ZERO: f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break;
45 case sw::SWIZZLE_ONE: f = sw::Float4(1.0f, 1.0f, 1.0f, 1.0f); break;
46 default: ASSERT(false);
47 }
48 }
49}
50
John Bauman89401822014-05-06 15:04:28 -040051namespace sw
52{
53 SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
54 {
55 }
56
Nicolas Capensc2534f42016-04-04 11:13:24 -040057 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
58 {
59 sampleTexture(texture, c, u, v, w, q, dsx, dsy, method, true);
60 }
61
62 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method, bool fixed12)
John Bauman89401822014-05-06 15:04:28 -040063 {
64 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -040065 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -040066
67 if(state.compressedFormat)
68 {
John Bauman66b8ab22014-05-06 15:57:45 -040069 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -040070 }
71 #endif
72
John Bauman89401822014-05-06 15:04:28 -040073 Float4 uuuu = u;
74 Float4 vvvv = v;
75 Float4 wwww = w;
76
77 if(state.textureType == TEXTURE_NULL)
78 {
John Bauman19bac1e2014-05-06 15:23:49 -040079 c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000);
80 c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000);
81 c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000);
John Bauman89401822014-05-06 15:04:28 -040082
83 if(fixed12) // FIXME: Convert to fixed12 at higher level, when required
84 {
John Bauman19bac1e2014-05-06 15:23:49 -040085 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -040086 }
87 else
88 {
John Bauman19bac1e2014-05-06 15:23:49 -040089 c.w = Short4((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); // FIXME
John Bauman89401822014-05-06 15:04:28 -040090 }
91 }
92 else
93 {
94 Int face[4];
Nicolas Capens2cfadc62016-04-19 09:09:29 -040095 Float4 lodX;
96 Float4 lodY;
97 Float4 lodZ;
John Bauman89401822014-05-06 15:04:28 -040098
Alexis Hetu3b96fa82016-02-04 21:15:03 -050099 if(state.textureType == TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400100 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -0400101 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
John Bauman89401822014-05-06 15:04:28 -0400102 }
103
104 Float lod;
105 Float anisotropy;
106 Float4 uDelta;
107 Float4 vDelta;
108
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500109 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400110 {
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500111 if(state.textureType != TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400112 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400113 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, method);
John Bauman89401822014-05-06 15:04:28 -0400114 }
115 else
116 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -0400117 computeLodCube(texture, lod, lodX, lodY, lodZ, q.x, dsx, dsy, method);
John Bauman89401822014-05-06 15:04:28 -0400118 }
119 }
120 else
121 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400122 computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method);
John Bauman89401822014-05-06 15:04:28 -0400123 }
124
John Bauman89401822014-05-06 15:04:28 -0400125 if(!hasFloatTexture())
126 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400127 sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
John Bauman89401822014-05-06 15:04:28 -0400128 }
129 else
130 {
John Bauman19bac1e2014-05-06 15:23:49 -0400131 Vector4f cf;
John Bauman89401822014-05-06 15:04:28 -0400132
Nicolas Capensc2534f42016-04-04 11:13:24 -0400133 sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
John Bauman89401822014-05-06 15:04:28 -0400134
135 convertFixed12(c, cf);
136 }
137
138 if(fixed12 && !hasFloatTexture())
139 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400140 if(has16bitTextureFormat())
John Bauman89401822014-05-06 15:04:28 -0400141 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400142 switch(state.textureFormat)
John Bauman89401822014-05-06 15:04:28 -0400143 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400144 case FORMAT_R5G6B5:
145 if(state.sRGB)
John Bauman89401822014-05-06 15:04:28 -0400146 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400147 sRGBtoLinear16_5_12(c.x);
148 sRGBtoLinear16_6_12(c.y);
149 sRGBtoLinear16_5_12(c.z);
John Bauman89401822014-05-06 15:04:28 -0400150 }
151 else
152 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400153 c.x = MulHigh(As<UShort4>(c.x), UShort4(0x10000000 / 0xF800));
154 c.y = MulHigh(As<UShort4>(c.y), UShort4(0x10000000 / 0xFC00));
155 c.z = MulHigh(As<UShort4>(c.z), UShort4(0x10000000 / 0xF800));
156 }
157 break;
158 default:
159 ASSERT(false);
160 }
161 }
162 else
163 {
164 for(int component = 0; component < textureComponentCount(); component++)
165 {
166 if(state.sRGB && isRGBComponent(component))
167 {
168 sRGBtoLinear16_8_12(c[component]); // FIXME: Perform linearization at surface level for read-only textures
169 }
170 else
171 {
172 if(hasUnsignedTextureComponent(component))
173 {
174 c[component] = As<UShort4>(c[component]) >> 4;
175 }
176 else
177 {
178 c[component] = c[component] >> 3;
179 }
John Bauman89401822014-05-06 15:04:28 -0400180 }
181 }
182 }
183 }
184
185 if(fixed12 && state.textureFilter != FILTER_GATHER)
186 {
187 int componentCount = textureComponentCount();
188
189 switch(state.textureFormat)
190 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400191 case FORMAT_R8I_SNORM:
192 case FORMAT_G8R8I_SNORM:
193 case FORMAT_X8B8G8R8I_SNORM:
194 case FORMAT_A8B8G8R8I_SNORM:
John Bauman89401822014-05-06 15:04:28 -0400195 case FORMAT_R8:
Nicolas Capens27496312015-05-12 15:16:06 -0400196 case FORMAT_R5G6B5:
Alexis Hetu3412d872015-10-26 16:40:26 -0400197 case FORMAT_G8R8:
198 case FORMAT_R8I:
199 case FORMAT_R8UI:
200 case FORMAT_G8R8I:
201 case FORMAT_G8R8UI:
202 case FORMAT_X8B8G8R8I:
203 case FORMAT_X8B8G8R8UI:
204 case FORMAT_A8B8G8R8I:
205 case FORMAT_A8B8G8R8UI:
206 case FORMAT_R16I:
207 case FORMAT_R16UI:
208 case FORMAT_G16R16:
209 case FORMAT_G16R16I:
210 case FORMAT_G16R16UI:
211 case FORMAT_X16B16G16R16I:
212 case FORMAT_X16B16G16R16UI:
213 case FORMAT_A16B16G16R16:
214 case FORMAT_A16B16G16R16I:
215 case FORMAT_A16B16G16R16UI:
216 case FORMAT_R32I:
217 case FORMAT_R32UI:
218 case FORMAT_G32R32I:
219 case FORMAT_G32R32UI:
220 case FORMAT_X32B32G32R32I:
221 case FORMAT_X32B32G32R32UI:
222 case FORMAT_A32B32G32R32I:
223 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -0400224 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400225 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -0400226 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400227 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400228 case FORMAT_SRGB8_X8:
229 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -0400230 case FORMAT_V8U8:
231 case FORMAT_Q8W8V8U8:
232 case FORMAT_X8L8V8U8:
233 case FORMAT_V16U16:
234 case FORMAT_A16W16V16U16:
235 case FORMAT_Q16W16V16U16:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -0400236 case FORMAT_YV12_BT601:
237 case FORMAT_YV12_BT709:
238 case FORMAT_YV12_JFIF:
John Bauman19bac1e2014-05-06 15:23:49 -0400239 if(componentCount < 2) c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000);
240 if(componentCount < 3) c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000);
241 if(componentCount < 4) c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400242 break;
243 case FORMAT_A8:
John Bauman19bac1e2014-05-06 15:23:49 -0400244 c.w = c.x;
245 c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000);
246 c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000);
247 c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000);
John Bauman89401822014-05-06 15:04:28 -0400248 break;
249 case FORMAT_L8:
250 case FORMAT_L16:
John Bauman19bac1e2014-05-06 15:23:49 -0400251 c.y = c.x;
252 c.z = c.x;
253 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400254 break;
255 case FORMAT_A8L8:
John Bauman19bac1e2014-05-06 15:23:49 -0400256 c.w = c.y;
257 c.y = c.x;
258 c.z = c.x;
John Bauman89401822014-05-06 15:04:28 -0400259 break;
260 case FORMAT_R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400261 c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400262 case FORMAT_G32R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400263 c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000);
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400264 case FORMAT_X32B32G32R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400265 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400266 case FORMAT_A32B32G32R32F:
267 break;
Alexis Hetu3412d872015-10-26 16:40:26 -0400268 case FORMAT_D32F:
John Bauman89401822014-05-06 15:04:28 -0400269 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400270 case FORMAT_D32FS8_TEXTURE:
271 case FORMAT_D32FS8_SHADOW:
John Bauman19bac1e2014-05-06 15:23:49 -0400272 c.y = c.x;
273 c.z = c.x;
274 c.w = c.x;
John Bauman89401822014-05-06 15:04:28 -0400275 break;
276 default:
277 ASSERT(false);
278 }
279 }
280 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400281
282 if(fixed12 &&
283 ((state.swizzleR != SWIZZLE_RED) ||
284 (state.swizzleG != SWIZZLE_GREEN) ||
285 (state.swizzleB != SWIZZLE_BLUE) ||
286 (state.swizzleA != SWIZZLE_ALPHA)))
287 {
288 const Vector4s col(c);
289 applySwizzle(state.swizzleR, c.x, col);
290 applySwizzle(state.swizzleG, c.y, col);
291 applySwizzle(state.swizzleB, c.z, col);
292 applySwizzle(state.swizzleA, c.w, col);
293 }
John Bauman89401822014-05-06 15:04:28 -0400294 }
295
Nicolas Capensc2534f42016-04-04 11:13:24 -0400296 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -0400297 {
298 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -0400299 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -0400300
301 if(state.compressedFormat)
302 {
John Bauman66b8ab22014-05-06 15:57:45 -0400303 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -0400304 }
305 #endif
306
John Bauman89401822014-05-06 15:04:28 -0400307 if(state.textureType == TEXTURE_NULL)
308 {
John Bauman19bac1e2014-05-06 15:23:49 -0400309 c.x = Float4(0.0f);
310 c.y = Float4(0.0f);
311 c.z = Float4(0.0f);
312 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400313 }
314 else
315 {
316 if(hasFloatTexture()) // FIXME: Mostly identical to integer sampling
317 {
318 Float4 uuuu = u;
319 Float4 vvvv = v;
320 Float4 wwww = w;
321
322 Int face[4];
Nicolas Capens2cfadc62016-04-19 09:09:29 -0400323 Float4 lodX;
324 Float4 lodY;
325 Float4 lodZ;
John Bauman89401822014-05-06 15:04:28 -0400326
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500327 if(state.textureType == TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400328 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -0400329 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w);
John Bauman89401822014-05-06 15:04:28 -0400330 }
331
332 Float lod;
333 Float anisotropy;
334 Float4 uDelta;
335 Float4 vDelta;
336
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500337 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400338 {
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500339 if(state.textureType != TEXTURE_CUBE)
John Bauman89401822014-05-06 15:04:28 -0400340 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400341 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, method);
John Bauman89401822014-05-06 15:04:28 -0400342 }
343 else
344 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -0400345 computeLodCube(texture, lod, lodX, lodY, lodZ, q.x, dsx, dsy, method);
John Bauman89401822014-05-06 15:04:28 -0400346 }
347 }
348 else
349 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400350 computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method);
John Bauman89401822014-05-06 15:04:28 -0400351 }
352
Nicolas Capensc2534f42016-04-04 11:13:24 -0400353 sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
John Bauman89401822014-05-06 15:04:28 -0400354 }
355 else
356 {
Alexis Hetu96517182015-04-15 10:30:23 -0400357 Vector4s cs;
John Bauman89401822014-05-06 15:04:28 -0400358
Nicolas Capensc2534f42016-04-04 11:13:24 -0400359 sampleTexture(texture, cs, u, v, w, q, dsx, dsy, method, false);
John Bauman89401822014-05-06 15:04:28 -0400360
361 for(int component = 0; component < textureComponentCount(); component++)
362 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400363 if(has16bitTextureFormat())
John Bauman89401822014-05-06 15:04:28 -0400364 {
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400365 switch(state.textureFormat)
366 {
367 case FORMAT_R5G6B5:
368 if(state.sRGB)
369 {
370 sRGBtoLinear16_5_12(cs.x);
371 sRGBtoLinear16_6_12(cs.y);
372 sRGBtoLinear16_5_12(cs.z);
373
374 convertSigned12(c.x, cs.x);
375 convertSigned12(c.y, cs.y);
376 convertSigned12(c.z, cs.z);
377 }
378 else
379 {
380 c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
381 c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
382 c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
383 }
384 break;
385 default:
386 ASSERT(false);
387 }
John Bauman89401822014-05-06 15:04:28 -0400388 }
389 else
390 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400391 switch(state.textureFormat)
John Bauman89401822014-05-06 15:04:28 -0400392 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400393 case FORMAT_R8I:
394 case FORMAT_G8R8I:
395 case FORMAT_X8B8G8R8I:
396 case FORMAT_A8B8G8R8I:
397 c[component] = As<Float4>(Int4(cs[component]) >> 8);
398 break;
399 case FORMAT_R8UI:
400 case FORMAT_G8R8UI:
401 case FORMAT_X8B8G8R8UI:
402 case FORMAT_A8B8G8R8UI:
403 c[component] = As<Float4>(Int4(As<UShort4>(cs[component]) >> 8));
404 break;
405 case FORMAT_R16I:
406 case FORMAT_G16R16I:
407 case FORMAT_X16B16G16R16I:
408 case FORMAT_A16B16G16R16I:
409 c[component] = As<Float4>(Int4(cs[component]));
410 break;
411 case FORMAT_R16UI:
412 case FORMAT_G16R16UI:
413 case FORMAT_X16B16G16R16UI:
414 case FORMAT_A16B16G16R16UI:
415 c[component] = As<Float4>(Int4(As<UShort4>(cs[component])));
416 break;
417 default:
418 // Normalized integer formats
419 if(state.sRGB && isRGBComponent(component))
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400420 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400421 sRGBtoLinear16_8_12(cs[component]); // FIXME: Perform linearization at surface level for read-only textures
422 convertSigned12(c[component], cs[component]);
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400423 }
424 else
425 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400426 if(hasUnsignedTextureComponent(component))
427 {
428 convertUnsigned16(c[component], cs[component]);
429 }
430 else
431 {
432 convertSigned15(c[component], cs[component]);
433 }
Nicolas Capens3a014ff2015-05-26 14:05:36 -0400434 }
Alexis Hetu3412d872015-10-26 16:40:26 -0400435 break;
John Bauman89401822014-05-06 15:04:28 -0400436 }
437 }
438 }
439 }
440
441 int componentCount = textureComponentCount();
442
443 if(state.textureFilter != FILTER_GATHER)
444 {
445 switch(state.textureFormat)
446 {
Alexis Hetu3412d872015-10-26 16:40:26 -0400447 case FORMAT_R8I:
448 case FORMAT_R8UI:
449 case FORMAT_R16I:
450 case FORMAT_R16UI:
451 case FORMAT_R32I:
452 case FORMAT_R32UI:
453 c.y = As<Float4>(UInt4(0));
454 case FORMAT_G8R8I:
455 case FORMAT_G8R8UI:
456 case FORMAT_G16R16I:
457 case FORMAT_G16R16UI:
458 case FORMAT_G32R32I:
459 case FORMAT_G32R32UI:
460 c.z = As<Float4>(UInt4(0));
461 case FORMAT_X8B8G8R8I:
462 case FORMAT_X8B8G8R8UI:
463 case FORMAT_X16B16G16R16I:
464 case FORMAT_X16B16G16R16UI:
465 case FORMAT_X32B32G32R32I:
466 case FORMAT_X32B32G32R32UI:
467 c.w = As<Float4>(UInt4(1));
468 case FORMAT_A8B8G8R8I:
469 case FORMAT_A8B8G8R8UI:
470 case FORMAT_A16B16G16R16I:
471 case FORMAT_A16B16G16R16UI:
472 case FORMAT_A32B32G32R32I:
473 case FORMAT_A32B32G32R32UI:
474 break;
475 case FORMAT_R8I_SNORM:
476 case FORMAT_G8R8I_SNORM:
477 case FORMAT_X8B8G8R8I_SNORM:
478 case FORMAT_A8B8G8R8I_SNORM:
John Bauman89401822014-05-06 15:04:28 -0400479 case FORMAT_R8:
Nicolas Capens27496312015-05-12 15:16:06 -0400480 case FORMAT_R5G6B5:
Alexis Hetu3412d872015-10-26 16:40:26 -0400481 case FORMAT_G8R8:
482 case FORMAT_G16R16:
483 case FORMAT_A16B16G16R16:
John Bauman89401822014-05-06 15:04:28 -0400484 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400485 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -0400486 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -0400487 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -0400488 case FORMAT_SRGB8_X8:
489 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -0400490 case FORMAT_V8U8:
491 case FORMAT_Q8W8V8U8:
492 case FORMAT_X8L8V8U8:
493 case FORMAT_V16U16:
494 case FORMAT_A16W16V16U16:
495 case FORMAT_Q16W16V16U16:
John Bauman19bac1e2014-05-06 15:23:49 -0400496 if(componentCount < 2) c.y = Float4(1.0f);
497 if(componentCount < 3) c.z = Float4(1.0f);
498 if(componentCount < 4) c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400499 break;
500 case FORMAT_A8:
John Bauman19bac1e2014-05-06 15:23:49 -0400501 c.w = c.x;
502 c.x = Float4(0.0f);
503 c.y = Float4(0.0f);
504 c.z = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -0400505 break;
506 case FORMAT_L8:
507 case FORMAT_L16:
John Bauman19bac1e2014-05-06 15:23:49 -0400508 c.y = c.x;
509 c.z = c.x;
510 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400511 break;
512 case FORMAT_A8L8:
John Bauman19bac1e2014-05-06 15:23:49 -0400513 c.w = c.y;
514 c.y = c.x;
515 c.z = c.x;
John Bauman89401822014-05-06 15:04:28 -0400516 break;
517 case FORMAT_R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400518 c.y = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400519 case FORMAT_G32R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400520 c.z = Float4(1.0f);
Alexis Hetudbd1a8e2016-04-13 11:40:30 -0400521 case FORMAT_X32B32G32R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400522 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400523 case FORMAT_A32B32G32R32F:
524 break;
Alexis Hetu3412d872015-10-26 16:40:26 -0400525 case FORMAT_D32F:
John Bauman89401822014-05-06 15:04:28 -0400526 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400527 case FORMAT_D32FS8_TEXTURE:
528 case FORMAT_D32FS8_SHADOW:
John Bauman19bac1e2014-05-06 15:23:49 -0400529 c.y = c.x;
530 c.z = c.x;
531 c.w = c.x;
John Bauman89401822014-05-06 15:04:28 -0400532 break;
533 default:
534 ASSERT(false);
535 }
536 }
537 }
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400538
539 if((state.swizzleR != SWIZZLE_RED) ||
540 (state.swizzleG != SWIZZLE_GREEN) ||
541 (state.swizzleB != SWIZZLE_BLUE) ||
542 (state.swizzleA != SWIZZLE_ALPHA))
543 {
544 const Vector4f col(c);
545 applySwizzle(state.swizzleR, c.x, col);
546 applySwizzle(state.swizzleG, c.y, col);
547 applySwizzle(state.swizzleB, c.z, col);
548 applySwizzle(state.swizzleA, c.w, col);
549 }
John Bauman89401822014-05-06 15:04:28 -0400550 }
551
552 void SamplerCore::border(Short4 &mask, Float4 &coordinates)
553 {
554 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
555 mask = As<Short4>(Int2(As<Int4>(Pack(border, border))));
556 }
557
558 void SamplerCore::border(Int4 &mask, Float4 &coordinates)
559 {
560 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
561 }
562
Nicolas Capens5989fab2016-02-15 10:31:49 -0500563 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
John Bauman89401822014-05-06 15:04:28 -0400564 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500565 Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
566
567 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
568 {
569 offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
570 }
571 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
572 {
573 offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
574 }
575
John Bauman89401822014-05-06 15:04:28 -0400576 if(wrap)
577 {
578 switch(count)
579 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500580 case -1: return uvw - offset;
John Bauman89401822014-05-06 15:04:28 -0400581 case 0: return uvw;
Nicolas Capens5989fab2016-02-15 10:31:49 -0500582 case +1: return uvw + offset;
583 case 2: return uvw + offset + offset;
John Bauman89401822014-05-06 15:04:28 -0400584 }
585 }
586 else // Clamp or mirror
587 {
588 switch(count)
589 {
Nicolas Capens5989fab2016-02-15 10:31:49 -0500590 case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset));
John Bauman89401822014-05-06 15:04:28 -0400591 case 0: return uvw;
Nicolas Capens5989fab2016-02-15 10:31:49 -0500592 case +1: return AddSat(As<UShort4>(uvw), As<UShort4>(offset));
593 case 2: return AddSat(AddSat(As<UShort4>(uvw), As<UShort4>(offset)), As<UShort4>(offset));
John Bauman89401822014-05-06 15:04:28 -0400594 }
595 }
596
597 return uvw;
598 }
599
Nicolas Capensc2534f42016-04-04 11:13:24 -0400600 void SamplerCore::sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -0400601 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400602 sampleAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, method);
John Bauman89401822014-05-06 15:04:28 -0400603
604 if(state.mipmapFilter > MIPMAP_POINT)
605 {
Alexis Hetu96517182015-04-15 10:30:23 -0400606 Vector4s cc;
John Bauman89401822014-05-06 15:04:28 -0400607
Nicolas Capensc2534f42016-04-04 11:13:24 -0400608 sampleAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, method);
John Bauman89401822014-05-06 15:04:28 -0400609
610 lod *= Float(1 << 16);
611
612 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize
613 Short4 stri = utri >> 1; // FIXME: Optimize
614
John Bauman19bac1e2014-05-06 15:23:49 -0400615 if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri);
616 if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri);
617 if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri);
618 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 -0400619
620 utri = ~utri;
621 stri = Short4(0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF) - stri;
622
John Bauman19bac1e2014-05-06 15:23:49 -0400623 if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri);
624 if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri);
625 if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri);
626 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 -0500627
John Bauman19bac1e2014-05-06 15:23:49 -0400628 c.x += cc.x;
629 c.y += cc.y;
630 c.z += cc.z;
631 c.w += cc.w;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500632
John Bauman19bac1e2014-05-06 15:23:49 -0400633 if(!hasUnsignedTextureComponent(0)) c.x += c.x;
634 if(!hasUnsignedTextureComponent(1)) c.y += c.y;
635 if(!hasUnsignedTextureComponent(2)) c.z += c.z;
636 if(!hasUnsignedTextureComponent(3)) c.w += c.w;
John Bauman89401822014-05-06 15:04:28 -0400637 }
638
639 Short4 borderMask;
640
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400641 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400642 {
643 Short4 u0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500644
John Bauman89401822014-05-06 15:04:28 -0400645 border(u0, u);
646
647 borderMask = u0;
648 }
649
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400650 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400651 {
652 Short4 v0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500653
John Bauman89401822014-05-06 15:04:28 -0400654 border(v0, v);
655
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400656 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400657 {
658 borderMask &= v0;
659 }
660 else
661 {
662 borderMask = v0;
663 }
664 }
665
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500666 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400667 {
668 Short4 s0;
669
670 border(s0, w);
671
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400672 if(state.addressingModeU == ADDRESSING_BORDER ||
673 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400674 {
675 borderMask &= s0;
676 }
677 else
678 {
679 borderMask = s0;
680 }
681 }
682
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400683 if(state.addressingModeU == ADDRESSING_BORDER ||
684 state.addressingModeV == ADDRESSING_BORDER ||
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500685 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
John Bauman89401822014-05-06 15:04:28 -0400686 {
687 Short4 b;
688
John Bauman19bac1e2014-05-06 15:23:49 -0400689 c.x = borderMask & c.x | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1));
690 c.y = borderMask & c.y | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1));
691 c.z = borderMask & c.z | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1));
692 c.w = borderMask & c.w | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1));
John Bauman89401822014-05-06 15:04:28 -0400693 }
694 }
695
Nicolas Capensc2534f42016-04-04 11:13:24 -0400696 void SamplerCore::sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -0400697 {
Nicolas Capensc2534f42016-04-04 11:13:24 -0400698 if(state.textureFilter != FILTER_ANISOTROPIC || method == Lod)
John Bauman89401822014-05-06 15:04:28 -0400699 {
700 sampleQuad(texture, c, u, v, w, lod, face, secondLOD);
701 }
702 else
703 {
704 Int a = RoundInt(anisotropy);
705
Alexis Hetu96517182015-04-15 10:30:23 -0400706 Vector4s cSum;
John Bauman89401822014-05-06 15:04:28 -0400707
John Bauman19bac1e2014-05-06 15:23:49 -0400708 cSum.x = Short4(0, 0, 0, 0);
709 cSum.y = Short4(0, 0, 0, 0);
710 cSum.z = Short4(0, 0, 0, 0);
711 cSum.w = Short4(0, 0, 0, 0);
John Bauman89401822014-05-06 15:04:28 -0400712
713 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
714 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
715 UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a);
716 Short4 sw = Short4(cw >> 1);
717
718 Float4 du = uDelta;
719 Float4 dv = vDelta;
720
721 Float4 u0 = u + B * du;
722 Float4 v0 = v + B * dv;
723
724 du *= A;
725 dv *= A;
726
727 Int i = 0;
728
729 Do
730 {
731 sampleQuad(texture, c, u0, v0, w, lod, face, secondLOD);
732
733 u0 += du;
734 v0 += dv;
735
John Bauman19bac1e2014-05-06 15:23:49 -0400736 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw);
737 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw);
738 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw);
739 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 -0400740
741 i++;
742 }
743 Until(i >= a)
744
John Bauman19bac1e2014-05-06 15:23:49 -0400745 if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x);
746 if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y);
747 if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z);
748 if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w);
John Bauman89401822014-05-06 15:04:28 -0400749 }
750 }
751
Alexis Hetu96517182015-04-15 10:30:23 -0400752 void SamplerCore::sampleQuad(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -0400753 {
Alexis Hetuc8b97852016-02-04 21:15:03 -0500754 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -0400755 {
Alexis Hetuc8b97852016-02-04 21:15:03 -0500756 sampleQuad2D(texture, c, u, v, w, lod, face, secondLOD);
John Bauman89401822014-05-06 15:04:28 -0400757 }
758 else
759 {
760 sample3D(texture, c, u, v, w, lod, secondLOD);
761 }
762 }
763
Alexis Hetuc8b97852016-02-04 21:15:03 -0500764 void SamplerCore::sampleQuad2D(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -0400765 {
766 int componentCount = textureComponentCount();
767 bool gather = state.textureFilter == FILTER_GATHER;
768
769 Pointer<Byte> mipmap;
770 Pointer<Byte> buffer[4];
771
772 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
773
Nicolas Capens7bb62682016-02-08 11:30:56 -0500774 Short4 uuuu = address(u, state.addressingModeU, mipmap);
775 Short4 vvvv = address(v, state.addressingModeV, mipmap);
776 Short4 wwww = address(w, state.addressingModeW, mipmap);
John Bauman89401822014-05-06 15:04:28 -0400777
Nicolas Capens5989fab2016-02-15 10:31:49 -0500778 if(state.textureFilter == FILTER_POINT)
John Bauman89401822014-05-06 15:04:28 -0400779 {
Alexis Hetuc8b97852016-02-04 21:15:03 -0500780 sampleTexel(c, uuuu, vvvv, wwww, mipmap, buffer);
John Bauman89401822014-05-06 15:04:28 -0400781 }
782 else
783 {
Alexis Hetu96517182015-04-15 10:30:23 -0400784 Vector4s c0;
785 Vector4s c1;
786 Vector4s c2;
787 Vector4s c3;
John Bauman89401822014-05-06 15:04:28 -0400788
Nicolas Capens5989fab2016-02-15 10:31:49 -0500789 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
790 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
791 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
792 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
John Bauman89401822014-05-06 15:04:28 -0400793
Alexis Hetuc8b97852016-02-04 21:15:03 -0500794 sampleTexel(c0, uuuu0, vvvv0, wwww, mipmap, buffer);
795 sampleTexel(c1, uuuu1, vvvv0, wwww, mipmap, buffer);
796 sampleTexel(c2, uuuu0, vvvv1, wwww, mipmap, buffer);
797 sampleTexel(c3, uuuu1, vvvv1, wwww, mipmap, buffer);
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500798
John Bauman89401822014-05-06 15:04:28 -0400799 if(!gather) // Blend
800 {
801 // Fractions
802 UShort4 f0u = uuuu0;
803 UShort4 f0v = vvvv0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500804
John Bauman89401822014-05-06 15:04:28 -0400805 if(!state.hasNPOTTexture)
806 {
807 f0u = f0u << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt)); // .u
808 f0v = f0v << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt)); // .v
809 }
810 else
811 {
812 f0u = f0u * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
813 f0v = f0v * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
814 }
815
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400816 UShort4 f1u = ~f0u;
817 UShort4 f1v = ~f0v;
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500818
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400819 UShort4 f0u0v = MulHigh(f0u, f0v);
820 UShort4 f1u0v = MulHigh(f1u, f0v);
821 UShort4 f0u1v = MulHigh(f0u, f1v);
822 UShort4 f1u1v = MulHigh(f1u, f1v);
John Bauman89401822014-05-06 15:04:28 -0400823
824 // Signed fractions
825 Short4 f1u1vs;
826 Short4 f0u1vs;
827 Short4 f1u0vs;
828 Short4 f0u0vs;
829
830 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
831 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400832 f1u1vs = f1u1v >> 1;
833 f0u1vs = f0u1v >> 1;
834 f1u0vs = f1u0v >> 1;
835 f0u0vs = f0u0v >> 1;
John Bauman89401822014-05-06 15:04:28 -0400836 }
837
838 // Bilinear interpolation
839 if(componentCount >= 1)
840 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400841 if(has16bitTextureComponents() && hasUnsignedTextureComponent(0))
John Bauman89401822014-05-06 15:04:28 -0400842 {
John Bauman19bac1e2014-05-06 15:23:49 -0400843 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u);
844 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u);
845 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 -0400846 }
847 else
848 {
849 if(hasUnsignedTextureComponent(0))
850 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400851 c0.x = MulHigh(As<UShort4>(c0.x), f1u1v);
852 c1.x = MulHigh(As<UShort4>(c1.x), f0u1v);
853 c2.x = MulHigh(As<UShort4>(c2.x), f1u0v);
854 c3.x = MulHigh(As<UShort4>(c3.x), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400855 }
856 else
857 {
John Bauman19bac1e2014-05-06 15:23:49 -0400858 c0.x = MulHigh(c0.x, f1u1vs);
859 c1.x = MulHigh(c1.x, f0u1vs);
860 c2.x = MulHigh(c2.x, f1u0vs);
861 c3.x = MulHigh(c3.x, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400862 }
863
John Bauman19bac1e2014-05-06 15:23:49 -0400864 c.x = (c0.x + c1.x) + (c2.x + c3.x);
865 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400866 }
867 }
868
869 if(componentCount >= 2)
870 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400871 if(has16bitTextureComponents() && hasUnsignedTextureComponent(1))
John Bauman89401822014-05-06 15:04:28 -0400872 {
John Bauman19bac1e2014-05-06 15:23:49 -0400873 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u);
874 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u);
875 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 -0400876 }
877 else
878 {
879 if(hasUnsignedTextureComponent(1))
880 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400881 c0.y = MulHigh(As<UShort4>(c0.y), f1u1v);
882 c1.y = MulHigh(As<UShort4>(c1.y), f0u1v);
883 c2.y = MulHigh(As<UShort4>(c2.y), f1u0v);
884 c3.y = MulHigh(As<UShort4>(c3.y), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400885 }
886 else
887 {
John Bauman19bac1e2014-05-06 15:23:49 -0400888 c0.y = MulHigh(c0.y, f1u1vs);
889 c1.y = MulHigh(c1.y, f0u1vs);
890 c2.y = MulHigh(c2.y, f1u0vs);
891 c3.y = MulHigh(c3.y, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400892 }
893
John Bauman19bac1e2014-05-06 15:23:49 -0400894 c.y = (c0.y + c1.y) + (c2.y + c3.y);
895 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400896 }
897 }
898
899 if(componentCount >= 3)
900 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400901 if(has16bitTextureComponents() && hasUnsignedTextureComponent(2))
John Bauman89401822014-05-06 15:04:28 -0400902 {
John Bauman19bac1e2014-05-06 15:23:49 -0400903 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u);
904 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u);
905 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 -0400906 }
907 else
908 {
909 if(hasUnsignedTextureComponent(2))
910 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400911 c0.z = MulHigh(As<UShort4>(c0.z), f1u1v);
912 c1.z = MulHigh(As<UShort4>(c1.z), f0u1v);
913 c2.z = MulHigh(As<UShort4>(c2.z), f1u0v);
914 c3.z = MulHigh(As<UShort4>(c3.z), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400915 }
916 else
917 {
John Bauman19bac1e2014-05-06 15:23:49 -0400918 c0.z = MulHigh(c0.z, f1u1vs);
919 c1.z = MulHigh(c1.z, f0u1vs);
920 c2.z = MulHigh(c2.z, f1u0vs);
921 c3.z = MulHigh(c3.z, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400922 }
923
John Bauman19bac1e2014-05-06 15:23:49 -0400924 c.z = (c0.z + c1.z) + (c2.z + c3.z);
925 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400926 }
927 }
928
929 if(componentCount >= 4)
930 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -0400931 if(has16bitTextureComponents() && hasUnsignedTextureComponent(3))
John Bauman89401822014-05-06 15:04:28 -0400932 {
John Bauman19bac1e2014-05-06 15:23:49 -0400933 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u);
934 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u);
935 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 -0400936 }
937 else
938 {
939 if(hasUnsignedTextureComponent(3))
940 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -0400941 c0.w = MulHigh(As<UShort4>(c0.w), f1u1v);
942 c1.w = MulHigh(As<UShort4>(c1.w), f0u1v);
943 c2.w = MulHigh(As<UShort4>(c2.w), f1u0v);
944 c3.w = MulHigh(As<UShort4>(c3.w), f0u0v);
John Bauman89401822014-05-06 15:04:28 -0400945 }
946 else
947 {
John Bauman19bac1e2014-05-06 15:23:49 -0400948 c0.w = MulHigh(c0.w, f1u1vs);
949 c1.w = MulHigh(c1.w, f0u1vs);
950 c2.w = MulHigh(c2.w, f1u0vs);
951 c3.w = MulHigh(c3.w, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400952 }
953
John Bauman19bac1e2014-05-06 15:23:49 -0400954 c.w = (c0.w + c1.w) + (c2.w + c3.w);
955 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400956 }
957 }
958 }
959 else
960 {
John Bauman19bac1e2014-05-06 15:23:49 -0400961 c.x = c1.x;
962 c.y = c2.x;
963 c.z = c3.x;
964 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -0400965 }
966 }
967 }
968
Alexis Hetu96517182015-04-15 10:30:23 -0400969 void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4s &c_, Float4 &u_, Float4 &v_, Float4 &w_, Float &lod, bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -0400970 {
971 int componentCount = textureComponentCount();
972
973 Pointer<Byte> mipmap;
974 Pointer<Byte> buffer[4];
975 Int face[4];
Alexis Hetu3b96fa82016-02-04 21:15:03 -0500976
John Bauman89401822014-05-06 15:04:28 -0400977 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
978
Nicolas Capens7bb62682016-02-08 11:30:56 -0500979 Short4 uuuu = address(u_, state.addressingModeU, mipmap);
980 Short4 vvvv = address(v_, state.addressingModeV, mipmap);
981 Short4 wwww = address(w_, state.addressingModeW, mipmap);
John Bauman89401822014-05-06 15:04:28 -0400982
Nicolas Capens5989fab2016-02-15 10:31:49 -0500983 if(state.textureFilter == FILTER_POINT)
John Bauman89401822014-05-06 15:04:28 -0400984 {
985 sampleTexel(c_, uuuu, vvvv, wwww, mipmap, buffer);
986 }
987 else
988 {
Alexis Hetu96517182015-04-15 10:30:23 -0400989 Vector4s c[2][2][2];
John Bauman89401822014-05-06 15:04:28 -0400990
991 Short4 u[2][2][2];
992 Short4 v[2][2][2];
993 Short4 s[2][2][2];
994
995 for(int i = 0; i < 2; i++)
996 {
997 for(int j = 0; j < 2; j++)
998 {
999 for(int k = 0; k < 2; k++)
1000 {
Nicolas Capens5989fab2016-02-15 10:31:49 -05001001 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
1002 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
1003 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 -04001004 }
1005 }
1006 }
1007
John Bauman89401822014-05-06 15:04:28 -04001008 // Fractions
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001009 UShort4 f[2][2][2];
1010 Short4 fs[2][2][2];
1011 UShort4 f0u;
1012 UShort4 f0v;
1013 UShort4 f0s;
John Bauman89401822014-05-06 15:04:28 -04001014
1015 if(!state.hasNPOTTexture)
1016 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001017 f0u = As<UShort4>(u[0][0][0]) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt));
1018 f0v = As<UShort4>(v[0][0][0]) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt));
1019 f0s = As<UShort4>(s[0][0][0]) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,wInt));
John Bauman89401822014-05-06 15:04:28 -04001020 }
1021 else
1022 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001023 f0u = As<UShort4>(u[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
1024 f0v = As<UShort4>(v[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
1025 f0s = As<UShort4>(s[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth));
John Bauman89401822014-05-06 15:04:28 -04001026 }
1027
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001028 UShort4 f1u = ~f0u;
1029 UShort4 f1v = ~f0v;
1030 UShort4 f1s = ~f0s;
John Bauman89401822014-05-06 15:04:28 -04001031
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001032 f[1][1][1] = MulHigh(f1u, f1v);
1033 f[0][1][1] = MulHigh(f0u, f1v);
1034 f[1][0][1] = MulHigh(f1u, f0v);
1035 f[0][0][1] = MulHigh(f0u, f0v);
1036 f[1][1][0] = MulHigh(f1u, f1v);
1037 f[0][1][0] = MulHigh(f0u, f1v);
1038 f[1][0][0] = MulHigh(f1u, f0v);
1039 f[0][0][0] = MulHigh(f0u, f0v);
John Bauman89401822014-05-06 15:04:28 -04001040
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001041 f[1][1][1] = MulHigh(f[1][1][1], f1s);
1042 f[0][1][1] = MulHigh(f[0][1][1], f1s);
1043 f[1][0][1] = MulHigh(f[1][0][1], f1s);
1044 f[0][0][1] = MulHigh(f[0][0][1], f1s);
1045 f[1][1][0] = MulHigh(f[1][1][0], f0s);
1046 f[0][1][0] = MulHigh(f[0][1][0], f0s);
1047 f[1][0][0] = MulHigh(f[1][0][0], f0s);
1048 f[0][0][0] = MulHigh(f[0][0][0], f0s);
John Bauman89401822014-05-06 15:04:28 -04001049
1050 // Signed fractions
1051 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
1052 {
Nicolas Capensdf08bd02015-03-29 11:19:59 -04001053 fs[0][0][0] = f[0][0][0] >> 1;
1054 fs[0][0][1] = f[0][0][1] >> 1;
1055 fs[0][1][0] = f[0][1][0] >> 1;
1056 fs[0][1][1] = f[0][1][1] >> 1;
1057 fs[1][0][0] = f[1][0][0] >> 1;
1058 fs[1][0][1] = f[1][0][1] >> 1;
1059 fs[1][1][0] = f[1][1][0] >> 1;
1060 fs[1][1][1] = f[1][1][1] >> 1;
John Bauman89401822014-05-06 15:04:28 -04001061 }
1062
1063 for(int i = 0; i < 2; i++)
1064 {
1065 for(int j = 0; j < 2; j++)
1066 {
1067 for(int k = 0; k < 2; k++)
1068 {
1069 sampleTexel(c[i][j][k], u[i][j][k], v[i][j][k], s[i][j][k], mipmap, buffer);
1070
Alexis Hetu0085c442015-06-12 15:19:20 -04001071 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]); }
1072 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]); }
1073 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]); }
1074 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 -04001075
1076 if(i != 0 || j != 0 || k != 0)
1077 {
John Bauman19bac1e2014-05-06 15:23:49 -04001078 if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x;
1079 if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y;
1080 if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z;
1081 if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w;
John Bauman89401822014-05-06 15:04:28 -04001082 }
1083 }
1084 }
1085 }
1086
John Bauman19bac1e2014-05-06 15:23:49 -04001087 if(componentCount >= 1) c_.x = c[0][0][0].x;
1088 if(componentCount >= 2) c_.y = c[0][0][0].y;
1089 if(componentCount >= 3) c_.z = c[0][0][0].z;
1090 if(componentCount >= 4) c_.w = c[0][0][0].w;
John Bauman89401822014-05-06 15:04:28 -04001091
1092 // Correct for signed fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001093 if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x);
1094 if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y);
1095 if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z);
1096 if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w);
John Bauman89401822014-05-06 15:04:28 -04001097 }
1098 }
1099
Nicolas Capensc2534f42016-04-04 11:13:24 -04001100 void SamplerCore::sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -04001101 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001102 sampleFloatAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, method);
John Bauman89401822014-05-06 15:04:28 -04001103
1104 if(state.mipmapFilter > MIPMAP_POINT)
1105 {
John Bauman19bac1e2014-05-06 15:23:49 -04001106 Vector4f cc;
John Bauman89401822014-05-06 15:04:28 -04001107
Nicolas Capensc2534f42016-04-04 11:13:24 -04001108 sampleFloatAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, method);
John Bauman89401822014-05-06 15:04:28 -04001109
John Bauman19bac1e2014-05-06 15:23:49 -04001110 Float4 lod4 = Float4(Frac(lod));
John Bauman89401822014-05-06 15:04:28 -04001111
John Bauman19bac1e2014-05-06 15:23:49 -04001112 c.x = (cc.x - c.x) * lod4 + c.x;
1113 c.y = (cc.y - c.y) * lod4 + c.y;
1114 c.z = (cc.z - c.z) * lod4 + c.z;
1115 c.w = (cc.w - c.w) * lod4 + c.w;
John Bauman89401822014-05-06 15:04:28 -04001116 }
1117
1118 Int4 borderMask;
1119
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001120 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001121 {
1122 Int4 u0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001123
John Bauman89401822014-05-06 15:04:28 -04001124 border(u0, u);
1125
1126 borderMask = u0;
1127 }
1128
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001129 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001130 {
1131 Int4 v0;
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001132
John Bauman89401822014-05-06 15:04:28 -04001133 border(v0, v);
1134
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001135 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001136 {
1137 borderMask &= v0;
1138 }
1139 else
1140 {
1141 borderMask = v0;
1142 }
1143 }
1144
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001145 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -04001146 {
1147 Int4 s0;
1148
1149 border(s0, w);
1150
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001151 if(state.addressingModeU == ADDRESSING_BORDER ||
1152 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -04001153 {
1154 borderMask &= s0;
1155 }
1156 else
1157 {
1158 borderMask = s0;
1159 }
1160 }
1161
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001162 if(state.addressingModeU == ADDRESSING_BORDER ||
1163 state.addressingModeV == ADDRESSING_BORDER ||
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001164 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
John Bauman89401822014-05-06 15:04:28 -04001165 {
1166 Int4 b;
1167
John Bauman19bac1e2014-05-06 15:23:49 -04001168 c.x = As<Float4>(borderMask & As<Int4>(c.x) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0])));
1169 c.y = As<Float4>(borderMask & As<Int4>(c.y) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1])));
1170 c.z = As<Float4>(borderMask & As<Int4>(c.z) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2])));
1171 c.w = As<Float4>(borderMask & As<Int4>(c.w) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3])));
John Bauman89401822014-05-06 15:04:28 -04001172 }
1173 }
1174
Nicolas Capensc2534f42016-04-04 11:13:24 -04001175 void SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -04001176 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001177 if(state.textureFilter != FILTER_ANISOTROPIC || method == Lod)
John Bauman89401822014-05-06 15:04:28 -04001178 {
1179 sampleFloat(texture, c, u, v, w, lod, face, secondLOD);
1180 }
1181 else
1182 {
1183 Int a = RoundInt(anisotropy);
1184
John Bauman19bac1e2014-05-06 15:23:49 -04001185 Vector4f cSum;
John Bauman89401822014-05-06 15:04:28 -04001186
John Bauman19bac1e2014-05-06 15:23:49 -04001187 cSum.x = Float4(0.0f);
1188 cSum.y = Float4(0.0f);
1189 cSum.z = Float4(0.0f);
1190 cSum.w = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -04001191
1192 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
1193 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
1194
1195 Float4 du = uDelta;
1196 Float4 dv = vDelta;
1197
1198 Float4 u0 = u + B * du;
1199 Float4 v0 = v + B * dv;
1200
1201 du *= A;
1202 dv *= A;
1203
1204 Int i = 0;
1205
1206 Do
1207 {
1208 sampleFloat(texture, c, u0, v0, w, lod, face, secondLOD);
1209
1210 u0 += du;
1211 v0 += dv;
1212
John Bauman19bac1e2014-05-06 15:23:49 -04001213 cSum.x += c.x * A;
1214 cSum.y += c.y * A;
1215 cSum.z += c.z * A;
1216 cSum.w += c.w * A;
John Bauman89401822014-05-06 15:04:28 -04001217
1218 i++;
1219 }
1220 Until(i >= a)
1221
John Bauman19bac1e2014-05-06 15:23:49 -04001222 c.x = cSum.x;
1223 c.y = cSum.y;
1224 c.z = cSum.z;
1225 c.w = cSum.w;
John Bauman89401822014-05-06 15:04:28 -04001226 }
1227 }
1228
John Bauman19bac1e2014-05-06 15:23:49 -04001229 void SamplerCore::sampleFloat(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -04001230 {
Alexis Hetuc8b97852016-02-04 21:15:03 -05001231 if(state.textureType != TEXTURE_3D)
John Bauman89401822014-05-06 15:04:28 -04001232 {
1233 sampleFloat2D(texture, c, u, v, w, lod, face, secondLOD);
1234 }
1235 else
1236 {
1237 sampleFloat3D(texture, c, u, v, w, lod, secondLOD);
1238 }
1239 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001240
Alexis Hetuc8b97852016-02-04 21:15:03 -05001241 void SamplerCore::sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -04001242 {
1243 int componentCount = textureComponentCount();
1244 bool gather = state.textureFilter == FILTER_GATHER;
1245
1246 Pointer<Byte> mipmap;
1247 Pointer<Byte> buffer[4];
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001248
John Bauman89401822014-05-06 15:04:28 -04001249 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1250
Nicolas Capens7bb62682016-02-08 11:30:56 -05001251 Short4 uuuu = address(u, state.addressingModeU, mipmap);
1252 Short4 vvvv = address(v, state.addressingModeV, mipmap);
1253 Short4 wwww = address(w, state.addressingModeW, mipmap);
John Bauman89401822014-05-06 15:04:28 -04001254
Nicolas Capens5989fab2016-02-15 10:31:49 -05001255 if(state.textureFilter == FILTER_POINT)
John Bauman89401822014-05-06 15:04:28 -04001256 {
Alexis Hetuc8b97852016-02-04 21:15:03 -05001257 sampleTexel(c, uuuu, vvvv, wwww, w, mipmap, buffer);
John Bauman89401822014-05-06 15:04:28 -04001258 }
1259 else
1260 {
John Bauman19bac1e2014-05-06 15:23:49 -04001261 Vector4f c0;
1262 Vector4f c1;
1263 Vector4f c2;
1264 Vector4f c3;
John Bauman89401822014-05-06 15:04:28 -04001265
Nicolas Capens5989fab2016-02-15 10:31:49 -05001266 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
1267 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
1268 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
1269 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
John Bauman89401822014-05-06 15:04:28 -04001270
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001271 sampleTexel(c0, uuuu0, vvvv0, wwww, w, mipmap, buffer);
Alexis Hetuc8b97852016-02-04 21:15:03 -05001272 sampleTexel(c1, uuuu1, vvvv0, wwww, w, mipmap, buffer);
1273 sampleTexel(c2, uuuu0, vvvv1, wwww, w, mipmap, buffer);
1274 sampleTexel(c3, uuuu1, vvvv1, wwww, w, mipmap, buffer);
John Bauman89401822014-05-06 15:04:28 -04001275
1276 if(!gather) // Blend
1277 {
1278 // Fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001279 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth)));
1280 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight)));
John Bauman89401822014-05-06 15:04:28 -04001281
John Bauman19bac1e2014-05-06 15:23:49 -04001282 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1283 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1284 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1285 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001286
John Bauman19bac1e2014-05-06 15:23:49 -04001287 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1288 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1289 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1290 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001291
John Bauman19bac1e2014-05-06 15:23:49 -04001292 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x);
1293 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y);
1294 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z);
1295 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001296 }
1297 else
1298 {
John Bauman19bac1e2014-05-06 15:23:49 -04001299 c.x = c1.x;
1300 c.y = c2.x;
1301 c.z = c3.x;
1302 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -04001303 }
1304 }
1305 }
1306
John Bauman19bac1e2014-05-06 15:23:49 -04001307 void SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -04001308 {
1309 int componentCount = textureComponentCount();
1310
1311 Pointer<Byte> mipmap;
1312 Pointer<Byte> buffer[4];
1313 Int face[4];
1314
1315 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1316
Nicolas Capens7bb62682016-02-08 11:30:56 -05001317 Short4 uuuu = address(u, state.addressingModeU, mipmap);
1318 Short4 vvvv = address(v, state.addressingModeV, mipmap);
1319 Short4 wwww = address(w, state.addressingModeW, mipmap);
John Bauman89401822014-05-06 15:04:28 -04001320
Nicolas Capens5989fab2016-02-15 10:31:49 -05001321 if(state.textureFilter == FILTER_POINT)
John Bauman89401822014-05-06 15:04:28 -04001322 {
1323 sampleTexel(c, uuuu, vvvv, wwww, w, mipmap, buffer);
1324 }
1325 else
1326 {
John Bauman19bac1e2014-05-06 15:23:49 -04001327 Vector4f &c0 = c;
1328 Vector4f c1;
1329 Vector4f c2;
1330 Vector4f c3;
1331 Vector4f c4;
1332 Vector4f c5;
1333 Vector4f c6;
1334 Vector4f c7;
John Bauman89401822014-05-06 15:04:28 -04001335
Nicolas Capens5989fab2016-02-15 10:31:49 -05001336 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, -1, lod);
1337 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, -1, lod);
1338 Short4 wwww0 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, -1, lod);
1339 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, +1, lod);
1340 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, +1, lod);
1341 Short4 wwww1 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, +1, lod);
John Bauman89401822014-05-06 15:04:28 -04001342
1343 sampleTexel(c0, uuuu0, vvvv0, wwww0, w, mipmap, buffer);
1344 sampleTexel(c1, uuuu1, vvvv0, wwww0, w, mipmap, buffer);
1345 sampleTexel(c2, uuuu0, vvvv1, wwww0, w, mipmap, buffer);
1346 sampleTexel(c3, uuuu1, vvvv1, wwww0, w, mipmap, buffer);
1347 sampleTexel(c4, uuuu0, vvvv0, wwww1, w, mipmap, buffer);
1348 sampleTexel(c5, uuuu1, vvvv0, wwww1, w, mipmap, buffer);
1349 sampleTexel(c6, uuuu0, vvvv1, wwww1, w, mipmap, buffer);
1350 sampleTexel(c7, uuuu1, vvvv1, wwww1, w, mipmap, buffer);
1351
1352 // Fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001353 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth)));
1354 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight)));
1355 Float4 fw = Frac(Float4(As<UShort4>(wwww0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fDepth)));
John Bauman89401822014-05-06 15:04:28 -04001356
1357 // Blend first slice
John Bauman19bac1e2014-05-06 15:23:49 -04001358 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1359 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1360 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1361 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001362
John Bauman19bac1e2014-05-06 15:23:49 -04001363 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1364 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1365 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1366 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001367
John Bauman19bac1e2014-05-06 15:23:49 -04001368 if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x);
1369 if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y);
1370 if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z);
1371 if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001372
1373 // Blend second slice
John Bauman19bac1e2014-05-06 15:23:49 -04001374 if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x);
1375 if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y);
1376 if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z);
1377 if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001378
John Bauman19bac1e2014-05-06 15:23:49 -04001379 if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x);
1380 if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y);
1381 if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z);
1382 if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w);
John Bauman89401822014-05-06 15:04:28 -04001383
John Bauman19bac1e2014-05-06 15:23:49 -04001384 if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x);
1385 if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y);
1386 if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z);
1387 if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001388
1389 // Blend slices
John Bauman19bac1e2014-05-06 15:23:49 -04001390 if(componentCount >= 1) c0.x = c0.x + fw * (c4.x - c0.x);
1391 if(componentCount >= 2) c0.y = c0.y + fw * (c4.y - c0.y);
1392 if(componentCount >= 3) c0.z = c0.z + fw * (c4.z - c0.z);
1393 if(componentCount >= 4) c0.w = c0.w + fw * (c4.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001394 }
1395 }
1396
Nicolas Capensc2534f42016-04-04 11:13:24 -04001397 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, SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -04001398 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001399 if(method != Lod)
John Bauman89401822014-05-06 15:04:28 -04001400 {
1401 Float4 duvdxy;
1402
Nicolas Capensc2534f42016-04-04 11:13:24 -04001403 if(method != Grad)
John Bauman89401822014-05-06 15:04:28 -04001404 {
1405 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1406 }
1407 else
1408 {
1409 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1410 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001411
John Bauman89401822014-05-06 15:04:28 -04001412 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1413 }
1414
1415 // Scale by texture dimensions and LOD
1416 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1417
1418 Float4 dUV2dxy = dUVdxy * dUVdxy;
1419 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1420
1421 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1422
1423 if(state.textureFilter == FILTER_ANISOTROPIC)
1424 {
1425 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1426
1427 Float4 dudx = duvdxy.xxxx;
1428 Float4 dudy = duvdxy.yyyy;
1429 Float4 dvdx = duvdxy.zzzz;
1430 Float4 dvdy = duvdxy.wwww;
1431
1432 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
1433 uDelta = As<Float4>(As<Int4>(dudx) & mask | As<Int4>(dudy) & ~mask);
1434 vDelta = As<Float4>(As<Int4>(dvdx) & mask | As<Int4>(dvdy) & ~mask);
1435
1436 anisotropy = lod * Rcp_pp(det);
1437 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1438
1439 lod *= Rcp_pp(anisotropy * anisotropy);
1440 }
1441
1442 // log2(sqrt(lod))
1443 lod = Float(As<Int>(lod));
1444 lod -= Float(0x3F800000);
1445 lod *= As<Float>(Int(0x33800000));
1446
Nicolas Capensc2534f42016-04-04 11:13:24 -04001447 if(method == Bias)
John Bauman89401822014-05-06 15:04:28 -04001448 {
1449 lod += lodBias;
1450 }
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001451 }
1452 else
1453 {
1454 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD));
1455 }
John Bauman89401822014-05-06 15:04:28 -04001456
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001457 lod = Max(lod, 0.0f);
1458 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1
1459 }
1460
1461 void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
1462 {
1463 if(method != Lod)
1464 {
1465 if(method != Grad)
John Bauman89401822014-05-06 15:04:28 -04001466 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001467 Float4 dudxy = u.ywyw - u;
1468 Float4 dvdxy = v.ywyw - v;
1469 Float4 dsdxy = s.ywyw - s;
1470
1471 // Scale by texture dimensions and LOD
1472 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1473 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1474 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1475
1476 dudxy *= dudxy;
1477 dvdxy *= dvdxy;
1478 dsdxy *= dsdxy;
1479
1480 dudxy += dvdxy;
1481 dudxy += dsdxy;
1482
1483 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1484 }
1485 else
1486 {
1487 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1488 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1489
1490 Float4 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1491
1492 // Scale by texture dimensions and LOD
1493 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1494
1495 Float4 dUV2dxy = dUVdxy * dUVdxy;
1496 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1497
1498 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1499 }
1500
1501 // log2(sqrt(lod))
1502 lod = Float(As<Int>(lod));
1503 lod -= Float(0x3F800000);
1504 lod *= As<Float>(Int(0x33800000));
1505
1506 if(method == Bias)
1507 {
1508 lod += lodBias;
John Bauman89401822014-05-06 15:04:28 -04001509 }
1510 }
1511 else
1512 {
1513 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD));
1514 }
1515
John Bauman66b8ab22014-05-06 15:57:45 -04001516 lod = Max(lod, 0.0f);
John Bauman89401822014-05-06 15:04:28 -04001517 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1
1518 }
1519
Nicolas Capensc2534f42016-04-04 11:13:24 -04001520 void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
John Bauman89401822014-05-06 15:04:28 -04001521 {
1522 if(state.mipmapFilter == MIPMAP_NONE)
1523 {
1524 }
1525 else // Point and linear filter
1526 {
Nicolas Capensc2534f42016-04-04 11:13:24 -04001527 if(method != Lod)
John Bauman89401822014-05-06 15:04:28 -04001528 {
1529 Float4 dudxy;
1530 Float4 dvdxy;
1531 Float4 dsdxy;
1532
Nicolas Capensc2534f42016-04-04 11:13:24 -04001533 if(method != Grad)
John Bauman89401822014-05-06 15:04:28 -04001534 {
1535 dudxy = uuuu.ywyw - uuuu;
1536 dvdxy = vvvv.ywyw - vvvv;
1537 dsdxy = wwww.ywyw - wwww;
1538 }
1539 else
1540 {
1541 dudxy = dsx.x;
1542 dvdxy = dsx.y;
1543 dsdxy = dsx.z;
1544
1545 dudxy = Float4(dudxy.xx, dsy.x.xx);
1546 dvdxy = Float4(dvdxy.xx, dsy.y.xx);
1547 dsdxy = Float4(dsdxy.xx, dsy.z.xx);
1548
1549 dudxy = Float4(dudxy.xz, dudxy.xz);
1550 dvdxy = Float4(dvdxy.xz, dvdxy.xz);
1551 dsdxy = Float4(dsdxy.xz, dsdxy.xz);
1552 }
1553
1554 // Scale by texture dimensions and LOD
1555 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1556 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
1557 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
1558
1559 dudxy *= dudxy;
1560 dvdxy *= dvdxy;
1561 dsdxy *= dsdxy;
1562
1563 dudxy += dvdxy;
1564 dudxy += dsdxy;
1565
1566 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1567
1568 // log2(sqrt(lod))
1569 lod = Float(As<Int>(lod));
1570 lod -= Float(0x3F800000);
1571 lod *= As<Float>(Int(0x33800000));
1572
Nicolas Capensc2534f42016-04-04 11:13:24 -04001573 if(method == Bias)
John Bauman89401822014-05-06 15:04:28 -04001574 {
1575 lod += lodBias;
1576 }
1577 }
1578 else
1579 {
1580 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD));
1581 }
1582
1583 lod = Max(lod, Float(0.0f)); // FIXME
1584 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1
1585 }
1586 }
1587
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001588 void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z)
John Bauman89401822014-05-06 15:04:28 -04001589 {
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001590 Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0
1591 Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0
1592 Int4 zn = CmpLT(z, Float4(0.0f)); // z < 0
John Bauman89401822014-05-06 15:04:28 -04001593
1594 Float4 absX = Abs(x);
1595 Float4 absY = Abs(y);
1596 Float4 absZ = Abs(z);
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001597
John Bauman89401822014-05-06 15:04:28 -04001598 Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y)
1599 Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z)
1600 Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x)
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001601 Int4 xMajor = xy & ~zx; // abs(x) > abs(y) && abs(x) > abs(z)
1602 Int4 yMajor = yz & ~xy; // abs(y) > abs(z) && abs(y) > abs(x)
1603 Int4 zMajor = zx & ~yz; // abs(z) > abs(x) && abs(z) > abs(y)
John Bauman89401822014-05-06 15:04:28 -04001604
1605 // FACE_POSITIVE_X = 000b
1606 // FACE_NEGATIVE_X = 001b
1607 // FACE_POSITIVE_Y = 010b
1608 // FACE_NEGATIVE_Y = 011b
1609 // FACE_POSITIVE_Z = 100b
1610 // FACE_NEGATIVE_Z = 101b
1611
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001612 Int yAxis = SignMask(yMajor);
1613 Int zAxis = SignMask(zMajor);
John Bauman89401822014-05-06 15:04:28 -04001614
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001615 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000);
John Bauman89401822014-05-06 15:04:28 -04001616 Int negative = SignMask(n);
1617
1618 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
1619 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4);
1620 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4);
1621 face[1] = (face[0] >> 4) & 0x7;
1622 face[2] = (face[0] >> 8) & 0x7;
1623 face[3] = (face[0] >> 12) & 0x7;
1624 face[0] &= 0x7;
1625
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001626 Float4 M = Max(Max(absX, absY), absZ);
John Bauman89401822014-05-06 15:04:28 -04001627
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001628 // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x)
1629 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x))));
John Bauman89401822014-05-06 15:04:28 -04001630
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001631 // V = !yMajor ? -y : (n ^ z)
1632 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z))));
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001633
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001634 M = reciprocal(M) * Float4(0.5f);
1635 U = U * M + Float4(0.5f);
1636 V = V * M + Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -04001637
Nicolas Capens2cfadc62016-04-19 09:09:29 -04001638 lodX = x * M;
1639 lodY = y * M;
1640 lodZ = z * M;
John Bauman89401822014-05-06 15:04:28 -04001641 }
1642
1643 void SamplerCore::computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap)
1644 {
1645 Short4 uuu2;
1646
1647 if(!state.hasNPOTTexture && !hasFloatTexture())
1648 {
1649 vvvv = As<UShort4>(vvvv) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,vFrac));
1650 uuu2 = uuuu;
1651 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1652 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1653 uuuu = As<Short4>(As<UInt2>(uuuu) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,uFrac)));
1654 uuu2 = As<Short4>(As<UInt2>(uuu2) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,uFrac)));
John Bauman89401822014-05-06 15:04:28 -04001655 }
1656 else
1657 {
1658 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width)));
1659 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height)));
1660 uuu2 = uuuu;
1661 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1662 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1663 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1664 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
Alexis Hetuf15e8942015-12-01 15:13:23 -05001665 }
John Bauman89401822014-05-06 15:04:28 -04001666
Alexis Hetuf15e8942015-12-01 15:13:23 -05001667 if((state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY))
1668 {
1669 if(state.textureType != TEXTURE_2D_ARRAY)
John Bauman89401822014-05-06 15:04:28 -04001670 {
Alexis Hetuf15e8942015-12-01 15:13:23 -05001671 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth)));
John Bauman89401822014-05-06 15:04:28 -04001672 }
Alexis Hetuf15e8942015-12-01 15:13:23 -05001673 Short4 www2 = wwww;
1674 wwww = As<Short4>(UnpackLow(wwww, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
1675 www2 = As<Short4>(UnpackHigh(www2, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
1676 wwww = As<Short4>(MulAdd(wwww, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP))));
1677 www2 = As<Short4>(MulAdd(www2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP))));
1678 uuuu = As<Short4>(As<Int2>(uuuu) + As<Int2>(wwww));
1679 uuu2 = As<Short4>(As<Int2>(uuu2) + As<Int2>(www2));
John Bauman89401822014-05-06 15:04:28 -04001680 }
1681
1682 index[0] = Extract(As<Int2>(uuuu), 0);
1683 index[1] = Extract(As<Int2>(uuuu), 1);
1684 index[2] = Extract(As<Int2>(uuu2), 0);
1685 index[3] = Extract(As<Int2>(uuu2), 1);
1686 }
1687
Alexis Hetu96517182015-04-15 10:30:23 -04001688 void SamplerCore::sampleTexel(Vector4s &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4])
John Bauman89401822014-05-06 15:04:28 -04001689 {
1690 Int index[4];
1691
1692 computeIndices(index, uuuu, vvvv, wwww, mipmap);
1693
1694 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1695 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1696 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1697 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1698
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001699 if(has16bitTextureFormat())
John Bauman89401822014-05-06 15:04:28 -04001700 {
Nicolas Capens27496312015-05-12 15:16:06 -04001701 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0);
1702 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1);
1703 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2);
1704 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3);
1705
1706 switch(state.textureFormat)
1707 {
1708 case FORMAT_R5G6B5:
1709 c.z = (c.x & Short4(0x001Fu)) << 11;
1710 c.y = (c.x & Short4(0x07E0u)) << 5;
1711 c.x = (c.x & Short4(0xF800u));
1712 break;
1713 default:
1714 ASSERT(false);
1715 }
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001716 }
Nicolas Capens21bda852015-09-01 10:23:33 -04001717 else if(has8bitTextureComponents())
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001718 {
John Bauman89401822014-05-06 15:04:28 -04001719 switch(textureComponentCount())
1720 {
1721 case 4:
1722 {
1723 Byte8 c0 = *Pointer<Byte8>(buffer[f0] + 4 * index[0]);
1724 Byte8 c1 = *Pointer<Byte8>(buffer[f1] + 4 * index[1]);
1725 Byte8 c2 = *Pointer<Byte8>(buffer[f2] + 4 * index[2]);
1726 Byte8 c3 = *Pointer<Byte8>(buffer[f3] + 4 * index[3]);
John Bauman19bac1e2014-05-06 15:23:49 -04001727 c.x = UnpackLow(c0, c1);
1728 c.y = UnpackLow(c2, c3);
Alexis Hetu3b96fa82016-02-04 21:15:03 -05001729
John Bauman89401822014-05-06 15:04:28 -04001730 switch(state.textureFormat)
1731 {
1732 case FORMAT_A8R8G8B8:
John Bauman19bac1e2014-05-06 15:23:49 -04001733 c.z = c.x;
1734 c.z = As<Short4>(UnpackLow(c.z, c.y));
1735 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1736 c.y = c.z;
1737 c.w = c.x;
1738 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1739 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1740 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1741 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
John Bauman89401822014-05-06 15:04:28 -04001742 break;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001743 case FORMAT_A8B8G8R8:
Alexis Hetu3412d872015-10-26 16:40:26 -04001744 case FORMAT_A8B8G8R8I:
1745 case FORMAT_A8B8G8R8UI:
1746 case FORMAT_A8B8G8R8I_SNORM:
John Bauman89401822014-05-06 15:04:28 -04001747 case FORMAT_Q8W8V8U8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001748 case FORMAT_SRGB8_A8:
John Bauman19bac1e2014-05-06 15:23:49 -04001749 c.z = c.x;
1750 c.x = As<Short4>(UnpackLow(c.x, c.y));
1751 c.z = As<Short4>(UnpackHigh(c.z, c.y));
1752 c.y = c.x;
1753 c.w = c.z;
1754 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1755 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1756 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1757 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
John Bauman89401822014-05-06 15:04:28 -04001758 break;
1759 default:
1760 ASSERT(false);
1761 }
1762 }
1763 break;
1764 case 3:
1765 {
1766 Byte8 c0 = *Pointer<Byte8>(buffer[f0] + 4 * index[0]);
1767 Byte8 c1 = *Pointer<Byte8>(buffer[f1] + 4 * index[1]);
1768 Byte8 c2 = *Pointer<Byte8>(buffer[f2] + 4 * index[2]);
1769 Byte8 c3 = *Pointer<Byte8>(buffer[f3] + 4 * index[3]);
John Bauman19bac1e2014-05-06 15:23:49 -04001770 c.x = UnpackLow(c0, c1);
1771 c.y = UnpackLow(c2, c3);
John Bauman89401822014-05-06 15:04:28 -04001772
1773 switch(state.textureFormat)
1774 {
1775 case FORMAT_X8R8G8B8:
John Bauman19bac1e2014-05-06 15:23:49 -04001776 c.z = c.x;
1777 c.z = As<Short4>(UnpackLow(c.z, c.y));
1778 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1779 c.y = c.z;
1780 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1781 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1782 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
John Bauman89401822014-05-06 15:04:28 -04001783 break;
Alexis Hetu3412d872015-10-26 16:40:26 -04001784 case FORMAT_X8B8G8R8I_SNORM:
1785 case FORMAT_X8B8G8R8UI:
1786 case FORMAT_X8B8G8R8I:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001787 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04001788 case FORMAT_X8L8V8U8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001789 case FORMAT_SRGB8_X8:
John Bauman19bac1e2014-05-06 15:23:49 -04001790 c.z = c.x;
1791 c.x = As<Short4>(UnpackLow(c.x, c.y));
1792 c.z = As<Short4>(UnpackHigh(c.z, c.y));
1793 c.y = c.x;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04001794 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1795 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
John Bauman19bac1e2014-05-06 15:23:49 -04001796 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
John Bauman89401822014-05-06 15:04:28 -04001797 break;
1798 default:
1799 ASSERT(false);
1800 }
1801 }
1802 break;
1803 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -04001804 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0);
1805 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1);
1806 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2);
1807 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3);
John Bauman89401822014-05-06 15:04:28 -04001808
1809 switch(state.textureFormat)
1810 {
1811 case FORMAT_G8R8:
Alexis Hetu3412d872015-10-26 16:40:26 -04001812 case FORMAT_G8R8I:
1813 case FORMAT_G8R8UI:
1814 case FORMAT_G8R8I_SNORM:
John Bauman89401822014-05-06 15:04:28 -04001815 case FORMAT_V8U8:
1816 case FORMAT_A8L8:
Nicolas Capens27496312015-05-12 15:16:06 -04001817 c.y = (c.x & Short4(0xFF00u, 0xFF00u, 0xFF00u, 0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
1818 c.x = (c.x & Short4(0x00FFu, 0x00FFu, 0x00FFu, 0x00FFu)) | (c.x << 8);
John Bauman89401822014-05-06 15:04:28 -04001819 break;
1820 default:
1821 ASSERT(false);
1822 }
1823 break;
1824 case 1:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04001825 {
1826 Int c0 = Int(*Pointer<Byte>(buffer[f0] + index[0]));
1827 Int c1 = Int(*Pointer<Byte>(buffer[f1] + index[1]));
1828 Int c2 = Int(*Pointer<Byte>(buffer[f2] + index[2]));
1829 Int c3 = Int(*Pointer<Byte>(buffer[f3] + index[3]));
1830 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1831 c.x = Unpack(As<Byte4>(c0));
1832 }
John Bauman89401822014-05-06 15:04:28 -04001833 break;
1834 default:
1835 ASSERT(false);
1836 }
1837 }
Nicolas Capens21bda852015-09-01 10:23:33 -04001838 else if(has16bitTextureComponents())
John Bauman89401822014-05-06 15:04:28 -04001839 {
1840 switch(textureComponentCount())
1841 {
1842 case 4:
John Bauman19bac1e2014-05-06 15:23:49 -04001843 c.x = *Pointer<Short4>(buffer[f0] + 8 * index[0]);
1844 c.y = *Pointer<Short4>(buffer[f1] + 8 * index[1]);
1845 c.z = *Pointer<Short4>(buffer[f2] + 8 * index[2]);
1846 c.w = *Pointer<Short4>(buffer[f3] + 8 * index[3]);
1847 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman89401822014-05-06 15:04:28 -04001848 break;
1849 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -04001850 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]);
1851 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1])));
1852 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]);
1853 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3])));
1854 c.y = c.x;
1855 c.x = As<Short4>(UnpackLow(As<Int2>(c.x), As<Int2>(c.z)));
1856 c.y = As<Short4>(UnpackHigh(As<Int2>(c.y), As<Int2>(c.z)));
John Bauman89401822014-05-06 15:04:28 -04001857 break;
1858 case 1:
John Bauman19bac1e2014-05-06 15:23:49 -04001859 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0);
1860 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1);
1861 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2);
1862 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3);
John Bauman89401822014-05-06 15:04:28 -04001863 break;
1864 default:
1865 ASSERT(false);
1866 }
1867 }
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04001868 else if(hasYuvFormat())
1869 {
1870 // Generic YPbPr to RGB transformation
1871 // R = Y + 2 * (1 - Kr) * Pr
1872 // G = Y - 2 * Kb * (1 - Kb) / Kg * Pb - 2 * Kr * (1 - Kr) / Kg * Pr
1873 // B = Y + 2 * (1 - Kb) * Pb
1874
1875 float Kb = 0.114f;
1876 float Kr = 0.299f;
1877 int studioSwing = 1;
1878
1879 switch(state.textureFormat)
1880 {
1881 case FORMAT_YV12_BT601:
1882 Kb = 0.114f;
1883 Kr = 0.299f;
1884 studioSwing = 1;
1885 break;
1886 case FORMAT_YV12_BT709:
1887 Kb = 0.0722f;
1888 Kr = 0.2126f;
1889 studioSwing = 1;
1890 break;
1891 case FORMAT_YV12_JFIF:
1892 Kb = 0.114f;
1893 Kr = 0.299f;
1894 studioSwing = 0;
1895 break;
1896 default:
1897 ASSERT(false);
1898 }
1899
1900 const float Kg = 1.0f - Kr - Kb;
1901
1902 const float Rr = 2 * (1 - Kr);
1903 const float Gb = -2 * Kb * (1 - Kb) / Kg;
1904 const float Gr = -2 * Kr * (1 - Kr) / Kg;
1905 const float Bb = 2 * (1 - Kb);
1906
1907 // Scaling and bias for studio-swing range: Y = [16 .. 235], U/V = [16 .. 240]
1908 const float Yy = studioSwing ? 255.0f / (235 - 16) : 1.0f;
1909 const float Uu = studioSwing ? 255.0f / (240 - 16) : 1.0f;
1910 const float Vv = studioSwing ? 255.0f / (240 - 16) : 1.0f;
1911
1912 const float Rv = Vv * Rr;
1913 const float Gu = Uu * Gb;
1914 const float Gv = Vv * Gr;
1915 const float Bu = Uu * Bb;
1916
1917 const float R0 = (studioSwing * -16 * Yy - 128 * Rv) / 255;
1918 const float G0 = (studioSwing * -16 * Yy - 128 * Gu - 128 * Gv) / 255;
1919 const float B0 = (studioSwing * -16 * Yy - 128 * Bu) / 255;
1920
1921 Int c0 = Int(*Pointer<Byte>(buffer[0] + index[0]));
1922 Int c1 = Int(*Pointer<Byte>(buffer[0] + index[1]));
1923 Int c2 = Int(*Pointer<Byte>(buffer[0] + index[2]));
1924 Int c3 = Int(*Pointer<Byte>(buffer[0] + index[3]));
1925 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1926 UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0)));
1927
1928 computeIndices(index, uuuu, vvvv, wwww, mipmap + sizeof(Mipmap));
1929 c0 = Int(*Pointer<Byte>(buffer[1] + index[0]));
1930 c1 = Int(*Pointer<Byte>(buffer[1] + index[1]));
1931 c2 = Int(*Pointer<Byte>(buffer[1] + index[2]));
1932 c3 = Int(*Pointer<Byte>(buffer[1] + index[3]));
1933 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1934 UShort4 V = As<UShort4>(Unpack(As<Byte4>(c0)));
1935
1936 c0 = Int(*Pointer<Byte>(buffer[2] + index[0]));
1937 c1 = Int(*Pointer<Byte>(buffer[2] + index[1]));
1938 c2 = Int(*Pointer<Byte>(buffer[2] + index[2]));
1939 c3 = Int(*Pointer<Byte>(buffer[2] + index[3]));
1940 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1941 UShort4 U = As<UShort4>(Unpack(As<Byte4>(c0)));
1942
1943 const UShort4 yY = UShort4(iround(Yy * 0x4000));
1944 const UShort4 rV = UShort4(iround(Rv * 0x4000));
1945 const UShort4 gU = UShort4(iround(-Gu * 0x4000));
1946 const UShort4 gV = UShort4(iround(-Gv * 0x4000));
1947 const UShort4 bU = UShort4(iround(Bu * 0x4000));
1948
1949 const UShort4 r0 = UShort4(iround(-R0 * 0x4000));
1950 const UShort4 g0 = UShort4(iround(G0 * 0x4000));
1951 const UShort4 b0 = UShort4(iround(-B0 * 0x4000));
1952
1953 UShort4 y = MulHigh(Y, yY);
1954 UShort4 r = SubSat(y + MulHigh(V, rV), r0);
1955 UShort4 g = SubSat(y + g0, MulHigh(U, gU) + MulHigh(V, gV));
1956 UShort4 b = SubSat(y + MulHigh(U, bU), b0);
1957
1958 c.x = Min(r, UShort4(0x3FFF)) << 2;
1959 c.y = Min(g, UShort4(0x3FFF)) << 2;
1960 c.z = Min(b, UShort4(0x3FFF)) << 2;
1961 }
1962 else ASSERT(false);
John Bauman89401822014-05-06 15:04:28 -04001963 }
1964
John Bauman19bac1e2014-05-06 15:23:49 -04001965 void SamplerCore::sampleTexel(Vector4f &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4])
John Bauman89401822014-05-06 15:04:28 -04001966 {
1967 Int index[4];
1968
1969 computeIndices(index, uuuu, vvvv, wwww, mipmap);
1970
1971 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1972 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1973 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1974 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1975
1976 // Read texels
1977 switch(textureComponentCount())
1978 {
1979 case 4:
John Bauman19bac1e2014-05-06 15:23:49 -04001980 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
1981 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
1982 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
1983 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
1984 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman89401822014-05-06 15:04:28 -04001985 break;
Alexis Hetu337f3d52016-04-18 16:27:28 -04001986 case 3:
1987 ASSERT(state.textureFormat == FORMAT_X32B32G32R32F);
1988 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
1989 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
1990 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
1991 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
1992 transpose4x3(c.x, c.y, c.z, c.w);
1993 c.w = Float4(1.0f);
1994 break;
John Bauman89401822014-05-06 15:04:28 -04001995 case 2:
1996 // FIXME: Optimal shuffling?
John Bauman19bac1e2014-05-06 15:23:49 -04001997 c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8);
1998 c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8);
1999 c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8);
2000 c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8);
2001 c.y = c.x;
2002 c.x = Float4(c.x.xz, c.z.xz);
2003 c.y = Float4(c.y.yw, c.z.yw);
John Bauman89401822014-05-06 15:04:28 -04002004 break;
2005 case 1:
2006 // FIXME: Optimal shuffling?
John Bauman19bac1e2014-05-06 15:23:49 -04002007 c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4);
2008 c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4);
2009 c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4);
2010 c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4);
John Bauman89401822014-05-06 15:04:28 -04002011
John Bauman66b8ab22014-05-06 15:57:45 -04002012 if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER)
John Bauman89401822014-05-06 15:04:28 -04002013 {
2014 Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f));
2015
John Bauman19bac1e2014-05-06 15:23:49 -04002016 c.x = As<Float4>(As<Int4>(CmpNLT(c.x, d)) & As<Int4>(Float4(1.0f))); // FIXME: Only less-equal?
John Bauman89401822014-05-06 15:04:28 -04002017 }
2018 break;
2019 default:
2020 ASSERT(false);
2021 }
2022 }
2023
2024 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
2025 {
2026 if(state.mipmapFilter < MIPMAP_POINT)
2027 {
2028 mipmap = texture + OFFSET(Texture,mipmap[0]);
2029 }
2030 else
2031 {
2032 Int ilod;
2033
2034 if(state.mipmapFilter == MIPMAP_POINT)
2035 {
2036 ilod = RoundInt(lod);
2037 }
2038 else // Linear
2039 {
2040 ilod = Int(lod);
2041 }
2042
2043 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
2044 }
2045
2046 if(state.textureType != TEXTURE_CUBE)
2047 {
John Bauman66b8ab22014-05-06 15:57:45 -04002048 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002049
2050 if(hasYuvFormat())
2051 {
2052 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1]));
2053 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2]));
2054 }
John Bauman89401822014-05-06 15:04:28 -04002055 }
2056 else
2057 {
2058 for(int i = 0; i < 4; i++)
2059 {
John Bauman66b8ab22014-05-06 15:57:45 -04002060 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -04002061 }
2062 }
2063 }
2064
Nicolas Capens7bb62682016-02-08 11:30:56 -05002065 Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap)
John Bauman89401822014-05-06 15:04:28 -04002066 {
Nicolas Capens7bb62682016-02-08 11:30:56 -05002067 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY)
2068 {
2069 return Short4(); // Unused
2070 }
2071 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY)
2072 {
2073 return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1));
2074 }
2075 else if(addressingMode == ADDRESSING_CLAMP)
John Bauman89401822014-05-06 15:04:28 -04002076 {
2077 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
2078
Nicolas Capens7bb62682016-02-08 11:30:56 -05002079 return Short4(Int4(clamp * Float4(1 << 16)));
John Bauman89401822014-05-06 15:04:28 -04002080 }
2081 else if(addressingMode == ADDRESSING_MIRROR)
2082 {
2083 Int4 convert = Int4(uw * Float4(1 << 16));
2084 Int4 mirror = (convert << 15) >> 31;
2085
2086 convert ^= mirror;
2087
Nicolas Capens7bb62682016-02-08 11:30:56 -05002088 return Short4(convert);
John Bauman89401822014-05-06 15:04:28 -04002089 }
2090 else if(addressingMode == ADDRESSING_MIRRORONCE)
2091 {
2092 // Absolute value
2093 Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
2094
2095 // Clamp
2096 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
2097 convert = As<Int4>(Pack(convert, convert));
2098
Nicolas Capens7bb62682016-02-08 11:30:56 -05002099 return As<Short4>(Int2(convert)) + Short4((short)0x8000, (short)0x8000, (short)0x8000, (short)0x8000);
John Bauman89401822014-05-06 15:04:28 -04002100 }
2101 else // Wrap (or border)
2102 {
Nicolas Capens7bb62682016-02-08 11:30:56 -05002103 return Short4(Int4(uw * Float4(1 << 16)));
Alexis Hetuf15e8942015-12-01 15:13:23 -05002104 }
2105 }
2106
Alexis Hetu96517182015-04-15 10:30:23 -04002107 void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
John Bauman89401822014-05-06 15:04:28 -04002108 {
Alexis Hetu96517182015-04-15 10:30:23 -04002109 cs = RoundShort4(cf * Float4(0x1000));
John Bauman89401822014-05-06 15:04:28 -04002110 }
2111
Alexis Hetu96517182015-04-15 10:30:23 -04002112 void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
John Bauman89401822014-05-06 15:04:28 -04002113 {
Alexis Hetu96517182015-04-15 10:30:23 -04002114 convertFixed12(cs.x, cf.x);
2115 convertFixed12(cs.y, cf.y);
2116 convertFixed12(cs.z, cf.z);
2117 convertFixed12(cs.w, cf.w);
John Bauman89401822014-05-06 15:04:28 -04002118 }
2119
Alexis Hetu96517182015-04-15 10:30:23 -04002120 void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002121 {
Alexis Hetu96517182015-04-15 10:30:23 -04002122 cf = Float4(cs) * Float4(1.0f / 0x0FFE);
John Bauman89401822014-05-06 15:04:28 -04002123 }
2124
Alexis Hetu96517182015-04-15 10:30:23 -04002125// void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
John Bauman89401822014-05-06 15:04:28 -04002126// {
Alexis Hetu96517182015-04-15 10:30:23 -04002127// convertSigned12(cf.x, cs.x);
2128// convertSigned12(cf.y, cs.y);
2129// convertSigned12(cf.z, cs.z);
2130// convertSigned12(cf.w, cs.w);
John Bauman89401822014-05-06 15:04:28 -04002131// }
2132
Alexis Hetu96517182015-04-15 10:30:23 -04002133 void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002134 {
Alexis Hetu96517182015-04-15 10:30:23 -04002135 cf = Float4(cs) * Float4(1.0f / 0x7FFF);
John Bauman89401822014-05-06 15:04:28 -04002136 }
2137
Alexis Hetu96517182015-04-15 10:30:23 -04002138 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
John Bauman89401822014-05-06 15:04:28 -04002139 {
Alexis Hetu96517182015-04-15 10:30:23 -04002140 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
John Bauman89401822014-05-06 15:04:28 -04002141 }
2142
Nicolas Capense1a50af2015-05-13 16:48:18 -04002143 void SamplerCore::sRGBtoLinear16_8_12(Short4 &c)
John Bauman89401822014-05-06 15:04:28 -04002144 {
2145 c = As<UShort4>(c) >> 8;
2146
Nicolas Capense1a50af2015-05-13 16:48:18 -04002147 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_12));
2148
2149 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2150 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2151 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2152 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2153 }
2154
2155 void SamplerCore::sRGBtoLinear16_6_12(Short4 &c)
2156 {
2157 c = As<UShort4>(c) >> 10;
2158
2159 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_12));
2160
2161 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2162 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2163 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2164 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2165 }
2166
2167 void SamplerCore::sRGBtoLinear16_5_12(Short4 &c)
2168 {
2169 c = As<UShort4>(c) >> 11;
2170
2171 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_12));
John Bauman89401822014-05-06 15:04:28 -04002172
2173 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
2174 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
2175 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
2176 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
2177 }
2178
2179 bool SamplerCore::hasFloatTexture() const
2180 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002181 return Surface::isFloatFormat(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04002182 }
2183
2184 bool SamplerCore::hasUnsignedTextureComponent(int component) const
2185 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002186 return Surface::isUnsignedComponent(state.textureFormat, component);
John Bauman89401822014-05-06 15:04:28 -04002187 }
2188
2189 int SamplerCore::textureComponentCount() const
2190 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002191 return Surface::componentCount(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04002192 }
2193
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002194 bool SamplerCore::has16bitTextureFormat() const
John Bauman89401822014-05-06 15:04:28 -04002195 {
2196 switch(state.textureFormat)
2197 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002198 case FORMAT_R5G6B5:
2199 return true;
Alexis Hetu3412d872015-10-26 16:40:26 -04002200 case FORMAT_R8I_SNORM:
2201 case FORMAT_G8R8I_SNORM:
2202 case FORMAT_X8B8G8R8I_SNORM:
2203 case FORMAT_A8B8G8R8I_SNORM:
2204 case FORMAT_R8I:
2205 case FORMAT_R8UI:
2206 case FORMAT_G8R8I:
2207 case FORMAT_G8R8UI:
2208 case FORMAT_X8B8G8R8I:
2209 case FORMAT_X8B8G8R8UI:
2210 case FORMAT_A8B8G8R8I:
2211 case FORMAT_A8B8G8R8UI:
2212 case FORMAT_R32I:
2213 case FORMAT_R32UI:
2214 case FORMAT_G32R32I:
2215 case FORMAT_G32R32UI:
2216 case FORMAT_X32B32G32R32I:
2217 case FORMAT_X32B32G32R32UI:
2218 case FORMAT_A32B32G32R32I:
2219 case FORMAT_A32B32G32R32UI:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002220 case FORMAT_G8R8:
2221 case FORMAT_X8R8G8B8:
2222 case FORMAT_X8B8G8R8:
2223 case FORMAT_A8R8G8B8:
2224 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002225 case FORMAT_SRGB8_X8:
2226 case FORMAT_SRGB8_A8:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002227 case FORMAT_V8U8:
2228 case FORMAT_Q8W8V8U8:
2229 case FORMAT_X8L8V8U8:
2230 case FORMAT_R32F:
2231 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002232 case FORMAT_X32B32G32R32F:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002233 case FORMAT_A32B32G32R32F:
2234 case FORMAT_A8:
2235 case FORMAT_R8:
2236 case FORMAT_L8:
2237 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002238 case FORMAT_D32F:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002239 case FORMAT_D32F_LOCKABLE:
2240 case FORMAT_D32FS8_TEXTURE:
2241 case FORMAT_D32FS8_SHADOW:
2242 case FORMAT_L16:
2243 case FORMAT_G16R16:
2244 case FORMAT_A16B16G16R16:
2245 case FORMAT_V16U16:
2246 case FORMAT_A16W16V16U16:
2247 case FORMAT_Q16W16V16U16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002248 case FORMAT_R16I:
2249 case FORMAT_R16UI:
2250 case FORMAT_G16R16I:
2251 case FORMAT_G16R16UI:
2252 case FORMAT_X16B16G16R16I:
2253 case FORMAT_X16B16G16R16UI:
2254 case FORMAT_A16B16G16R16I:
2255 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002256 case FORMAT_YV12_BT601:
2257 case FORMAT_YV12_BT709:
2258 case FORMAT_YV12_JFIF:
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002259 return false;
2260 default:
2261 ASSERT(false);
2262 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002263
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002264 return false;
2265 }
2266
Nicolas Capens21bda852015-09-01 10:23:33 -04002267 bool SamplerCore::has8bitTextureComponents() const
2268 {
2269 switch(state.textureFormat)
2270 {
Nicolas Capens21bda852015-09-01 10:23:33 -04002271 case FORMAT_G8R8:
2272 case FORMAT_X8R8G8B8:
2273 case FORMAT_X8B8G8R8:
2274 case FORMAT_A8R8G8B8:
2275 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002276 case FORMAT_SRGB8_X8:
2277 case FORMAT_SRGB8_A8:
Nicolas Capens21bda852015-09-01 10:23:33 -04002278 case FORMAT_V8U8:
2279 case FORMAT_Q8W8V8U8:
2280 case FORMAT_X8L8V8U8:
2281 case FORMAT_A8:
2282 case FORMAT_R8:
2283 case FORMAT_L8:
2284 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002285 case FORMAT_R8I_SNORM:
2286 case FORMAT_G8R8I_SNORM:
2287 case FORMAT_X8B8G8R8I_SNORM:
2288 case FORMAT_A8B8G8R8I_SNORM:
2289 case FORMAT_R8I:
2290 case FORMAT_R8UI:
2291 case FORMAT_G8R8I:
2292 case FORMAT_G8R8UI:
2293 case FORMAT_X8B8G8R8I:
2294 case FORMAT_X8B8G8R8UI:
2295 case FORMAT_A8B8G8R8I:
2296 case FORMAT_A8B8G8R8UI:
Nicolas Capens21bda852015-09-01 10:23:33 -04002297 return true;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002298 case FORMAT_R5G6B5:
Nicolas Capens21bda852015-09-01 10:23:33 -04002299 case FORMAT_R32F:
2300 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002301 case FORMAT_X32B32G32R32F:
Nicolas Capens21bda852015-09-01 10:23:33 -04002302 case FORMAT_A32B32G32R32F:
Alexis Hetu3412d872015-10-26 16:40:26 -04002303 case FORMAT_D32F:
Nicolas Capens21bda852015-09-01 10:23:33 -04002304 case FORMAT_D32F_LOCKABLE:
2305 case FORMAT_D32FS8_TEXTURE:
2306 case FORMAT_D32FS8_SHADOW:
2307 case FORMAT_L16:
2308 case FORMAT_G16R16:
2309 case FORMAT_A16B16G16R16:
2310 case FORMAT_V16U16:
2311 case FORMAT_A16W16V16U16:
2312 case FORMAT_Q16W16V16U16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002313 case FORMAT_R32I:
2314 case FORMAT_R32UI:
2315 case FORMAT_G32R32I:
2316 case FORMAT_G32R32UI:
2317 case FORMAT_X32B32G32R32I:
2318 case FORMAT_X32B32G32R32UI:
2319 case FORMAT_A32B32G32R32I:
2320 case FORMAT_A32B32G32R32UI:
2321 case FORMAT_R16I:
2322 case FORMAT_R16UI:
2323 case FORMAT_G16R16I:
2324 case FORMAT_G16R16UI:
2325 case FORMAT_X16B16G16R16I:
2326 case FORMAT_X16B16G16R16UI:
2327 case FORMAT_A16B16G16R16I:
2328 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002329 case FORMAT_YV12_BT601:
2330 case FORMAT_YV12_BT709:
2331 case FORMAT_YV12_JFIF:
Nicolas Capens21bda852015-09-01 10:23:33 -04002332 return false;
2333 default:
2334 ASSERT(false);
2335 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002336
Nicolas Capens21bda852015-09-01 10:23:33 -04002337 return false;
2338 }
2339
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002340 bool SamplerCore::has16bitTextureComponents() const
2341 {
2342 switch(state.textureFormat)
2343 {
2344 case FORMAT_R5G6B5:
Alexis Hetu3412d872015-10-26 16:40:26 -04002345 case FORMAT_R8I_SNORM:
2346 case FORMAT_G8R8I_SNORM:
2347 case FORMAT_X8B8G8R8I_SNORM:
2348 case FORMAT_A8B8G8R8I_SNORM:
2349 case FORMAT_R8I:
2350 case FORMAT_R8UI:
2351 case FORMAT_G8R8I:
2352 case FORMAT_G8R8UI:
2353 case FORMAT_X8B8G8R8I:
2354 case FORMAT_X8B8G8R8UI:
2355 case FORMAT_A8B8G8R8I:
2356 case FORMAT_A8B8G8R8UI:
2357 case FORMAT_R32I:
2358 case FORMAT_R32UI:
2359 case FORMAT_G32R32I:
2360 case FORMAT_G32R32UI:
2361 case FORMAT_X32B32G32R32I:
2362 case FORMAT_X32B32G32R32UI:
2363 case FORMAT_A32B32G32R32I:
2364 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002365 case FORMAT_G8R8:
2366 case FORMAT_X8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002367 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04002368 case FORMAT_A8R8G8B8:
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002369 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002370 case FORMAT_SRGB8_X8:
2371 case FORMAT_SRGB8_A8:
John Bauman89401822014-05-06 15:04:28 -04002372 case FORMAT_V8U8:
2373 case FORMAT_Q8W8V8U8:
2374 case FORMAT_X8L8V8U8:
2375 case FORMAT_R32F:
2376 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002377 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002378 case FORMAT_A32B32G32R32F:
2379 case FORMAT_A8:
2380 case FORMAT_R8:
2381 case FORMAT_L8:
2382 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002383 case FORMAT_D32F:
John Bauman89401822014-05-06 15:04:28 -04002384 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04002385 case FORMAT_D32FS8_TEXTURE:
2386 case FORMAT_D32FS8_SHADOW:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002387 case FORMAT_YV12_BT601:
2388 case FORMAT_YV12_BT709:
2389 case FORMAT_YV12_JFIF:
John Bauman89401822014-05-06 15:04:28 -04002390 return false;
2391 case FORMAT_L16:
2392 case FORMAT_G16R16:
2393 case FORMAT_A16B16G16R16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002394 case FORMAT_R16I:
2395 case FORMAT_R16UI:
2396 case FORMAT_G16R16I:
2397 case FORMAT_G16R16UI:
2398 case FORMAT_X16B16G16R16I:
2399 case FORMAT_X16B16G16R16UI:
2400 case FORMAT_A16B16G16R16I:
2401 case FORMAT_A16B16G16R16UI:
John Bauman89401822014-05-06 15:04:28 -04002402 case FORMAT_V16U16:
2403 case FORMAT_A16W16V16U16:
2404 case FORMAT_Q16W16V16U16:
2405 return true;
2406 default:
2407 ASSERT(false);
2408 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002409
John Bauman89401822014-05-06 15:04:28 -04002410 return false;
2411 }
2412
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002413 bool SamplerCore::hasYuvFormat() const
2414 {
2415 switch(state.textureFormat)
2416 {
2417 case FORMAT_YV12_BT601:
2418 case FORMAT_YV12_BT709:
2419 case FORMAT_YV12_JFIF:
2420 return true;
2421 case FORMAT_R5G6B5:
Alexis Hetu3412d872015-10-26 16:40:26 -04002422 case FORMAT_R8I_SNORM:
2423 case FORMAT_G8R8I_SNORM:
2424 case FORMAT_X8B8G8R8I_SNORM:
2425 case FORMAT_A8B8G8R8I_SNORM:
2426 case FORMAT_R8I:
2427 case FORMAT_R8UI:
2428 case FORMAT_G8R8I:
2429 case FORMAT_G8R8UI:
2430 case FORMAT_X8B8G8R8I:
2431 case FORMAT_X8B8G8R8UI:
2432 case FORMAT_A8B8G8R8I:
2433 case FORMAT_A8B8G8R8UI:
2434 case FORMAT_R32I:
2435 case FORMAT_R32UI:
2436 case FORMAT_G32R32I:
2437 case FORMAT_G32R32UI:
2438 case FORMAT_X32B32G32R32I:
2439 case FORMAT_X32B32G32R32UI:
2440 case FORMAT_A32B32G32R32I:
2441 case FORMAT_A32B32G32R32UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002442 case FORMAT_G8R8:
2443 case FORMAT_X8R8G8B8:
2444 case FORMAT_X8B8G8R8:
2445 case FORMAT_A8R8G8B8:
2446 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04002447 case FORMAT_SRGB8_X8:
2448 case FORMAT_SRGB8_A8:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002449 case FORMAT_V8U8:
2450 case FORMAT_Q8W8V8U8:
2451 case FORMAT_X8L8V8U8:
2452 case FORMAT_R32F:
2453 case FORMAT_G32R32F:
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002454 case FORMAT_X32B32G32R32F:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002455 case FORMAT_A32B32G32R32F:
2456 case FORMAT_A8:
2457 case FORMAT_R8:
2458 case FORMAT_L8:
2459 case FORMAT_A8L8:
Alexis Hetu3412d872015-10-26 16:40:26 -04002460 case FORMAT_D32F:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002461 case FORMAT_D32F_LOCKABLE:
2462 case FORMAT_D32FS8_TEXTURE:
2463 case FORMAT_D32FS8_SHADOW:
2464 case FORMAT_L16:
2465 case FORMAT_G16R16:
2466 case FORMAT_A16B16G16R16:
Alexis Hetu3412d872015-10-26 16:40:26 -04002467 case FORMAT_R16I:
2468 case FORMAT_R16UI:
2469 case FORMAT_G16R16I:
2470 case FORMAT_G16R16UI:
2471 case FORMAT_X16B16G16R16I:
2472 case FORMAT_X16B16G16R16UI:
2473 case FORMAT_A16B16G16R16I:
2474 case FORMAT_A16B16G16R16UI:
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002475 case FORMAT_V16U16:
2476 case FORMAT_A16W16V16U16:
2477 case FORMAT_Q16W16V16U16:
2478 return false;
2479 default:
2480 ASSERT(false);
2481 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002482
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002483 return false;
2484 }
2485
John Bauman89401822014-05-06 15:04:28 -04002486 bool SamplerCore::isRGBComponent(int component) const
2487 {
2488 switch(state.textureFormat)
2489 {
Nicolas Capensd43f4ce2015-05-13 17:39:44 -04002490 case FORMAT_R5G6B5: return component < 3;
Alexis Hetu3412d872015-10-26 16:40:26 -04002491 case FORMAT_R8I_SNORM: return component < 1;
2492 case FORMAT_G8R8I_SNORM: return component < 2;
2493 case FORMAT_X8B8G8R8I_SNORM: return component < 3;
2494 case FORMAT_A8B8G8R8I_SNORM: return component < 3;
2495 case FORMAT_R8I: return component < 1;
2496 case FORMAT_R8UI: return component < 1;
2497 case FORMAT_G8R8I: return component < 2;
2498 case FORMAT_G8R8UI: return component < 2;
2499 case FORMAT_X8B8G8R8I: return component < 3;
2500 case FORMAT_X8B8G8R8UI: return component < 3;
2501 case FORMAT_A8B8G8R8I: return component < 3;
2502 case FORMAT_A8B8G8R8UI: return component < 3;
2503 case FORMAT_R32I: return component < 1;
2504 case FORMAT_R32UI: return component < 1;
2505 case FORMAT_G32R32I: return component < 2;
2506 case FORMAT_G32R32UI: return component < 2;
2507 case FORMAT_X32B32G32R32I: return component < 3;
2508 case FORMAT_X32B32G32R32UI: return component < 3;
2509 case FORMAT_A32B32G32R32I: return component < 3;
2510 case FORMAT_A32B32G32R32UI: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002511 case FORMAT_G8R8: return component < 2;
2512 case FORMAT_X8R8G8B8: return component < 3;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002513 case FORMAT_X8B8G8R8: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002514 case FORMAT_A8R8G8B8: return component < 3;
Nicolas Capensb508eaf2015-03-28 18:44:48 -04002515 case FORMAT_A8B8G8R8: return component < 3;
Alexis Hetu049a1872016-04-25 16:59:58 -04002516 case FORMAT_SRGB8_X8: return component < 3;
2517 case FORMAT_SRGB8_A8: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002518 case FORMAT_V8U8: return false;
2519 case FORMAT_Q8W8V8U8: return false;
2520 case FORMAT_X8L8V8U8: return false;
2521 case FORMAT_R32F: return component < 1;
2522 case FORMAT_G32R32F: return component < 2;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002523 case FORMAT_X32B32G32R32F: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002524 case FORMAT_A32B32G32R32F: return component < 3;
2525 case FORMAT_A8: return false;
2526 case FORMAT_R8: return component < 1;
2527 case FORMAT_L8: return component < 1;
2528 case FORMAT_A8L8: return component < 1;
Alexis Hetu3412d872015-10-26 16:40:26 -04002529 case FORMAT_D32F: return false;
John Bauman66b8ab22014-05-06 15:57:45 -04002530 case FORMAT_D32F_LOCKABLE: return false;
2531 case FORMAT_D32FS8_TEXTURE: return false;
2532 case FORMAT_D32FS8_SHADOW: return false;
2533 case FORMAT_L16: return component < 1;
2534 case FORMAT_G16R16: return component < 2;
2535 case FORMAT_A16B16G16R16: return component < 3;
Alexis Hetu3412d872015-10-26 16:40:26 -04002536 case FORMAT_R16I: return component < 1;
2537 case FORMAT_R16UI: return component < 1;
2538 case FORMAT_G16R16I: return component < 2;
2539 case FORMAT_G16R16UI: return component < 2;
2540 case FORMAT_X16B16G16R16I: return component < 3;
2541 case FORMAT_X16B16G16R16UI: return component < 3;
2542 case FORMAT_A16B16G16R16I: return component < 3;
2543 case FORMAT_A16B16G16R16UI: return component < 3;
John Bauman66b8ab22014-05-06 15:57:45 -04002544 case FORMAT_V16U16: return false;
2545 case FORMAT_A16W16V16U16: return false;
2546 case FORMAT_Q16W16V16U16: return false;
Nicolas Capens8e8a7e82015-09-01 14:39:57 -04002547 case FORMAT_YV12_BT601: return component < 3;
2548 case FORMAT_YV12_BT709: return component < 3;
2549 case FORMAT_YV12_JFIF: return component < 3;
John Bauman89401822014-05-06 15:04:28 -04002550 default:
2551 ASSERT(false);
2552 }
Alexis Hetu3b96fa82016-02-04 21:15:03 -05002553
John Bauman89401822014-05-06 15:04:28 -04002554 return false;
2555 }
2556}