Talvos  0.1
SPIR-V interpreter and dynamic analysis framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Image.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018 the Talvos developers. All rights reserved.
2 //
3 // This file is distributed under a three-clause BSD license. For full license
4 // terms please see the LICENSE file distributed with this source code.
5 
8 
9 #include <algorithm>
10 #include <cassert>
11 #include <cmath>
12 #include <cstring>
13 #include <limits>
14 
15 #include "talvos/Device.h"
16 #include "talvos/Image.h"
17 #include "talvos/Memory.h"
18 #include "talvos/Object.h"
19 #include "talvos/Type.h"
20 
21 namespace talvos
22 {
23 
25 {
26  assert(Obj.getType()->getScalarType()->getSize() == 4);
27  assert(Obj.getType()->getElementCount() <= 4);
28  memcpy(Data, Obj.getData(), Obj.getType()->getSize());
29 }
30 
31 Image::Texel::Texel(const VkClearColorValue &ClearColor)
32 {
33  memcpy(Data, ClearColor.float32, 16);
34 }
35 
36 template <typename T> void Image::Texel::loadSFloat(const T *Data)
37 {
38  set<float>(0, Data[0]);
39  set<float>(1, Data[1]);
40  set<float>(2, Data[2]);
41  set<float>(3, Data[3]);
42 }
43 
44 template <typename T> void Image::Texel::loadSInt(const T *Data)
45 {
46  set<int32_t>(0, Data[0]);
47  set<int32_t>(1, Data[1]);
48  set<int32_t>(2, Data[2]);
49  set<int32_t>(3, Data[3]);
50 }
51 
52 template <typename T> void Image::Texel::loadSNorm(const T *Data)
53 {
54  set<float>(0, Data[0] / (float)std::numeric_limits<T>::max());
55  set<float>(1, Data[1] / (float)std::numeric_limits<T>::max());
56  set<float>(2, Data[2] / (float)std::numeric_limits<T>::max());
57  set<float>(3, Data[3] / (float)std::numeric_limits<T>::max());
58 }
59 
60 template <typename T> void Image::Texel::loadUInt(const T *Data)
61 {
62  set<uint32_t>(0, Data[0]);
63  set<uint32_t>(1, Data[1]);
64  set<uint32_t>(2, Data[2]);
65  set<uint32_t>(3, Data[3]);
66 }
67 
68 template <typename T> void Image::Texel::loadUNorm(const T *Data)
69 {
70  set<float>(0, Data[0] / (float)(T)(~0U));
71  set<float>(1, Data[1] / (float)(T)(~0U));
72  set<float>(2, Data[2] / (float)(T)(~0U));
73  set<float>(3, Data[3] / (float)(T)(~0U));
74 }
75 
76 template <typename T> void Image::Texel::storeSInt(T *Data) const
77 {
78  // Clamp each component value to the range of T.
79  auto convert = [](int32_t V) -> T {
80  return (T)std::clamp<int32_t>(V, std::numeric_limits<T>::min(),
81  std::numeric_limits<T>::max());
82  };
83  Data[0] = convert(get<int32_t>(0));
84  Data[1] = convert(get<int32_t>(1));
85  Data[2] = convert(get<int32_t>(2));
86  Data[3] = convert(get<int32_t>(3));
87 }
88 
89 template <typename T> void Image::Texel::storeSNorm(T *Data) const
90 {
91  // Clamp and normalize each component value.
92  auto convert = [](float v) -> T {
93  if (v < -1.f)
94  return std::numeric_limits<T>::min();
95  else if (v >= 1.f)
96  return std::numeric_limits<T>::max();
97  else
98  return (T)std::round(v * std::numeric_limits<T>::max());
99  };
100  Data[0] = convert(get<float>(0));
101  Data[1] = convert(get<float>(1));
102  Data[2] = convert(get<float>(2));
103  Data[3] = convert(get<float>(3));
104 }
105 
106 template <typename T> void Image::Texel::storeUInt(T *Data) const
107 {
108  // Clamp each component value to the range of T.
109  auto convert = [](int32_t V) -> T {
110  return (T)std::clamp<uint32_t>(V, 0, std::numeric_limits<T>::max());
111  };
112  Data[0] = convert(get<uint32_t>(0));
113  Data[1] = convert(get<uint32_t>(1));
114  Data[2] = convert(get<uint32_t>(2));
115  Data[3] = convert(get<uint32_t>(3));
116 }
117 
118 template <typename T> void Image::Texel::storeUNorm(T *Data) const
119 {
120  // Clamp and normalize each component value.
121  auto convert = [](float v) -> T {
122  if (v < 0.f)
123  return 0;
124  else if (v >= 1.f)
125  return (T)~0U;
126  else
127  return (T)std::round(v * (T)(~0U));
128  };
129  Data[0] = convert(get<float>(0));
130  Data[1] = convert(get<float>(1));
131  Data[2] = convert(get<float>(2));
132  Data[3] = convert(get<float>(3));
133 }
134 
136 {
137  assert(Ty->getScalarType()->getSize() == 4);
138  assert(Ty->getElementCount() <= 4);
139  Object Obj(Ty);
140  memcpy(Obj.getData(), Data, Ty->getSize());
141  return Obj;
142 }
143 
145 {
146  assert(this->Address == 0 && "image address is already bound");
147  this->Address = Address;
148 }
149 
150 uint32_t Image::getDepth(uint32_t Level) const
151 {
152  uint32_t Ret = Extent.depth >> Level;
153  return Ret ? Ret : 1;
154 }
155 
156 uint32_t Image::getElementSize() const
157 {
159 }
160 
161 uint32_t Image::getHeight(uint32_t Level) const
162 {
163  uint32_t Ret = Extent.height >> Level;
164  return Ret ? Ret : 1;
165 }
166 
167 uint64_t Image::getMipLevelOffset(uint32_t Level) const
168 {
169  // TODO: Precompute these offsets in constructor?
170  uint64_t Offset = 0;
171  for (uint32_t l = 0; l < Level; l++)
172  {
173  Offset += getWidth(l) * getHeight(l) * getDepth(l) * NumArrayLayers *
174  getElementSize();
175  }
176  return Offset;
177 }
178 
179 uint64_t Image::getTexelAddress(uint32_t X, uint32_t Y, uint32_t Z,
180  uint32_t Layer, uint32_t MipLevel) const
181 {
182  assert(Z == 0 || Layer == 0);
183  return Address + getMipLevelOffset(MipLevel) +
184  (X + (Y + (Z + Layer) * getHeight(MipLevel)) * getWidth(MipLevel)) *
185  getElementSize();
186 }
187 
188 uint32_t Image::getWidth(uint32_t Level) const
189 {
190  uint32_t Ret = Extent.width >> Level;
191  return Ret ? Ret : 1;
192 }
193 
194 void Image::read(Texel &T, uint64_t Address) const { read(T, Address, Format); }
195 
196 void Image::read(Texel &T, uint64_t Address, VkFormat ReadFormat) const
197 {
198  assert(getElementSize() <= 16);
199  assert(getElementSize() == talvos::getElementSize(ReadFormat));
200 
201  // Load raw texel data.
202  uint8_t Data[16];
203  memset(Data, 0, 16);
204  Dev.getGlobalMemory().load(Data, Address, getElementSize());
205 
206  // Load component values.
207  switch (ReadFormat)
208  {
209  case VK_FORMAT_R8_SINT:
210  case VK_FORMAT_R8G8_SINT:
211  case VK_FORMAT_R8G8B8_SINT:
212  ((int8_t *)Data)[3] = 1;
213  case VK_FORMAT_R8G8B8A8_SINT:
214  T.loadSInt((int8_t *)Data);
215  break;
216 
217  case VK_FORMAT_R8_UINT:
218  case VK_FORMAT_R8G8_UINT:
219  case VK_FORMAT_R8G8B8_UINT:
220  ((uint8_t *)Data)[3] = 1;
221  case VK_FORMAT_R8G8B8A8_UINT:
222  T.loadUInt((uint8_t *)Data);
223  break;
224 
225  case VK_FORMAT_R16_SINT:
226  case VK_FORMAT_R16G16_SINT:
227  case VK_FORMAT_R16G16B16_SINT:
228  ((int16_t *)Data)[3] = 1;
229  case VK_FORMAT_R16G16B16A16_SINT:
230  T.loadSInt((int16_t *)Data);
231  break;
232 
233  case VK_FORMAT_R16_UINT:
234  case VK_FORMAT_R16G16_UINT:
235  case VK_FORMAT_R16G16B16_UINT:
236  ((uint16_t *)Data)[3] = 1;
237  case VK_FORMAT_R16G16B16A16_UINT:
238  T.loadUInt((uint16_t *)Data);
239  break;
240 
241  case VK_FORMAT_R32_SINT:
242  case VK_FORMAT_R32G32_SINT:
243  case VK_FORMAT_R32G32B32_SINT:
244  ((int32_t *)Data)[3] = 1;
245  case VK_FORMAT_R32G32B32A32_SINT:
246  T.loadSInt((int32_t *)Data);
247  break;
248 
249  case VK_FORMAT_R32_UINT:
250  case VK_FORMAT_R32G32_UINT:
251  case VK_FORMAT_R32G32B32_UINT:
252  ((uint32_t *)Data)[3] = 1;
253  case VK_FORMAT_R32G32B32A32_UINT:
254  T.loadUInt((uint32_t *)Data);
255  break;
256 
257  case VK_FORMAT_R32_SFLOAT:
258  case VK_FORMAT_R32G32_SFLOAT:
259  case VK_FORMAT_R32G32B32_SFLOAT:
260  ((float *)Data)[3] = 1.f;
261  case VK_FORMAT_R32G32B32A32_SFLOAT:
262  T.loadSFloat((float *)Data);
263  break;
264 
265  case VK_FORMAT_R8_SNORM:
266  case VK_FORMAT_R8G8_SNORM:
267  case VK_FORMAT_R8G8B8_SNORM:
268  ((int8_t *)Data)[3] = 1;
269  case VK_FORMAT_R8G8B8A8_SNORM:
270  T.loadSNorm((int8_t *)Data);
271  break;
272 
273  case VK_FORMAT_R8_UNORM:
274  case VK_FORMAT_R8G8_UNORM:
275  case VK_FORMAT_R8G8B8_UNORM:
276  ((uint8_t *)Data)[3] = 1;
277  case VK_FORMAT_R8G8B8A8_UNORM:
278  T.loadUNorm(Data);
279  break;
280 
281  case VK_FORMAT_R16_SNORM:
282  case VK_FORMAT_R16G16_SNORM:
283  case VK_FORMAT_R16G16B16_SNORM:
284  ((int16_t *)Data)[3] = 1;
285  case VK_FORMAT_R16G16B16A16_SNORM:
286  T.loadSNorm((int16_t *)Data);
287  break;
288 
289  case VK_FORMAT_R16_UNORM:
290  case VK_FORMAT_R16G16_UNORM:
291  case VK_FORMAT_R16G16B16_UNORM:
292  ((uint16_t *)Data)[3] = 1;
293  case VK_FORMAT_R16G16B16A16_UNORM:
294  T.loadUNorm((uint16_t *)Data);
295  break;
296 
297  case VK_FORMAT_B8G8R8_SINT:
298  ((int8_t *)Data)[3] = 1;
299  case VK_FORMAT_B8G8R8A8_SINT:
300  std::swap(Data[0], Data[2]);
301  T.loadSInt((int8_t *)Data);
302  break;
303 
304  case VK_FORMAT_B8G8R8_UINT:
305  ((uint8_t *)Data)[3] = 1;
306  case VK_FORMAT_B8G8R8A8_UINT:
307  std::swap(Data[0], Data[2]);
308  T.loadUInt((uint8_t *)Data);
309  break;
310 
311  case VK_FORMAT_B8G8R8_SNORM:
312  ((int8_t *)Data)[3] = 1;
313  case VK_FORMAT_B8G8R8A8_SNORM:
314  std::swap(Data[0], Data[2]);
315  T.loadSNorm((int8_t *)Data);
316  break;
317 
318  case VK_FORMAT_B8G8R8_UNORM:
319  ((uint8_t *)Data)[3] = 1;
320  case VK_FORMAT_B8G8R8A8_UNORM:
321  std::swap(Data[0], Data[2]);
322  T.loadUNorm((uint8_t *)Data);
323  break;
324 
325  default:
326  assert(false && "Unhandled format");
327  }
328 }
329 
330 void Image::write(const Texel &T, uint64_t Address) const
331 {
332  write(T, Address, Format);
333 }
334 
335 void Image::write(const Texel &T, uint64_t Address, VkFormat WriteFormat) const
336 {
337  assert(getElementSize() <= 16);
338  assert(getElementSize() == talvos::getElementSize(WriteFormat));
339 
340  // Will point to texel data to be written to memory.
341  const uint8_t *Data;
342 
343  // Used as intermediate buffer when conversions need to happen.
344  uint8_t TData[16];
345 
346  switch (WriteFormat)
347  {
348  case VK_FORMAT_R8_SINT:
349  case VK_FORMAT_R8G8_SINT:
350  case VK_FORMAT_R8G8B8_SINT:
351  case VK_FORMAT_R8G8B8A8_SINT:
352  T.storeSInt((int8_t *)TData);
353  Data = TData;
354  break;
355  case VK_FORMAT_R8_UINT:
356  case VK_FORMAT_R8G8_UINT:
357  case VK_FORMAT_R8G8B8_UINT:
358  case VK_FORMAT_R8G8B8A8_UINT:
359  T.storeUInt((uint8_t *)TData);
360  Data = TData;
361  break;
362  case VK_FORMAT_R16_SINT:
363  case VK_FORMAT_R16G16_SINT:
364  case VK_FORMAT_R16G16B16_SINT:
365  case VK_FORMAT_R16G16B16A16_SINT:
366  T.storeSInt((int16_t *)TData);
367  Data = TData;
368  break;
369  case VK_FORMAT_R16_UINT:
370  case VK_FORMAT_R16G16_UINT:
371  case VK_FORMAT_R16G16B16_UINT:
372  case VK_FORMAT_R16G16B16A16_UINT:
373  T.storeUInt((uint16_t *)TData);
374  Data = TData;
375  break;
376  case VK_FORMAT_R32_SFLOAT:
377  case VK_FORMAT_R32G32_SFLOAT:
378  case VK_FORMAT_R32G32B32_SFLOAT:
379  case VK_FORMAT_R32G32B32A32_SFLOAT:
380  case VK_FORMAT_R32_SINT:
381  case VK_FORMAT_R32G32_SINT:
382  case VK_FORMAT_R32G32B32_SINT:
383  case VK_FORMAT_R32G32B32A32_SINT:
384  case VK_FORMAT_R32_UINT:
385  case VK_FORMAT_R32G32_UINT:
386  case VK_FORMAT_R32G32B32_UINT:
387  case VK_FORMAT_R32G32B32A32_UINT:
388  Data = T.getData();
389  break;
390  case VK_FORMAT_R8_SNORM:
391  case VK_FORMAT_R8G8_SNORM:
392  case VK_FORMAT_R8G8B8_SNORM:
393  case VK_FORMAT_R8G8B8A8_SNORM:
394  T.storeSNorm((int8_t *)TData);
395  Data = TData;
396  break;
397  case VK_FORMAT_R8_UNORM:
398  case VK_FORMAT_R8G8_UNORM:
399  case VK_FORMAT_R8G8B8_UNORM:
400  case VK_FORMAT_R8G8B8A8_UNORM:
401  T.storeUNorm(TData);
402  Data = TData;
403  break;
404  case VK_FORMAT_R16_SNORM:
405  case VK_FORMAT_R16G16_SNORM:
406  case VK_FORMAT_R16G16B16_SNORM:
407  case VK_FORMAT_R16G16B16A16_SNORM:
408  T.storeSNorm((int16_t *)TData);
409  Data = TData;
410  break;
411  case VK_FORMAT_R16_UNORM:
412  case VK_FORMAT_R16G16_UNORM:
413  case VK_FORMAT_R16G16B16_UNORM:
414  case VK_FORMAT_R16G16B16A16_UNORM:
415  T.storeUNorm((uint16_t *)TData);
416  Data = TData;
417  break;
418  case VK_FORMAT_B8G8R8_SINT:
419  case VK_FORMAT_B8G8R8A8_SINT:
420  T.storeSInt((int8_t *)TData);
421  std::swap(TData[0], TData[2]);
422  Data = TData;
423  break;
424  case VK_FORMAT_B8G8R8_UINT:
425  case VK_FORMAT_B8G8R8A8_UINT:
426  T.storeUInt((uint8_t *)TData);
427  std::swap(TData[0], TData[2]);
428  Data = TData;
429  break;
430  case VK_FORMAT_B8G8R8_SNORM:
431  case VK_FORMAT_B8G8R8A8_SNORM:
432  T.storeSNorm((int8_t *)TData);
433  std::swap(TData[0], TData[2]);
434  Data = TData;
435  break;
436  case VK_FORMAT_B8G8R8_UNORM:
437  case VK_FORMAT_B8G8R8A8_UNORM:
438  T.storeUNorm(TData);
439  std::swap(TData[0], TData[2]);
440  Data = TData;
441  break;
442  default:
443  assert(false && "Unhandled format");
444  }
445 
446  // Write raw texel data.
447  Dev.getGlobalMemory().store(Address, getElementSize(), Data);
448 }
449 
450 ImageView::ImageView(const Image &Img, VkImageViewType Type, VkFormat Format,
451  VkImageSubresourceRange Range)
452  : Img(Img), Type(Type), Format(Format)
453 {
454  BaseArrayLayer = Range.baseArrayLayer;
455  NumArrayLayers = Range.layerCount;
456  if (NumArrayLayers == VK_REMAINING_ARRAY_LAYERS)
458 
459  BaseMipLevel = Range.baseMipLevel;
460  NumMipLevels = Range.levelCount;
461  if (NumMipLevels == VK_REMAINING_MIP_LEVELS)
463 }
464 
465 uint32_t ImageView::getDepth(uint32_t Level) const
466 {
467  return Img.getDepth(BaseMipLevel + Level);
468 }
469 
470 uint32_t ImageView::getHeight(uint32_t Level) const
471 {
472  return Img.getHeight(BaseMipLevel + Level);
473 }
474 
475 uint64_t ImageView::getTexelAddress(uint32_t X, uint32_t Y, uint32_t Z,
476  uint32_t Layer, uint32_t MipLevel) const
477 {
478  return Img.getTexelAddress(X, Y, Z, BaseArrayLayer + Layer,
479  BaseMipLevel + MipLevel);
480 }
481 
482 uint32_t ImageView::getWidth(uint32_t Level) const
483 {
484  return Img.getWidth(BaseMipLevel + Level);
485 }
486 
487 bool ImageView::is1D() const
488 {
489  return Type == VK_IMAGE_VIEW_TYPE_1D || Type == VK_IMAGE_VIEW_TYPE_1D_ARRAY;
490 }
491 
492 bool ImageView::is2D() const
493 {
494  return Type == VK_IMAGE_VIEW_TYPE_2D || Type == VK_IMAGE_VIEW_TYPE_2D_ARRAY;
495 }
496 
497 bool ImageView::is3D() const { return Type == VK_IMAGE_VIEW_TYPE_3D; }
498 
499 bool ImageView::isCube() const
500 {
501  return Type == VK_IMAGE_VIEW_TYPE_CUBE ||
502  Type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
503 }
504 
505 void ImageView::read(Image::Texel &T, uint32_t X, uint32_t Y, uint32_t Z,
506  uint32_t Layer, uint32_t MipLevel) const
507 {
508  Img.read(T, getTexelAddress(X, Y, Z, Layer, MipLevel), Format);
509 }
510 
511 void ImageView::write(const Image::Texel &T, uint32_t X, uint32_t Y, uint32_t Z,
512  uint32_t Layer, uint32_t MipLevel) const
513 {
514  Img.write(T, getTexelAddress(X, Y, Z, Layer, MipLevel), Format);
515 }
516 
518  float S, float T, float R, float A, float Lod) const
519 {
520  // TODO: Handle non-zero Lod
521  assert(Lod == 0);
522 
523  // TODO: Handle other formats (with integer types)
524  assert(Image->getFormat() == VK_FORMAT_R8G8B8A8_UNORM);
525 
526  // TODO: Handle anisotropic filtering
527  assert(Info.anisotropyEnable == VK_FALSE);
528 
529  // TODO: Handle comparison
530  assert(Info.compareEnable == VK_FALSE);
531 
532  // TODO: Handle cube maps
533  assert(!Image->isCube());
534 
535  // Select array layer.
536  uint32_t Layer =
537  std::clamp((uint32_t)std::round(A), 0U, Image->getNumArrayLayers() - 1);
538 
539  // TODO: Handle unnormalized coordinates
540  assert(Info.unnormalizedCoordinates == VK_FALSE);
541  float U = S * Image->getWidth();
542  float V = T * Image->getHeight();
543  float W = R * Image->getDepth();
544 
545  // Compute neighboring coordinates and weights for linear filtering.
546  int32_t I0 = floor(U - 0.5f);
547  int32_t I1 = I0 + 1;
548  int32_t J0 = floor(V - 0.5f);
549  int32_t J1 = J0 + 1;
550  int32_t K0 = floor(W - 0.5f);
551  int32_t K1 = K0 + 1;
552  float Alpha = (U - 0.5f) - I0;
553  float Beta = (V - 0.5f) - J0;
554  float Gamma = (W - 0.5f) - K0;
555 
556  // Handle edge behavior for coordinates.
557  auto handleEdge = [](VkSamplerAddressMode AddrMode, int32_t Coord,
558  uint32_t Dim) {
559  switch (AddrMode)
560  {
561  case VK_SAMPLER_ADDRESS_MODE_REPEAT:
562  return Coord % Dim;
563  case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
564  return (uint32_t)std::clamp(Coord, 0, (int32_t)Dim - 1);
565  default:
566  // TODO: handle other addressing modes
567  assert(false && "unhandled sampler addressing mode");
568  return ~0U;
569  }
570  };
571  I0 = handleEdge(Info.addressModeU, I0, Image->getWidth());
572  I1 = handleEdge(Info.addressModeU, I1, Image->getWidth());
573  J0 = handleEdge(Info.addressModeV, J0, Image->getHeight());
574  J1 = handleEdge(Info.addressModeV, J1, Image->getHeight());
575  K0 = handleEdge(Info.addressModeW, K0, Image->getDepth());
576  K1 = handleEdge(Info.addressModeW, K1, Image->getDepth());
577 
578  // TODO: Select magFilter/minFilter based on Lod
579  if (Info.magFilter == VK_FILTER_LINEAR)
580  {
581  // Load texel region for linear filtering.
582  // Re-use texels when dimensionality is not 3D.
583  Image::Texel T000, T100, T010, T110, T001, T101, T011, T111;
584  Image->getImage().read(T000, Image->getTexelAddress(I0, J0, K0, Layer));
585  Image->getImage().read(T100, Image->getTexelAddress(I1, J0, K0, Layer));
586  if (Image->is1D())
587  {
588  T010 = T000;
589  T110 = T100;
590  T001 = T000;
591  T101 = T100;
592  T011 = T000;
593  T111 = T100;
594  }
595  else
596  {
597  Image->getImage().read(T010, Image->getTexelAddress(I0, J1, K0, Layer));
598  Image->getImage().read(T110, Image->getTexelAddress(I1, J1, K0, Layer));
599  if (Image->is2D())
600  {
601  T001 = T000;
602  T101 = T100;
603  T011 = T010;
604  T111 = T110;
605  }
606  else
607  {
608  assert(Image->is3D());
609  Image->getImage().read(T001, Image->getTexelAddress(I0, J0, K1, Layer));
610  Image->getImage().read(T101, Image->getTexelAddress(I1, J0, K1, Layer));
611  Image->getImage().read(T011, Image->getTexelAddress(I0, J1, K1, Layer));
612  Image->getImage().read(T111, Image->getTexelAddress(I1, J1, K1, Layer));
613  }
614  }
615 
616  // Apply linear filter to texels.
617  auto linear = [&](uint32_t C) {
618  return ((1 - Alpha) * (1 - Beta) * (1 - Gamma) * T000.get<float>(C)) +
619  (Alpha * (1 - Beta) * (1 - Gamma) * T100.get<float>(C)) +
620  ((1 - Alpha) * Beta * (1 - Gamma) * T010.get<float>(C)) +
621  (Alpha * Beta * (1 - Gamma) * T110.get<float>(C)) +
622  ((1 - Alpha) * (1 - Beta) * Gamma * T001.get<float>(C)) +
623  (Alpha * (1 - Beta) * Gamma * T101.get<float>(C)) +
624  ((1 - Alpha) * Beta * Gamma * T011.get<float>(C)) +
625  (Alpha * Beta * Gamma * T111.get<float>(C));
626  };
627  Texel.set<float>(0, linear(0));
628  Texel.set<float>(1, linear(1));
629  Texel.set<float>(2, linear(2));
630  Texel.set<float>(3, linear(3));
631  }
632  else
633  {
634  assert(Info.magFilter == VK_FILTER_NEAREST);
635 
636  // Select nearest coordinates based on weights.
637  int32_t I = Alpha <= 0.5 ? I0 : I1;
638  int32_t J = Beta <= 0.5 ? J0 : J1;
639  int32_t K = Gamma <= 0.5 ? K0 : K1;
640 
641  // Load texel.
642  Image::Texel T;
643  Image->getImage().read(T, Image->getTexelAddress(I, J, K, Layer));
644  Texel.set<float>(0, T.get<float>(0));
645  Texel.set<float>(1, T.get<float>(1));
646  Texel.set<float>(2, T.get<float>(2));
647  Texel.set<float>(3, T.get<float>(3));
648  }
649 }
650 
651 uint32_t getElementSize(VkFormat Format)
652 {
653  switch (Format)
654  {
655  case VK_FORMAT_R4G4_UNORM_PACK8:
656  case VK_FORMAT_R8_UNORM:
657  case VK_FORMAT_R8_SNORM:
658  case VK_FORMAT_R8_USCALED:
659  case VK_FORMAT_R8_SSCALED:
660  case VK_FORMAT_R8_UINT:
661  case VK_FORMAT_R8_SINT:
662  case VK_FORMAT_R8_SRGB:
663  case VK_FORMAT_S8_UINT:
664  return 1;
665 
666  case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
667  case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
668  case VK_FORMAT_R5G6B5_UNORM_PACK16:
669  case VK_FORMAT_B5G6R5_UNORM_PACK16:
670  case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
671  case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
672  case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
673  case VK_FORMAT_R8G8_UNORM:
674  case VK_FORMAT_R8G8_SNORM:
675  case VK_FORMAT_R8G8_USCALED:
676  case VK_FORMAT_R8G8_SSCALED:
677  case VK_FORMAT_R8G8_UINT:
678  case VK_FORMAT_R8G8_SINT:
679  case VK_FORMAT_R8G8_SRGB:
680  case VK_FORMAT_R16_UNORM:
681  case VK_FORMAT_R16_SNORM:
682  case VK_FORMAT_R16_USCALED:
683  case VK_FORMAT_R16_SSCALED:
684  case VK_FORMAT_R16_UINT:
685  case VK_FORMAT_R16_SINT:
686  case VK_FORMAT_R16_SFLOAT:
687  case VK_FORMAT_D16_UNORM:
688  case VK_FORMAT_R10X6_UNORM_PACK16:
689  case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
690  case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
691  case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
692  case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
693  case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
694  case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
695  case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
696  case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
697  case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
698  case VK_FORMAT_R12X4_UNORM_PACK16:
699  case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
700  case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
701  case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
702  case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
703  case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
704  case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
705  case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
706  case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
707  case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
708  return 2;
709 
710  case VK_FORMAT_R8G8B8_UNORM:
711  case VK_FORMAT_R8G8B8_SNORM:
712  case VK_FORMAT_R8G8B8_USCALED:
713  case VK_FORMAT_R8G8B8_SSCALED:
714  case VK_FORMAT_R8G8B8_UINT:
715  case VK_FORMAT_R8G8B8_SINT:
716  case VK_FORMAT_R8G8B8_SRGB:
717  case VK_FORMAT_B8G8R8_UNORM:
718  case VK_FORMAT_B8G8R8_SNORM:
719  case VK_FORMAT_B8G8R8_USCALED:
720  case VK_FORMAT_B8G8R8_SSCALED:
721  case VK_FORMAT_B8G8R8_UINT:
722  case VK_FORMAT_B8G8R8_SINT:
723  case VK_FORMAT_B8G8R8_SRGB:
724  case VK_FORMAT_D16_UNORM_S8_UINT:
725  return 3;
726 
727  case VK_FORMAT_R8G8B8A8_UNORM:
728  case VK_FORMAT_R8G8B8A8_SNORM:
729  case VK_FORMAT_R8G8B8A8_USCALED:
730  case VK_FORMAT_R8G8B8A8_SSCALED:
731  case VK_FORMAT_R8G8B8A8_UINT:
732  case VK_FORMAT_R8G8B8A8_SINT:
733  case VK_FORMAT_R8G8B8A8_SRGB:
734  case VK_FORMAT_B8G8R8A8_UNORM:
735  case VK_FORMAT_B8G8R8A8_SNORM:
736  case VK_FORMAT_B8G8R8A8_USCALED:
737  case VK_FORMAT_B8G8R8A8_SSCALED:
738  case VK_FORMAT_B8G8R8A8_UINT:
739  case VK_FORMAT_B8G8R8A8_SINT:
740  case VK_FORMAT_B8G8R8A8_SRGB:
741  case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
742  case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
743  case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
744  case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
745  case VK_FORMAT_A8B8G8R8_UINT_PACK32:
746  case VK_FORMAT_A8B8G8R8_SINT_PACK32:
747  case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
748  case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
749  case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
750  case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
751  case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
752  case VK_FORMAT_A2R10G10B10_UINT_PACK32:
753  case VK_FORMAT_A2R10G10B10_SINT_PACK32:
754  case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
755  case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
756  case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
757  case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
758  case VK_FORMAT_A2B10G10R10_UINT_PACK32:
759  case VK_FORMAT_A2B10G10R10_SINT_PACK32:
760  case VK_FORMAT_R16G16_UNORM:
761  case VK_FORMAT_R16G16_SNORM:
762  case VK_FORMAT_R16G16_USCALED:
763  case VK_FORMAT_R16G16_SSCALED:
764  case VK_FORMAT_R16G16_UINT:
765  case VK_FORMAT_R16G16_SINT:
766  case VK_FORMAT_R16G16_SFLOAT:
767  case VK_FORMAT_R32_UINT:
768  case VK_FORMAT_R32_SINT:
769  case VK_FORMAT_R32_SFLOAT:
770  case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
771  case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
772  case VK_FORMAT_X8_D24_UNORM_PACK32:
773  case VK_FORMAT_D32_SFLOAT:
774  case VK_FORMAT_D24_UNORM_S8_UINT:
775  case VK_FORMAT_D32_SFLOAT_S8_UINT:
776  case VK_FORMAT_G8B8G8R8_422_UNORM:
777  case VK_FORMAT_B8G8R8G8_422_UNORM:
778  return 4;
779 
780  case VK_FORMAT_R16G16B16_UNORM:
781  case VK_FORMAT_R16G16B16_SNORM:
782  case VK_FORMAT_R16G16B16_USCALED:
783  case VK_FORMAT_R16G16B16_SSCALED:
784  case VK_FORMAT_R16G16B16_UINT:
785  case VK_FORMAT_R16G16B16_SINT:
786  case VK_FORMAT_R16G16B16_SFLOAT:
787  return 6;
788 
789  case VK_FORMAT_R16G16B16A16_UNORM:
790  case VK_FORMAT_R16G16B16A16_SNORM:
791  case VK_FORMAT_R16G16B16A16_USCALED:
792  case VK_FORMAT_R16G16B16A16_SSCALED:
793  case VK_FORMAT_R16G16B16A16_UINT:
794  case VK_FORMAT_R16G16B16A16_SINT:
795  case VK_FORMAT_R16G16B16A16_SFLOAT:
796  case VK_FORMAT_R32G32_UINT:
797  case VK_FORMAT_R32G32_SINT:
798  case VK_FORMAT_R32G32_SFLOAT:
799  case VK_FORMAT_R64_UINT:
800  case VK_FORMAT_R64_SINT:
801  case VK_FORMAT_R64_SFLOAT:
802  case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
803  case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
804  case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
805  case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
806  case VK_FORMAT_BC4_UNORM_BLOCK:
807  case VK_FORMAT_BC4_SNORM_BLOCK:
808  case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
809  case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
810  case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
811  case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
812  case VK_FORMAT_EAC_R11_UNORM_BLOCK:
813  case VK_FORMAT_EAC_R11_SNORM_BLOCK:
814  case VK_FORMAT_G16B16G16R16_422_UNORM:
815  case VK_FORMAT_B16G16R16G16_422_UNORM:
816  return 8;
817 
818  case VK_FORMAT_R32G32B32_UINT:
819  case VK_FORMAT_R32G32B32_SINT:
820  case VK_FORMAT_R32G32B32_SFLOAT:
821  return 12;
822 
823  case VK_FORMAT_R32G32B32A32_UINT:
824  case VK_FORMAT_R32G32B32A32_SINT:
825  case VK_FORMAT_R32G32B32A32_SFLOAT:
826  case VK_FORMAT_R64G64_UINT:
827  case VK_FORMAT_R64G64_SINT:
828  case VK_FORMAT_R64G64_SFLOAT:
829  case VK_FORMAT_BC2_UNORM_BLOCK:
830  case VK_FORMAT_BC2_SRGB_BLOCK:
831  case VK_FORMAT_BC3_UNORM_BLOCK:
832  case VK_FORMAT_BC3_SRGB_BLOCK:
833  case VK_FORMAT_BC5_UNORM_BLOCK:
834  case VK_FORMAT_BC5_SNORM_BLOCK:
835  case VK_FORMAT_BC6H_UFLOAT_BLOCK:
836  case VK_FORMAT_BC6H_SFLOAT_BLOCK:
837  case VK_FORMAT_BC7_UNORM_BLOCK:
838  case VK_FORMAT_BC7_SRGB_BLOCK:
839  case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
840  case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
841  case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
842  case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
843  case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
844  case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
845  case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
846  case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
847  case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
848  case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
849  case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
850  case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
851  case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
852  case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
853  case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
854  case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
855  case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
856  case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
857  case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
858  case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
859  case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
860  case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
861  case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
862  case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
863  case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
864  case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
865  case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
866  case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
867  case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
868  case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
869  case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
870  case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
871  return 16;
872 
873  case VK_FORMAT_R64G64B64_UINT:
874  case VK_FORMAT_R64G64B64_SINT:
875  case VK_FORMAT_R64G64B64_SFLOAT:
876  return 24;
877 
878  case VK_FORMAT_R64G64B64A64_UINT:
879  case VK_FORMAT_R64G64B64A64_SINT:
880  case VK_FORMAT_R64G64B64A64_SFLOAT:
881  return 32;
882 
883  default:
884  assert(false && "Unrecognized image format");
885  return 0;
886  }
887 }
888 
889 bool hasAlphaChannel(VkFormat Format)
890 {
891  switch (Format)
892  {
893  case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
894  case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
895  case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
896  case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
897  case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
898  case VK_FORMAT_R8G8B8A8_UNORM:
899  case VK_FORMAT_R8G8B8A8_SNORM:
900  case VK_FORMAT_R8G8B8A8_USCALED:
901  case VK_FORMAT_R8G8B8A8_SSCALED:
902  case VK_FORMAT_R8G8B8A8_UINT:
903  case VK_FORMAT_R8G8B8A8_SINT:
904  case VK_FORMAT_R8G8B8A8_SRGB:
905  case VK_FORMAT_B8G8R8A8_UNORM:
906  case VK_FORMAT_B8G8R8A8_SNORM:
907  case VK_FORMAT_B8G8R8A8_USCALED:
908  case VK_FORMAT_B8G8R8A8_SSCALED:
909  case VK_FORMAT_B8G8R8A8_UINT:
910  case VK_FORMAT_B8G8R8A8_SINT:
911  case VK_FORMAT_B8G8R8A8_SRGB:
912  case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
913  case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
914  case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
915  case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
916  case VK_FORMAT_A8B8G8R8_UINT_PACK32:
917  case VK_FORMAT_A8B8G8R8_SINT_PACK32:
918  case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
919  case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
920  case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
921  case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
922  case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
923  case VK_FORMAT_A2R10G10B10_UINT_PACK32:
924  case VK_FORMAT_A2R10G10B10_SINT_PACK32:
925  case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
926  case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
927  case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
928  case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
929  case VK_FORMAT_A2B10G10R10_UINT_PACK32:
930  case VK_FORMAT_A2B10G10R10_SINT_PACK32:
931  case VK_FORMAT_R16G16B16A16_UNORM:
932  case VK_FORMAT_R16G16B16A16_SNORM:
933  case VK_FORMAT_R16G16B16A16_USCALED:
934  case VK_FORMAT_R16G16B16A16_SSCALED:
935  case VK_FORMAT_R16G16B16A16_UINT:
936  case VK_FORMAT_R16G16B16A16_SINT:
937  case VK_FORMAT_R16G16B16A16_SFLOAT:
938  case VK_FORMAT_R32G32B32A32_UINT:
939  case VK_FORMAT_R32G32B32A32_SINT:
940  case VK_FORMAT_R32G32B32A32_SFLOAT:
941  case VK_FORMAT_R64G64B64A64_UINT:
942  case VK_FORMAT_R64G64B64A64_SINT:
943  case VK_FORMAT_R64G64B64A64_SFLOAT:
944  case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
945  case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
946  case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
947  case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
948  case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
949  case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
950  case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
951  case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
952  case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
953  case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
954  case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
955  case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
956  case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
957  case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
958  case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
959  case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
960  case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
961  case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
962  case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
963  case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
964  case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
965  case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
966  case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
967  case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
968  case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
969  case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
970  case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
971  case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
972  case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
973  case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
974  case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
975  case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
976  case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
977  case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
978  case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
979  case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
980  return true;
981 
982  case VK_FORMAT_R4G4_UNORM_PACK8:
983  case VK_FORMAT_R5G6B5_UNORM_PACK16:
984  case VK_FORMAT_B5G6R5_UNORM_PACK16:
985  case VK_FORMAT_R8_UNORM:
986  case VK_FORMAT_R8_SNORM:
987  case VK_FORMAT_R8_USCALED:
988  case VK_FORMAT_R8_SSCALED:
989  case VK_FORMAT_R8_UINT:
990  case VK_FORMAT_R8_SINT:
991  case VK_FORMAT_R8_SRGB:
992  case VK_FORMAT_R8G8_UNORM:
993  case VK_FORMAT_R8G8_SNORM:
994  case VK_FORMAT_R8G8_USCALED:
995  case VK_FORMAT_R8G8_SSCALED:
996  case VK_FORMAT_R8G8_UINT:
997  case VK_FORMAT_R8G8_SINT:
998  case VK_FORMAT_R8G8_SRGB:
999  case VK_FORMAT_R8G8B8_UNORM:
1000  case VK_FORMAT_R8G8B8_SNORM:
1001  case VK_FORMAT_R8G8B8_USCALED:
1002  case VK_FORMAT_R8G8B8_SSCALED:
1003  case VK_FORMAT_R8G8B8_UINT:
1004  case VK_FORMAT_R8G8B8_SINT:
1005  case VK_FORMAT_R8G8B8_SRGB:
1006  case VK_FORMAT_B8G8R8_UNORM:
1007  case VK_FORMAT_B8G8R8_SNORM:
1008  case VK_FORMAT_B8G8R8_USCALED:
1009  case VK_FORMAT_B8G8R8_SSCALED:
1010  case VK_FORMAT_B8G8R8_UINT:
1011  case VK_FORMAT_B8G8R8_SINT:
1012  case VK_FORMAT_B8G8R8_SRGB:
1013  case VK_FORMAT_R16_UNORM:
1014  case VK_FORMAT_R16_SNORM:
1015  case VK_FORMAT_R16_USCALED:
1016  case VK_FORMAT_R16_SSCALED:
1017  case VK_FORMAT_R16_UINT:
1018  case VK_FORMAT_R16_SINT:
1019  case VK_FORMAT_R16_SFLOAT:
1020  case VK_FORMAT_R16G16_UNORM:
1021  case VK_FORMAT_R16G16_SNORM:
1022  case VK_FORMAT_R16G16_USCALED:
1023  case VK_FORMAT_R16G16_SSCALED:
1024  case VK_FORMAT_R16G16_UINT:
1025  case VK_FORMAT_R16G16_SINT:
1026  case VK_FORMAT_R16G16_SFLOAT:
1027  case VK_FORMAT_R16G16B16_UNORM:
1028  case VK_FORMAT_R16G16B16_SNORM:
1029  case VK_FORMAT_R16G16B16_USCALED:
1030  case VK_FORMAT_R16G16B16_SSCALED:
1031  case VK_FORMAT_R16G16B16_UINT:
1032  case VK_FORMAT_R16G16B16_SINT:
1033  case VK_FORMAT_R16G16B16_SFLOAT:
1034  case VK_FORMAT_R32_UINT:
1035  case VK_FORMAT_R32_SINT:
1036  case VK_FORMAT_R32_SFLOAT:
1037  case VK_FORMAT_R32G32_UINT:
1038  case VK_FORMAT_R32G32_SINT:
1039  case VK_FORMAT_R32G32_SFLOAT:
1040  case VK_FORMAT_R32G32B32_UINT:
1041  case VK_FORMAT_R32G32B32_SINT:
1042  case VK_FORMAT_R32G32B32_SFLOAT:
1043  case VK_FORMAT_R64_UINT:
1044  case VK_FORMAT_R64_SINT:
1045  case VK_FORMAT_R64_SFLOAT:
1046  case VK_FORMAT_R64G64_UINT:
1047  case VK_FORMAT_R64G64_SINT:
1048  case VK_FORMAT_R64G64_SFLOAT:
1049  case VK_FORMAT_R64G64B64_UINT:
1050  case VK_FORMAT_R64G64B64_SINT:
1051  case VK_FORMAT_R64G64B64_SFLOAT:
1052  case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
1053  case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
1054  case VK_FORMAT_D16_UNORM:
1055  case VK_FORMAT_X8_D24_UNORM_PACK32:
1056  case VK_FORMAT_D32_SFLOAT:
1057  case VK_FORMAT_S8_UINT:
1058  case VK_FORMAT_D16_UNORM_S8_UINT:
1059  case VK_FORMAT_D24_UNORM_S8_UINT:
1060  case VK_FORMAT_D32_SFLOAT_S8_UINT:
1061  case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
1062  case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
1063  case VK_FORMAT_BC2_UNORM_BLOCK:
1064  case VK_FORMAT_BC2_SRGB_BLOCK:
1065  case VK_FORMAT_BC3_UNORM_BLOCK:
1066  case VK_FORMAT_BC3_SRGB_BLOCK:
1067  case VK_FORMAT_BC4_UNORM_BLOCK:
1068  case VK_FORMAT_BC4_SNORM_BLOCK:
1069  case VK_FORMAT_BC5_UNORM_BLOCK:
1070  case VK_FORMAT_BC5_SNORM_BLOCK:
1071  case VK_FORMAT_BC6H_UFLOAT_BLOCK:
1072  case VK_FORMAT_BC6H_SFLOAT_BLOCK:
1073  case VK_FORMAT_BC7_UNORM_BLOCK:
1074  case VK_FORMAT_BC7_SRGB_BLOCK:
1075  case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
1076  case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
1077  case VK_FORMAT_EAC_R11_UNORM_BLOCK:
1078  case VK_FORMAT_EAC_R11_SNORM_BLOCK:
1079  case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
1080  case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
1081  case VK_FORMAT_G8B8G8R8_422_UNORM:
1082  case VK_FORMAT_B8G8R8G8_422_UNORM:
1083  case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
1084  case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
1085  case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
1086  case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
1087  case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
1088  case VK_FORMAT_R10X6_UNORM_PACK16:
1089  case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
1090  case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
1091  case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
1092  case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
1093  case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
1094  case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
1095  case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
1096  case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
1097  case VK_FORMAT_R12X4_UNORM_PACK16:
1098  case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
1099  case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
1100  case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
1101  case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
1102  case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
1103  case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
1104  case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
1105  case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
1106  case VK_FORMAT_G16B16G16R16_422_UNORM:
1107  case VK_FORMAT_B16G16R16G16_422_UNORM:
1108  case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
1109  case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
1110  case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
1111  case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
1112  case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
1113  return false;
1114 
1115  default:
1116  assert(false && "Unrecognized image format");
1117  return false;
1118  }
1119 }
1120 
1121 } // namespace talvos
uint64_t Address
The memory address of the image data.
Definition: Image.h:174
VkFormat Format
The image format.
Definition: Image.h:169
void bindAddress(uint64_t Address)
Bind a memory address to the image (can only be called once).
Definition: Image.cpp:144
This file declares the Device class.
void write(const Image::Texel &T, uint32_t X, uint32_t Y=0, uint32_t Z=0, uint32_t Layer=0, uint32_t MipLevel=0) const
Write a texel to the image view at the specified coordinate.
Definition: Image.cpp:511
This class represents an image object.
Definition: Image.h:24
uint64_t getMipLevelOffset(uint32_t Level) const
Returns the offset in bytes to the beginning of the specified mip level.
Definition: Image.cpp:167
size_t getSize() const
Returns the size of this type in bytes.
Definition: Type.h:81
bool hasAlphaChannel(VkFormat Format)
Returns true if Format includes an alpha channel.
Definition: Image.cpp:889
uint32_t BaseArrayLayer
The base array layer.
Definition: Image.h:245
const Type * getScalarType() const
Returns the element type for vector types, or this for scalar types.
Definition: Type.cpp:49
void loadUInt(const T *Data)
Load unsigned integer texel components.
Definition: Image.cpp:60
Object toObject(const Type *Ty) const
Create an object with type Ty from the texel data.
Definition: Image.cpp:135
void sample(const ImageView *Image, Image::Texel &Texel, float S, float T=0, float R=0, float A=0, float Lod=0) const
Sample a texel from an image at the specified coordinates.
Definition: Image.cpp:517
T get(unsigned C) const
Get a component value from the texel.
Definition: Image.h:44
This class represents a view into a range of image subresources.
Definition: Image.h:178
void set(unsigned C, T Value)
Set a component value in the texel.
Definition: Image.h:71
uint32_t getElementSize(VkFormat Format)
Returns the size in bytes for each element of an image with type Format.
Definition: Image.cpp:651
void write(const Texel &T, uint64_t Address) const
Write a texel to the image at the specified address.
Definition: Image.cpp:330
void storeSNorm(T *Data) const
Store normalized texel components as signed integers.
Definition: Image.cpp:89
void loadSInt(const T *Data)
Load signed integer texel components.
Definition: Image.cpp:44
uint32_t getWidth(uint32_t Level=0) const
Returns the width of the image at the specified mip level.
Definition: Image.cpp:188
uint32_t getNumArrayLayers() const
Returns the number of array layers in the image.
Definition: Image.h:135
VkExtent3D Extent
The image extent.
Definition: Image.h:170
void storeSInt(T *Data) const
Store signed integer texel components, truncating as necessary.
Definition: Image.cpp:76
VkSamplerCreateInfo Info
The sampler parameters.
Definition: Image.h:264
This class represents a single texel with four 32-bit component values.
Definition: Image.h:28
uint32_t getElementCount() const
Returns the number of elements in this array, struct, or vector type.
Definition: Type.h:64
VkFormat getFormat() const
Returns the format of the image.
Definition: Image.h:195
uint32_t getNumArrayLayers() const
Returns the number of array layers in the image view.
Definition: Image.h:204
void loadUNorm(const T *Data)
Load normalized texel components from unsigned integer data.
Definition: Image.cpp:68
const Image & getImage() const
Returns the image that the image view corresponds to.
Definition: Image.h:201
uint32_t getWidth(uint32_t Level=0) const
Get the width of the image view at the specified mip level.
Definition: Image.cpp:482
This file declares the Type class.
VkFormat Format
The format of the image view.
Definition: Image.h:243
uint32_t getDepth(uint32_t Level=0) const
Get the depth of the image view at the specified mip level.
Definition: Image.cpp:465
uint32_t NumMipLevels
The number of mip levels.
Definition: Image.h:248
ImageView(const Image &Img, VkImageViewType Type, VkFormat Format, VkImageSubresourceRange Range)
Create an image view.
Definition: Image.cpp:450
uint32_t getHeight(uint32_t Level=0) const
Returns the height of the image at the specified mip level.
Definition: Image.cpp:161
This file declares data structures and functions for handling images.
Texel()
Create a texel with uninitialized component values.
Definition: Image.h:32
void storeUNorm(T *Data) const
Store normalized texel components as unsigned integers.
Definition: Image.cpp:118
uint32_t getDepth(uint32_t Level=0) const
Returns the depth of the image at the specified mip level.
Definition: Image.cpp:150
This file declares the Object class.
void read(Texel &T, uint64_t Address) const
Read a texel from the image at the specified address.
Definition: Image.cpp:194
uint8_t * getData()
Returns a mutable pointer to the raw data backing this object.
Definition: Object.h:88
const uint8_t * getData() const
Returns a const pointer to the raw data backing the texel.
Definition: Image.h:52
const Type * getType() const
Returns the type of this object.
Definition: Object.h:101
uint32_t getHeight(uint32_t Level=0) const
Get the height of the image view at the specified mip level.
Definition: Image.cpp:470
This file declares the Memory class.
uint32_t getElementSize() const
Returns the size in bytes of a single pixel in the image.
Definition: Image.cpp:156
uint32_t NumArrayLayers
The number of array layers.
Definition: Image.h:246
bool isCube() const
Returns true if this image view corresponds to a cube map.
Definition: Image.cpp:499
Memory & getGlobalMemory()
Get the global memory instance associated with this device.
Definition: Device.h:42
void load(uint8_t *Result, uint64_t Address, uint64_t NumBytes) const
Load NumBytes of data from Address into Result.
Definition: Memory.cpp:249
Device & Dev
The device this image view is created on.
Definition: Image.h:166
uint32_t NumArrayLayers
The number of array layers.
Definition: Image.h:171
This class represents a SPIR-V type.
Definition: Type.h:33
bool is1D() const
Returns true if this image view corresponds to a 1D image.
Definition: Image.cpp:487
bool is2D() const
Returns true if this image view corresponds to a 2D image.
Definition: Image.cpp:492
void storeUInt(T *Data) const
Store unsigned integer texel components, truncating as necessary.
Definition: Image.cpp:106
uint64_t getTexelAddress(uint32_t X, uint32_t Y=0, uint32_t Z=0, uint32_t Layer=0, uint32_t MipLevel=0) const
Returns the address in memory of the texel at the specified coordinate.
Definition: Image.cpp:179
This class represents an instruction result.
Definition: Object.h:51
void store(uint64_t Address, uint64_t NumBytes, const uint8_t *Data)
Store NumBytes of data from Data to Address.
Definition: Memory.cpp:306
void loadSNorm(const T *Data)
Load normalized texel components from signed integer data.
Definition: Image.cpp:52
uint8_t Data[16]
The data backing this texel.
Definition: Image.h:97
const Image & Img
The image that the image corresponds to.
Definition: Image.h:240
uint32_t BaseMipLevel
The base mip level.
Definition: Image.h:247
void loadSFloat(const T *Data)
Load signed floating point texel components.
Definition: Image.cpp:36
bool is3D() const
Returns true if this image view corresponds to a 3D image.
Definition: Image.cpp:497
void read(Image::Texel &T, uint32_t X, uint32_t Y=0, uint32_t Z=0, uint32_t Layer=0, uint32_t MipLevel=0) const
Read a texel from the image view at the specified coordinate.
Definition: Image.cpp:505
uint32_t getNumMipLevels() const
Returns the number of mip levels in the image.
Definition: Image.h:138
uint64_t getTexelAddress(uint32_t X, uint32_t Y=0, uint32_t Z=0, uint32_t Layer=0, uint32_t MipLevel=0) const
Returns the address in memory of the texel at the specified coordinate.
Definition: Image.cpp:475