Added object release queue notification to the RHI Device and ObjectCollector.
Signed-off-by: dmcdiar <dmcdiar@amazon.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/ObjectCollector.h>
|
||||
#include <Atom/RHI.Reflect/DeviceDescriptor.h>
|
||||
#include <Atom/RHI.Reflect/DeviceFeatures.h>
|
||||
#include <Atom/RHI.Reflect/DeviceLimits.h>
|
||||
@@ -140,6 +141,9 @@ namespace AZ
|
||||
//! Get the memory requirements for allocating a buffer resource.
|
||||
virtual ResourceMemoryRequirements GetResourceMemoryRequirements(const BufferDescriptor& descriptor) = 0;
|
||||
|
||||
//! Notifies after all objects currently in the platform release queue are released
|
||||
virtual void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) = 0;
|
||||
|
||||
protected:
|
||||
DeviceFeatures m_features;
|
||||
DeviceLimits m_limits;
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace AZ
|
||||
using MutexType = NullMutex;
|
||||
};
|
||||
|
||||
using ObjectCollectorNotifyFunction = AZStd::function<void()>;
|
||||
|
||||
/**
|
||||
* Deferred-releases reference-counted objects at a specific latency. Example: Use to batch-release
|
||||
* objects that exist on the GPU timeline at the end of the frame after syncing the oldest GPU frame.
|
||||
@@ -85,6 +87,9 @@ namespace AZ
|
||||
/// Must not be called at collection time.
|
||||
size_t GetObjectCount() const;
|
||||
|
||||
/// Notifies after the current set of pending objects is released.
|
||||
void Notify(ObjectCollectorNotifyFunction notifyFunction);
|
||||
|
||||
private:
|
||||
void QueueForCollectInternal(ObjectPtrType object);
|
||||
|
||||
@@ -92,6 +97,7 @@ namespace AZ
|
||||
{
|
||||
AZStd::vector<ObjectPtrType> m_objects;
|
||||
uint64_t m_collectIteration;
|
||||
AZStd::vector<ObjectCollectorNotifyFunction> m_notifies;
|
||||
};
|
||||
|
||||
inline bool IsGarbageReady(size_t collectIteration)
|
||||
@@ -106,6 +112,7 @@ namespace AZ
|
||||
mutable typename Traits::MutexType m_mutex;
|
||||
AZStd::vector<ObjectPtrType> m_pendingObjects;
|
||||
AZStd::vector<Garbage> m_pendingGarbage;
|
||||
AZStd::vector<ObjectCollectorNotifyFunction> m_pendingNotifies;
|
||||
};
|
||||
|
||||
template <typename Traits>
|
||||
@@ -174,6 +181,45 @@ namespace AZ
|
||||
}
|
||||
m_mutex.unlock();
|
||||
|
||||
if (m_pendingNotifies.size())
|
||||
{
|
||||
if (m_pendingGarbage.size())
|
||||
{
|
||||
// find the newest garbage entry and add any pending notifies
|
||||
Garbage& latestGarbage = m_pendingGarbage.front();
|
||||
size_t latestGarbageAge = m_currentIteration - latestGarbage.m_collectIteration;
|
||||
size_t i = 1;
|
||||
while (i < m_pendingGarbage.size())
|
||||
{
|
||||
size_t age = m_currentIteration - m_pendingGarbage[i].m_collectIteration;
|
||||
if (age < latestGarbageAge)
|
||||
{
|
||||
latestGarbage = m_pendingGarbage[i];
|
||||
latestGarbageAge = age;
|
||||
}
|
||||
}
|
||||
|
||||
latestGarbage.m_notifies.insert(latestGarbage.m_notifies.end(), m_pendingNotifies.begin(), m_pendingNotifies.end());
|
||||
|
||||
m_mutex.lock();
|
||||
m_pendingNotifies.clear();
|
||||
m_mutex.unlock();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// garbage queue is empty, notify now
|
||||
m_mutex.lock();
|
||||
for (auto& notifyFunction : m_pendingNotifies)
|
||||
{
|
||||
notifyFunction();
|
||||
}
|
||||
|
||||
m_pendingNotifies.clear();
|
||||
m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
size_t objectCount = 0;
|
||||
size_t i = 0;
|
||||
while (i < m_pendingGarbage.size())
|
||||
@@ -189,6 +235,12 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
objectCount += garbage.m_objects.size();
|
||||
|
||||
for (auto& notifyFunction : garbage.m_notifies)
|
||||
{
|
||||
notifyFunction();
|
||||
}
|
||||
|
||||
garbage = AZStd::move(m_pendingGarbage.back());
|
||||
m_pendingGarbage.pop_back();
|
||||
}
|
||||
@@ -215,5 +267,13 @@ namespace AZ
|
||||
|
||||
return objectCount;
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void ObjectCollector<Traits>::Notify(ObjectCollectorNotifyFunction notifyFunction)
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_pendingNotifies.push_back(notifyFunction);
|
||||
m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace UnitTest
|
||||
AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::ImageDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; };
|
||||
|
||||
AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::BufferDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; };
|
||||
|
||||
void ObjectCollectionNotify(AZ::RHI::ObjectCollectorNotifyFunction notifyFunction) override {}
|
||||
};
|
||||
|
||||
AZ::RHI::Ptr<AZ::RHI::Device> MakeTestDevice();
|
||||
|
||||
@@ -292,6 +292,11 @@ namespace AZ
|
||||
return memoryRequirements;
|
||||
}
|
||||
|
||||
void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction)
|
||||
{
|
||||
m_releaseQueue.Notify(notifyFunction);
|
||||
}
|
||||
|
||||
//AZStd::vector<RHI::Format> Device::GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const
|
||||
//{
|
||||
// AZStd::vector<RHI::Format> formatsList;
|
||||
|
||||
@@ -162,6 +162,7 @@ namespace AZ
|
||||
void PreShutdown() override;
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor & descriptor) override;
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor & descriptor) override;
|
||||
void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RHI::ResultCode InitSubPlatform(RHI::PhysicalDevice& physicalDevice);
|
||||
|
||||
@@ -315,7 +315,12 @@ namespace AZ
|
||||
memoryRequirements.m_sizeInBytes = bufferSizeAndAlign.size;
|
||||
return memoryRequirements;
|
||||
}
|
||||
|
||||
|
||||
void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction)
|
||||
{
|
||||
m_releaseQueue.Notify(notifyFunction);
|
||||
}
|
||||
|
||||
void Device::InitFeatures()
|
||||
{
|
||||
|
||||
|
||||
@@ -151,7 +151,8 @@ namespace AZ
|
||||
NullDescriptorManager& GetNullDescriptorManager();
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor & descriptor) override;
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor & descriptor) override;
|
||||
|
||||
void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override;
|
||||
|
||||
private:
|
||||
Device() = default;
|
||||
|
||||
|
||||
@@ -20,5 +20,10 @@ namespace AZ
|
||||
{
|
||||
formatsCapabilities.fill(static_cast<RHI::FormatCapabilities>(~0));
|
||||
}
|
||||
|
||||
void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction)
|
||||
{
|
||||
notifyFunction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace AZ
|
||||
void PreShutdown() override {}
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const RHI::ImageDescriptor& descriptor) override { return RHI::ResourceMemoryRequirements();}
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const RHI::BufferDescriptor& descriptor) override { return RHI::ResourceMemoryRequirements();}
|
||||
void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
}
|
||||
|
||||
@@ -652,6 +652,11 @@ namespace AZ
|
||||
return RHI::ResourceMemoryRequirements{ vkRequirements.alignment, vkRequirements.size };
|
||||
}
|
||||
|
||||
void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction)
|
||||
{
|
||||
m_releaseQueue.Notify(notifyFunction);
|
||||
}
|
||||
|
||||
void Device::InitFeaturesAndLimits(const PhysicalDevice& physicalDevice)
|
||||
{
|
||||
m_features.m_tessellationShader = (m_enabledDeviceFeatures.tessellationShader == VK_TRUE);
|
||||
|
||||
@@ -134,6 +134,7 @@ namespace AZ
|
||||
void PreShutdown() override;
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor& descriptor) override;
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor& descriptor) override;
|
||||
void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InitFeaturesAndLimits(const PhysicalDevice& physicalDevice);
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace UnitTest
|
||||
void PreShutdown() override {}
|
||||
AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::ImageDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; };
|
||||
AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::BufferDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; };
|
||||
void ObjectCollectionNotify(AZ::RHI::ObjectCollectorNotifyFunction notifyFunction) override {}
|
||||
};
|
||||
|
||||
class ImageView
|
||||
|
||||
Reference in New Issue
Block a user