/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AZ { namespace RPI { ImageSystemInterface* ImageSystemInterface::Get() { return Interface::Get(); } void ImageSystem::Reflect(AZ::ReflectContext* context) { ImageAsset::Reflect(context); ImageMipChainAsset::Reflect(context); ImageSystemDescriptor::Reflect(context); StreamingImageAsset::Reflect(context); StreamingImagePoolAsset::Reflect(context); StreamingImageControllerAsset::Reflect(context); DefaultStreamingImageControllerAsset::Reflect(context); AttachmentImageAsset::Reflect(context); } void ImageSystem::GetAssetHandlers(AssetHandlerPtrList& assetHandlers) { assetHandlers.emplace_back(MakeAssetHandler()); assetHandlers.emplace_back(MakeAssetHandler()); assetHandlers.emplace_back(MakeAssetHandler()); assetHandlers.emplace_back(MakeAssetHandler()); assetHandlers.emplace_back(MakeAssetHandler( azrtti_typeid(), []() { return aznew DefaultStreamingImageControllerAsset(); })); } void ImageSystem::Init(const ImageSystemDescriptor& desc) { RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); // Register attachment image instance database. { Data::InstanceHandler handler; handler.m_createFunction = [](Data::AssetData* imageAsset) { return AttachmentImage::CreateInternal(*(azrtti_cast(imageAsset))); }; Data::InstanceDatabase::Create(azrtti_typeid(), handler); } { Data::InstanceHandler handler; handler.m_createFunction = [device](Data::AssetData* poolAsset) { return AttachmentImagePool::CreateInternal(*device, *(azrtti_cast(poolAsset))); }; Data::InstanceDatabase::Create(azrtti_typeid(), handler); } // Register streaming image instance database. { Data::InstanceHandler handler; handler.m_createFunction = [](Data::AssetData* imageAsset) { return StreamingImage::CreateInternal(*(azrtti_cast(imageAsset))); }; Data::InstanceDatabase::Create(azrtti_typeid(), handler); } { Data::InstanceHandler handler; handler.m_createFunction = [this, device](Data::AssetData* poolAsset) { Data::Instance instance = StreamingImagePool::CreateInternal(*device, *(azrtti_cast(poolAsset))); if (instance) { m_activeStreamingPoolMutex.lock(); m_activeStreamingPools.emplace_back(instance.get()); m_activeStreamingPoolMutex.unlock(); } return instance; }; handler.m_deleteFunction = [this](StreamingImagePool* pool) { m_activeStreamingPoolMutex.lock(); auto findIt = AZStd::find(m_activeStreamingPools.begin(), m_activeStreamingPools.end(), pool); AZ_Assert(findIt != m_activeStreamingPools.end(), "Pool must exist in the container."); m_activeStreamingPools.erase(findIt); m_activeStreamingPoolMutex.unlock(); delete pool; }; Data::InstanceDatabase::Create(azrtti_typeid(), handler); } // Register streaming image controller instance database. { Data::InstanceHandler handler; handler.m_createFunction = DefaultStreamingImageController::CreateInternal; Data::InstanceDatabase::Create(azrtti_typeid(), handler); } m_defaultStreamingImageControllerAsset = Data::AssetManager::Instance().CreateAsset( DefaultStreamingImageControllerAsset::BuiltInAssetId, AZ::Data::AssetLoadBehavior::PreLoad); CreateDefaultResources(desc); Interface::Register(this); m_initialized = true; } void ImageSystem::Shutdown() { if (!m_initialized) { return; } Interface::Unregister(this); m_defaultStreamingImageControllerAsset.Release(); m_systemImages.clear(); m_systemStreamingPool = nullptr; m_systemAttachmentPool = nullptr; m_assetStreamingPool = nullptr; Data::InstanceDatabase::Destroy(); Data::InstanceDatabase::Destroy(); Data::InstanceDatabase::Destroy(); Data::InstanceDatabase::Destroy(); Data::InstanceDatabase::Destroy(); m_activeStreamingPools.clear(); m_initialized = false; } void ImageSystem::Update() { AZ_ATOM_PROFILE_FUNCTION("RPI", "ImageSystem: Update"); AZStd::lock_guard lock(m_activeStreamingPoolMutex); for (StreamingImagePool* imagePool : m_activeStreamingPools) { imagePool->Update(); } } const Data::Instance& ImageSystem::GetSystemStreamingPool() const { return m_systemStreamingPool; } const Data::Instance& ImageSystem::GetStreamingPool() const { return m_assetStreamingPool; } const Data::Instance& ImageSystem::GetSystemAttachmentPool() const { return m_systemAttachmentPool; } const Data::Instance& ImageSystem::GetSystemImage(SystemImage simpleImage) const { return m_systemImages[static_cast(simpleImage)]; } void ImageSystem::CreateDefaultResources(const ImageSystemDescriptor& desc) { struct SystemImageDescriptor { SystemImageDescriptor(const Color color, const char* name) : m_color{color} , m_name{name} , m_assetId{Uuid::CreateName(name)} {} Color m_color; const char* m_name; Data::AssetId m_assetId; }; const SystemImageDescriptor systemImageDescriptors[static_cast(SystemImage::Count)] = { { Color(1.0f, 1.0f, 1.0f, 1.0f), "Image_White" }, { Color(0.0f, 0.0f, 0.0f, 1.0f), "Image_Black" }, { Color(0.5f, 0.5f, 0.5f, 1.0f), "Image_Grey" }, { Color(1.0f, 0.0f, 1.0f, 1.0f), "Image_Magenta" } }; static_assert(AZ_ARRAY_SIZE(systemImageDescriptors) == static_cast(SystemImage::Count), "System image arrays do not match."); struct SystemImagePoolDescriptor { SystemImagePoolDescriptor(size_t budgetInBytes, const char* name) : m_budgetInBytes{budgetInBytes} , m_name{name} , m_assetId{Uuid::CreateName(name)} {} size_t m_budgetInBytes; const char* m_name; Data::AssetId m_assetId; }; const SystemImagePoolDescriptor systemStreamingPoolDescriptor{ desc.m_systemStreamingImagePoolSize, "ImageSystem::SystemStreamingImagePool" }; const SystemImagePoolDescriptor systemAttachmentPoolDescriptor{desc.m_systemAttachmentImagePoolSize, "ImageSystem::AttachmentImagePool" }; const SystemImagePoolDescriptor assetStreamingPoolDescriptor{ desc.m_assetStreamingImagePoolSize, "ImageSystem::AssetStreamingImagePool" }; // Create the system streaming pool { AZStd::unique_ptr imagePoolDescriptor = AZStd::make_unique(); imagePoolDescriptor->m_budgetInBytes = systemStreamingPoolDescriptor.m_budgetInBytes; Data::Asset poolAsset; StreamingImagePoolAssetCreator poolAssetCreator; poolAssetCreator.Begin(systemStreamingPoolDescriptor.m_assetId); poolAssetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor)); poolAssetCreator.SetControllerAsset(m_defaultStreamingImageControllerAsset); poolAssetCreator.SetPoolName(systemStreamingPoolDescriptor.m_name); [[maybe_unused]] const bool created = poolAssetCreator.End(poolAsset); AZ_Assert(created, "Failed to build streaming image pool"); m_systemStreamingPool = StreamingImagePool::FindOrCreate(poolAsset); } // Create the streaming pool for streaming image from asset { AZStd::unique_ptr imagePoolDescriptor = AZStd::make_unique(); imagePoolDescriptor->m_budgetInBytes = assetStreamingPoolDescriptor.m_budgetInBytes; Data::Asset poolAsset; StreamingImagePoolAssetCreator poolAssetCreator; poolAssetCreator.Begin(assetStreamingPoolDescriptor.m_assetId); poolAssetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor)); poolAssetCreator.SetControllerAsset(m_defaultStreamingImageControllerAsset); poolAssetCreator.SetPoolName(assetStreamingPoolDescriptor.m_name); [[maybe_unused]] const bool created = poolAssetCreator.End(poolAsset); AZ_Assert(created, "Failed to build streaming image pool for assets"); m_assetStreamingPool = StreamingImagePool::FindOrCreate(poolAsset); } // Create the system attachment pool. { AZStd::unique_ptr imagePoolDescriptor = AZStd::make_unique(); imagePoolDescriptor->m_budgetInBytes = systemAttachmentPoolDescriptor.m_budgetInBytes; imagePoolDescriptor->m_bindFlags = RHI::ImageBindFlags::ShaderRead | RHI::ImageBindFlags::ShaderWrite | RHI::ImageBindFlags::Color | RHI::ImageBindFlags::DepthStencil | RHI::ImageBindFlags::CopyRead | RHI::ImageBindFlags::CopyWrite; Data::Asset poolAsset; ResourcePoolAssetCreator poolAssetCreator; poolAssetCreator.Begin(systemAttachmentPoolDescriptor.m_assetId); poolAssetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor)); poolAssetCreator.SetPoolName(systemAttachmentPoolDescriptor.m_name); [[maybe_unused]] const bool created = poolAssetCreator.End(poolAsset); AZ_Assert(created, "Failed to build attachment image pool"); m_systemAttachmentPool = AttachmentImagePool::FindOrCreate(poolAsset); } // Create the set of system images. { const size_t systemImageCount = static_cast(SystemImage::Count); m_systemImages.resize(systemImageCount); for (size_t imageIndex = 0; imageIndex < systemImageCount; imageIndex++) { const uint32_t colorU32 = systemImageDescriptors[imageIndex].m_color.ToU32(); m_systemImages[imageIndex] = StreamingImage::CreateFromCpuData( *m_systemStreamingPool, RHI::ImageDimension::Image2D, RHI::Size{ 1, 1, 1 }, RHI::Format::R8G8B8A8_UNORM_SRGB, &colorU32, sizeof(uint32_t)); } } } } // namespace RPI }// namespace AZ