blob: 60226476be83b1f373a4ee9704a48cd84d83e3da [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman66b8ab22014-05-06 15:57:45 -04003// Copyright(c) 2005-2013 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "SamplerCore.hpp"
13
14#include "Constants.hpp"
15#include "Debug.hpp"
16
17namespace sw
18{
19 SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
20 {
21 }
22
John Bauman19bac1e2014-05-06 15:23:49 -040023 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias, bool fixed12, bool gradients, bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -040024 {
25 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -040026 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -040027
28 if(state.compressedFormat)
29 {
John Bauman66b8ab22014-05-06 15:57:45 -040030 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -040031 }
32 #endif
33
34 bool cubeTexture = state.textureType == TEXTURE_CUBE;
35 bool volumeTexture = state.textureType == TEXTURE_3D;
36
37 Float4 uuuu = u;
38 Float4 vvvv = v;
39 Float4 wwww = w;
40
41 if(state.textureType == TEXTURE_NULL)
42 {
John Bauman19bac1e2014-05-06 15:23:49 -040043 c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000);
44 c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000);
45 c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000);
John Bauman89401822014-05-06 15:04:28 -040046
47 if(fixed12) // FIXME: Convert to fixed12 at higher level, when required
48 {
John Bauman19bac1e2014-05-06 15:23:49 -040049 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -040050 }
51 else
52 {
John Bauman19bac1e2014-05-06 15:23:49 -040053 c.w = Short4((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); // FIXME
John Bauman89401822014-05-06 15:04:28 -040054 }
55 }
56 else
57 {
58 Int face[4];
59 Float4 lodU;
60 Float4 lodV;
61
62 if(cubeTexture)
63 {
64 cubeFace(face, uuuu, vvvv, lodU, lodV, u, v, w);
65 }
66
67 Float lod;
68 Float anisotropy;
69 Float4 uDelta;
70 Float4 vDelta;
71
72 if(!volumeTexture)
73 {
74 if(!cubeTexture)
75 {
John Bauman66b8ab22014-05-06 15:57:45 -040076 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, bias, gradients, lodProvided);
John Bauman89401822014-05-06 15:04:28 -040077 }
78 else
79 {
John Bauman66b8ab22014-05-06 15:57:45 -040080 computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, bias, gradients, lodProvided);
John Bauman89401822014-05-06 15:04:28 -040081 }
82 }
83 else
84 {
John Bauman66b8ab22014-05-06 15:57:45 -040085 computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, bias, gradients, lodProvided);
John Bauman89401822014-05-06 15:04:28 -040086 }
87
88 if(cubeTexture)
89 {
John Bauman19bac1e2014-05-06 15:23:49 -040090 uuuu += Float4(0.5f);
91 vvvv += Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -040092 }
93
94 if(!hasFloatTexture())
95 {
96 sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided);
97 }
98 else
99 {
John Bauman19bac1e2014-05-06 15:23:49 -0400100 Vector4f cf;
John Bauman89401822014-05-06 15:04:28 -0400101
102 sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided);
103
104 convertFixed12(c, cf);
105 }
106
107 if(fixed12 && !hasFloatTexture())
108 {
109 for(int component = 0; component < textureComponentCount(); component++)
110 {
111 if(state.sRGB && isRGBComponent(component))
112 {
113 sRGBtoLinear16_12(c[component]); // FIXME: Perform linearization at surface level for read-only textures
114 }
115 else
116 {
117 if(hasUnsignedTextureComponent(component))
118 {
119 c[component] = As<UShort4>(c[component]) >> 4;
120 }
121 else
122 {
123 c[component] = c[component] >> 3;
124 }
125 }
126 }
127 }
128
129 if(fixed12 && state.textureFilter != FILTER_GATHER)
130 {
131 int componentCount = textureComponentCount();
132
133 switch(state.textureFormat)
134 {
135 case FORMAT_R8:
136 case FORMAT_X8R8G8B8:
137 case FORMAT_A8R8G8B8:
138 case FORMAT_V8U8:
139 case FORMAT_Q8W8V8U8:
140 case FORMAT_X8L8V8U8:
141 case FORMAT_V16U16:
142 case FORMAT_A16W16V16U16:
143 case FORMAT_Q16W16V16U16:
144 case FORMAT_G8R8:
145 case FORMAT_G16R16:
146 case FORMAT_A16B16G16R16:
John Bauman19bac1e2014-05-06 15:23:49 -0400147 if(componentCount < 2) c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000);
148 if(componentCount < 3) c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000);
149 if(componentCount < 4) c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400150 break;
151 case FORMAT_A8:
John Bauman19bac1e2014-05-06 15:23:49 -0400152 c.w = c.x;
153 c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000);
154 c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000);
155 c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000);
John Bauman89401822014-05-06 15:04:28 -0400156 break;
157 case FORMAT_L8:
158 case FORMAT_L16:
John Bauman19bac1e2014-05-06 15:23:49 -0400159 c.y = c.x;
160 c.z = c.x;
161 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400162 break;
163 case FORMAT_A8L8:
John Bauman19bac1e2014-05-06 15:23:49 -0400164 c.w = c.y;
165 c.y = c.x;
166 c.z = c.x;
John Bauman89401822014-05-06 15:04:28 -0400167 break;
168 case FORMAT_R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400169 c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400170 case FORMAT_G32R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400171 c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000);
172 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000);
John Bauman89401822014-05-06 15:04:28 -0400173 case FORMAT_A32B32G32R32F:
174 break;
175 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400176 case FORMAT_D32FS8_TEXTURE:
177 case FORMAT_D32FS8_SHADOW:
John Bauman19bac1e2014-05-06 15:23:49 -0400178 c.y = c.x;
179 c.z = c.x;
180 c.w = c.x;
John Bauman89401822014-05-06 15:04:28 -0400181 break;
182 default:
183 ASSERT(false);
184 }
185 }
186 }
187 }
188
John Bauman19bac1e2014-05-06 15:23:49 -0400189 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -0400190 {
191 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -0400192 AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
John Bauman89401822014-05-06 15:04:28 -0400193
194 if(state.compressedFormat)
195 {
John Bauman66b8ab22014-05-06 15:57:45 -0400196 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
John Bauman89401822014-05-06 15:04:28 -0400197 }
198 #endif
199
200 bool cubeTexture = state.textureType == TEXTURE_CUBE;
201 bool volumeTexture = state.textureType == TEXTURE_3D;
202
203 if(state.textureType == TEXTURE_NULL)
204 {
John Bauman19bac1e2014-05-06 15:23:49 -0400205 c.x = Float4(0.0f);
206 c.y = Float4(0.0f);
207 c.z = Float4(0.0f);
208 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400209 }
210 else
211 {
212 if(hasFloatTexture()) // FIXME: Mostly identical to integer sampling
213 {
214 Float4 uuuu = u;
215 Float4 vvvv = v;
216 Float4 wwww = w;
217
218 Int face[4];
219 Float4 lodU;
220 Float4 lodV;
221
222 if(cubeTexture)
223 {
224 cubeFace(face, uuuu, vvvv, lodU, lodV, u, v, w);
225 }
226
227 Float lod;
228 Float anisotropy;
229 Float4 uDelta;
230 Float4 vDelta;
231
232 if(!volumeTexture)
233 {
234 if(!cubeTexture)
235 {
John Bauman66b8ab22014-05-06 15:57:45 -0400236 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, bias, gradients, lodProvided);
John Bauman89401822014-05-06 15:04:28 -0400237 }
238 else
239 {
John Bauman66b8ab22014-05-06 15:57:45 -0400240 computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, bias, gradients, lodProvided);
John Bauman89401822014-05-06 15:04:28 -0400241 }
242 }
243 else
244 {
John Bauman66b8ab22014-05-06 15:57:45 -0400245 computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, bias, gradients, lodProvided);
John Bauman89401822014-05-06 15:04:28 -0400246 }
247
248 if(cubeTexture)
249 {
John Bauman19bac1e2014-05-06 15:23:49 -0400250 uuuu += Float4(0.5f);
251 vvvv += Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -0400252 }
253
254 sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided);
255 }
256 else
257 {
John Bauman19bac1e2014-05-06 15:23:49 -0400258 Vector4i ci;
John Bauman89401822014-05-06 15:04:28 -0400259
260 sampleTexture(texture, ci, u, v, w, q, dsx, dsy, bias, false, gradients, lodProvided);
261
262 for(int component = 0; component < textureComponentCount(); component++)
263 {
264 if(state.sRGB && isRGBComponent(component))
265 {
266 sRGBtoLinear16_12(ci[component]); // FIXME: Perform linearization at surface level for read-only textures
267 convertSigned12(c[component], ci[component]);
268 }
269 else
270 {
271 if(hasUnsignedTextureComponent(component))
272 {
273 convertUnsigned16(c[component], ci[component]);
274 }
275 else
276 {
277 convertSigned15(c[component], ci[component]);
278 }
279 }
280 }
281 }
282
283 int componentCount = textureComponentCount();
284
285 if(state.textureFilter != FILTER_GATHER)
286 {
287 switch(state.textureFormat)
288 {
289 case FORMAT_R8:
290 case FORMAT_X8R8G8B8:
291 case FORMAT_A8R8G8B8:
292 case FORMAT_V8U8:
293 case FORMAT_Q8W8V8U8:
294 case FORMAT_X8L8V8U8:
295 case FORMAT_V16U16:
296 case FORMAT_A16W16V16U16:
297 case FORMAT_Q16W16V16U16:
298 case FORMAT_G8R8:
299 case FORMAT_G16R16:
300 case FORMAT_A16B16G16R16:
John Bauman19bac1e2014-05-06 15:23:49 -0400301 if(componentCount < 2) c.y = Float4(1.0f);
302 if(componentCount < 3) c.z = Float4(1.0f);
303 if(componentCount < 4) c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400304 break;
305 case FORMAT_A8:
John Bauman19bac1e2014-05-06 15:23:49 -0400306 c.w = c.x;
307 c.x = Float4(0.0f);
308 c.y = Float4(0.0f);
309 c.z = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -0400310 break;
311 case FORMAT_L8:
312 case FORMAT_L16:
John Bauman19bac1e2014-05-06 15:23:49 -0400313 c.y = c.x;
314 c.z = c.x;
315 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400316 break;
317 case FORMAT_A8L8:
John Bauman19bac1e2014-05-06 15:23:49 -0400318 c.w = c.y;
319 c.y = c.x;
320 c.z = c.x;
John Bauman89401822014-05-06 15:04:28 -0400321 break;
322 case FORMAT_R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400323 c.y = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400324 case FORMAT_G32R32F:
John Bauman19bac1e2014-05-06 15:23:49 -0400325 c.z = Float4(1.0f);
326 c.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -0400327 case FORMAT_A32B32G32R32F:
328 break;
329 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -0400330 case FORMAT_D32FS8_TEXTURE:
331 case FORMAT_D32FS8_SHADOW:
John Bauman19bac1e2014-05-06 15:23:49 -0400332 c.y = c.x;
333 c.z = c.x;
334 c.w = c.x;
John Bauman89401822014-05-06 15:04:28 -0400335 break;
336 default:
337 ASSERT(false);
338 }
339 }
340 }
341 }
342
343 void SamplerCore::border(Short4 &mask, Float4 &coordinates)
344 {
345 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
346 mask = As<Short4>(Int2(As<Int4>(Pack(border, border))));
347 }
348
349 void SamplerCore::border(Int4 &mask, Float4 &coordinates)
350 {
351 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
352 }
353
354 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count)
355 {
356 if(wrap)
357 {
358 switch(count)
359 {
360 case -1: return uvw - *Pointer<Short4>(mipmap + halfOffset);
361 case 0: return uvw;
362 case +1: return uvw + *Pointer<Short4>(mipmap + halfOffset);
363 case 2: return uvw + *Pointer<Short4>(mipmap + halfOffset) + *Pointer<Short4>(mipmap + halfOffset);
364 }
365 }
366 else // Clamp or mirror
367 {
368 switch(count)
369 {
370 case -1: return SubSat(As<UShort4>(uvw), *Pointer<UShort4>(mipmap + halfOffset));
371 case 0: return uvw;
372 case +1: return AddSat(As<UShort4>(uvw), *Pointer<UShort4>(mipmap + halfOffset));
373 case 2: return AddSat(AddSat(As<UShort4>(uvw), *Pointer<UShort4>(mipmap + halfOffset)), *Pointer<UShort4>(mipmap + halfOffset));
374 }
375 }
376
377 return uvw;
378 }
379
John Bauman19bac1e2014-05-06 15:23:49 -0400380 void SamplerCore::sampleFilter(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -0400381 {
382 bool volumeTexture = state.textureType == TEXTURE_3D;
383
384 sampleAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, lodProvided);
385
386 if(state.mipmapFilter > MIPMAP_POINT)
387 {
John Bauman19bac1e2014-05-06 15:23:49 -0400388 Vector4i cc;
John Bauman89401822014-05-06 15:04:28 -0400389
390 sampleAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, lodProvided);
391
392 lod *= Float(1 << 16);
393
394 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize
395 Short4 stri = utri >> 1; // FIXME: Optimize
396
John Bauman19bac1e2014-05-06 15:23:49 -0400397 if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri);
398 if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri);
399 if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri);
400 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 -0400401
402 utri = ~utri;
403 stri = Short4(0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF) - stri;
404
John Bauman19bac1e2014-05-06 15:23:49 -0400405 if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri);
406 if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri);
407 if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri);
408 if(hasUnsignedTextureComponent(3)) c.w = MulHigh(As<UShort4>(c.w), utri); else c.w = MulHigh(c.w, stri);
John Bauman89401822014-05-06 15:04:28 -0400409
John Bauman19bac1e2014-05-06 15:23:49 -0400410 c.x += cc.x;
411 c.y += cc.y;
412 c.z += cc.z;
413 c.w += cc.w;
John Bauman89401822014-05-06 15:04:28 -0400414
John Bauman19bac1e2014-05-06 15:23:49 -0400415 if(!hasUnsignedTextureComponent(0)) c.x += c.x;
416 if(!hasUnsignedTextureComponent(1)) c.y += c.y;
417 if(!hasUnsignedTextureComponent(2)) c.z += c.z;
418 if(!hasUnsignedTextureComponent(3)) c.w += c.w;
John Bauman89401822014-05-06 15:04:28 -0400419 }
420
421 Short4 borderMask;
422
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400423 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400424 {
425 Short4 u0;
426
427 border(u0, u);
428
429 borderMask = u0;
430 }
431
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400432 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400433 {
434 Short4 v0;
435
436 border(v0, v);
437
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400438 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400439 {
440 borderMask &= v0;
441 }
442 else
443 {
444 borderMask = v0;
445 }
446 }
447
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400448 if(state.addressingModeW == ADDRESSING_BORDER && volumeTexture)
John Bauman89401822014-05-06 15:04:28 -0400449 {
450 Short4 s0;
451
452 border(s0, w);
453
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400454 if(state.addressingModeU == ADDRESSING_BORDER ||
455 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400456 {
457 borderMask &= s0;
458 }
459 else
460 {
461 borderMask = s0;
462 }
463 }
464
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400465 if(state.addressingModeU == ADDRESSING_BORDER ||
466 state.addressingModeV == ADDRESSING_BORDER ||
467 (state.addressingModeW == ADDRESSING_BORDER && volumeTexture))
John Bauman89401822014-05-06 15:04:28 -0400468 {
469 Short4 b;
470
John Bauman19bac1e2014-05-06 15:23:49 -0400471 c.x = borderMask & c.x | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1));
472 c.y = borderMask & c.y | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1));
473 c.z = borderMask & c.z | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1));
474 c.w = borderMask & c.w | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1));
John Bauman89401822014-05-06 15:04:28 -0400475 }
476 }
477
John Bauman19bac1e2014-05-06 15:23:49 -0400478 void SamplerCore::sampleAniso(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -0400479 {
480 if(state.textureFilter != FILTER_ANISOTROPIC || lodProvided)
481 {
482 sampleQuad(texture, c, u, v, w, lod, face, secondLOD);
483 }
484 else
485 {
486 Int a = RoundInt(anisotropy);
487
John Bauman19bac1e2014-05-06 15:23:49 -0400488 Vector4i cSum;
John Bauman89401822014-05-06 15:04:28 -0400489
John Bauman19bac1e2014-05-06 15:23:49 -0400490 cSum.x = Short4(0, 0, 0, 0);
491 cSum.y = Short4(0, 0, 0, 0);
492 cSum.z = Short4(0, 0, 0, 0);
493 cSum.w = Short4(0, 0, 0, 0);
John Bauman89401822014-05-06 15:04:28 -0400494
495 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
496 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
497 UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a);
498 Short4 sw = Short4(cw >> 1);
499
500 Float4 du = uDelta;
501 Float4 dv = vDelta;
502
503 Float4 u0 = u + B * du;
504 Float4 v0 = v + B * dv;
505
506 du *= A;
507 dv *= A;
508
509 Int i = 0;
510
511 Do
512 {
513 sampleQuad(texture, c, u0, v0, w, lod, face, secondLOD);
514
515 u0 += du;
516 v0 += dv;
517
John Bauman19bac1e2014-05-06 15:23:49 -0400518 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw);
519 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw);
520 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw);
521 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 -0400522
523 i++;
524 }
525 Until(i >= a)
526
John Bauman19bac1e2014-05-06 15:23:49 -0400527 if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x);
528 if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y);
529 if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z);
530 if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w);
John Bauman89401822014-05-06 15:04:28 -0400531 }
532 }
533
John Bauman19bac1e2014-05-06 15:23:49 -0400534 void SamplerCore::sampleQuad(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -0400535 {
536 if(state.textureType != TEXTURE_3D)
537 {
538 sampleQuad2D(texture, c, u, v, lod, face, secondLOD);
539 }
540 else
541 {
542 sample3D(texture, c, u, v, w, lod, secondLOD);
543 }
544 }
545
John Bauman19bac1e2014-05-06 15:23:49 -0400546 void SamplerCore::sampleQuad2D(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -0400547 {
548 int componentCount = textureComponentCount();
549 bool gather = state.textureFilter == FILTER_GATHER;
550
551 Pointer<Byte> mipmap;
552 Pointer<Byte> buffer[4];
553
554 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
555
556 Short4 uuuu;
557 Short4 vvvv;
558
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400559 address(uuuu, u, state.addressingModeU);
560 address(vvvv, v, state.addressingModeV);
John Bauman89401822014-05-06 15:04:28 -0400561
562 if(state.textureFilter == FILTER_POINT)
563 {
564 sampleTexel(c, uuuu, vvvv, vvvv, mipmap, buffer);
565 }
566 else
567 {
John Bauman19bac1e2014-05-06 15:23:49 -0400568 Vector4i c0;
569 Vector4i c1;
570 Vector4i c2;
571 Vector4i c3;
John Bauman89401822014-05-06 15:04:28 -0400572
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400573 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1);
574 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1);
575 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1);
576 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1);
John Bauman89401822014-05-06 15:04:28 -0400577
578 sampleTexel(c0, uuuu0, vvvv0, vvvv0, mipmap, buffer);
579 sampleTexel(c1, uuuu1, vvvv0, vvvv0, mipmap, buffer);
580 sampleTexel(c2, uuuu0, vvvv1, vvvv1, mipmap, buffer);
581 sampleTexel(c3, uuuu1, vvvv1, vvvv1, mipmap, buffer);
582
583 if(!gather) // Blend
584 {
585 // Fractions
586 UShort4 f0u = uuuu0;
587 UShort4 f0v = vvvv0;
588
589 if(!state.hasNPOTTexture)
590 {
591 f0u = f0u << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt)); // .u
592 f0v = f0v << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt)); // .v
593 }
594 else
595 {
596 f0u = f0u * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width));
597 f0v = f0v * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height));
598 }
599
600 Short4 f1u = ~f0u;
601 Short4 f1v = ~f0v;
602
603 Short4 f0u0v = MulHigh(As<UShort4>(f0u), As<UShort4>(f0v));
604 Short4 f1u0v = MulHigh(As<UShort4>(f1u), As<UShort4>(f0v));
605 Short4 f0u1v = MulHigh(As<UShort4>(f0u), As<UShort4>(f1v));
606 Short4 f1u1v = MulHigh(As<UShort4>(f1u), As<UShort4>(f1v));
607
608 // Signed fractions
609 Short4 f1u1vs;
610 Short4 f0u1vs;
611 Short4 f1u0vs;
612 Short4 f0u0vs;
613
614 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
615 {
616 f1u1vs = As<UShort4>(f1u1v) >> 1;
617 f0u1vs = As<UShort4>(f0u1v) >> 1;
618 f1u0vs = As<UShort4>(f1u0v) >> 1;
619 f0u0vs = As<UShort4>(f0u0v) >> 1;
620 }
621
622 // Bilinear interpolation
623 if(componentCount >= 1)
624 {
625 if(has16bitTexture() && hasUnsignedTextureComponent(0))
626 {
John Bauman19bac1e2014-05-06 15:23:49 -0400627 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u);
628 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u);
629 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 -0400630 }
631 else
632 {
633 if(hasUnsignedTextureComponent(0))
634 {
John Bauman19bac1e2014-05-06 15:23:49 -0400635 c0.x = MulHigh(As<UShort4>(c0.x), As<UShort4>(f1u1v));
636 c1.x = MulHigh(As<UShort4>(c1.x), As<UShort4>(f0u1v));
637 c2.x = MulHigh(As<UShort4>(c2.x), As<UShort4>(f1u0v));
638 c3.x = MulHigh(As<UShort4>(c3.x), As<UShort4>(f0u0v));
John Bauman89401822014-05-06 15:04:28 -0400639 }
640 else
641 {
John Bauman19bac1e2014-05-06 15:23:49 -0400642 c0.x = MulHigh(c0.x, f1u1vs);
643 c1.x = MulHigh(c1.x, f0u1vs);
644 c2.x = MulHigh(c2.x, f1u0vs);
645 c3.x = MulHigh(c3.x, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400646 }
647
John Bauman19bac1e2014-05-06 15:23:49 -0400648 c.x = (c0.x + c1.x) + (c2.x + c3.x);
649 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400650 }
651 }
652
653 if(componentCount >= 2)
654 {
655 if(has16bitTexture() && hasUnsignedTextureComponent(1))
656 {
John Bauman19bac1e2014-05-06 15:23:49 -0400657 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u);
658 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u);
659 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 -0400660 }
661 else
662 {
663 if(hasUnsignedTextureComponent(1))
664 {
John Bauman19bac1e2014-05-06 15:23:49 -0400665 c0.y = MulHigh(As<UShort4>(c0.y), As<UShort4>(f1u1v));
666 c1.y = MulHigh(As<UShort4>(c1.y), As<UShort4>(f0u1v));
667 c2.y = MulHigh(As<UShort4>(c2.y), As<UShort4>(f1u0v));
668 c3.y = MulHigh(As<UShort4>(c3.y), As<UShort4>(f0u0v));
John Bauman89401822014-05-06 15:04:28 -0400669 }
670 else
671 {
John Bauman19bac1e2014-05-06 15:23:49 -0400672 c0.y = MulHigh(c0.y, f1u1vs);
673 c1.y = MulHigh(c1.y, f0u1vs);
674 c2.y = MulHigh(c2.y, f1u0vs);
675 c3.y = MulHigh(c3.y, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400676 }
677
John Bauman19bac1e2014-05-06 15:23:49 -0400678 c.y = (c0.y + c1.y) + (c2.y + c3.y);
679 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400680 }
681 }
682
683 if(componentCount >= 3)
684 {
685 if(has16bitTexture() && hasUnsignedTextureComponent(2))
686 {
John Bauman19bac1e2014-05-06 15:23:49 -0400687 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u);
688 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u);
689 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 -0400690 }
691 else
692 {
693 if(hasUnsignedTextureComponent(2))
694 {
John Bauman19bac1e2014-05-06 15:23:49 -0400695 c0.z = MulHigh(As<UShort4>(c0.z), As<UShort4>(f1u1v));
696 c1.z = MulHigh(As<UShort4>(c1.z), As<UShort4>(f0u1v));
697 c2.z = MulHigh(As<UShort4>(c2.z), As<UShort4>(f1u0v));
698 c3.z = MulHigh(As<UShort4>(c3.z), As<UShort4>(f0u0v));
John Bauman89401822014-05-06 15:04:28 -0400699 }
700 else
701 {
John Bauman19bac1e2014-05-06 15:23:49 -0400702 c0.z = MulHigh(c0.z, f1u1vs);
703 c1.z = MulHigh(c1.z, f0u1vs);
704 c2.z = MulHigh(c2.z, f1u0vs);
705 c3.z = MulHigh(c3.z, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400706 }
707
John Bauman19bac1e2014-05-06 15:23:49 -0400708 c.z = (c0.z + c1.z) + (c2.z + c3.z);
709 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400710 }
711 }
712
713 if(componentCount >= 4)
714 {
715 if(has16bitTexture() && hasUnsignedTextureComponent(3))
716 {
John Bauman19bac1e2014-05-06 15:23:49 -0400717 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u);
718 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u);
719 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 -0400720 }
721 else
722 {
723 if(hasUnsignedTextureComponent(3))
724 {
John Bauman19bac1e2014-05-06 15:23:49 -0400725 c0.w = MulHigh(As<UShort4>(c0.w), As<UShort4>(f1u1v));
726 c1.w = MulHigh(As<UShort4>(c1.w), As<UShort4>(f0u1v));
727 c2.w = MulHigh(As<UShort4>(c2.w), As<UShort4>(f1u0v));
728 c3.w = MulHigh(As<UShort4>(c3.w), As<UShort4>(f0u0v));
John Bauman89401822014-05-06 15:04:28 -0400729 }
730 else
731 {
John Bauman19bac1e2014-05-06 15:23:49 -0400732 c0.w = MulHigh(c0.w, f1u1vs);
733 c1.w = MulHigh(c1.w, f0u1vs);
734 c2.w = MulHigh(c2.w, f1u0vs);
735 c3.w = MulHigh(c3.w, f0u0vs);
John Bauman89401822014-05-06 15:04:28 -0400736 }
737
John Bauman19bac1e2014-05-06 15:23:49 -0400738 c.w = (c0.w + c1.w) + (c2.w + c3.w);
739 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w); // Correct for signed fractions
John Bauman89401822014-05-06 15:04:28 -0400740 }
741 }
742 }
743 else
744 {
John Bauman19bac1e2014-05-06 15:23:49 -0400745 c.x = c1.x;
746 c.y = c2.x;
747 c.z = c3.x;
748 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -0400749 }
750 }
751 }
752
John Bauman19bac1e2014-05-06 15:23:49 -0400753 void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4i &c_, Float4 &u_, Float4 &v_, Float4 &w_, Float &lod, bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -0400754 {
755 int componentCount = textureComponentCount();
756
757 Pointer<Byte> mipmap;
758 Pointer<Byte> buffer[4];
759 Int face[4];
760
761 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
762
763 Short4 uuuu;
764 Short4 vvvv;
765 Short4 wwww;
766
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400767 address(uuuu, u_, state.addressingModeU);
768 address(vvvv, v_, state.addressingModeV);
769 address(wwww, w_, state.addressingModeW);
John Bauman89401822014-05-06 15:04:28 -0400770
771 if(state.textureFilter <= FILTER_POINT)
772 {
773 sampleTexel(c_, uuuu, vvvv, wwww, mipmap, buffer);
774 }
775 else
776 {
John Bauman19bac1e2014-05-06 15:23:49 -0400777 Vector4i c[2][2][2];
John Bauman89401822014-05-06 15:04:28 -0400778
779 Short4 u[2][2][2];
780 Short4 v[2][2][2];
781 Short4 s[2][2][2];
782
783 for(int i = 0; i < 2; i++)
784 {
785 for(int j = 0; j < 2; j++)
786 {
787 for(int k = 0; k < 2; k++)
788 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400789 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1);
790 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1);
791 s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1);
John Bauman89401822014-05-06 15:04:28 -0400792 }
793 }
794 }
795
796 Short4 f[2][2][2];
797 Short4 fs[2][2][2];
798 Short4 f0u;
799 Short4 f0v;
800 Short4 f0s;
801 Short4 f1u;
802 Short4 f1v;
803 Short4 f1s;
804
805 // Fractions
806 f0u = u[0][0][0];
807 f0v = v[0][0][0];
808 f0s = s[0][0][0];
809
810 if(!state.hasNPOTTexture)
811 {
812 f0u = f0u << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt));
813 f0v = f0v << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt));
814 f0s = f0s << *Pointer<Long1>(mipmap + OFFSET(Mipmap,wInt));
815 }
816 else
817 {
818 f0u *= *Pointer<Short4>(mipmap + OFFSET(Mipmap,width));
819 f0v *= *Pointer<Short4>(mipmap + OFFSET(Mipmap,height));
820 f0s *= *Pointer<Short4>(mipmap + OFFSET(Mipmap,depth));
821 }
822
823 f1u = ~f0u;
824 f1v = ~f0v;
825 f1s = ~f0s;
826
827 f[1][1][1] = MulHigh(As<UShort4>(f1u), As<UShort4>(f1v));
828 f[0][1][1] = MulHigh(As<UShort4>(f0u), As<UShort4>(f1v));
829 f[1][0][1] = MulHigh(As<UShort4>(f1u), As<UShort4>(f0v));
830 f[0][0][1] = MulHigh(As<UShort4>(f0u), As<UShort4>(f0v));
831 f[1][1][0] = MulHigh(As<UShort4>(f1u), As<UShort4>(f1v));
832 f[0][1][0] = MulHigh(As<UShort4>(f0u), As<UShort4>(f1v));
833 f[1][0][0] = MulHigh(As<UShort4>(f1u), As<UShort4>(f0v));
834 f[0][0][0] = MulHigh(As<UShort4>(f0u), As<UShort4>(f0v));
835
836 f[1][1][1] = MulHigh(As<UShort4>(f[1][1][1]), As<UShort4>(f1s));
837 f[0][1][1] = MulHigh(As<UShort4>(f[0][1][1]), As<UShort4>(f1s));
838 f[1][0][1] = MulHigh(As<UShort4>(f[1][0][1]), As<UShort4>(f1s));
839 f[0][0][1] = MulHigh(As<UShort4>(f[0][0][1]), As<UShort4>(f1s));
840 f[1][1][0] = MulHigh(As<UShort4>(f[1][1][0]), As<UShort4>(f0s));
841 f[0][1][0] = MulHigh(As<UShort4>(f[0][1][0]), As<UShort4>(f0s));
842 f[1][0][0] = MulHigh(As<UShort4>(f[1][0][0]), As<UShort4>(f0s));
843 f[0][0][0] = MulHigh(As<UShort4>(f[0][0][0]), As<UShort4>(f0s));
844
845 // Signed fractions
846 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3))
847 {
848 fs[0][0][0] = As<UShort4>(f[0][0][0]) >> 1;
849 fs[0][0][1] = As<UShort4>(f[0][0][1]) >> 1;
850 fs[0][1][0] = As<UShort4>(f[0][1][0]) >> 1;
851 fs[0][1][1] = As<UShort4>(f[0][1][1]) >> 1;
852 fs[1][0][0] = As<UShort4>(f[1][0][0]) >> 1;
853 fs[1][0][1] = As<UShort4>(f[1][0][1]) >> 1;
854 fs[1][1][0] = As<UShort4>(f[1][1][0]) >> 1;
855 fs[1][1][1] = As<UShort4>(f[1][1][1]) >> 1;
856 }
857
858 for(int i = 0; i < 2; i++)
859 {
860 for(int j = 0; j < 2; j++)
861 {
862 for(int k = 0; k < 2; k++)
863 {
864 sampleTexel(c[i][j][k], u[i][j][k], v[i][j][k], s[i][j][k], mipmap, buffer);
865
John Bauman19bac1e2014-05-06 15:23:49 -0400866 if(componentCount >= 1) if(hasUnsignedTextureComponent(0)) c[i][j][k].x = MulHigh(As<UShort4>(c[i][j][k].x), As<UShort4>(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]);
867 if(componentCount >= 2) if(hasUnsignedTextureComponent(1)) c[i][j][k].y = MulHigh(As<UShort4>(c[i][j][k].y), As<UShort4>(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]);
868 if(componentCount >= 3) if(hasUnsignedTextureComponent(2)) c[i][j][k].z = MulHigh(As<UShort4>(c[i][j][k].z), As<UShort4>(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]);
869 if(componentCount >= 4) if(hasUnsignedTextureComponent(3)) c[i][j][k].w = MulHigh(As<UShort4>(c[i][j][k].w), As<UShort4>(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 -0400870
871 if(i != 0 || j != 0 || k != 0)
872 {
John Bauman19bac1e2014-05-06 15:23:49 -0400873 if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x;
874 if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y;
875 if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z;
876 if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w;
John Bauman89401822014-05-06 15:04:28 -0400877 }
878 }
879 }
880 }
881
John Bauman19bac1e2014-05-06 15:23:49 -0400882 if(componentCount >= 1) c_.x = c[0][0][0].x;
883 if(componentCount >= 2) c_.y = c[0][0][0].y;
884 if(componentCount >= 3) c_.z = c[0][0][0].z;
885 if(componentCount >= 4) c_.w = c[0][0][0].w;
John Bauman89401822014-05-06 15:04:28 -0400886
887 // Correct for signed fractions
John Bauman19bac1e2014-05-06 15:23:49 -0400888 if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x);
889 if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y);
890 if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z);
891 if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w);
John Bauman89401822014-05-06 15:04:28 -0400892 }
893 }
894
John Bauman19bac1e2014-05-06 15:23:49 -0400895 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], bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -0400896 {
897 bool volumeTexture = state.textureType == TEXTURE_3D;
898
899 sampleFloatAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, lodProvided);
900
901 if(state.mipmapFilter > MIPMAP_POINT)
902 {
John Bauman19bac1e2014-05-06 15:23:49 -0400903 Vector4f cc;
John Bauman89401822014-05-06 15:04:28 -0400904
905 sampleFloatAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, lodProvided);
906
John Bauman19bac1e2014-05-06 15:23:49 -0400907 Float4 lod4 = Float4(Frac(lod));
John Bauman89401822014-05-06 15:04:28 -0400908
John Bauman19bac1e2014-05-06 15:23:49 -0400909 c.x = (cc.x - c.x) * lod4 + c.x;
910 c.y = (cc.y - c.y) * lod4 + c.y;
911 c.z = (cc.z - c.z) * lod4 + c.z;
912 c.w = (cc.w - c.w) * lod4 + c.w;
John Bauman89401822014-05-06 15:04:28 -0400913 }
914
915 Int4 borderMask;
916
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400917 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400918 {
919 Int4 u0;
920
921 border(u0, u);
922
923 borderMask = u0;
924 }
925
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400926 if(state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400927 {
928 Int4 v0;
929
930 border(v0, v);
931
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400932 if(state.addressingModeU == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400933 {
934 borderMask &= v0;
935 }
936 else
937 {
938 borderMask = v0;
939 }
940 }
941
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400942 if(state.addressingModeW == ADDRESSING_BORDER && volumeTexture)
John Bauman89401822014-05-06 15:04:28 -0400943 {
944 Int4 s0;
945
946 border(s0, w);
947
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400948 if(state.addressingModeU == ADDRESSING_BORDER ||
949 state.addressingModeV == ADDRESSING_BORDER)
John Bauman89401822014-05-06 15:04:28 -0400950 {
951 borderMask &= s0;
952 }
953 else
954 {
955 borderMask = s0;
956 }
957 }
958
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400959 if(state.addressingModeU == ADDRESSING_BORDER ||
960 state.addressingModeV == ADDRESSING_BORDER ||
961 (state.addressingModeW == ADDRESSING_BORDER && volumeTexture))
John Bauman89401822014-05-06 15:04:28 -0400962 {
963 Int4 b;
964
John Bauman19bac1e2014-05-06 15:23:49 -0400965 c.x = As<Float4>(borderMask & As<Int4>(c.x) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0])));
966 c.y = As<Float4>(borderMask & As<Int4>(c.y) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1])));
967 c.z = As<Float4>(borderMask & As<Int4>(c.z) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2])));
968 c.w = As<Float4>(borderMask & As<Int4>(c.w) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3])));
John Bauman89401822014-05-06 15:04:28 -0400969 }
970 }
971
John Bauman19bac1e2014-05-06 15:23:49 -0400972 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, bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -0400973 {
974 if(state.textureFilter != FILTER_ANISOTROPIC || lodProvided)
975 {
976 sampleFloat(texture, c, u, v, w, lod, face, secondLOD);
977 }
978 else
979 {
980 Int a = RoundInt(anisotropy);
981
John Bauman19bac1e2014-05-06 15:23:49 -0400982 Vector4f cSum;
John Bauman89401822014-05-06 15:04:28 -0400983
John Bauman19bac1e2014-05-06 15:23:49 -0400984 cSum.x = Float4(0.0f);
985 cSum.y = Float4(0.0f);
986 cSum.z = Float4(0.0f);
987 cSum.w = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -0400988
989 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a);
990 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a);
991
992 Float4 du = uDelta;
993 Float4 dv = vDelta;
994
995 Float4 u0 = u + B * du;
996 Float4 v0 = v + B * dv;
997
998 du *= A;
999 dv *= A;
1000
1001 Int i = 0;
1002
1003 Do
1004 {
1005 sampleFloat(texture, c, u0, v0, w, lod, face, secondLOD);
1006
1007 u0 += du;
1008 v0 += dv;
1009
John Bauman19bac1e2014-05-06 15:23:49 -04001010 cSum.x += c.x * A;
1011 cSum.y += c.y * A;
1012 cSum.z += c.z * A;
1013 cSum.w += c.w * A;
John Bauman89401822014-05-06 15:04:28 -04001014
1015 i++;
1016 }
1017 Until(i >= a)
1018
John Bauman19bac1e2014-05-06 15:23:49 -04001019 c.x = cSum.x;
1020 c.y = cSum.y;
1021 c.z = cSum.z;
1022 c.w = cSum.w;
John Bauman89401822014-05-06 15:04:28 -04001023 }
1024 }
1025
John Bauman19bac1e2014-05-06 15:23:49 -04001026 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 -04001027 {
1028 if(state.textureType != TEXTURE_3D)
1029 {
1030 sampleFloat2D(texture, c, u, v, w, lod, face, secondLOD);
1031 }
1032 else
1033 {
1034 sampleFloat3D(texture, c, u, v, w, lod, secondLOD);
1035 }
1036 }
1037
John Bauman19bac1e2014-05-06 15:23:49 -04001038 void SamplerCore::sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &z, Float &lod, Int face[4], bool secondLOD)
John Bauman89401822014-05-06 15:04:28 -04001039 {
1040 int componentCount = textureComponentCount();
1041 bool gather = state.textureFilter == FILTER_GATHER;
1042
1043 Pointer<Byte> mipmap;
1044 Pointer<Byte> buffer[4];
1045
1046 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1047
1048 Short4 uuuu;
1049 Short4 vvvv;
1050
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001051 address(uuuu, u, state.addressingModeU);
1052 address(vvvv, v, state.addressingModeV);
John Bauman89401822014-05-06 15:04:28 -04001053
1054 if(state.textureFilter == FILTER_POINT)
1055 {
1056 sampleTexel(c, uuuu, vvvv, vvvv, z, mipmap, buffer);
1057 }
1058 else
1059 {
John Bauman19bac1e2014-05-06 15:23:49 -04001060 Vector4f c0;
1061 Vector4f c1;
1062 Vector4f c2;
1063 Vector4f c3;
John Bauman89401822014-05-06 15:04:28 -04001064
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001065 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1);
1066 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1);
1067 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1);
1068 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1);
John Bauman89401822014-05-06 15:04:28 -04001069
1070 sampleTexel(c0, uuuu0, vvvv0, vvvv0, z, mipmap, buffer);
1071 sampleTexel(c1, uuuu1, vvvv0, vvvv0, z, mipmap, buffer);
1072 sampleTexel(c2, uuuu0, vvvv1, vvvv1, z, mipmap, buffer);
1073 sampleTexel(c3, uuuu1, vvvv1, vvvv1, z, mipmap, buffer);
1074
1075 if(!gather) // Blend
1076 {
1077 // Fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001078 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth)));
1079 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight)));
John Bauman89401822014-05-06 15:04:28 -04001080
John Bauman19bac1e2014-05-06 15:23:49 -04001081 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1082 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1083 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1084 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001085
John Bauman19bac1e2014-05-06 15:23:49 -04001086 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1087 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1088 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1089 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001090
John Bauman19bac1e2014-05-06 15:23:49 -04001091 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x);
1092 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y);
1093 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z);
1094 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001095 }
1096 else
1097 {
John Bauman19bac1e2014-05-06 15:23:49 -04001098 c.x = c1.x;
1099 c.y = c2.x;
1100 c.z = c3.x;
1101 c.w = c0.x;
John Bauman89401822014-05-06 15:04:28 -04001102 }
1103 }
1104 }
1105
John Bauman19bac1e2014-05-06 15:23:49 -04001106 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 -04001107 {
1108 int componentCount = textureComponentCount();
1109
1110 Pointer<Byte> mipmap;
1111 Pointer<Byte> buffer[4];
1112 Int face[4];
1113
1114 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD);
1115
1116 Short4 uuuu;
1117 Short4 vvvv;
1118 Short4 wwww;
1119
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001120 address(uuuu, u, state.addressingModeU);
1121 address(vvvv, v, state.addressingModeV);
1122 address(wwww, w, state.addressingModeW);
John Bauman89401822014-05-06 15:04:28 -04001123
1124 if(state.textureFilter <= FILTER_POINT)
1125 {
1126 sampleTexel(c, uuuu, vvvv, wwww, w, mipmap, buffer);
1127 }
1128 else
1129 {
John Bauman19bac1e2014-05-06 15:23:49 -04001130 Vector4f &c0 = c;
1131 Vector4f c1;
1132 Vector4f c2;
1133 Vector4f c3;
1134 Vector4f c4;
1135 Vector4f c5;
1136 Vector4f c6;
1137 Vector4f c7;
John Bauman89401822014-05-06 15:04:28 -04001138
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001139 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, -1);
1140 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, -1);
1141 Short4 wwww0 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, -1);
1142 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, +1);
1143 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, +1);
1144 Short4 wwww1 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, +1);
John Bauman89401822014-05-06 15:04:28 -04001145
1146 sampleTexel(c0, uuuu0, vvvv0, wwww0, w, mipmap, buffer);
1147 sampleTexel(c1, uuuu1, vvvv0, wwww0, w, mipmap, buffer);
1148 sampleTexel(c2, uuuu0, vvvv1, wwww0, w, mipmap, buffer);
1149 sampleTexel(c3, uuuu1, vvvv1, wwww0, w, mipmap, buffer);
1150 sampleTexel(c4, uuuu0, vvvv0, wwww1, w, mipmap, buffer);
1151 sampleTexel(c5, uuuu1, vvvv0, wwww1, w, mipmap, buffer);
1152 sampleTexel(c6, uuuu0, vvvv1, wwww1, w, mipmap, buffer);
1153 sampleTexel(c7, uuuu1, vvvv1, wwww1, w, mipmap, buffer);
1154
1155 // Fractions
John Bauman19bac1e2014-05-06 15:23:49 -04001156 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth)));
1157 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight)));
1158 Float4 fw = Frac(Float4(As<UShort4>(wwww0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fDepth)));
John Bauman89401822014-05-06 15:04:28 -04001159
1160 // Blend first slice
John Bauman19bac1e2014-05-06 15:23:49 -04001161 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x);
1162 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y);
1163 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z);
1164 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001165
John Bauman19bac1e2014-05-06 15:23:49 -04001166 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x);
1167 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y);
1168 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z);
1169 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w);
John Bauman89401822014-05-06 15:04:28 -04001170
John Bauman19bac1e2014-05-06 15:23:49 -04001171 if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x);
1172 if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y);
1173 if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z);
1174 if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001175
1176 // Blend second slice
John Bauman19bac1e2014-05-06 15:23:49 -04001177 if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x);
1178 if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y);
1179 if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z);
1180 if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001181
John Bauman19bac1e2014-05-06 15:23:49 -04001182 if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x);
1183 if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y);
1184 if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z);
1185 if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w);
John Bauman89401822014-05-06 15:04:28 -04001186
John Bauman19bac1e2014-05-06 15:23:49 -04001187 if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x);
1188 if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y);
1189 if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z);
1190 if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w);
John Bauman89401822014-05-06 15:04:28 -04001191
1192 // Blend slices
John Bauman19bac1e2014-05-06 15:23:49 -04001193 if(componentCount >= 1) c0.x = c0.x + fw * (c4.x - c0.x);
1194 if(componentCount >= 2) c0.y = c0.y + fw * (c4.y - c0.y);
1195 if(componentCount >= 3) c0.z = c0.z + fw * (c4.z - c0.z);
1196 if(componentCount >= 4) c0.w = c0.w + fw * (c4.w - c0.w);
John Bauman89401822014-05-06 15:04:28 -04001197 }
1198 }
1199
John Bauman66b8ab22014-05-06 15:57:45 -04001200 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, bool bias, bool gradients, bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -04001201 {
1202 if(!lodProvided)
1203 {
1204 Float4 duvdxy;
1205
1206 if(!gradients)
1207 {
1208 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
1209 }
1210 else
1211 {
1212 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
1213 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
1214
1215 duvdxy = Float4(dudxy.xz, dvdxy.xz);
1216 }
1217
1218 // Scale by texture dimensions and LOD
1219 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
1220
1221 Float4 dUV2dxy = dUVdxy * dUVdxy;
1222 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
1223
1224 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis
1225
1226 if(state.textureFilter == FILTER_ANISOTROPIC)
1227 {
1228 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
1229
1230 Float4 dudx = duvdxy.xxxx;
1231 Float4 dudy = duvdxy.yyyy;
1232 Float4 dvdx = duvdxy.zzzz;
1233 Float4 dvdy = duvdxy.wwww;
1234
1235 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
1236 uDelta = As<Float4>(As<Int4>(dudx) & mask | As<Int4>(dudy) & ~mask);
1237 vDelta = As<Float4>(As<Int4>(dvdx) & mask | As<Int4>(dvdy) & ~mask);
1238
1239 anisotropy = lod * Rcp_pp(det);
1240 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
1241
1242 lod *= Rcp_pp(anisotropy * anisotropy);
1243 }
1244
1245 // log2(sqrt(lod))
1246 lod = Float(As<Int>(lod));
1247 lod -= Float(0x3F800000);
1248 lod *= As<Float>(Int(0x33800000));
1249
1250 if(bias)
1251 {
1252 lod += lodBias;
1253 }
1254
1255 // FIXME: Hack to satisfy WHQL
1256 if(state.textureType == TEXTURE_CUBE)
1257 {
1258 lod += Float(-0.15f);
1259 }
1260 }
1261 else
1262 {
1263 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD));
1264 }
1265
John Bauman66b8ab22014-05-06 15:57:45 -04001266 lod = Max(lod, 0.0f);
John Bauman89401822014-05-06 15:04:28 -04001267 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1
1268 }
1269
John Bauman66b8ab22014-05-06 15:57:45 -04001270 void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided)
John Bauman89401822014-05-06 15:04:28 -04001271 {
1272 if(state.mipmapFilter == MIPMAP_NONE)
1273 {
1274 }
1275 else // Point and linear filter
1276 {
1277 if(!lodProvided)
1278 {
1279 Float4 dudxy;
1280 Float4 dvdxy;
1281 Float4 dsdxy;
1282
1283 if(!gradients)
1284 {
1285 dudxy = uuuu.ywyw - uuuu;
1286 dvdxy = vvvv.ywyw - vvvv;
1287 dsdxy = wwww.ywyw - wwww;
1288 }
1289 else
1290 {
1291 dudxy = dsx.x;
1292 dvdxy = dsx.y;
1293 dsdxy = dsx.z;
1294
1295 dudxy = Float4(dudxy.xx, dsy.x.xx);
1296 dvdxy = Float4(dvdxy.xx, dsy.y.xx);
1297 dsdxy = Float4(dsdxy.xx, dsy.z.xx);
1298
1299 dudxy = Float4(dudxy.xz, dudxy.xz);
1300 dvdxy = Float4(dvdxy.xz, dvdxy.xz);
1301 dsdxy = Float4(dsdxy.xz, dsdxy.xz);
1302 }
1303
1304 // Scale by texture dimensions and LOD
1305 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
1306 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
1307 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
1308
1309 dudxy *= dudxy;
1310 dvdxy *= dvdxy;
1311 dsdxy *= dsdxy;
1312
1313 dudxy += dvdxy;
1314 dudxy += dsdxy;
1315
1316 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y);
1317
1318 // log2(sqrt(lod))
1319 lod = Float(As<Int>(lod));
1320 lod -= Float(0x3F800000);
1321 lod *= As<Float>(Int(0x33800000));
1322
1323 if(bias)
1324 {
1325 lod += lodBias;
1326 }
1327 }
1328 else
1329 {
1330 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD));
1331 }
1332
1333 lod = Max(lod, Float(0.0f)); // FIXME
1334 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1
1335 }
1336 }
1337
1338 void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodU, Float4 &lodV, Float4 &x, Float4 &y, Float4 &z)
1339 {
John Bauman19bac1e2014-05-06 15:23:49 -04001340 Int4 xp = CmpNLE(x, Float4(0.0f)); // x > 0
1341 Int4 yp = CmpNLE(y, Float4(0.0f)); // y > 0
1342 Int4 zp = CmpNLE(z, Float4(0.0f)); // z > 0
John Bauman89401822014-05-06 15:04:28 -04001343
1344 Float4 absX = Abs(x);
1345 Float4 absY = Abs(y);
1346 Float4 absZ = Abs(z);
1347 Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y)
1348 Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z)
1349 Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x)
1350
1351 Int4 xyz = ~zx & xy; // abs(x) > abs(y) && abs(x) > abs(z)
1352 Int4 yzx = ~xy & yz; // abs(y) > abs(z) && abs(y) > abs(x)
1353 Int4 zxy = ~yz & zx; // abs(z) > abs(x) && abs(z) > abs(y)
1354
1355 // FACE_POSITIVE_X = 000b
1356 // FACE_NEGATIVE_X = 001b
1357 // FACE_POSITIVE_Y = 010b
1358 // FACE_NEGATIVE_Y = 011b
1359 // FACE_POSITIVE_Z = 100b
1360 // FACE_NEGATIVE_Z = 101b
1361
1362 Int yAxis = SignMask(yzx);
1363 Int zAxis = SignMask(zxy);
1364
1365 Int4 n = (~xp & xyz) | (~yp & yzx) | (~zp & zxy);
1366 Int negative = SignMask(n);
1367
1368 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4);
1369 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4);
1370 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4);
1371 face[1] = (face[0] >> 4) & 0x7;
1372 face[2] = (face[0] >> 8) & 0x7;
1373 face[3] = (face[0] >> 12) & 0x7;
1374 face[0] &= 0x7;
1375
1376 // U = xyz * -z + ~xyz * (yzx * ~yp * -x + (yzx * ~yp) * x)
1377 U = As<Float4>((xyz & As<Int4>(-z)) | (~xyz & (((yzx & ~yp) & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(x))));
1378
1379 // V = yzx * z + ~yzx * (~neg * -y + neg * y)
1380 V = As<Float4>((~yzx & ((~n & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(y))) | (yzx & As<Int4>(z)));
1381
1382 // M = xyz * x + yzx * y + zxy * z
1383 Float4 M = As<Float4>((xyz & As<Int4>(x)) | (yzx & As<Int4>(y)) | (zxy & As<Int4>(z)));
1384
1385 M = reciprocal(M);
John Bauman19bac1e2014-05-06 15:23:49 -04001386 U *= M * Float4(0.5f);
1387 V *= M * Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -04001388
1389 // Project coordinates onto one face for consistent LOD calculation
1390 {
1391 yp = Swizzle(yp, 0);
1392 n = Swizzle(n, 0);
1393 xyz = Swizzle(xyz, 0);
1394 yzx = Swizzle(yzx, 0);
1395 zxy = Swizzle(zxy, 0);
1396
1397 // U = xyz * -z + ~xyz * (yzx * ~yp * -x + (yzx * ~yp) * x)
1398 lodU = As<Float4>((xyz & As<Int4>(-z)) | (~xyz & (((yzx & ~yp) & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(x))));
1399
1400 // V = yzx * z + ~yzx * (~neg * -y + neg * y)
1401 lodV = As<Float4>((~yzx & ((~n & Int4(0x80000000, 0x80000000, 0x80000000, 0x80000000)) ^ As<Int4>(y))) | (yzx & As<Int4>(z)));
1402
1403 // M = xyz * x + yzx * y + zxy * z
1404 Float4 M = As<Float4>((xyz & As<Int4>(x)) | (yzx & As<Int4>(y)) | (zxy & As<Int4>(z)));
1405
1406 M = Rcp_pp(M);
John Bauman19bac1e2014-05-06 15:23:49 -04001407 lodU *= M * Float4(0.5f);
1408 lodV *= M * Float4(0.5f);
John Bauman89401822014-05-06 15:04:28 -04001409 }
1410 }
1411
1412 void SamplerCore::computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap)
1413 {
1414 Short4 uuu2;
1415
1416 if(!state.hasNPOTTexture && !hasFloatTexture())
1417 {
1418 vvvv = As<UShort4>(vvvv) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,vFrac));
1419 uuu2 = uuuu;
1420 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1421 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1422 uuuu = As<Short4>(As<UInt2>(uuuu) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,uFrac)));
1423 uuu2 = As<Short4>(As<UInt2>(uuu2) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,uFrac)));
1424
1425 if(state.textureType == TEXTURE_3D)
1426 {
1427 wwww = As<UShort4>(wwww) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,wFrac));
1428 Short4 www2 = wwww;
1429 wwww = As<Short4>(UnpackLow(wwww, wwww));
1430 www2 = As<Short4>(UnpackHigh(www2, www2));
1431 wwww = As<Short4>(As<UInt2>(wwww) >> 16);
1432 www2 = As<Short4>(As<UInt2>(www2) >> 16);
1433 wwww = As<Short4>(As<Int2>(wwww) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt)));
1434 www2 = As<Short4>(As<Int2>(www2) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt)));
1435 wwww = As<Short4>(As<Int2>(wwww) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt))); // FIXME: Combine uInt and vInt shift
1436 www2 = As<Short4>(As<Int2>(www2) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt)));
1437 uuuu = As<Short4>(As<Int2>(uuuu) + As<Int2>(wwww));
1438 uuu2 = As<Short4>(As<Int2>(uuu2) + As<Int2>(www2));
1439 }
1440 }
1441 else
1442 {
1443 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width)));
1444 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height)));
1445 uuu2 = uuuu;
1446 uuuu = As<Short4>(UnpackLow(uuuu, vvvv));
1447 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv));
1448 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1449 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP))));
1450
1451 if(state.textureType == TEXTURE_3D)
1452 {
1453 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth)));
1454 Short4 www2 = wwww;
1455 wwww = As<Short4>(UnpackLow(wwww, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
1456 www2 = As<Short4>(UnpackHigh(www2, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
1457 wwww = As<Short4>(MulAdd(wwww, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP))));
1458 www2 = As<Short4>(MulAdd(www2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP))));
1459 uuuu = As<Short4>(As<Int2>(uuuu) + As<Int2>(wwww));
1460 uuu2 = As<Short4>(As<Int2>(uuu2) + As<Int2>(www2));
1461 }
1462 }
1463
1464 index[0] = Extract(As<Int2>(uuuu), 0);
1465 index[1] = Extract(As<Int2>(uuuu), 1);
1466 index[2] = Extract(As<Int2>(uuu2), 0);
1467 index[3] = Extract(As<Int2>(uuu2), 1);
1468 }
1469
John Bauman19bac1e2014-05-06 15:23:49 -04001470 void SamplerCore::sampleTexel(Vector4i &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4])
John Bauman89401822014-05-06 15:04:28 -04001471 {
1472 Int index[4];
1473
1474 computeIndices(index, uuuu, vvvv, wwww, mipmap);
1475
1476 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1477 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1478 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1479 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1480
1481 if(!has16bitTexture())
1482 {
1483 Int c0;
1484 Int c1;
1485 Int c2;
1486 Int c3;
1487
1488 switch(textureComponentCount())
1489 {
1490 case 4:
1491 {
1492 Byte8 c0 = *Pointer<Byte8>(buffer[f0] + 4 * index[0]);
1493 Byte8 c1 = *Pointer<Byte8>(buffer[f1] + 4 * index[1]);
1494 Byte8 c2 = *Pointer<Byte8>(buffer[f2] + 4 * index[2]);
1495 Byte8 c3 = *Pointer<Byte8>(buffer[f3] + 4 * index[3]);
John Bauman19bac1e2014-05-06 15:23:49 -04001496 c.x = UnpackLow(c0, c1);
1497 c.y = UnpackLow(c2, c3);
John Bauman89401822014-05-06 15:04:28 -04001498
1499 switch(state.textureFormat)
1500 {
1501 case FORMAT_A8R8G8B8:
John Bauman19bac1e2014-05-06 15:23:49 -04001502 c.z = c.x;
1503 c.z = As<Short4>(UnpackLow(c.z, c.y));
1504 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1505 c.y = c.z;
1506 c.w = c.x;
1507 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1508 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1509 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1510 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
John Bauman89401822014-05-06 15:04:28 -04001511 break;
1512 case FORMAT_Q8W8V8U8:
John Bauman19bac1e2014-05-06 15:23:49 -04001513 c.z = c.x;
1514 c.x = As<Short4>(UnpackLow(c.x, c.y));
1515 c.z = As<Short4>(UnpackHigh(c.z, c.y));
1516 c.y = c.x;
1517 c.w = c.z;
1518 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
1519 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1520 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1521 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w));
John Bauman89401822014-05-06 15:04:28 -04001522 break;
1523 default:
1524 ASSERT(false);
1525 }
1526 }
1527 break;
1528 case 3:
1529 {
1530 Byte8 c0 = *Pointer<Byte8>(buffer[f0] + 4 * index[0]);
1531 Byte8 c1 = *Pointer<Byte8>(buffer[f1] + 4 * index[1]);
1532 Byte8 c2 = *Pointer<Byte8>(buffer[f2] + 4 * index[2]);
1533 Byte8 c3 = *Pointer<Byte8>(buffer[f3] + 4 * index[3]);
John Bauman19bac1e2014-05-06 15:23:49 -04001534 c.x = UnpackLow(c0, c1);
1535 c.y = UnpackLow(c2, c3);
John Bauman89401822014-05-06 15:04:28 -04001536
1537 switch(state.textureFormat)
1538 {
1539 case FORMAT_X8R8G8B8:
John Bauman19bac1e2014-05-06 15:23:49 -04001540 c.z = c.x;
1541 c.z = As<Short4>(UnpackLow(c.z, c.y));
1542 c.x = As<Short4>(UnpackHigh(c.x, c.y));
1543 c.y = c.z;
1544 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
1545 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y));
1546 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x));
John Bauman89401822014-05-06 15:04:28 -04001547 break;
1548 case FORMAT_X8L8V8U8:
John Bauman19bac1e2014-05-06 15:23:49 -04001549 c.z = c.x;
1550 c.x = As<Short4>(UnpackLow(c.x, c.y));
1551 c.z = As<Short4>(UnpackHigh(c.z, c.y));
1552 c.y = c.x;
1553 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(Short4(0x0000, 0x0000, 0x0000, 0x0000)));
1554 c.x = c.x << 8;
1555 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(Short4(0x0000, 0x0000, 0x0000, 0x0000)));
1556 c.y = c.y << 8;
1557 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z));
John Bauman89401822014-05-06 15:04:28 -04001558 break;
1559 default:
1560 ASSERT(false);
1561 }
1562 }
1563 break;
1564 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -04001565 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0);
1566 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1);
1567 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2);
1568 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3);
John Bauman89401822014-05-06 15:04:28 -04001569
1570 switch(state.textureFormat)
1571 {
1572 case FORMAT_G8R8:
1573 case FORMAT_V8U8:
1574 case FORMAT_A8L8:
Nicolas Capens6e48fc82014-05-06 16:45:31 -04001575 c.y = (c.x & Short4(0xFF00, 0xFF00, 0xFF00, 0xFF00)) | As<Short4>(As<UShort4>(c.x) >> 8);
1576 c.x = (c.x & Short4(0x00FF, 0x00FF, 0x00FF, 0x00FF)) | (c.x << 8);
John Bauman89401822014-05-06 15:04:28 -04001577 break;
1578 default:
1579 ASSERT(false);
1580 }
1581 break;
1582 case 1:
1583 c0 = Int(*Pointer<Byte>(buffer[f0] + index[0]));
1584 c1 = Int(*Pointer<Byte>(buffer[f1] + index[1]));
1585 c2 = Int(*Pointer<Byte>(buffer[f2] + index[2]));
1586 c3 = Int(*Pointer<Byte>(buffer[f3] + index[3]));
1587 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
John Bauman19bac1e2014-05-06 15:23:49 -04001588 c.x = Unpack(As<Byte4>(c0));
John Bauman89401822014-05-06 15:04:28 -04001589 break;
1590 default:
1591 ASSERT(false);
1592 }
1593 }
1594 else
1595 {
1596 switch(textureComponentCount())
1597 {
1598 case 4:
John Bauman19bac1e2014-05-06 15:23:49 -04001599 c.x = *Pointer<Short4>(buffer[f0] + 8 * index[0]);
1600 c.y = *Pointer<Short4>(buffer[f1] + 8 * index[1]);
1601 c.z = *Pointer<Short4>(buffer[f2] + 8 * index[2]);
1602 c.w = *Pointer<Short4>(buffer[f3] + 8 * index[3]);
1603 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman89401822014-05-06 15:04:28 -04001604 break;
1605 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -04001606 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]);
1607 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1])));
1608 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]);
1609 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3])));
1610 c.y = c.x;
1611 c.x = As<Short4>(UnpackLow(As<Int2>(c.x), As<Int2>(c.z)));
1612 c.y = As<Short4>(UnpackHigh(As<Int2>(c.y), As<Int2>(c.z)));
John Bauman89401822014-05-06 15:04:28 -04001613 break;
1614 case 1:
John Bauman19bac1e2014-05-06 15:23:49 -04001615 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0);
1616 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1);
1617 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2);
1618 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3);
John Bauman89401822014-05-06 15:04:28 -04001619 break;
1620 default:
1621 ASSERT(false);
1622 }
1623 }
1624 }
1625
John Bauman19bac1e2014-05-06 15:23:49 -04001626 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 -04001627 {
1628 Int index[4];
1629
1630 computeIndices(index, uuuu, vvvv, wwww, mipmap);
1631
1632 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0;
1633 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0;
1634 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0;
1635 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0;
1636
1637 // Read texels
1638 switch(textureComponentCount())
1639 {
1640 case 4:
John Bauman19bac1e2014-05-06 15:23:49 -04001641 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16);
1642 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16);
1643 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16);
1644 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16);
1645 transpose4x4(c.x, c.y, c.z, c.w);
John Bauman89401822014-05-06 15:04:28 -04001646 break;
1647 case 2:
1648 // FIXME: Optimal shuffling?
John Bauman19bac1e2014-05-06 15:23:49 -04001649 c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8);
1650 c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8);
1651 c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8);
1652 c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8);
1653 c.y = c.x;
1654 c.x = Float4(c.x.xz, c.z.xz);
1655 c.y = Float4(c.y.yw, c.z.yw);
John Bauman89401822014-05-06 15:04:28 -04001656 break;
1657 case 1:
1658 // FIXME: Optimal shuffling?
John Bauman19bac1e2014-05-06 15:23:49 -04001659 c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4);
1660 c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4);
1661 c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4);
1662 c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4);
John Bauman89401822014-05-06 15:04:28 -04001663
John Bauman66b8ab22014-05-06 15:57:45 -04001664 if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER)
John Bauman89401822014-05-06 15:04:28 -04001665 {
1666 Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f));
1667
John Bauman19bac1e2014-05-06 15:23:49 -04001668 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 -04001669 }
1670 break;
1671 default:
1672 ASSERT(false);
1673 }
1674 }
1675
1676 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD)
1677 {
1678 if(state.mipmapFilter < MIPMAP_POINT)
1679 {
1680 mipmap = texture + OFFSET(Texture,mipmap[0]);
1681 }
1682 else
1683 {
1684 Int ilod;
1685
1686 if(state.mipmapFilter == MIPMAP_POINT)
1687 {
1688 ilod = RoundInt(lod);
1689 }
1690 else // Linear
1691 {
1692 ilod = Int(lod);
1693 }
1694
1695 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap);
1696 }
1697
1698 if(state.textureType != TEXTURE_CUBE)
1699 {
John Bauman66b8ab22014-05-06 15:57:45 -04001700 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0]));
John Bauman89401822014-05-06 15:04:28 -04001701 }
1702 else
1703 {
1704 for(int i = 0; i < 4; i++)
1705 {
John Bauman66b8ab22014-05-06 15:57:45 -04001706 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -04001707 }
1708 }
1709 }
1710
1711 void SamplerCore::address(Short4 &uuuu, Float4 &uw, AddressingMode addressingMode)
1712 {
1713 if(addressingMode == ADDRESSING_CLAMP)
1714 {
1715 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f));
1716
1717 uuuu = Short4(Int4(clamp * Float4(1 << 16)));
1718 }
1719 else if(addressingMode == ADDRESSING_MIRROR)
1720 {
1721 Int4 convert = Int4(uw * Float4(1 << 16));
1722 Int4 mirror = (convert << 15) >> 31;
1723
1724 convert ^= mirror;
1725
1726 uuuu = Short4(convert);
1727 }
1728 else if(addressingMode == ADDRESSING_MIRRORONCE)
1729 {
1730 // Absolute value
1731 Int4 convert = Int4(Abs(uw * Float4(1 << 16)));
1732
1733 // Clamp
1734 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000);
1735 convert = As<Int4>(Pack(convert, convert));
1736
1737 uuuu = As<Short4>(Int2(convert)) + Short4((short)0x8000, (short)0x8000, (short)0x8000, (short)0x8000);
1738 }
1739 else // Wrap (or border)
1740 {
1741 uuuu = Short4(Int4(uw * Float4(1 << 16)));
1742 }
1743 }
1744
1745 void SamplerCore::convertFixed12(Short4 &ci, Float4 &cf)
1746 {
John Bauman19bac1e2014-05-06 15:23:49 -04001747 ci = RoundShort4(cf * Float4(0x1000));
John Bauman89401822014-05-06 15:04:28 -04001748 }
1749
John Bauman19bac1e2014-05-06 15:23:49 -04001750 void SamplerCore::convertFixed12(Vector4i &ci, Vector4f &cf)
John Bauman89401822014-05-06 15:04:28 -04001751 {
John Bauman19bac1e2014-05-06 15:23:49 -04001752 convertFixed12(ci.x, cf.x);
1753 convertFixed12(ci.y, cf.y);
1754 convertFixed12(ci.z, cf.z);
1755 convertFixed12(ci.w, cf.w);
John Bauman89401822014-05-06 15:04:28 -04001756 }
1757
1758 void SamplerCore::convertSigned12(Float4 &cf, Short4 &ci)
1759 {
1760 cf = Float4(ci) * Float4(1.0f / 0x0FFE);
1761 }
1762
John Bauman19bac1e2014-05-06 15:23:49 -04001763// void SamplerCore::convertSigned12(Vector4f &cf, Vector4i &ci)
John Bauman89401822014-05-06 15:04:28 -04001764// {
John Bauman19bac1e2014-05-06 15:23:49 -04001765// convertSigned12(cf.x, ci.x);
1766// convertSigned12(cf.y, ci.y);
1767// convertSigned12(cf.z, ci.z);
1768// convertSigned12(cf.w, ci.w);
John Bauman89401822014-05-06 15:04:28 -04001769// }
1770
1771 void SamplerCore::convertSigned15(Float4 &cf, Short4 &ci)
1772 {
John Bauman19bac1e2014-05-06 15:23:49 -04001773 cf = Float4(ci) * Float4(1.0f / 0x7FFF);
John Bauman89401822014-05-06 15:04:28 -04001774 }
1775
1776 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &ci)
1777 {
John Bauman19bac1e2014-05-06 15:23:49 -04001778 cf = Float4(As<UShort4>(ci)) * Float4(1.0f / 0xFFFF);
John Bauman89401822014-05-06 15:04:28 -04001779 }
1780
1781 void SamplerCore::sRGBtoLinear16_12(Short4 &c)
1782 {
1783 c = As<UShort4>(c) >> 8;
1784
1785 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8));
1786
1787 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
1788 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
1789 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2);
1790 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3);
1791 }
1792
1793 bool SamplerCore::hasFloatTexture() const
1794 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001795 return Surface::isFloatFormat(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04001796 }
1797
1798 bool SamplerCore::hasUnsignedTextureComponent(int component) const
1799 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001800 return Surface::isUnsignedComponent(state.textureFormat, component);
John Bauman89401822014-05-06 15:04:28 -04001801 }
1802
1803 int SamplerCore::textureComponentCount() const
1804 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001805 return Surface::componentCount(state.textureFormat);
John Bauman89401822014-05-06 15:04:28 -04001806 }
1807
1808 bool SamplerCore::has16bitTexture() const
1809 {
1810 switch(state.textureFormat)
1811 {
1812 case FORMAT_G8R8:
1813 case FORMAT_X8R8G8B8:
1814 case FORMAT_A8R8G8B8:
1815 case FORMAT_V8U8:
1816 case FORMAT_Q8W8V8U8:
1817 case FORMAT_X8L8V8U8:
1818 case FORMAT_R32F:
1819 case FORMAT_G32R32F:
1820 case FORMAT_A32B32G32R32F:
1821 case FORMAT_A8:
1822 case FORMAT_R8:
1823 case FORMAT_L8:
1824 case FORMAT_A8L8:
1825 case FORMAT_D32F_LOCKABLE:
John Bauman66b8ab22014-05-06 15:57:45 -04001826 case FORMAT_D32FS8_TEXTURE:
1827 case FORMAT_D32FS8_SHADOW:
John Bauman89401822014-05-06 15:04:28 -04001828 return false;
1829 case FORMAT_L16:
1830 case FORMAT_G16R16:
1831 case FORMAT_A16B16G16R16:
1832 case FORMAT_V16U16:
1833 case FORMAT_A16W16V16U16:
1834 case FORMAT_Q16W16V16U16:
1835 return true;
1836 default:
1837 ASSERT(false);
1838 }
1839
1840 return false;
1841 }
1842
1843 bool SamplerCore::isRGBComponent(int component) const
1844 {
1845 switch(state.textureFormat)
1846 {
John Bauman66b8ab22014-05-06 15:57:45 -04001847 case FORMAT_G8R8: return component < 2;
1848 case FORMAT_X8R8G8B8: return component < 3;
1849 case FORMAT_A8R8G8B8: return component < 3;
1850 case FORMAT_V8U8: return false;
1851 case FORMAT_Q8W8V8U8: return false;
1852 case FORMAT_X8L8V8U8: return false;
1853 case FORMAT_R32F: return component < 1;
1854 case FORMAT_G32R32F: return component < 2;
1855 case FORMAT_A32B32G32R32F: return component < 3;
1856 case FORMAT_A8: return false;
1857 case FORMAT_R8: return component < 1;
1858 case FORMAT_L8: return component < 1;
1859 case FORMAT_A8L8: return component < 1;
1860 case FORMAT_D32F_LOCKABLE: return false;
1861 case FORMAT_D32FS8_TEXTURE: return false;
1862 case FORMAT_D32FS8_SHADOW: return false;
1863 case FORMAT_L16: return component < 1;
1864 case FORMAT_G16R16: return component < 2;
1865 case FORMAT_A16B16G16R16: return component < 3;
1866 case FORMAT_V16U16: return false;
1867 case FORMAT_A16W16V16U16: return false;
1868 case FORMAT_Q16W16V16U16: return false;
John Bauman89401822014-05-06 15:04:28 -04001869 default:
1870 ASSERT(false);
1871 }
1872
1873 return false;
1874 }
1875}