John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1 | // SwiftShader Software Renderer |
| 2 | // |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 3 | // Copyright(c) 2005-2013 TransGaming Inc. |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 4 | // |
| 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 | |
| 17 | namespace sw |
| 18 | { |
| 19 | SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state) |
| 20 | { |
| 21 | } |
| 22 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 23 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 24 | { |
| 25 | #if PERF_PROFILE |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 26 | AddAtomic(Pointer<Long>(&profiler.texOperations), 4); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 27 | |
| 28 | if(state.compressedFormat) |
| 29 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 30 | AddAtomic(Pointer<Long>(&profiler.compressedTex), 4); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 31 | } |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 43 | c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000); |
| 44 | c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000); |
| 45 | c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 46 | |
| 47 | if(fixed12) // FIXME: Convert to fixed12 at higher level, when required |
| 48 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 49 | c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 50 | } |
| 51 | else |
| 52 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 53 | c.w = Short4((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); // FIXME |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 54 | } |
| 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 Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 76 | computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, bias, gradients, lodProvided); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 77 | } |
| 78 | else |
| 79 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 80 | computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, bias, gradients, lodProvided); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 81 | } |
| 82 | } |
| 83 | else |
| 84 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 85 | computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, bias, gradients, lodProvided); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | if(cubeTexture) |
| 89 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 90 | uuuu += Float4(0.5f); |
| 91 | vvvv += Float4(0.5f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | if(!hasFloatTexture()) |
| 95 | { |
| 96 | sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided); |
| 97 | } |
| 98 | else |
| 99 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 100 | Vector4f cf; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 101 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 147 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 150 | break; |
| 151 | case FORMAT_A8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 152 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 156 | break; |
| 157 | case FORMAT_L8: |
| 158 | case FORMAT_L16: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 159 | c.y = c.x; |
| 160 | c.z = c.x; |
| 161 | c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 162 | break; |
| 163 | case FORMAT_A8L8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 164 | c.w = c.y; |
| 165 | c.y = c.x; |
| 166 | c.z = c.x; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 167 | break; |
| 168 | case FORMAT_R32F: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 169 | c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 170 | case FORMAT_G32R32F: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 171 | c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000); |
| 172 | c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 173 | case FORMAT_A32B32G32R32F: |
| 174 | break; |
| 175 | case FORMAT_D32F_LOCKABLE: |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 176 | case FORMAT_D32FS8_TEXTURE: |
| 177 | case FORMAT_D32FS8_SHADOW: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 178 | c.y = c.x; |
| 179 | c.z = c.x; |
| 180 | c.w = c.x; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 181 | break; |
| 182 | default: |
| 183 | ASSERT(false); |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 189 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 190 | { |
| 191 | #if PERF_PROFILE |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 192 | AddAtomic(Pointer<Long>(&profiler.texOperations), 4); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 193 | |
| 194 | if(state.compressedFormat) |
| 195 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 196 | AddAtomic(Pointer<Long>(&profiler.compressedTex), 4); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 197 | } |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 205 | c.x = Float4(0.0f); |
| 206 | c.y = Float4(0.0f); |
| 207 | c.z = Float4(0.0f); |
| 208 | c.w = Float4(1.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 209 | } |
| 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 Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 236 | computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, bias, gradients, lodProvided); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 237 | } |
| 238 | else |
| 239 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 240 | computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, bias, gradients, lodProvided); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 241 | } |
| 242 | } |
| 243 | else |
| 244 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 245 | computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, bias, gradients, lodProvided); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | if(cubeTexture) |
| 249 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 250 | uuuu += Float4(0.5f); |
| 251 | vvvv += Float4(0.5f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided); |
| 255 | } |
| 256 | else |
| 257 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 258 | Vector4i ci; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 259 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 301 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 304 | break; |
| 305 | case FORMAT_A8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 306 | c.w = c.x; |
| 307 | c.x = Float4(0.0f); |
| 308 | c.y = Float4(0.0f); |
| 309 | c.z = Float4(0.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 310 | break; |
| 311 | case FORMAT_L8: |
| 312 | case FORMAT_L16: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 313 | c.y = c.x; |
| 314 | c.z = c.x; |
| 315 | c.w = Float4(1.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 316 | break; |
| 317 | case FORMAT_A8L8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 318 | c.w = c.y; |
| 319 | c.y = c.x; |
| 320 | c.z = c.x; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 321 | break; |
| 322 | case FORMAT_R32F: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 323 | c.y = Float4(1.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 324 | case FORMAT_G32R32F: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 325 | c.z = Float4(1.0f); |
| 326 | c.w = Float4(1.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 327 | case FORMAT_A32B32G32R32F: |
| 328 | break; |
| 329 | case FORMAT_D32F_LOCKABLE: |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 330 | case FORMAT_D32FS8_TEXTURE: |
| 331 | case FORMAT_D32FS8_SHADOW: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 332 | c.y = c.x; |
| 333 | c.z = c.x; |
| 334 | c.w = c.x; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 335 | 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 380 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 381 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 388 | Vector4i cc; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 389 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 397 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 401 | |
| 402 | utri = ~utri; |
| 403 | stri = Short4(0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF) - stri; |
| 404 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 405 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 409 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 410 | c.x += cc.x; |
| 411 | c.y += cc.y; |
| 412 | c.z += cc.z; |
| 413 | c.w += cc.w; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 414 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 415 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 419 | } |
| 420 | |
| 421 | Short4 borderMask; |
| 422 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 423 | if(state.addressingModeU == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 424 | { |
| 425 | Short4 u0; |
| 426 | |
| 427 | border(u0, u); |
| 428 | |
| 429 | borderMask = u0; |
| 430 | } |
| 431 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 432 | if(state.addressingModeV == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 433 | { |
| 434 | Short4 v0; |
| 435 | |
| 436 | border(v0, v); |
| 437 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 438 | if(state.addressingModeU == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 439 | { |
| 440 | borderMask &= v0; |
| 441 | } |
| 442 | else |
| 443 | { |
| 444 | borderMask = v0; |
| 445 | } |
| 446 | } |
| 447 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 448 | if(state.addressingModeW == ADDRESSING_BORDER && volumeTexture) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 449 | { |
| 450 | Short4 s0; |
| 451 | |
| 452 | border(s0, w); |
| 453 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 454 | if(state.addressingModeU == ADDRESSING_BORDER || |
| 455 | state.addressingModeV == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 456 | { |
| 457 | borderMask &= s0; |
| 458 | } |
| 459 | else |
| 460 | { |
| 461 | borderMask = s0; |
| 462 | } |
| 463 | } |
| 464 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 465 | if(state.addressingModeU == ADDRESSING_BORDER || |
| 466 | state.addressingModeV == ADDRESSING_BORDER || |
| 467 | (state.addressingModeW == ADDRESSING_BORDER && volumeTexture)) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 468 | { |
| 469 | Short4 b; |
| 470 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 471 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 475 | } |
| 476 | } |
| 477 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 478 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 479 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 488 | Vector4i cSum; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 489 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 490 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 494 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 518 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 522 | |
| 523 | i++; |
| 524 | } |
| 525 | Until(i >= a) |
| 526 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 527 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 531 | } |
| 532 | } |
| 533 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 534 | void SamplerCore::sampleQuad(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 535 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 546 | void SamplerCore::sampleQuad2D(Pointer<Byte> &texture, Vector4i &c, Float4 &u, Float4 &v, Float &lod, Int face[4], bool secondLOD) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 547 | { |
| 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 Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 559 | address(uuuu, u, state.addressingModeU); |
| 560 | address(vvvv, v, state.addressingModeV); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 561 | |
| 562 | if(state.textureFilter == FILTER_POINT) |
| 563 | { |
| 564 | sampleTexel(c, uuuu, vvvv, vvvv, mipmap, buffer); |
| 565 | } |
| 566 | else |
| 567 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 568 | Vector4i c0; |
| 569 | Vector4i c1; |
| 570 | Vector4i c2; |
| 571 | Vector4i c3; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 572 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 573 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 577 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 627 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 630 | } |
| 631 | else |
| 632 | { |
| 633 | if(hasUnsignedTextureComponent(0)) |
| 634 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 635 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 639 | } |
| 640 | else |
| 641 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 642 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 646 | } |
| 647 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 648 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 650 | } |
| 651 | } |
| 652 | |
| 653 | if(componentCount >= 2) |
| 654 | { |
| 655 | if(has16bitTexture() && hasUnsignedTextureComponent(1)) |
| 656 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 657 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 660 | } |
| 661 | else |
| 662 | { |
| 663 | if(hasUnsignedTextureComponent(1)) |
| 664 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 665 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 669 | } |
| 670 | else |
| 671 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 672 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 676 | } |
| 677 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 678 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 680 | } |
| 681 | } |
| 682 | |
| 683 | if(componentCount >= 3) |
| 684 | { |
| 685 | if(has16bitTexture() && hasUnsignedTextureComponent(2)) |
| 686 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 687 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 690 | } |
| 691 | else |
| 692 | { |
| 693 | if(hasUnsignedTextureComponent(2)) |
| 694 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 695 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 699 | } |
| 700 | else |
| 701 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 702 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 706 | } |
| 707 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 708 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 710 | } |
| 711 | } |
| 712 | |
| 713 | if(componentCount >= 4) |
| 714 | { |
| 715 | if(has16bitTexture() && hasUnsignedTextureComponent(3)) |
| 716 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 717 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 720 | } |
| 721 | else |
| 722 | { |
| 723 | if(hasUnsignedTextureComponent(3)) |
| 724 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 725 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 729 | } |
| 730 | else |
| 731 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 732 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 736 | } |
| 737 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 738 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 740 | } |
| 741 | } |
| 742 | } |
| 743 | else |
| 744 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 745 | c.x = c1.x; |
| 746 | c.y = c2.x; |
| 747 | c.z = c3.x; |
| 748 | c.w = c0.x; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 749 | } |
| 750 | } |
| 751 | } |
| 752 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 753 | void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4i &c_, Float4 &u_, Float4 &v_, Float4 &w_, Float &lod, bool secondLOD) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 754 | { |
| 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 Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 767 | address(uuuu, u_, state.addressingModeU); |
| 768 | address(vvvv, v_, state.addressingModeV); |
| 769 | address(wwww, w_, state.addressingModeW); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 770 | |
| 771 | if(state.textureFilter <= FILTER_POINT) |
| 772 | { |
| 773 | sampleTexel(c_, uuuu, vvvv, wwww, mipmap, buffer); |
| 774 | } |
| 775 | else |
| 776 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 777 | Vector4i c[2][2][2]; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 778 | |
| 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 Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 789 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 792 | } |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 866 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 870 | |
| 871 | if(i != 0 || j != 0 || k != 0) |
| 872 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 873 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 877 | } |
| 878 | } |
| 879 | } |
| 880 | } |
| 881 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 882 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 886 | |
| 887 | // Correct for signed fractions |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 888 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 892 | } |
| 893 | } |
| 894 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 895 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 896 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 903 | Vector4f cc; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 904 | |
| 905 | sampleFloatAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, lodProvided); |
| 906 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 907 | Float4 lod4 = Float4(Frac(lod)); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 908 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 909 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 913 | } |
| 914 | |
| 915 | Int4 borderMask; |
| 916 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 917 | if(state.addressingModeU == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 918 | { |
| 919 | Int4 u0; |
| 920 | |
| 921 | border(u0, u); |
| 922 | |
| 923 | borderMask = u0; |
| 924 | } |
| 925 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 926 | if(state.addressingModeV == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 927 | { |
| 928 | Int4 v0; |
| 929 | |
| 930 | border(v0, v); |
| 931 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 932 | if(state.addressingModeU == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 933 | { |
| 934 | borderMask &= v0; |
| 935 | } |
| 936 | else |
| 937 | { |
| 938 | borderMask = v0; |
| 939 | } |
| 940 | } |
| 941 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 942 | if(state.addressingModeW == ADDRESSING_BORDER && volumeTexture) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 943 | { |
| 944 | Int4 s0; |
| 945 | |
| 946 | border(s0, w); |
| 947 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 948 | if(state.addressingModeU == ADDRESSING_BORDER || |
| 949 | state.addressingModeV == ADDRESSING_BORDER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 950 | { |
| 951 | borderMask &= s0; |
| 952 | } |
| 953 | else |
| 954 | { |
| 955 | borderMask = s0; |
| 956 | } |
| 957 | } |
| 958 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 959 | if(state.addressingModeU == ADDRESSING_BORDER || |
| 960 | state.addressingModeV == ADDRESSING_BORDER || |
| 961 | (state.addressingModeW == ADDRESSING_BORDER && volumeTexture)) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 962 | { |
| 963 | Int4 b; |
| 964 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 965 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 969 | } |
| 970 | } |
| 971 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 972 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 973 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 982 | Vector4f cSum; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 983 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 984 | cSum.x = Float4(0.0f); |
| 985 | cSum.y = Float4(0.0f); |
| 986 | cSum.z = Float4(0.0f); |
| 987 | cSum.w = Float4(0.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 988 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1010 | cSum.x += c.x * A; |
| 1011 | cSum.y += c.y * A; |
| 1012 | cSum.z += c.z * A; |
| 1013 | cSum.w += c.w * A; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1014 | |
| 1015 | i++; |
| 1016 | } |
| 1017 | Until(i >= a) |
| 1018 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1019 | c.x = cSum.x; |
| 1020 | c.y = cSum.y; |
| 1021 | c.z = cSum.z; |
| 1022 | c.w = cSum.w; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1023 | } |
| 1024 | } |
| 1025 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1026 | void SamplerCore::sampleFloat(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1027 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1038 | void SamplerCore::sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &z, Float &lod, Int face[4], bool secondLOD) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1039 | { |
| 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 Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1051 | address(uuuu, u, state.addressingModeU); |
| 1052 | address(vvvv, v, state.addressingModeV); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1053 | |
| 1054 | if(state.textureFilter == FILTER_POINT) |
| 1055 | { |
| 1056 | sampleTexel(c, uuuu, vvvv, vvvv, z, mipmap, buffer); |
| 1057 | } |
| 1058 | else |
| 1059 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1060 | Vector4f c0; |
| 1061 | Vector4f c1; |
| 1062 | Vector4f c2; |
| 1063 | Vector4f c3; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1064 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1065 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1069 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1078 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1080 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1081 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1085 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1086 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1090 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1091 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1095 | } |
| 1096 | else |
| 1097 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1098 | c.x = c1.x; |
| 1099 | c.y = c2.x; |
| 1100 | c.z = c3.x; |
| 1101 | c.w = c0.x; |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1102 | } |
| 1103 | } |
| 1104 | } |
| 1105 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1106 | void SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1107 | { |
| 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 Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1120 | address(uuuu, u, state.addressingModeU); |
| 1121 | address(vvvv, v, state.addressingModeV); |
| 1122 | address(wwww, w, state.addressingModeW); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1123 | |
| 1124 | if(state.textureFilter <= FILTER_POINT) |
| 1125 | { |
| 1126 | sampleTexel(c, uuuu, vvvv, wwww, w, mipmap, buffer); |
| 1127 | } |
| 1128 | else |
| 1129 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1130 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1138 | |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1139 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1145 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1156 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1159 | |
| 1160 | // Blend first slice |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1161 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1165 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1166 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1170 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1171 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1175 | |
| 1176 | // Blend second slice |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1177 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1181 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1182 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1186 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1187 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1191 | |
| 1192 | // Blend slices |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1193 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1197 | } |
| 1198 | } |
| 1199 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1200 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1201 | { |
| 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 Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1266 | lod = Max(lod, 0.0f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1267 | lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1 |
| 1268 | } |
| 1269 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1270 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1271 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1340 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1343 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1386 | U *= M * Float4(0.5f); |
| 1387 | V *= M * Float4(0.5f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1388 | |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1407 | lodU *= M * Float4(0.5f); |
| 1408 | lodV *= M * Float4(0.5f); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1409 | } |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1470 | void SamplerCore::sampleTexel(Vector4i &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1471 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1496 | c.x = UnpackLow(c0, c1); |
| 1497 | c.y = UnpackLow(c2, c3); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1498 | |
| 1499 | switch(state.textureFormat) |
| 1500 | { |
| 1501 | case FORMAT_A8R8G8B8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1502 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1511 | break; |
| 1512 | case FORMAT_Q8W8V8U8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1513 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1522 | 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1534 | c.x = UnpackLow(c0, c1); |
| 1535 | c.y = UnpackLow(c2, c3); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1536 | |
| 1537 | switch(state.textureFormat) |
| 1538 | { |
| 1539 | case FORMAT_X8R8G8B8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1540 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1547 | break; |
| 1548 | case FORMAT_X8L8V8U8: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1549 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1558 | break; |
| 1559 | default: |
| 1560 | ASSERT(false); |
| 1561 | } |
| 1562 | } |
| 1563 | break; |
| 1564 | case 2: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1565 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1569 | |
| 1570 | switch(state.textureFormat) |
| 1571 | { |
| 1572 | case FORMAT_G8R8: |
| 1573 | case FORMAT_V8U8: |
| 1574 | case FORMAT_A8L8: |
Nicolas Capens | 6e48fc8 | 2014-05-06 16:45:31 -0400 | [diff] [blame] | 1575 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1577 | 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1588 | c.x = Unpack(As<Byte4>(c0)); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1589 | break; |
| 1590 | default: |
| 1591 | ASSERT(false); |
| 1592 | } |
| 1593 | } |
| 1594 | else |
| 1595 | { |
| 1596 | switch(textureComponentCount()) |
| 1597 | { |
| 1598 | case 4: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1599 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1604 | break; |
| 1605 | case 2: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1606 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1613 | break; |
| 1614 | case 1: |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1615 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1619 | break; |
| 1620 | default: |
| 1621 | ASSERT(false); |
| 1622 | } |
| 1623 | } |
| 1624 | } |
| 1625 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1626 | void SamplerCore::sampleTexel(Vector4f &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1627 | { |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1641 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1646 | break; |
| 1647 | case 2: |
| 1648 | // FIXME: Optimal shuffling? |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1649 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1656 | break; |
| 1657 | case 1: |
| 1658 | // FIXME: Optimal shuffling? |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1659 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1663 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1664 | if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1665 | { |
| 1666 | Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f)); |
| 1667 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1668 | c.x = As<Float4>(As<Int4>(CmpNLT(c.x, d)) & As<Int4>(Float4(1.0f))); // FIXME: Only less-equal? |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1669 | } |
| 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 Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1700 | buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0])); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1701 | } |
| 1702 | else |
| 1703 | { |
| 1704 | for(int i = 0; i < 4; i++) |
| 1705 | { |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1706 | buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*)); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1707 | } |
| 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 Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1747 | ci = RoundShort4(cf * Float4(0x1000)); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1748 | } |
| 1749 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1750 | void SamplerCore::convertFixed12(Vector4i &ci, Vector4f &cf) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1751 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1752 | convertFixed12(ci.x, cf.x); |
| 1753 | convertFixed12(ci.y, cf.y); |
| 1754 | convertFixed12(ci.z, cf.z); |
| 1755 | convertFixed12(ci.w, cf.w); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1756 | } |
| 1757 | |
| 1758 | void SamplerCore::convertSigned12(Float4 &cf, Short4 &ci) |
| 1759 | { |
| 1760 | cf = Float4(ci) * Float4(1.0f / 0x0FFE); |
| 1761 | } |
| 1762 | |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1763 | // void SamplerCore::convertSigned12(Vector4f &cf, Vector4i &ci) |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1764 | // { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1765 | // convertSigned12(cf.x, ci.x); |
| 1766 | // convertSigned12(cf.y, ci.y); |
| 1767 | // convertSigned12(cf.z, ci.z); |
| 1768 | // convertSigned12(cf.w, ci.w); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1769 | // } |
| 1770 | |
| 1771 | void SamplerCore::convertSigned15(Float4 &cf, Short4 &ci) |
| 1772 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1773 | cf = Float4(ci) * Float4(1.0f / 0x7FFF); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1774 | } |
| 1775 | |
| 1776 | void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &ci) |
| 1777 | { |
John Bauman | 19bac1e | 2014-05-06 15:23:49 -0400 | [diff] [blame] | 1778 | cf = Float4(As<UShort4>(ci)) * Float4(1.0f / 0xFFFF); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1779 | } |
| 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 Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1795 | return Surface::isFloatFormat(state.textureFormat); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1796 | } |
| 1797 | |
| 1798 | bool SamplerCore::hasUnsignedTextureComponent(int component) const |
| 1799 | { |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1800 | return Surface::isUnsignedComponent(state.textureFormat, component); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1801 | } |
| 1802 | |
| 1803 | int SamplerCore::textureComponentCount() const |
| 1804 | { |
Nicolas Capens | a0f4be8 | 2014-10-22 14:35:30 -0400 | [diff] [blame^] | 1805 | return Surface::componentCount(state.textureFormat); |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1806 | } |
| 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 Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1826 | case FORMAT_D32FS8_TEXTURE: |
| 1827 | case FORMAT_D32FS8_SHADOW: |
John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1828 | 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 Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 1847 | 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 Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1869 | default: |
| 1870 | ASSERT(false); |
| 1871 | } |
| 1872 | |
| 1873 | return false; |
| 1874 | } |
| 1875 | } |