3
0

PixelFormatInfo.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <Processing/AzDXGIFormat.h> // DX10+ formats. DXGI_FORMAT
  10. #include <Atom/ImageProcessing/PixelFormats.h>
  11. #include <AzCore/std/containers/map.h>
  12. #include <AzCore/std/string/string.h>
  13. #include <ImageBuilderBaseType.h>
  14. namespace ImageProcessingAtom
  15. {
  16. //The original implementation was from cryhalf's CryConvertFloatToHalf and CryConvertHalfToFloat function
  17. struct SHalf
  18. {
  19. explicit SHalf(float floatValue)
  20. {
  21. AZ::u32 Result;
  22. AZ::u32 intValue = ((AZ::u32*)(&floatValue))[0];
  23. AZ::u32 Sign = (intValue & 0x80000000U) >> 16U;
  24. intValue = intValue & 0x7FFFFFFFU;
  25. if (intValue > 0x47FFEFFFU)
  26. {
  27. // The number is too large to be represented as a half. Saturate to infinity.
  28. Result = 0x7FFFU;
  29. }
  30. else
  31. {
  32. if (intValue < 0x38800000U)
  33. {
  34. // The number is too small to be represented as a normalized half.
  35. // Convert it to a denormalized value.
  36. AZ::u32 Shift = 113U - (intValue >> 23U);
  37. intValue = (0x800000U | (intValue & 0x7FFFFFU)) >> Shift;
  38. }
  39. else
  40. {
  41. // Rebias the exponent to represent the value as a normalized half.
  42. intValue += 0xC8000000U;
  43. }
  44. Result = ((intValue + 0x0FFFU + ((intValue >> 13U) & 1U)) >> 13U) & 0x7FFFU;
  45. }
  46. h = static_cast<AZ::u16>(Result | Sign);
  47. }
  48. operator float() const
  49. {
  50. AZ::u32 Mantissa;
  51. AZ::u32 Exponent;
  52. AZ::u32 Result;
  53. Mantissa = h & 0x03FF;
  54. if ((h & 0x7C00) != 0) // The value is normalized
  55. {
  56. Exponent = ((h >> 10) & 0x1F);
  57. }
  58. else if (Mantissa != 0) // The value is denormalized
  59. {
  60. // Normalize the value in the resulting float
  61. Exponent = 1;
  62. do
  63. {
  64. Exponent--;
  65. Mantissa <<= 1;
  66. } while ((Mantissa & 0x0400) == 0);
  67. Mantissa &= 0x03FF;
  68. }
  69. else // The value is zero
  70. {
  71. Exponent = static_cast<AZ::u32>(-112);
  72. }
  73. Result = ((h & 0x8000) << 16) | // Sign
  74. ((Exponent + 112) << 23) | // Exponent
  75. (Mantissa << 13); // Mantissa
  76. return *(float*)&Result;
  77. }
  78. private:
  79. AZ::u16 h;
  80. };
  81. enum class ESampleType
  82. {
  83. eSampleType_Uint8,
  84. eSampleType_Uint16,
  85. eSampleType_Uint32,
  86. eSampleType_Half,
  87. eSampleType_Float,
  88. eSampleType_Compressed,
  89. };
  90. struct PixelFormatInfo
  91. {
  92. uint32_t nChannels; // channel count per pixel
  93. bool bHasAlpha; // has alpha channel or not
  94. const char* szAlpha; // a string of bits of alpha channel used to show brief of the pixel format
  95. uint32_t minWidth; // minimum width required for image using this pixel format
  96. uint32_t minHeight; // minimum height required for image using this pixel format
  97. uint32_t blockWidth; // width of the block for block based compressing
  98. uint32_t blockHeight; // Height of the block for block based compressing
  99. uint32_t bitsPerBlock; // bits per pixel before uncompressed
  100. bool bSquarePow2; // whether the pixel format requires image size be square and power of 2.
  101. DXGI_FORMAT d3d10Format; // the mapping d3d10 pixel format
  102. ESampleType eSampleType; // the data type used to present pixel
  103. const char* szName; // name for showing in editors
  104. const char* szDescription; // description for showing in editors
  105. bool bCompressed; // if it's a compressed format
  106. bool bSelectable; // shows up in the list of usable destination pixel formats in the dialog window
  107. uint32_t fourCC; // fourCC to identify a none d3d10 format
  108. PixelFormatInfo()
  109. : szAlpha(0)
  110. , bitsPerBlock(0)
  111. , d3d10Format(DXGI_FORMAT_UNKNOWN)
  112. , szName(0)
  113. , szDescription(0)
  114. , fourCC(0)
  115. {
  116. }
  117. PixelFormatInfo(
  118. uint32_t a_bitsPerPixel,
  119. uint32_t a_Channels,
  120. bool a_Alpha,
  121. const char* a_szAlpha,
  122. uint32_t a_minWidth,
  123. uint32_t a_minHeight,
  124. uint32_t a_blockWidth,
  125. uint32_t a_blockHeight,
  126. uint32_t a_bitsPerBlock,
  127. bool a_bSquarePow2,
  128. DXGI_FORMAT a_d3d10Format,
  129. uint32_t a_fourCC,
  130. ESampleType a_eSampleType,
  131. const char* a_szName,
  132. const char* a_szDescription,
  133. bool a_bCompressed,
  134. bool a_bSelectable);
  135. };
  136. class CPixelFormats
  137. {
  138. public:
  139. //singleton
  140. static CPixelFormats& GetInstance();
  141. static void DestroyInstance();
  142. const PixelFormatInfo* GetPixelFormatInfo(EPixelFormat format);
  143. bool IsPixelFormatWithoutAlpha(EPixelFormat format);
  144. bool IsPixelFormatUncompressed(EPixelFormat format);
  145. //functions seems only used for BC compressions. need re-evaluate later
  146. bool IsFormatSingleChannel(EPixelFormat fmt);
  147. bool IsFormatSigned(EPixelFormat fmt);
  148. bool IsFormatFloatingPoint(EPixelFormat fmt, bool bFullPrecision);
  149. //find pixel format by its name
  150. EPixelFormat FindPixelFormatByName(const char* name);
  151. //returns maximum lod levels for image which has certain pixel format, width and height.
  152. uint32 ComputeMaxMipCount(EPixelFormat format, uint32 imageWidth, uint32 imageHeight, uint32_t imageDepth = 1);
  153. //check if the input image size work with the pixel format. Some compression formats have requirements with the input image size.
  154. bool IsImageSizeValid(EPixelFormat format, uint32 imageWidth, uint32 imageHeight, bool logWarning);
  155. //get suitable new size for an image with certain width, height and pixel format
  156. void GetSuitableImageSize(EPixelFormat format, AZ::u32 imageWidth, AZ::u32 imageHeight,
  157. AZ::u32& outWidth, AZ::u32& outHeight);
  158. //check if the image size of the specified pixel format need to be integer mutiple of block size
  159. bool CanImageSizeIgnoreBlockSize(EPixelFormat format);
  160. //eavluate image data size. it doesn't include mips
  161. uint32 EvaluateImageDataSize(EPixelFormat format, uint32 imageWidth, uint32 imageHeight);
  162. private:
  163. CPixelFormats();
  164. void InitPixelFormats();
  165. void InitPixelFormat(EPixelFormat format, const PixelFormatInfo& formatInfo);
  166. private:
  167. static CPixelFormats* s_instance;
  168. PixelFormatInfo m_pixelFormatInfo[ePixelFormat_Count];
  169. //pixel format name to pixel format enum
  170. AZStd::map<AZStd::string, EPixelFormat> m_pixelFormatNameMap;
  171. };
  172. template <class TInteger>
  173. bool IsPowerOfTwo(TInteger x);
  174. } // namespace ImageProcessingAtom