зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Add a new garbage type gated by fences.
This allows Vulkan EGL objects such as EGL Syncs and EGL Images to give their garbage to the renderer before destroying. BUG=angleproject:2464 Change-Id: I59b8e1080e4292bd0856e59a928750c7e77a372e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1562522 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
d7d42395ac
Коммит
e755a5374f
|
@ -32,13 +32,34 @@ void ImageVk::onDestroy(const egl::Display *display)
|
|||
DisplayVk *displayVk = vk::GetImpl(display);
|
||||
RendererVk *renderer = displayVk->getRenderer();
|
||||
|
||||
std::vector<vk::GarbageObjectBase> garbage;
|
||||
|
||||
if (mImage != nullptr && mOwnsImage)
|
||||
{
|
||||
mImage->releaseImage(renderer);
|
||||
mImage->releaseStagingBuffer(renderer);
|
||||
mImage->releaseImage(displayVk, &garbage);
|
||||
mImage->releaseStagingBuffer(displayVk, &garbage);
|
||||
delete mImage;
|
||||
}
|
||||
else if (egl::IsExternalImageTarget(mState.target))
|
||||
{
|
||||
ASSERT(mState.source != nullptr);
|
||||
ExternalImageSiblingVk *externalImageSibling =
|
||||
GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
|
||||
externalImageSibling->release(displayVk, &garbage);
|
||||
}
|
||||
mImage = nullptr;
|
||||
|
||||
if (!garbage.empty())
|
||||
{
|
||||
renderer->addGarbage(std::move(mImageLastUseFences), std::move(garbage));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (vk::Shared<vk::Fence> &fence : mImageLastUseFences)
|
||||
{
|
||||
fence.reset(displayVk->getDevice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
egl::Error ImageVk::initialize(const egl::Display *display)
|
||||
|
@ -129,6 +150,19 @@ angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sib
|
|||
}
|
||||
}
|
||||
|
||||
// Grab a fence from the releasing context to know when the image is no longer used
|
||||
ASSERT(mContext != nullptr);
|
||||
ContextVk *contextVk = vk::GetImpl(mContext);
|
||||
|
||||
// Flush the context to make sure the fence has been submitted.
|
||||
ANGLE_TRY(contextVk->flushImpl());
|
||||
|
||||
vk::Shared<vk::Fence> fence = contextVk->getRenderer()->getLastSubmittedFence();
|
||||
if (fence.isReferenced())
|
||||
{
|
||||
mImageLastUseFences.push_back(std::move(fence));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ class ExternalImageSiblingVk : public ExternalImageSiblingImpl
|
|||
~ExternalImageSiblingVk() override {}
|
||||
|
||||
virtual vk::ImageHelper *getImage() const = 0;
|
||||
|
||||
virtual void release(DisplayVk *display, std::vector<vk::GarbageObjectBase> *garbageQueue) = 0;
|
||||
};
|
||||
|
||||
class ImageVk : public ImageImpl
|
||||
|
@ -49,6 +51,8 @@ class ImageVk : public ImageImpl
|
|||
bool mOwnsImage;
|
||||
vk::ImageHelper *mImage;
|
||||
|
||||
std::vector<vk::Shared<vk::Fence>> mImageLastUseFences;
|
||||
|
||||
const gl::Context *mContext;
|
||||
};
|
||||
|
||||
|
|
|
@ -486,6 +486,30 @@ void InitializeSubmitInfo(VkSubmitInfo *submitInfo,
|
|||
}
|
||||
}
|
||||
|
||||
angle::Result WaitFences(vk::Context *context,
|
||||
std::vector<vk::Shared<vk::Fence>> *fences,
|
||||
bool block)
|
||||
{
|
||||
uint64_t timeout = block ? kMaxFenceWaitTimeNs : 0;
|
||||
|
||||
// Iterate backwards over the fences, removing them from the list in constant time when they are
|
||||
// complete.
|
||||
while (!fences->empty())
|
||||
{
|
||||
VkResult result = fences->back().get().wait(context->getDevice(), timeout);
|
||||
if (result == VK_TIMEOUT)
|
||||
{
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
ANGLE_VK_TRY(context, result);
|
||||
|
||||
fences->back().reset(context->getDevice());
|
||||
fences->pop_back();
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
// Initially dumping the command graphs is disabled.
|
||||
constexpr bool kEnableCommandGraphDiagnostics = false;
|
||||
|
||||
|
@ -544,11 +568,15 @@ RendererVk::RendererVk()
|
|||
mFormatProperties.fill(invalid);
|
||||
}
|
||||
|
||||
RendererVk::~RendererVk() {}
|
||||
RendererVk::~RendererVk()
|
||||
{
|
||||
ASSERT(mGarbage.empty());
|
||||
ASSERT(mFencedGarbage.empty());
|
||||
}
|
||||
|
||||
void RendererVk::onDestroy(vk::Context *context)
|
||||
{
|
||||
if (!mInFlightCommands.empty() || !mGarbage.empty())
|
||||
if (!mInFlightCommands.empty() || !mGarbage.empty() || !mFencedGarbage.empty())
|
||||
{
|
||||
// TODO(jmadill): Not nice to pass nullptr here, but shouldn't be a problem.
|
||||
(void)finish(context, nullptr, nullptr);
|
||||
|
@ -1392,6 +1420,9 @@ angle::Result RendererVk::finish(vk::Context *context,
|
|||
ANGLE_VK_TRY(context, vkQueueWaitIdle(mQueue));
|
||||
freeAllInFlightResources();
|
||||
|
||||
ANGLE_TRY(cleanupFencedGarbage(context, true));
|
||||
ASSERT(mFencedGarbage.empty());
|
||||
|
||||
if (mGpuEventsEnabled)
|
||||
{
|
||||
// This loop should in practice execute once since the queue is already idle.
|
||||
|
@ -1473,6 +1504,8 @@ angle::Result RendererVk::checkCompletedCommands(vk::Context *context)
|
|||
mGarbage.erase(mGarbage.begin(), mGarbage.begin() + freeIndex);
|
||||
}
|
||||
|
||||
ANGLE_TRY(cleanupFencedGarbage(context, false));
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
|
@ -2204,6 +2237,20 @@ void RendererVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpu
|
|||
mGpuEvents.clear();
|
||||
}
|
||||
|
||||
void RendererVk::addGarbage(vk::Shared<vk::Fence> &&fence,
|
||||
std::vector<vk::GarbageObjectBase> &&garbage)
|
||||
{
|
||||
std::vector<vk::Shared<vk::Fence>> fences;
|
||||
fences.push_back(std::move(fence));
|
||||
addGarbage(std::move(fences), std::move(garbage));
|
||||
}
|
||||
|
||||
void RendererVk::addGarbage(std::vector<vk::Shared<vk::Fence>> &&fences,
|
||||
std::vector<vk::GarbageObjectBase> &&garbage)
|
||||
{
|
||||
mFencedGarbage.emplace_back(std::move(fences), std::move(garbage));
|
||||
}
|
||||
|
||||
template <VkFormatFeatureFlags VkFormatProperties::*features>
|
||||
VkFormatFeatureFlags RendererVk::getFormatFeatureBits(VkFormat format,
|
||||
const VkFormatFeatureFlags featureBits)
|
||||
|
@ -2234,6 +2281,29 @@ bool RendererVk::hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlag
|
|||
return IsMaskFlagSet(getFormatFeatureBits<features>(format, featureBits), featureBits);
|
||||
}
|
||||
|
||||
angle::Result RendererVk::cleanupFencedGarbage(vk::Context *context, bool block)
|
||||
{
|
||||
auto garbageIter = mFencedGarbage.begin();
|
||||
while (garbageIter != mFencedGarbage.end())
|
||||
{
|
||||
ANGLE_TRY(WaitFences(context, &garbageIter->first, block));
|
||||
if (garbageIter->first.empty())
|
||||
{
|
||||
for (vk::GarbageObjectBase &garbageObject : garbageIter->second)
|
||||
{
|
||||
garbageObject.destroy(mDevice);
|
||||
}
|
||||
garbageIter = mFencedGarbage.erase(garbageIter);
|
||||
}
|
||||
else
|
||||
{
|
||||
garbageIter++;
|
||||
}
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
uint32_t GetUniformBufferDescriptorCount()
|
||||
{
|
||||
return kUniformBufferDescriptorsPerDescriptorSet;
|
||||
|
|
|
@ -213,6 +213,10 @@ class RendererVk : angle::NonCopyable
|
|||
void pushDebugMarker(GLenum source, GLuint id, std::string &&marker);
|
||||
void popDebugMarker();
|
||||
|
||||
void addGarbage(vk::Shared<vk::Fence> &&fence, std::vector<vk::GarbageObjectBase> &&garbage);
|
||||
void addGarbage(std::vector<vk::Shared<vk::Fence>> &&fences,
|
||||
std::vector<vk::GarbageObjectBase> &&garbage);
|
||||
|
||||
static constexpr size_t kMaxExtensionNames = 200;
|
||||
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
|
||||
|
||||
|
@ -254,6 +258,8 @@ class RendererVk : angle::NonCopyable
|
|||
|
||||
void nextSerial();
|
||||
|
||||
angle::Result cleanupFencedGarbage(vk::Context *context, bool block);
|
||||
|
||||
egl::Display *mDisplay;
|
||||
|
||||
mutable bool mCapsInitialized;
|
||||
|
@ -302,6 +308,11 @@ class RendererVk : angle::NonCopyable
|
|||
|
||||
std::vector<CommandBatch> mInFlightCommands;
|
||||
std::vector<vk::GarbageObject> mGarbage;
|
||||
|
||||
using FencedGarbage =
|
||||
std::pair<std::vector<vk::Shared<vk::Fence>>, std::vector<vk::GarbageObjectBase>>;
|
||||
std::vector<FencedGarbage> mFencedGarbage;
|
||||
|
||||
vk::MemoryProperties mMemoryProperties;
|
||||
vk::FormatTable mFormatTable;
|
||||
|
||||
|
|
|
@ -31,6 +31,14 @@ void FenceSyncVk::onDestroy(RendererVk *renderer)
|
|||
mFence.reset(renderer->getDevice());
|
||||
}
|
||||
|
||||
void FenceSyncVk::onDestroy(DisplayVk *display)
|
||||
{
|
||||
std::vector<vk::GarbageObjectBase> garbage;
|
||||
mEvent.dumpResources(&garbage);
|
||||
|
||||
display->getRenderer()->addGarbage(std::move(mFence), std::move(garbage));
|
||||
}
|
||||
|
||||
angle::Result FenceSyncVk::initialize(ContextVk *contextVk)
|
||||
{
|
||||
ASSERT(!mEvent.valid());
|
||||
|
|
|
@ -31,6 +31,7 @@ class FenceSyncVk
|
|||
~FenceSyncVk();
|
||||
|
||||
void onDestroy(RendererVk *renderer);
|
||||
void onDestroy(DisplayVk *display);
|
||||
|
||||
angle::Result initialize(ContextVk *contextVk);
|
||||
angle::Result clientWait(vk::Context *context,
|
||||
|
|
|
@ -164,15 +164,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
|
|||
|
||||
void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
|
||||
{
|
||||
DisplayVk *displayVk = vk::GetImpl(display);
|
||||
RendererVk *renderer = displayVk->getRenderer();
|
||||
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
mImage->releaseImage(renderer);
|
||||
mImage->releaseStagingBuffer(renderer);
|
||||
SafeDelete(mImage);
|
||||
}
|
||||
ASSERT(mImage == nullptr);
|
||||
}
|
||||
|
||||
gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
|
||||
|
@ -205,4 +197,16 @@ vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
|
|||
{
|
||||
return mImage;
|
||||
}
|
||||
|
||||
void HardwareBufferImageSiblingVkAndroid::release(DisplayVk *display,
|
||||
std::vector<vk::GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
mImage->releaseImage(display, garbageQueue);
|
||||
mImage->releaseStagingBuffer(display, garbageQueue);
|
||||
SafeDelete(mImage);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -36,6 +36,8 @@ class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
|
|||
// ExternalImageSiblingVk interface
|
||||
vk::ImageHelper *getImage() const override;
|
||||
|
||||
void release(DisplayVk *display, std::vector<vk::GarbageObjectBase> *garbageQueue) override;
|
||||
|
||||
private:
|
||||
angle::Result initImpl(DisplayVk *displayVk);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "libANGLE/Context.h"
|
||||
#include "libANGLE/renderer/vulkan/BufferVk.h"
|
||||
#include "libANGLE/renderer/vulkan/ContextVk.h"
|
||||
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
|
||||
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
||||
#include "libANGLE/renderer/vulkan/vk_utils.h"
|
||||
|
@ -375,6 +376,21 @@ void DynamicBuffer::release(RendererVk *renderer)
|
|||
}
|
||||
}
|
||||
|
||||
void DynamicBuffer::release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
reset();
|
||||
releaseRetainedBuffers(display, garbageQueue);
|
||||
|
||||
if (mBuffer)
|
||||
{
|
||||
mBuffer->unmap(display->getDevice());
|
||||
|
||||
mBuffer->release(display, garbageQueue);
|
||||
delete mBuffer;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicBuffer::releaseRetainedBuffers(RendererVk *renderer)
|
||||
{
|
||||
for (BufferHelper *toFree : mRetainedBuffers)
|
||||
|
@ -388,6 +404,18 @@ void DynamicBuffer::releaseRetainedBuffers(RendererVk *renderer)
|
|||
mRetainedBuffers.clear();
|
||||
}
|
||||
|
||||
void DynamicBuffer::releaseRetainedBuffers(DisplayVk *display,
|
||||
std::vector<GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
for (BufferHelper *toFree : mRetainedBuffers)
|
||||
{
|
||||
toFree->release(display, garbageQueue);
|
||||
delete toFree;
|
||||
}
|
||||
|
||||
mRetainedBuffers.clear();
|
||||
}
|
||||
|
||||
void DynamicBuffer::destroy(VkDevice device)
|
||||
{
|
||||
reset();
|
||||
|
@ -1120,6 +1148,17 @@ void BufferHelper::release(RendererVk *renderer)
|
|||
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
|
||||
}
|
||||
|
||||
void BufferHelper::release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
unmap(display->getDevice());
|
||||
mSize = 0;
|
||||
mViewFormat = nullptr;
|
||||
|
||||
mBuffer.dumpResources(garbageQueue);
|
||||
mBufferView.dumpResources(garbageQueue);
|
||||
mDeviceMemory.dumpResources(garbageQueue);
|
||||
}
|
||||
|
||||
void BufferHelper::onWrite(VkAccessFlagBits writeAccessType)
|
||||
{
|
||||
if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0)
|
||||
|
@ -1351,6 +1390,12 @@ void ImageHelper::releaseImage(RendererVk *renderer)
|
|||
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
|
||||
}
|
||||
|
||||
void ImageHelper::releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
mImage.dumpResources(garbageQueue);
|
||||
mDeviceMemory.dumpResources(garbageQueue);
|
||||
}
|
||||
|
||||
void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
|
||||
{
|
||||
// Remove updates that never made it to the texture.
|
||||
|
@ -1362,6 +1407,18 @@ void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
|
|||
mSubresourceUpdates.clear();
|
||||
}
|
||||
|
||||
void ImageHelper::releaseStagingBuffer(DisplayVk *display,
|
||||
std::vector<GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
// Remove updates that never made it to the texture.
|
||||
for (SubresourceUpdate &update : mSubresourceUpdates)
|
||||
{
|
||||
update.release(display, garbageQueue);
|
||||
}
|
||||
mStagingBuffer.release(display, garbageQueue);
|
||||
mSubresourceUpdates.clear();
|
||||
}
|
||||
|
||||
void ImageHelper::resetImageWeakReference()
|
||||
{
|
||||
mImage.reset();
|
||||
|
@ -2269,6 +2326,17 @@ void ImageHelper::SubresourceUpdate::release(RendererVk *renderer)
|
|||
}
|
||||
}
|
||||
|
||||
void ImageHelper::SubresourceUpdate::release(DisplayVk *display,
|
||||
std::vector<GarbageObjectBase> *garbageQueue)
|
||||
{
|
||||
if (updateSource == UpdateSource::Image)
|
||||
{
|
||||
image.image->releaseImage(display, garbageQueue);
|
||||
image.image->releaseStagingBuffer(display, garbageQueue);
|
||||
SafeDelete(image.image);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageHelper::SubresourceUpdate::isUpdateToLayerLevel(uint32_t layerIndex,
|
||||
uint32_t levelIndex) const
|
||||
{
|
||||
|
|
|
@ -58,9 +58,11 @@ class DynamicBuffer : angle::NonCopyable
|
|||
|
||||
// This releases resources when they might currently be in use.
|
||||
void release(RendererVk *renderer);
|
||||
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||
|
||||
// This releases all the buffers that have been allocated since this was last called.
|
||||
void releaseRetainedBuffers(RendererVk *renderer);
|
||||
void releaseRetainedBuffers(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||
|
||||
// This frees resources immediately.
|
||||
void destroy(VkDevice device);
|
||||
|
@ -397,7 +399,9 @@ class BufferHelper final : public CommandGraphResource
|
|||
const VkBufferCreateInfo &createInfo,
|
||||
VkMemoryPropertyFlags memoryPropertyFlags);
|
||||
void destroy(VkDevice device);
|
||||
|
||||
void release(RendererVk *renderer);
|
||||
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||
|
||||
bool valid() const { return mBuffer.valid(); }
|
||||
const Buffer &getBuffer() const { return mBuffer; }
|
||||
|
@ -585,7 +589,10 @@ class ImageHelper final : public CommandGraphResource
|
|||
uint32_t layerCount);
|
||||
|
||||
void releaseImage(RendererVk *renderer);
|
||||
void releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||
|
||||
void releaseStagingBuffer(RendererVk *renderer);
|
||||
void releaseStagingBuffer(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||
|
||||
bool valid() const { return mImage.valid(); }
|
||||
|
||||
|
@ -756,6 +763,7 @@ class ImageHelper final : public CommandGraphResource
|
|||
SubresourceUpdate(const SubresourceUpdate &other);
|
||||
|
||||
void release(RendererVk *renderer);
|
||||
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||
|
||||
const VkImageSubresourceLayers &dstSubresource() const
|
||||
{
|
||||
|
|
|
@ -415,27 +415,11 @@ angle::Result InitShaderAndSerial(Context *context,
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
// GarbageObject implementation.
|
||||
GarbageObject::GarbageObject()
|
||||
: mSerial(), mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE)
|
||||
GarbageObjectBase::GarbageObjectBase() : mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE)
|
||||
{}
|
||||
|
||||
GarbageObject::GarbageObject(const GarbageObject &other) = default;
|
||||
|
||||
GarbageObject &GarbageObject::operator=(const GarbageObject &other) = default;
|
||||
|
||||
bool GarbageObject::destroyIfComplete(VkDevice device, Serial completedSerial)
|
||||
{
|
||||
if (completedSerial >= mSerial)
|
||||
{
|
||||
destroy(device);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GarbageObject::destroy(VkDevice device)
|
||||
// GarbageObjectBase implementation
|
||||
void GarbageObjectBase::destroy(VkDevice device)
|
||||
{
|
||||
switch (mHandleType)
|
||||
{
|
||||
|
@ -503,6 +487,25 @@ void GarbageObject::destroy(VkDevice device)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// GarbageObject implementation.
|
||||
GarbageObject::GarbageObject() : mSerial() {}
|
||||
|
||||
GarbageObject::GarbageObject(const GarbageObject &other) = default;
|
||||
|
||||
GarbageObject &GarbageObject::operator=(const GarbageObject &other) = default;
|
||||
|
||||
bool GarbageObject::destroyIfComplete(VkDevice device, Serial completedSerial)
|
||||
{
|
||||
if (completedSerial >= mSerial)
|
||||
{
|
||||
destroy(device);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
|
||||
// VK_EXT_debug_utils
|
||||
|
|
|
@ -163,30 +163,41 @@ GetImplType<T> *GetImpl(const T *glObject)
|
|||
return GetImplAs<GetImplType<T>>(glObject);
|
||||
}
|
||||
|
||||
class GarbageObject final
|
||||
class GarbageObjectBase
|
||||
{
|
||||
public:
|
||||
template <typename ObjectT>
|
||||
GarbageObject(Serial serial, const ObjectT &object)
|
||||
: mSerial(serial),
|
||||
mHandleType(HandleTypeHelper<ObjectT>::kHandleType),
|
||||
GarbageObjectBase(const ObjectT &object)
|
||||
: mHandleType(HandleTypeHelper<ObjectT>::kHandleType),
|
||||
mHandle(reinterpret_cast<VkDevice>(object.getHandle()))
|
||||
{}
|
||||
GarbageObjectBase();
|
||||
|
||||
void destroy(VkDevice device);
|
||||
|
||||
private:
|
||||
HandleType mHandleType;
|
||||
VkDevice mHandle;
|
||||
};
|
||||
|
||||
class GarbageObject final : public GarbageObjectBase
|
||||
{
|
||||
public:
|
||||
template <typename ObjectT>
|
||||
GarbageObject(Serial serial, const ObjectT &object) : GarbageObjectBase(object), mSerial(serial)
|
||||
{}
|
||||
|
||||
GarbageObject();
|
||||
GarbageObject(const GarbageObject &other);
|
||||
GarbageObject &operator=(const GarbageObject &other);
|
||||
|
||||
bool destroyIfComplete(VkDevice device, Serial completedSerial);
|
||||
void destroy(VkDevice device);
|
||||
|
||||
private:
|
||||
// TODO(jmadill): Since many objects will have the same serial, it might be more efficient to
|
||||
// store the serial outside of the garbage object itself. We could index ranges of garbage
|
||||
// objects in the Renderer, using a circular buffer.
|
||||
Serial mSerial;
|
||||
HandleType mHandleType;
|
||||
VkDevice mHandle;
|
||||
};
|
||||
|
||||
class MemoryProperties final : angle::NonCopyable
|
||||
|
@ -465,6 +476,7 @@ class Shared final : angle::NonCopyable
|
|||
private:
|
||||
RefCounted<T> *mRefCounted;
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
|
||||
// List of function pointers for used extensions.
|
||||
|
|
|
@ -39,6 +39,16 @@ class WrappedObject : angle::NonCopyable
|
|||
}
|
||||
}
|
||||
|
||||
template <typename ResourceOutType>
|
||||
void dumpResources(std::vector<ResourceOutType> *outQueue)
|
||||
{
|
||||
if (valid())
|
||||
{
|
||||
outQueue->emplace_back(*static_cast<DerivedT *>(this));
|
||||
mHandle = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
WrappedObject() : mHandle(VK_NULL_HANDLE) {}
|
||||
~WrappedObject() { ASSERT(!valid()); }
|
||||
|
|
Загрузка…
Ссылка в новой задаче