ImageSubresource.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. #include <Atom/RHI.Reflect/ImageSubresource.h>
  9. #include <Atom/RHI.Reflect/ImageDescriptor.h>
  10. #include <Atom/RHI.Reflect/ImageViewDescriptor.h>
  11. #include <Atom/RHI/RHISystemInterface.h>
  12. #include <AzCore/std/algorithm.h>
  13. #include <AzCore/Serialization/SerializeContext.h>
  14. namespace AZ::RHI
  15. {
  16. ImageSubresource::ImageSubresource(uint16_t mipSlice, uint16_t arraySlice)
  17. : m_mipSlice{mipSlice}
  18. , m_arraySlice{arraySlice}
  19. {}
  20. ImageSubresource::ImageSubresource(uint16_t mipSlice, uint16_t arraySlice, ImageAspect aspect)
  21. : m_mipSlice{ mipSlice }
  22. , m_arraySlice{ arraySlice }
  23. , m_aspect{ aspect }
  24. {}
  25. void ImageSubresource::Reflect(AZ::ReflectContext* context)
  26. {
  27. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  28. {
  29. serializeContext->Class<ImageSubresource>()
  30. ->Version(0)
  31. ->Field("m_mipSlice", &ImageSubresource::m_mipSlice)
  32. ->Field("m_arraySlice", &ImageSubresource::m_arraySlice)
  33. ->Field("m_aspect", &ImageSubresource::m_aspect)
  34. ;
  35. }
  36. }
  37. ImageSubresourceRange::ImageSubresourceRange(
  38. uint16_t mipSliceMin,
  39. uint16_t mipSliceMax,
  40. uint16_t arraySliceMin,
  41. uint16_t arraySliceMax)
  42. : m_mipSliceMin{mipSliceMin}
  43. , m_mipSliceMax{mipSliceMax}
  44. , m_arraySliceMin{arraySliceMin}
  45. , m_arraySliceMax{arraySliceMax}
  46. {}
  47. ImageSubresourceRange::ImageSubresourceRange(const ImageDescriptor& descriptor)
  48. : m_mipSliceMin{ 0 }
  49. , m_mipSliceMax{ aznumeric_caster(descriptor.m_mipLevels - 1) }
  50. , m_arraySliceMin{ 0 }
  51. , m_arraySliceMax{ aznumeric_caster(descriptor.m_arraySize - 1) }
  52. , m_aspectFlags{ GetImageAspectFlags(descriptor.m_format) }
  53. {
  54. }
  55. ImageSubresourceRange::ImageSubresourceRange(const ImageViewDescriptor& descriptor)
  56. : m_mipSliceMin{ descriptor.m_mipSliceMin }
  57. , m_mipSliceMax{ descriptor.m_mipSliceMax }
  58. , m_arraySliceMin{ descriptor.m_arraySliceMin }
  59. , m_arraySliceMax{ descriptor.m_arraySliceMax }
  60. , m_aspectFlags{ descriptor.m_aspectFlags }
  61. {
  62. }
  63. bool ImageSubresourceRange::operator==(const ImageSubresourceRange& other) const
  64. {
  65. return
  66. m_mipSliceMin == other.m_mipSliceMin &&
  67. m_mipSliceMax == other.m_mipSliceMax &&
  68. m_arraySliceMin == other.m_arraySliceMin &&
  69. m_arraySliceMax == other.m_arraySliceMax &&
  70. m_aspectFlags == other.m_aspectFlags;
  71. }
  72. AZ::HashValue64 ImageSubresourceRange::GetHash(AZ::HashValue64 seed) const
  73. {
  74. return TypeHash64(*this, seed);
  75. }
  76. void ImageSubresourceRange::Reflect(AZ::ReflectContext* context)
  77. {
  78. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  79. {
  80. serializeContext->Class<ImageSubresourceRange>()
  81. ->Version(0)
  82. ->Field("m_mipSliceMin", &ImageSubresourceRange::m_mipSliceMin)
  83. ->Field("m_mipSliceMax", &ImageSubresourceRange::m_mipSliceMax)
  84. ->Field("m_arraySliceMin", &ImageSubresourceRange::m_arraySliceMin)
  85. ->Field("m_arraySliceMax", &ImageSubresourceRange::m_arraySliceMax)
  86. ->Field("m_aspectFlags", &ImageSubresourceRange::m_aspectFlags)
  87. ;
  88. }
  89. }
  90. void DeviceImageSubresourceLayout::Reflect(AZ::ReflectContext* context)
  91. {
  92. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  93. {
  94. serializeContext->Class<DeviceImageSubresourceLayout>()
  95. ->Version(2)
  96. ->Field("m_size", &DeviceImageSubresourceLayout::m_size)
  97. ->Field("m_rowCount", &DeviceImageSubresourceLayout::m_rowCount)
  98. ->Field("m_bytesPerRow", &DeviceImageSubresourceLayout::m_bytesPerRow)
  99. ->Field("m_bytesPerImage", &DeviceImageSubresourceLayout::m_bytesPerImage)
  100. ->Field("m_blockElementWidth", &DeviceImageSubresourceLayout::m_blockElementWidth)
  101. ->Field("m_blockElementHeight", &DeviceImageSubresourceLayout::m_blockElementHeight)
  102. ->Field("m_offset", &DeviceImageSubresourceLayout::m_offset)
  103. ;
  104. }
  105. }
  106. DeviceImageSubresourceLayout::DeviceImageSubresourceLayout(
  107. Size size,
  108. uint32_t rowCount,
  109. uint32_t bytesPerRow,
  110. uint32_t bytesPerImage,
  111. uint32_t blockElementWidth,
  112. uint32_t blockElementHeight,
  113. uint32_t offset)
  114. : m_size{size}
  115. , m_rowCount{rowCount}
  116. , m_bytesPerRow{bytesPerRow}
  117. , m_bytesPerImage{bytesPerImage}
  118. , m_blockElementWidth{blockElementWidth}
  119. , m_blockElementHeight{blockElementHeight}
  120. , m_offset{offset}
  121. {}
  122. DeviceImageSubresourceLayout GetImageSubresourceLayout(Size imageSize, Format imageFormat)
  123. {
  124. DeviceImageSubresourceLayout subresourceLayout;
  125. bool isBlockCompressed = false;
  126. bool isPacked = false;
  127. bool isPlanar = false;
  128. uint32_t bytesPerElement = 0; //For block compressions this is bytesPerBlock
  129. uint32_t numBlocks = 0;
  130. switch (imageFormat)
  131. {
  132. case Format::R32G32B32A32_FLOAT:
  133. case Format::R32G32B32A32_UINT:
  134. case Format::R32G32B32A32_SINT:
  135. case Format::R32G32B32_FLOAT:
  136. case Format::R32G32B32_UINT:
  137. case Format::R32G32B32_SINT:
  138. case Format::R16G16B16A16_FLOAT:
  139. case Format::R16G16B16A16_UNORM:
  140. case Format::R16G16B16A16_UINT:
  141. case Format::R16G16B16A16_SNORM:
  142. case Format::R16G16B16A16_SINT:
  143. case Format::R32G32_FLOAT:
  144. case Format::R32G32_UINT:
  145. case Format::R32G32_SINT:
  146. case Format::D32_FLOAT_S8X24_UINT:
  147. case Format::R10G10B10A2_UNORM:
  148. case Format::R10G10B10A2_UINT:
  149. case Format::R11G11B10_FLOAT:
  150. case Format::R8G8B8A8_UNORM:
  151. case Format::R8G8B8A8_UNORM_SRGB:
  152. case Format::R8G8B8A8_UINT:
  153. case Format::R8G8B8A8_SNORM:
  154. case Format::R8G8B8A8_SINT:
  155. case Format::R16G16_FLOAT:
  156. case Format::R16G16_UNORM:
  157. case Format::R16G16_UINT:
  158. case Format::R16G16_SNORM:
  159. case Format::R16G16_SINT:
  160. case Format::D32_FLOAT:
  161. case Format::R32_FLOAT:
  162. case Format::R32_UINT:
  163. case Format::R32_SINT:
  164. case Format::D24_UNORM_S8_UINT:
  165. case Format::B8G8R8A8_UNORM:
  166. case Format::B8G8R8X8_UNORM:
  167. case Format::B8G8R8A8_UNORM_SRGB:
  168. case Format::B8G8R8X8_UNORM_SRGB:
  169. case Format::R8G8_UNORM:
  170. case Format::R8G8_UINT:
  171. case Format::R8G8_SNORM:
  172. case Format::R8G8_SINT:
  173. case Format::R16_FLOAT:
  174. case Format::D16_UNORM:
  175. case Format::R16_UNORM:
  176. case Format::R16_UINT:
  177. case Format::R16_SNORM:
  178. case Format::R16_SINT:
  179. case Format::R8_UNORM:
  180. case Format::R8_UINT:
  181. case Format::R8_SNORM:
  182. case Format::R8_SINT:
  183. case Format::A8_UNORM:
  184. case Format::R1_UNORM:
  185. case Format::R9G9B9E5_SHAREDEXP:
  186. break;
  187. case RHI::Format::BC1_UNORM:
  188. case RHI::Format::BC1_UNORM_SRGB:
  189. case RHI::Format::BC4_UNORM:
  190. case RHI::Format::BC4_SNORM:
  191. isBlockCompressed = true;
  192. bytesPerElement = 8;
  193. numBlocks = 4;
  194. break;
  195. case RHI::Format::BC2_UNORM:
  196. case RHI::Format::BC2_UNORM_SRGB:
  197. case RHI::Format::BC3_UNORM:
  198. case RHI::Format::BC3_UNORM_SRGB:
  199. case RHI::Format::BC5_UNORM:
  200. case RHI::Format::BC5_SNORM:
  201. case RHI::Format::BC6H_UF16:
  202. case RHI::Format::BC6H_SF16:
  203. case RHI::Format::BC7_UNORM:
  204. case RHI::Format::BC7_UNORM_SRGB:
  205. case RHI::Format::ASTC_4x4_UNORM:
  206. case RHI::Format::ASTC_4x4_UNORM_SRGB:
  207. isBlockCompressed = true;
  208. bytesPerElement = 16;
  209. numBlocks = 4;
  210. break;
  211. case RHI::Format::ASTC_6x6_UNORM:
  212. case RHI::Format::ASTC_6x6_UNORM_SRGB:
  213. isBlockCompressed = true;
  214. bytesPerElement = 16;
  215. numBlocks = 6;
  216. break;
  217. case RHI::Format::ASTC_8x8_UNORM:
  218. case RHI::Format::ASTC_8x8_UNORM_SRGB:
  219. isBlockCompressed = true;
  220. bytesPerElement = 16;
  221. numBlocks = 8;
  222. break;
  223. case RHI::Format::ASTC_10x10_UNORM:
  224. case RHI::Format::ASTC_10x10_UNORM_SRGB:
  225. isBlockCompressed = true;
  226. bytesPerElement = 16;
  227. numBlocks = 10;
  228. break;
  229. case RHI::Format::ASTC_12x12_UNORM:
  230. case RHI::Format::ASTC_12x12_UNORM_SRGB:
  231. isBlockCompressed = true;
  232. bytesPerElement = 16;
  233. numBlocks = 12;
  234. break;
  235. case RHI::Format::R8G8_B8G8_UNORM:
  236. case RHI::Format::G8R8_G8B8_UNORM:
  237. case RHI::Format::YUY2:
  238. isPacked = true;
  239. bytesPerElement = 4;
  240. break;
  241. case RHI::Format::Y210:
  242. case RHI::Format::Y216:
  243. isPacked = true;
  244. bytesPerElement = 8;
  245. break;
  246. case RHI::Format::NV12:
  247. break;
  248. case RHI::Format::P010:
  249. case RHI::Format::P016:
  250. isPlanar = true;
  251. bytesPerElement = 4;
  252. break;
  253. case RHI::Format::ETC2_UNORM:
  254. case RHI::Format::ETC2_UNORM_SRGB:
  255. case RHI::Format::ETC2A1_UNORM:
  256. case RHI::Format::ETC2A1_UNORM_SRGB:
  257. isBlockCompressed = true;
  258. bytesPerElement = 8;
  259. numBlocks = 4;
  260. break;
  261. case RHI::Format::ETC2A_UNORM:
  262. case RHI::Format::ETC2A_UNORM_SRGB:
  263. isBlockCompressed = true;
  264. bytesPerElement = 16;
  265. numBlocks = 4;
  266. break;
  267. case RHI::Format::EAC_R11_UNORM:
  268. case RHI::Format::EAC_R11_SNORM:
  269. isBlockCompressed = true;
  270. bytesPerElement = 8;
  271. numBlocks = 4;
  272. break;
  273. case RHI::Format::EAC_RG11_UNORM:
  274. case RHI::Format::EAC_RG11_SNORM:
  275. isBlockCompressed = true;
  276. bytesPerElement = 16;
  277. numBlocks = 4;
  278. break;
  279. default:
  280. AZ_Assert(false, "Unimplemented esoteric format %i.", static_cast<int>(imageFormat));
  281. }
  282. if (isBlockCompressed)
  283. {
  284. uint32_t numBlocksWide = 0;
  285. if (imageSize.m_width > 0)
  286. {
  287. numBlocksWide = AZStd::max<uint32_t>(1, (imageSize.m_width + (numBlocks - 1)) / numBlocks);
  288. }
  289. uint32_t numBlocksHigh = 0;
  290. if (imageSize.m_height > 0)
  291. {
  292. numBlocksHigh = AZStd::max<uint32_t>(1, (imageSize.m_height + (numBlocks - 1)) / numBlocks);
  293. }
  294. subresourceLayout.m_bytesPerRow = numBlocksWide * bytesPerElement;
  295. subresourceLayout.m_rowCount = numBlocksHigh;
  296. subresourceLayout.m_size.m_width = imageSize.m_width;
  297. subresourceLayout.m_size.m_height = imageSize.m_height;
  298. subresourceLayout.m_blockElementWidth = numBlocks;
  299. subresourceLayout.m_blockElementHeight = numBlocks;
  300. }
  301. else if (isPacked)
  302. {
  303. subresourceLayout.m_bytesPerRow = ((imageSize.m_width + 1) >> 1) * bytesPerElement;
  304. subresourceLayout.m_rowCount = imageSize.m_height;
  305. subresourceLayout.m_size.m_width = imageSize.m_width;
  306. subresourceLayout.m_size.m_height = imageSize.m_height;
  307. }
  308. else if (imageFormat == RHI::Format::NV11)
  309. {
  310. subresourceLayout.m_bytesPerRow = ((imageSize.m_width + 3) >> 2) * 4;
  311. subresourceLayout.m_rowCount = imageSize.m_height * 2;
  312. subresourceLayout.m_size.m_width = AlignUp(imageSize.m_width, 2);
  313. subresourceLayout.m_size.m_height = AlignUp(imageSize.m_height, 2);
  314. }
  315. else if (isPlanar)
  316. {
  317. subresourceLayout.m_bytesPerRow = ((imageSize.m_width + 1) >> 1) * bytesPerElement;
  318. subresourceLayout.m_rowCount = imageSize.m_height + ((imageSize.m_height + 1) >> 1);
  319. subresourceLayout.m_size.m_width = AlignUp(imageSize.m_width, 2);
  320. subresourceLayout.m_size.m_height = AlignUp(imageSize.m_height, 2);
  321. }
  322. else
  323. {
  324. subresourceLayout.m_bytesPerRow = imageSize.m_width * RHI::GetFormatSize(imageFormat);
  325. subresourceLayout.m_rowCount = imageSize.m_height;
  326. subresourceLayout.m_size.m_width = imageSize.m_width;
  327. subresourceLayout.m_size.m_height = imageSize.m_height;
  328. }
  329. subresourceLayout.m_bytesPerImage = subresourceLayout.m_bytesPerRow * subresourceLayout.m_rowCount;
  330. subresourceLayout.m_size.m_depth = imageSize.m_depth;
  331. return subresourceLayout;
  332. }
  333. DeviceImageSubresourceLayout GetImageSubresourceLayout(const ImageDescriptor& imageDescriptor, const ImageSubresource& subresource)
  334. {
  335. return GetImageSubresourceLayout(imageDescriptor.m_size.GetReducedMip(subresource.m_mipSlice), imageDescriptor.m_format);
  336. }
  337. uint32_t GetImageSubresourceIndex(uint32_t mipSlice, uint32_t arraySlice, uint32_t mipLevels)
  338. {
  339. return mipSlice + arraySlice * mipLevels;
  340. }
  341. uint32_t GetImageSubresourceIndex(ImageSubresource subresource, uint32_t mipLevels)
  342. {
  343. return GetImageSubresourceIndex(subresource.m_mipSlice, subresource.m_arraySlice, mipLevels);
  344. }
  345. }