StreamingImageAssetCreator.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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/RPI.Reflect/Image/ImageMipChainAssetCreator.h>
  9. #include <Atom/RPI.Reflect/Image/StreamingImageAssetCreator.h>
  10. #include <AzCore/Asset/AssetManager.h>
  11. namespace AZ
  12. {
  13. namespace RPI
  14. {
  15. void StreamingImageAssetCreator::Begin(const Data::AssetId& assetId)
  16. {
  17. BeginCommon(assetId);
  18. m_mipLevels = 0;
  19. }
  20. void StreamingImageAssetCreator::SetImageDescriptor(const RHI::ImageDescriptor& descriptor)
  21. {
  22. if (!ValidateIsReady())
  23. {
  24. return;
  25. }
  26. if (descriptor.m_mipLevels > RHI::Limits::Image::MipCountMax)
  27. {
  28. ReportError("Exceeded the maximum number of mip levels supported by the RHI.");
  29. return;
  30. }
  31. m_asset->m_imageDescriptor = descriptor;
  32. }
  33. void StreamingImageAssetCreator::SetImageViewDescriptor(const RHI::ImageViewDescriptor& descriptor)
  34. {
  35. if (ValidateIsReady())
  36. {
  37. m_asset->m_imageViewDescriptor = descriptor;
  38. }
  39. }
  40. void StreamingImageAssetCreator::AddMipChainAsset(ImageMipChainAsset& mipChainAsset)
  41. {
  42. if (!ValidateIsReady())
  43. {
  44. return;
  45. }
  46. if (!mipChainAsset.GetId().IsValid())
  47. {
  48. ReportError("ImageMipChainAsset does not have a valid id. A valid id is required.");
  49. return;
  50. }
  51. const uint16_t mipLevelOffset = m_mipLevels;
  52. const uint16_t localMipCount = mipChainAsset.GetMipLevelCount();
  53. const uint16_t localMipBegin = m_mipLevels;
  54. const uint16_t localMipEnd = m_mipLevels + localMipCount;
  55. const uint16_t mipChainIndex = static_cast<uint16_t>(m_asset->m_mipChains.size());
  56. if (localMipEnd > RHI::Limits::Image::MipCountMax)
  57. {
  58. ReportError("Exceeded the maximum number of mip levels supported by the RHI.");
  59. return;
  60. }
  61. // Map the image mip slice indices to mip chain asset. This is likely a many-to-one mapping.
  62. for (uint16_t localMipIndex = localMipBegin; localMipIndex < localMipEnd; ++localMipIndex)
  63. {
  64. m_asset->m_mipLevelToChainIndex[localMipIndex] = mipChainIndex;
  65. }
  66. StreamingImageAsset::MipChain mipChain;
  67. mipChain.m_mipOffset = mipLevelOffset;
  68. mipChain.m_mipCount = localMipCount;
  69. // Mipchain assets are not loaded by default
  70. mipChain.m_asset = { &mipChainAsset, AZ::Data::AssetLoadBehavior::NoLoad };
  71. m_asset->m_mipChains.push_back(mipChain);
  72. m_mipLevels += localMipCount;
  73. }
  74. void StreamingImageAssetCreator::SetPoolAssetId(const Data::AssetId& poolAssetId)
  75. {
  76. if (ValidateIsReady())
  77. {
  78. m_asset->m_poolAssetId = poolAssetId;
  79. }
  80. }
  81. void StreamingImageAssetCreator::SetFlags(StreamingImageFlags flag)
  82. {
  83. if (ValidateIsReady())
  84. {
  85. m_asset->m_flags = flag;
  86. }
  87. }
  88. void StreamingImageAssetCreator::SetAverageColor(Color avgColor)
  89. {
  90. if (ValidateIsReady())
  91. {
  92. m_asset->m_averageColor = avgColor;
  93. }
  94. }
  95. void StreamingImageAssetCreator::AddTag(AZ::Name tag)
  96. {
  97. if (ValidateIsReady())
  98. {
  99. // add tag if it doesn't already exist
  100. if (auto it = AZStd::find(m_asset->m_tags.begin(), m_asset->m_tags.end(), tag); it == m_asset->m_tags.end())
  101. {
  102. m_asset->m_tags.push_back(AZStd::move(tag));
  103. }
  104. }
  105. }
  106. bool StreamingImageAssetCreator::End(Data::Asset<StreamingImageAsset>& result)
  107. {
  108. if (!ValidateIsReady())
  109. {
  110. return false;
  111. }
  112. const RHI::ImageDescriptor& imageDescriptor = m_asset->GetImageDescriptor();
  113. const uint16_t expectedMipLevels = imageDescriptor.m_mipLevels;
  114. if (m_mipLevels != expectedMipLevels)
  115. {
  116. ReportError("Expected %u mip levels, but %u were added through mip chains.", expectedMipLevels, m_mipLevels);
  117. return false;
  118. }
  119. size_t totalImageBytes = 0;
  120. for (const StreamingImageAsset::MipChain& mipChain : m_asset->m_mipChains)
  121. {
  122. totalImageBytes += mipChain.m_asset->GetImageDataSize();
  123. }
  124. m_asset->m_totalImageDataSize = aznumeric_cast<uint32_t>(totalImageBytes);
  125. Data::Asset<ImageMipChainAsset> mipChainTail(m_asset->m_mipChains.back().m_asset);
  126. m_asset->m_tailMipChain.CopyFrom(*mipChainTail.Get());
  127. m_asset->m_mipChains.back().m_asset = Data::Asset<ImageMipChainAsset>();
  128. // If the streaming image is not streamable, it should have one and only one mip chain
  129. if (RHI::CheckBitsAny(m_asset->GetFlags(), StreamingImageFlags::NotStreamable) && m_asset->GetMipChainCount() != 1)
  130. {
  131. ReportError("Expected only one mip chain asset for non-streamable streaming image");
  132. return false;
  133. }
  134. m_asset->SetReady();
  135. return EndCommon(result);
  136. }
  137. }
  138. }