You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetCreator.cpp

147 lines
5.0 KiB
C++

/*
* 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 <Atom/RPI.Reflect/Image/ImageMipChainAssetCreator.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAssetCreator.h>
#include <AzCore/Asset/AssetManager.h>
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<uint16_t>(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<StreamingImageAsset>& 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<uint32_t>(totalImageBytes);
Data::Asset<ImageMipChainAsset> mipChainTail(m_asset->m_mipChains.back().m_asset);
m_asset->m_tailMipChain.CopyFrom(*mipChainTail.Get());
m_asset->m_mipChains.back().m_asset = Data::Asset<ImageMipChainAsset>();
// 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);
}
}
}