зеркало из 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);
|
DisplayVk *displayVk = vk::GetImpl(display);
|
||||||
RendererVk *renderer = displayVk->getRenderer();
|
RendererVk *renderer = displayVk->getRenderer();
|
||||||
|
|
||||||
|
std::vector<vk::GarbageObjectBase> garbage;
|
||||||
|
|
||||||
if (mImage != nullptr && mOwnsImage)
|
if (mImage != nullptr && mOwnsImage)
|
||||||
{
|
{
|
||||||
mImage->releaseImage(renderer);
|
mImage->releaseImage(displayVk, &garbage);
|
||||||
mImage->releaseStagingBuffer(renderer);
|
mImage->releaseStagingBuffer(displayVk, &garbage);
|
||||||
delete mImage;
|
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;
|
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)
|
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;
|
return angle::Result::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ class ExternalImageSiblingVk : public ExternalImageSiblingImpl
|
||||||
~ExternalImageSiblingVk() override {}
|
~ExternalImageSiblingVk() override {}
|
||||||
|
|
||||||
virtual vk::ImageHelper *getImage() const = 0;
|
virtual vk::ImageHelper *getImage() const = 0;
|
||||||
|
|
||||||
|
virtual void release(DisplayVk *display, std::vector<vk::GarbageObjectBase> *garbageQueue) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ImageVk : public ImageImpl
|
class ImageVk : public ImageImpl
|
||||||
|
@ -49,6 +51,8 @@ class ImageVk : public ImageImpl
|
||||||
bool mOwnsImage;
|
bool mOwnsImage;
|
||||||
vk::ImageHelper *mImage;
|
vk::ImageHelper *mImage;
|
||||||
|
|
||||||
|
std::vector<vk::Shared<vk::Fence>> mImageLastUseFences;
|
||||||
|
|
||||||
const gl::Context *mContext;
|
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.
|
// Initially dumping the command graphs is disabled.
|
||||||
constexpr bool kEnableCommandGraphDiagnostics = false;
|
constexpr bool kEnableCommandGraphDiagnostics = false;
|
||||||
|
|
||||||
|
@ -544,11 +568,15 @@ RendererVk::RendererVk()
|
||||||
mFormatProperties.fill(invalid);
|
mFormatProperties.fill(invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererVk::~RendererVk() {}
|
RendererVk::~RendererVk()
|
||||||
|
{
|
||||||
|
ASSERT(mGarbage.empty());
|
||||||
|
ASSERT(mFencedGarbage.empty());
|
||||||
|
}
|
||||||
|
|
||||||
void RendererVk::onDestroy(vk::Context *context)
|
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.
|
// TODO(jmadill): Not nice to pass nullptr here, but shouldn't be a problem.
|
||||||
(void)finish(context, nullptr, nullptr);
|
(void)finish(context, nullptr, nullptr);
|
||||||
|
@ -1392,6 +1420,9 @@ angle::Result RendererVk::finish(vk::Context *context,
|
||||||
ANGLE_VK_TRY(context, vkQueueWaitIdle(mQueue));
|
ANGLE_VK_TRY(context, vkQueueWaitIdle(mQueue));
|
||||||
freeAllInFlightResources();
|
freeAllInFlightResources();
|
||||||
|
|
||||||
|
ANGLE_TRY(cleanupFencedGarbage(context, true));
|
||||||
|
ASSERT(mFencedGarbage.empty());
|
||||||
|
|
||||||
if (mGpuEventsEnabled)
|
if (mGpuEventsEnabled)
|
||||||
{
|
{
|
||||||
// This loop should in practice execute once since the queue is already idle.
|
// 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);
|
mGarbage.erase(mGarbage.begin(), mGarbage.begin() + freeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ANGLE_TRY(cleanupFencedGarbage(context, false));
|
||||||
|
|
||||||
return angle::Result::Continue;
|
return angle::Result::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2204,6 +2237,20 @@ void RendererVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpu
|
||||||
mGpuEvents.clear();
|
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>
|
template <VkFormatFeatureFlags VkFormatProperties::*features>
|
||||||
VkFormatFeatureFlags RendererVk::getFormatFeatureBits(VkFormat format,
|
VkFormatFeatureFlags RendererVk::getFormatFeatureBits(VkFormat format,
|
||||||
const VkFormatFeatureFlags featureBits)
|
const VkFormatFeatureFlags featureBits)
|
||||||
|
@ -2234,6 +2281,29 @@ bool RendererVk::hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlag
|
||||||
return IsMaskFlagSet(getFormatFeatureBits<features>(format, featureBits), featureBits);
|
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()
|
uint32_t GetUniformBufferDescriptorCount()
|
||||||
{
|
{
|
||||||
return kUniformBufferDescriptorsPerDescriptorSet;
|
return kUniformBufferDescriptorsPerDescriptorSet;
|
||||||
|
|
|
@ -213,6 +213,10 @@ class RendererVk : angle::NonCopyable
|
||||||
void pushDebugMarker(GLenum source, GLuint id, std::string &&marker);
|
void pushDebugMarker(GLenum source, GLuint id, std::string &&marker);
|
||||||
void popDebugMarker();
|
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;
|
static constexpr size_t kMaxExtensionNames = 200;
|
||||||
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
|
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
|
||||||
|
|
||||||
|
@ -254,6 +258,8 @@ class RendererVk : angle::NonCopyable
|
||||||
|
|
||||||
void nextSerial();
|
void nextSerial();
|
||||||
|
|
||||||
|
angle::Result cleanupFencedGarbage(vk::Context *context, bool block);
|
||||||
|
|
||||||
egl::Display *mDisplay;
|
egl::Display *mDisplay;
|
||||||
|
|
||||||
mutable bool mCapsInitialized;
|
mutable bool mCapsInitialized;
|
||||||
|
@ -302,6 +308,11 @@ class RendererVk : angle::NonCopyable
|
||||||
|
|
||||||
std::vector<CommandBatch> mInFlightCommands;
|
std::vector<CommandBatch> mInFlightCommands;
|
||||||
std::vector<vk::GarbageObject> mGarbage;
|
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::MemoryProperties mMemoryProperties;
|
||||||
vk::FormatTable mFormatTable;
|
vk::FormatTable mFormatTable;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,14 @@ void FenceSyncVk::onDestroy(RendererVk *renderer)
|
||||||
mFence.reset(renderer->getDevice());
|
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)
|
angle::Result FenceSyncVk::initialize(ContextVk *contextVk)
|
||||||
{
|
{
|
||||||
ASSERT(!mEvent.valid());
|
ASSERT(!mEvent.valid());
|
||||||
|
|
|
@ -31,6 +31,7 @@ class FenceSyncVk
|
||||||
~FenceSyncVk();
|
~FenceSyncVk();
|
||||||
|
|
||||||
void onDestroy(RendererVk *renderer);
|
void onDestroy(RendererVk *renderer);
|
||||||
|
void onDestroy(DisplayVk *display);
|
||||||
|
|
||||||
angle::Result initialize(ContextVk *contextVk);
|
angle::Result initialize(ContextVk *contextVk);
|
||||||
angle::Result clientWait(vk::Context *context,
|
angle::Result clientWait(vk::Context *context,
|
||||||
|
|
|
@ -164,15 +164,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
|
||||||
|
|
||||||
void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
|
void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
|
||||||
{
|
{
|
||||||
DisplayVk *displayVk = vk::GetImpl(display);
|
ASSERT(mImage == nullptr);
|
||||||
RendererVk *renderer = displayVk->getRenderer();
|
|
||||||
|
|
||||||
if (mImage != nullptr)
|
|
||||||
{
|
|
||||||
mImage->releaseImage(renderer);
|
|
||||||
mImage->releaseStagingBuffer(renderer);
|
|
||||||
SafeDelete(mImage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
|
gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
|
||||||
|
@ -205,4 +197,16 @@ vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
|
||||||
{
|
{
|
||||||
return mImage;
|
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
|
} // namespace rx
|
||||||
|
|
|
@ -36,6 +36,8 @@ class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
|
||||||
// ExternalImageSiblingVk interface
|
// ExternalImageSiblingVk interface
|
||||||
vk::ImageHelper *getImage() const override;
|
vk::ImageHelper *getImage() const override;
|
||||||
|
|
||||||
|
void release(DisplayVk *display, std::vector<vk::GarbageObjectBase> *garbageQueue) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
angle::Result initImpl(DisplayVk *displayVk);
|
angle::Result initImpl(DisplayVk *displayVk);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "libANGLE/Context.h"
|
#include "libANGLE/Context.h"
|
||||||
#include "libANGLE/renderer/vulkan/BufferVk.h"
|
#include "libANGLE/renderer/vulkan/BufferVk.h"
|
||||||
#include "libANGLE/renderer/vulkan/ContextVk.h"
|
#include "libANGLE/renderer/vulkan/ContextVk.h"
|
||||||
|
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||||
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
|
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
|
||||||
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
||||||
#include "libANGLE/renderer/vulkan/vk_utils.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)
|
void DynamicBuffer::releaseRetainedBuffers(RendererVk *renderer)
|
||||||
{
|
{
|
||||||
for (BufferHelper *toFree : mRetainedBuffers)
|
for (BufferHelper *toFree : mRetainedBuffers)
|
||||||
|
@ -388,6 +404,18 @@ void DynamicBuffer::releaseRetainedBuffers(RendererVk *renderer)
|
||||||
mRetainedBuffers.clear();
|
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)
|
void DynamicBuffer::destroy(VkDevice device)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
@ -1120,6 +1148,17 @@ void BufferHelper::release(RendererVk *renderer)
|
||||||
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
|
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)
|
void BufferHelper::onWrite(VkAccessFlagBits writeAccessType)
|
||||||
{
|
{
|
||||||
if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0)
|
if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0)
|
||||||
|
@ -1351,6 +1390,12 @@ void ImageHelper::releaseImage(RendererVk *renderer)
|
||||||
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
|
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageHelper::releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
|
||||||
|
{
|
||||||
|
mImage.dumpResources(garbageQueue);
|
||||||
|
mDeviceMemory.dumpResources(garbageQueue);
|
||||||
|
}
|
||||||
|
|
||||||
void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
|
void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
|
||||||
{
|
{
|
||||||
// Remove updates that never made it to the texture.
|
// Remove updates that never made it to the texture.
|
||||||
|
@ -1362,6 +1407,18 @@ void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
|
||||||
mSubresourceUpdates.clear();
|
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()
|
void ImageHelper::resetImageWeakReference()
|
||||||
{
|
{
|
||||||
mImage.reset();
|
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,
|
bool ImageHelper::SubresourceUpdate::isUpdateToLayerLevel(uint32_t layerIndex,
|
||||||
uint32_t levelIndex) const
|
uint32_t levelIndex) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,9 +58,11 @@ class DynamicBuffer : angle::NonCopyable
|
||||||
|
|
||||||
// This releases resources when they might currently be in use.
|
// This releases resources when they might currently be in use.
|
||||||
void release(RendererVk *renderer);
|
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.
|
// This releases all the buffers that have been allocated since this was last called.
|
||||||
void releaseRetainedBuffers(RendererVk *renderer);
|
void releaseRetainedBuffers(RendererVk *renderer);
|
||||||
|
void releaseRetainedBuffers(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||||
|
|
||||||
// This frees resources immediately.
|
// This frees resources immediately.
|
||||||
void destroy(VkDevice device);
|
void destroy(VkDevice device);
|
||||||
|
@ -397,7 +399,9 @@ class BufferHelper final : public CommandGraphResource
|
||||||
const VkBufferCreateInfo &createInfo,
|
const VkBufferCreateInfo &createInfo,
|
||||||
VkMemoryPropertyFlags memoryPropertyFlags);
|
VkMemoryPropertyFlags memoryPropertyFlags);
|
||||||
void destroy(VkDevice device);
|
void destroy(VkDevice device);
|
||||||
|
|
||||||
void release(RendererVk *renderer);
|
void release(RendererVk *renderer);
|
||||||
|
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||||
|
|
||||||
bool valid() const { return mBuffer.valid(); }
|
bool valid() const { return mBuffer.valid(); }
|
||||||
const Buffer &getBuffer() const { return mBuffer; }
|
const Buffer &getBuffer() const { return mBuffer; }
|
||||||
|
@ -585,7 +589,10 @@ class ImageHelper final : public CommandGraphResource
|
||||||
uint32_t layerCount);
|
uint32_t layerCount);
|
||||||
|
|
||||||
void releaseImage(RendererVk *renderer);
|
void releaseImage(RendererVk *renderer);
|
||||||
|
void releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||||
|
|
||||||
void releaseStagingBuffer(RendererVk *renderer);
|
void releaseStagingBuffer(RendererVk *renderer);
|
||||||
|
void releaseStagingBuffer(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||||
|
|
||||||
bool valid() const { return mImage.valid(); }
|
bool valid() const { return mImage.valid(); }
|
||||||
|
|
||||||
|
@ -756,6 +763,7 @@ class ImageHelper final : public CommandGraphResource
|
||||||
SubresourceUpdate(const SubresourceUpdate &other);
|
SubresourceUpdate(const SubresourceUpdate &other);
|
||||||
|
|
||||||
void release(RendererVk *renderer);
|
void release(RendererVk *renderer);
|
||||||
|
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
|
||||||
|
|
||||||
const VkImageSubresourceLayers &dstSubresource() const
|
const VkImageSubresourceLayers &dstSubresource() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -415,27 +415,11 @@ angle::Result InitShaderAndSerial(Context *context,
|
||||||
return angle::Result::Continue;
|
return angle::Result::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GarbageObject implementation.
|
GarbageObjectBase::GarbageObjectBase() : mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE)
|
||||||
GarbageObject::GarbageObject()
|
|
||||||
: mSerial(), mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
GarbageObject::GarbageObject(const GarbageObject &other) = default;
|
// GarbageObjectBase implementation
|
||||||
|
void GarbageObjectBase::destroy(VkDevice device)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
switch (mHandleType)
|
switch (mHandleType)
|
||||||
{
|
{
|
||||||
|
@ -503,6 +487,25 @@ void GarbageObject::destroy(VkDevice device)
|
||||||
break;
|
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
|
} // namespace vk
|
||||||
|
|
||||||
// VK_EXT_debug_utils
|
// VK_EXT_debug_utils
|
||||||
|
|
|
@ -163,30 +163,41 @@ GetImplType<T> *GetImpl(const T *glObject)
|
||||||
return GetImplAs<GetImplType<T>>(glObject);
|
return GetImplAs<GetImplType<T>>(glObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
class GarbageObject final
|
class GarbageObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <typename ObjectT>
|
template <typename ObjectT>
|
||||||
GarbageObject(Serial serial, const ObjectT &object)
|
GarbageObjectBase(const ObjectT &object)
|
||||||
: mSerial(serial),
|
: mHandleType(HandleTypeHelper<ObjectT>::kHandleType),
|
||||||
mHandleType(HandleTypeHelper<ObjectT>::kHandleType),
|
|
||||||
mHandle(reinterpret_cast<VkDevice>(object.getHandle()))
|
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();
|
||||||
GarbageObject(const GarbageObject &other);
|
GarbageObject(const GarbageObject &other);
|
||||||
GarbageObject &operator=(const GarbageObject &other);
|
GarbageObject &operator=(const GarbageObject &other);
|
||||||
|
|
||||||
bool destroyIfComplete(VkDevice device, Serial completedSerial);
|
bool destroyIfComplete(VkDevice device, Serial completedSerial);
|
||||||
void destroy(VkDevice device);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO(jmadill): Since many objects will have the same serial, it might be more efficient to
|
// 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
|
// store the serial outside of the garbage object itself. We could index ranges of garbage
|
||||||
// objects in the Renderer, using a circular buffer.
|
// objects in the Renderer, using a circular buffer.
|
||||||
Serial mSerial;
|
Serial mSerial;
|
||||||
HandleType mHandleType;
|
|
||||||
VkDevice mHandle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemoryProperties final : angle::NonCopyable
|
class MemoryProperties final : angle::NonCopyable
|
||||||
|
@ -465,6 +476,7 @@ class Shared final : angle::NonCopyable
|
||||||
private:
|
private:
|
||||||
RefCounted<T> *mRefCounted;
|
RefCounted<T> *mRefCounted;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace vk
|
} // namespace vk
|
||||||
|
|
||||||
// List of function pointers for used extensions.
|
// 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:
|
protected:
|
||||||
WrappedObject() : mHandle(VK_NULL_HANDLE) {}
|
WrappedObject() : mHandle(VK_NULL_HANDLE) {}
|
||||||
~WrappedObject() { ASSERT(!valid()); }
|
~WrappedObject() { ASSERT(!valid()); }
|
||||||
|
|
Загрузка…
Ссылка в новой задаче