Files
o3de/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp
T
Vicky 01b2798fe1 Integrate from 1.0 to main: LYN-3436 AutomatedTesting.GameLauncher crashes at launch if assets are not all processed (#612)
* Atom/qingtao/lyn 3436 (#558)

* LYN-3436 AutomatedTesting.GameLauncher crashes at launch if assets are not all processed

Change RPISystem so that the application would exit if the RPI system couldn't load critical assets.
Added code to avoid the GetLayout crash when layout for each platforms were not ready.
Added LoadCriticalAsset function to force compile and load critical assets.
Added default value to viewport size for ViewportContext.

* Change RPISystem asset initialization order so it returns earlier when those critical assets are not ready
2021-05-10 16:46:25 -07:00

217 lines
9.0 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Public/Buffer/BufferSystem.h>
#include <Atom/RPI.Public/Buffer/Buffer.h>
#include <Atom/RPI.Public/Buffer/BufferPool.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RPI.Reflect/Buffer/BufferAssetCreator.h>
#include <Atom/RPI.Reflect/Buffer/BufferAssetView.h>
#include <AzCore/Debug/EventTrace.h>
#include <AtomCore/Instance/InstanceDatabase.h>
#include <AzCore/Interface/Interface.h>
namespace AZ
{
namespace RPI
{
void BufferSystem::Reflect(ReflectContext* context)
{
BufferAsset::Reflect(context);
BufferAssetView::Reflect(context);
}
void BufferSystem::GetAssetHandlers(AssetHandlerPtrList& assetHandlers)
{
assetHandlers.emplace_back(MakeAssetHandler<BufferAssetHandler>());
}
void BufferSystem::Init()
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
{
Data::InstanceHandler<Buffer> handler;
handler.m_createFunction = [](Data::AssetData* bufferAsset)
{
return Buffer::CreateInternal(*(azrtti_cast<BufferAsset*>(bufferAsset)));
};
Data::InstanceDatabase<Buffer>::Create(azrtti_typeid<BufferAsset>(), handler);
}
{
Data::InstanceHandler<BufferPool> handler;
handler.m_createFunction = [device](Data::AssetData* poolAsset)
{
return BufferPool::CreateInternal(*device, *(azrtti_cast<ResourcePoolAsset*>(poolAsset)));
};
Data::InstanceDatabase<BufferPool>::Create(azrtti_typeid<ResourcePoolAsset>(), handler);
}
Interface<BufferSystemInterface>::Register(this);
m_initialized = true;
}
void BufferSystem::Shutdown()
{
if (!m_initialized)
{
return;
}
for (uint8_t index = 0; index < static_cast<uint8_t>(CommonBufferPoolType::Count); index++)
{
m_commonPools[index] = nullptr;
}
Interface<BufferSystemInterface>::Unregister(this);
Data::InstanceDatabase<Buffer>::Destroy();
Data::InstanceDatabase<BufferPool>::Destroy();
m_initialized = false;
}
RHI::Ptr<RHI::BufferPool> BufferSystem::GetCommonBufferPool(CommonBufferPoolType poolType)
{
const uint8_t index = static_cast<uint8_t>(poolType);
if (!m_commonPools[index])
{
CreateCommonBufferPool(poolType);
}
return m_commonPools[index];
}
bool BufferSystem::CreateCommonBufferPool(CommonBufferPoolType poolType)
{
if (!m_initialized)
{
return false;
}
auto* device = RHI::RHISystemInterface::Get()->GetDevice();
RHI::Ptr<RHI::BufferPool> bufferPool = RHI::Factory::Get().CreateBufferPool();
RHI::BufferPoolDescriptor bufferPoolDesc;
switch (poolType)
{
case CommonBufferPoolType::Constant:
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::Constant;
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
break;
case CommonBufferPoolType::StaticInputAssembly:
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::ShaderRead;
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
break;
case CommonBufferPoolType::DynamicInputAssembly:
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::ShaderRead;
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
break;
case CommonBufferPoolType::ReadBack:
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::CopyWrite;
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Read;
break;
case CommonBufferPoolType::ReadWrite:
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::ShaderWrite | RHI::BufferBindFlags::ShaderRead;
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
break;
case CommonBufferPoolType::ReadOnly:
bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::ShaderRead;
bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
break;
default:
AZ_Error("BufferSystem", false, "Unknown common buffer pool type: %d", poolType);
return false;
}
RHI::ResultCode resultCode = bufferPool->Init(*device, bufferPoolDesc);
if (resultCode != RHI::ResultCode::Success)
{
AZ_Error("BufferSystem", false, "Failed to create buffer pool: %d", poolType);
return false;
}
m_commonPools[static_cast<uint8_t>(poolType)] = bufferPool;
return true;
}
Data::Instance<Buffer> BufferSystem::CreateBufferFromCommonPool(const CommonBufferDescriptor& descriptor)
{
Uuid bufferId = Uuid::CreateName(descriptor.m_bufferName.c_str());
// Report error if there is a buffer with same name.
// Note: this shouldn't return the existing buffer because users are expecting a newly created buffer.
if (Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId(bufferId)))
{
AZ_Error("BufferSystem", false, "Buffer with same name '%s' already exist", descriptor.m_bufferName.c_str());
return nullptr;
}
RHI::Ptr<RHI::BufferPool> bufferPool = GetCommonBufferPool(descriptor.m_poolType);
if (!bufferPool)
{
AZ_Error("BufferSystem", false, "Common buffer pool type %d doesn't exist", descriptor.m_poolType);
return nullptr;
}
RHI::BufferDescriptor bufferDesc;
bufferDesc.m_alignment = descriptor.m_elementSize;
bufferDesc.m_bindFlags = bufferPool->GetDescriptor().m_bindFlags;
bufferDesc.m_byteCount = descriptor.m_byteCount;
Data::Asset<BufferAsset> bufferAsset;
BufferAssetCreator creator;
creator.Begin(bufferId);
creator.SetBufferName(descriptor.m_bufferName);
creator.SetBuffer(descriptor.m_bufferData, descriptor.m_bufferData? descriptor.m_byteCount : 0, bufferDesc);
creator.SetUseCommonPool(descriptor.m_poolType);
RHI::BufferViewDescriptor viewDescriptor;
if (descriptor.m_elementFormat != RHI::Format::Unknown)
{
viewDescriptor = RHI::BufferViewDescriptor::CreateTyped(
0,
aznumeric_cast<uint32_t>(bufferDesc.m_byteCount / descriptor.m_elementSize),
descriptor.m_elementFormat);
}
else
{
viewDescriptor = RHI::BufferViewDescriptor::CreateStructured(
0, aznumeric_cast<uint32_t>(bufferDesc.m_byteCount / descriptor.m_elementSize), descriptor.m_elementSize);
}
creator.SetBufferViewDescriptor(viewDescriptor);
if (creator.End(bufferAsset))
{
Data::Instance<Buffer> bufferInst = Buffer::FindOrCreate(bufferAsset);
return bufferInst;
}
return nullptr;
}
Data::Instance<Buffer> BufferSystem::FindCommonBuffer(AZStd::string_view bufferName)
{
Uuid bufferId = Uuid::CreateName(bufferName.data());
return Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId(bufferId));
}
} // namespace RPI
} // namespace AZ