Texture.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 
  2. // zlib open source license
  3. //
  4. // Copyright (c) 2025 David Forsgren Piuva
  5. //
  6. // This software is provided 'as-is', without any express or implied
  7. // warranty. In no event will the authors be held liable for any damages
  8. // arising from the use of this software.
  9. //
  10. // Permission is granted to anyone to use this software for any purpose,
  11. // including commercial applications, and to alter it and redistribute it
  12. // freely, subject to the following restrictions:
  13. //
  14. // 1. The origin of this software must not be misrepresented; you must not
  15. // claim that you wrote the original software. If you use this software
  16. // in a product, an acknowledgment in the product documentation would be
  17. // appreciated but is not required.
  18. //
  19. // 2. Altered source versions must be plainly marked as such, and must not be
  20. // misrepresented as being the original software.
  21. //
  22. // 3. This notice may not be removed or altered from any source
  23. // distribution.
  24. #ifndef DFPSR_TEXTURE_TYPES
  25. #define DFPSR_TEXTURE_TYPES
  26. #include "Image.h"
  27. #include "../../base/noSimd.h" // Scalar versions of the SIMD functions for creating template functions both with and without SIMD.
  28. #include "../../base/DsrTraits.h" // Scalar versions of the SIMD functions for creating template functions both with and without SIMD.
  29. #include "../math/scalar.h"
  30. namespace dsr {
  31. // MIP is a latin acronym "multum in parvo" meaning much in little.
  32. static const uint32_t DSR_MIP_LEVEL_COUNT = 16;
  33. // Mip index 0 is full resolution.
  34. // Mip index 1 is half resolution.
  35. // Mip index 2 is quarter resolution.
  36. // ...
  37. struct Texture {
  38. Buffer impl_buffer;
  39. // Base-two logarithms of the highest resolution.
  40. uint32_t impl_log2width = 0;
  41. uint32_t impl_log2height = 0;
  42. // Mip level indices from 0 to impl_maxMipLevel.
  43. uint32_t impl_maxMipLevel = 0;
  44. // Number of pixels before the largest mip level.
  45. uint32_t impl_startOffset = 0;
  46. uint32_t impl_maxLevelMask = 0;
  47. // Tiling of unsigned pixel coordinates using bit masks.
  48. uint32_t impl_minWidthOrMask = 0;
  49. uint32_t impl_minHeightOrMask = 0;
  50. uint32_t impl_maxWidthAndMask = 0;
  51. uint32_t impl_maxHeightAndMask = 0;
  52. // Maximum dimensions for calculating mip level.
  53. float impl_floatMaxWidth = 0.0f;
  54. float impl_floatMaxHeight = 0.0f;
  55. // What each pixel contains.
  56. uint8_t impl_pixelFormat = 0;
  57. Texture() {}
  58. // TODO: Allow creating a single layer from an existing pixel buffer, which must be free from padding.
  59. // If not using multi-threading to write to an image, one can use less than a cache line for alignment.
  60. // Store a bit in image saying if the image is a thread-safe write target with cache aligned rows.
  61. Texture(uint32_t log2width, uint32_t log2height, uint32_t maxMipLevel, PixelFormat format, uint32_t pixelSize)
  62. : impl_log2width(log2width), impl_log2height(log2height), impl_maxMipLevel(maxMipLevel), impl_pixelFormat(uint8_t(format)) {
  63. if (maxMipLevel < 0) maxMipLevel = 0;
  64. if (maxMipLevel >= DSR_MIP_LEVEL_COUNT) maxMipLevel = DSR_MIP_LEVEL_COUNT - 1;
  65. if ((int32_t)log2width - maxMipLevel < 0 || (int32_t)log2height - maxMipLevel < 0) {
  66. // TODO: Indicate failure.
  67. this->impl_pixelFormat = 0;
  68. } else {
  69. uint32_t highestLayerPixelCount = uint32_t(1) << (log2width + log2height);
  70. uint64_t pixelCount = 0;
  71. uint32_t levelPixelCount = highestLayerPixelCount;
  72. for (int32_t level = maxMipLevel; level >= 0; level--) {
  73. pixelCount = pixelCount | levelPixelCount;
  74. levelPixelCount = levelPixelCount >> 2;
  75. }
  76. if (pixelCount > 4294967296) {
  77. // TODO: Indicate failure to index pixels using 32-bit gather.
  78. } else {
  79. this->impl_startOffset = (uint32_t)pixelCount & ~highestLayerPixelCount;
  80. this->impl_maxLevelMask = highestLayerPixelCount - 1;
  81. this->impl_minWidthOrMask = (uint32_t(1) << (log2width - maxMipLevel)) - 1;
  82. this->impl_minHeightOrMask = (uint32_t(1) << (log2height - maxMipLevel)) - 1;
  83. this->impl_maxWidthAndMask = (uint32_t(1) << log2width) - 1;
  84. this->impl_maxHeightAndMask = (uint32_t(1) << log2height) - 1;
  85. this->impl_floatMaxWidth = float((uint32_t(1) << log2width));
  86. this->impl_floatMaxHeight = float((uint32_t(1) << log2height));
  87. this->impl_buffer = buffer_create((uint32_t)pixelCount * pixelSize);
  88. }
  89. }
  90. }
  91. };
  92. struct TextureRgbaU8 : public Texture {
  93. TextureRgbaU8() {}
  94. TextureRgbaU8(uint32_t log2width, uint32_t log2height, uint32_t maxMipLevel = DSR_MIP_LEVEL_COUNT - 1)
  95. : Texture(log2width, log2height, min(log2width, log2height, maxMipLevel), PixelFormat::RgbaU8, sizeof(uint32_t)) {}
  96. };
  97. }
  98. #endif