/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include namespace AZ { namespace RPI { void StreamingImageAssetCreator::Begin(const Data::AssetId& assetId) { BeginCommon(assetId); m_mipLevels = 0; } void StreamingImageAssetCreator::SetImageDescriptor(const RHI::ImageDescriptor& descriptor) { if (!ValidateIsReady()) { return; } if (descriptor.m_mipLevels > RHI::Limits::Image::MipCountMax) { ReportError("Exceeded the maximum number of mip levels supported by the RHI."); return; } m_asset->m_imageDescriptor = descriptor; } void StreamingImageAssetCreator::SetImageViewDescriptor(const RHI::ImageViewDescriptor& descriptor) { if (ValidateIsReady()) { m_asset->m_imageViewDescriptor = descriptor; } } void StreamingImageAssetCreator::AddMipChainAsset(ImageMipChainAsset& mipChainAsset) { if (!ValidateIsReady()) { return; } if (!mipChainAsset.GetId().IsValid()) { ReportError("ImageMipChainAsset does not have a valid id. A valid id is required."); return; } const uint16_t mipLevelOffset = m_mipLevels; const uint16_t localMipCount = mipChainAsset.GetMipLevelCount(); const uint16_t localMipBegin = m_mipLevels; const uint16_t localMipEnd = m_mipLevels + localMipCount; const uint16_t mipChainIndex = static_cast(m_asset->m_mipChains.size()); if (localMipEnd > RHI::Limits::Image::MipCountMax) { ReportError("Exceeded the maximum number of mip levels supported by the RHI."); return; } // Map the image mip slice indices to mip chain asset. This is likely a many-to-one mapping. for (uint16_t localMipIndex = localMipBegin; localMipIndex < localMipEnd; ++localMipIndex) { m_asset->m_mipLevelToChainIndex[localMipIndex] = mipChainIndex; } StreamingImageAsset::MipChain mipChain; mipChain.m_mipOffset = mipLevelOffset; mipChain.m_mipCount = localMipCount; // Mipchain assets are not loaded by default mipChain.m_asset = { &mipChainAsset, AZ::Data::AssetLoadBehavior::NoLoad }; m_asset->m_mipChains.push_back(mipChain); m_mipLevels += localMipCount; } void StreamingImageAssetCreator::SetPoolAssetId(const Data::AssetId& poolAssetId) { if (ValidateIsReady()) { m_asset->m_poolAssetId = poolAssetId; } } void StreamingImageAssetCreator::SetFlags(StreamingImageFlags flag) { if (ValidateIsReady()) { m_asset->m_flags = flag; } } bool StreamingImageAssetCreator::End(Data::Asset& result) { if (!ValidateIsReady()) { return false; } const RHI::ImageDescriptor& imageDescriptor = m_asset->GetImageDescriptor(); const uint16_t expectedMipLevels = imageDescriptor.m_mipLevels; if (m_mipLevels != expectedMipLevels) { ReportError("Expected %d mip levels, but %d were added through mip chains.", expectedMipLevels, m_mipLevels); return false; } size_t totalImageBytes = 0; for (const StreamingImageAsset::MipChain& mipChain : m_asset->m_mipChains) { totalImageBytes += mipChain.m_asset->GetImageDataSize(); } m_asset->m_totalImageDataSize = aznumeric_cast(totalImageBytes); Data::Asset mipChainTail(m_asset->m_mipChains.back().m_asset); m_asset->m_tailMipChain.CopyFrom(*mipChainTail.Get()); m_asset->m_mipChains.back().m_asset = Data::Asset(); // If the streaming image is not streamable, it should have one and only one mip chain if (RHI::CheckBitsAny(m_asset->GetFlags(), StreamingImageFlags::NotStreamable) && m_asset->GetMipChainCount() != 1) { ReportError("Expected only one mip chain asset for non-streamable streaming image"); return false; } m_asset->SetReady(); return EndCommon(result); } } }