Commit 33ffed01 by Jamie Madill Committed by Commit Bot

Vulkan: Clean up garbage APIs.

Instead of dumping resources to a context, we use the release APIs consistently. Refactoring/cleanup change only. Should have very litte impact on runtime behaviour. Bug: angleproject:2464 Change-Id: I2dc7f8316c466f7ccfad50a7b792ba0ee7bc2e49 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1804883Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 2bdefbf8
......@@ -319,7 +319,7 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk,
VK_ACCESS_HOST_WRITE_BIT, copyRegion));
// Immediately release staging buffer. We should probably be using a DynamicBuffer here.
contextVk->addGarbage(&stagingBuffer);
stagingBuffer.release(contextVk);
}
else
{
......
......@@ -1282,7 +1282,7 @@ void ContextVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuT
void ContextVk::clearAllGarbage()
{
VkDevice device = getDevice();
for (vk::GarbageObjectBase &garbage : mCurrentGarbage)
for (vk::GarbageObject &garbage : mCurrentGarbage)
{
garbage.destroy(device);
}
......@@ -1290,7 +1290,7 @@ void ContextVk::clearAllGarbage()
for (vk::GarbageAndSerial &garbageList : mGarbageQueue)
{
for (vk::GarbageObjectBase &garbage : garbageList.get())
for (vk::GarbageObject &garbage : garbageList.get())
{
garbage.destroy(device);
}
......@@ -2731,7 +2731,7 @@ angle::Result ContextVk::checkCompletedCommands()
vk::GarbageAndSerial &garbageList = mGarbageQueue[freeIndex];
if (garbageList.getSerial() < lastCompleted)
{
for (vk::GarbageObjectBase &garbage : garbageList.get())
for (vk::GarbageObject &garbage : garbageList.get())
{
garbage.destroy(device);
}
......
......@@ -271,7 +271,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
template <typename T>
void addGarbage(T *object)
{
object->dumpResources(&mCurrentGarbage);
mCurrentGarbage.emplace_back(vk::GetGarbage(object));
}
// Check to see which batches have finished completion (forward progress for
......
......@@ -32,7 +32,7 @@ void ImageVk::onDestroy(const egl::Display *display)
DisplayVk *displayVk = vk::GetImpl(display);
RendererVk *renderer = displayVk->getRenderer();
std::vector<vk::GarbageObjectBase> garbage;
std::vector<vk::GarbageObject> garbage;
if (mImage != nullptr && mOwnsImage)
{
......
......@@ -24,7 +24,7 @@ class ExternalImageSiblingVk : public ExternalImageSiblingImpl
virtual vk::ImageHelper *getImage() const = 0;
virtual void release(DisplayVk *display, std::vector<vk::GarbageObjectBase> *garbageQueue) = 0;
virtual void release(DisplayVk *display, std::vector<vk::GarbageObject> *garbageQueue) = 0;
};
class ImageVk : public ImageImpl
......
......@@ -151,7 +151,7 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk)
RendererVk *rendererVk = contextVk->getRenderer();
// Release old culledWidgets image
contextVk->addGarbage(&mCulledWidgets);
mCulledWidgets.releaseImage(contextVk);
contextVk->addGarbage(&mCulledWidgetsView);
// Create a buffer to contain coordinates of enabled text and graph widgets. This buffer will
......
......@@ -1616,8 +1616,7 @@ angle::Result RendererVk::newSharedFence(vk::Context *context,
return angle::Result::Continue;
}
void RendererVk::addGarbage(vk::Shared<vk::Fence> &&fence,
std::vector<vk::GarbageObjectBase> &&garbage)
void RendererVk::addGarbage(vk::Shared<vk::Fence> &&fence, std::vector<vk::GarbageObject> &&garbage)
{
std::vector<vk::Shared<vk::Fence>> fences;
fences.push_back(std::move(fence));
......@@ -1625,7 +1624,7 @@ void RendererVk::addGarbage(vk::Shared<vk::Fence> &&fence,
}
void RendererVk::addGarbage(std::vector<vk::Shared<vk::Fence>> &&fences,
std::vector<vk::GarbageObjectBase> &&garbage)
std::vector<vk::GarbageObject> &&garbage)
{
std::lock_guard<decltype(mGarbageMutex)> lock(mGarbageMutex);
mFencedGarbage.emplace_back(std::move(fences), std::move(garbage));
......@@ -1677,7 +1676,7 @@ angle::Result RendererVk::cleanupGarbage(vk::Context *context, bool block)
ANGLE_TRY(WaitFences(context, &garbageIter->first, block));
if (garbageIter->first.empty())
{
for (vk::GarbageObjectBase &garbageObject : garbageIter->second)
for (vk::GarbageObject &garbageObject : garbageIter->second)
{
garbageObject.destroy(mDevice);
}
......
......@@ -150,9 +150,9 @@ class RendererVk : angle::NonCopyable
sharedFenceIn->resetAndRecycle(&mFenceRecycler);
}
void addGarbage(vk::Shared<vk::Fence> &&fence, std::vector<vk::GarbageObjectBase> &&garbage);
void addGarbage(vk::Shared<vk::Fence> &&fence, std::vector<vk::GarbageObject> &&garbage);
void addGarbage(std::vector<vk::Shared<vk::Fence>> &&fences,
std::vector<vk::GarbageObjectBase> &&garbage);
std::vector<vk::GarbageObject> &&garbage);
static constexpr size_t kMaxExtensionNames = 200;
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
......@@ -230,7 +230,7 @@ class RendererVk : angle::NonCopyable
std::mutex mGarbageMutex;
using FencedGarbage =
std::pair<std::vector<vk::Shared<vk::Fence>>, std::vector<vk::GarbageObjectBase>>;
std::pair<std::vector<vk::Shared<vk::Fence>>, std::vector<vk::GarbageObject>>;
std::vector<FencedGarbage> mFencedGarbage;
vk::MemoryProperties mMemoryProperties;
......
......@@ -162,21 +162,13 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display)
{
DisplayVk *displayVk = vk::GetImpl(display);
std::vector<vk::GarbageObjectBase> garbageObjects;
image.releaseImage(displayVk, &garbageObjects);
image.releaseStagingBuffer(displayVk, &garbageObjects);
VkDevice device = displayVk->getDevice();
// It should be safe to immediately destroy the backing images of a surface on surface
// destruction.
// If this assumption is broken, we could track the last submit fence for the last context that
// used this surface to garbage collect the surfaces.
for (vk::GarbageObjectBase &garbage : garbageObjects)
{
garbage.destroy(displayVk->getDevice());
}
imageView.destroy(displayVk->getDevice());
// destruction. If this assumption is incorrect, we could use the last submit serial
// to determine when to destroy the surface.
image.destroy(device);
imageView.destroy(device);
}
OffscreenSurfaceVk::OffscreenSurfaceVk(const egl::SurfaceState &surfaceState,
......@@ -936,49 +928,21 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk)
void WindowSurfaceVk::destroySwapChainImages(DisplayVk *displayVk)
{
std::vector<vk::GarbageObjectBase> garbageObjects;
if (mDepthStencilImage.valid())
{
mDepthStencilImage.releaseImage(displayVk, &garbageObjects);
mDepthStencilImage.releaseStagingBuffer(displayVk, &garbageObjects);
if (mDepthStencilImageView.valid())
{
mDepthStencilImageView.dumpResources(&garbageObjects);
}
}
if (mColorImageMS.valid())
{
mColorImageMS.releaseImage(displayVk, &garbageObjects);
mColorImageMS.releaseImage(displayVk, &garbageObjects);
mColorImageViewMS.dumpResources(&garbageObjects);
mFramebufferMS.dumpResources(&garbageObjects);
}
VkDevice device = displayVk->getDevice();
for (vk::GarbageObjectBase &garbage : garbageObjects)
{
garbage.destroy(device);
}
mDepthStencilImage.destroy(device);
mDepthStencilImageView.destroy(device);
mColorImageMS.destroy(device);
mColorImageViewMS.destroy(device);
mFramebufferMS.destroy(device);
for (SwapchainImage &swapchainImage : mSwapchainImages)
{
// We don't own the swapchain image handles, so we just remove our reference to it.
swapchainImage.image.resetImageWeakReference();
swapchainImage.image.destroy(device);
if (swapchainImage.imageView.valid())
{
swapchainImage.imageView.destroy(device);
}
if (swapchainImage.framebuffer.valid())
{
swapchainImage.framebuffer.destroy(device);
}
swapchainImage.imageView.destroy(device);
swapchainImage.framebuffer.destroy(device);
for (ImagePresentHistory &presentHistory : swapchainImage.presentHistory)
{
......
......@@ -36,8 +36,8 @@ void FenceSyncVk::onDestroy(ContextVk *contextVk)
void FenceSyncVk::onDestroy(DisplayVk *display)
{
std::vector<vk::GarbageObjectBase> garbage;
mEvent.dumpResources(&garbage);
std::vector<vk::GarbageObject> garbage;
garbage.emplace_back(vk::GetGarbage(&mEvent));
display->getRenderer()->addGarbage(std::move(mFences), std::move(garbage));
}
......
......@@ -202,7 +202,7 @@ vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
}
void HardwareBufferImageSiblingVkAndroid::release(DisplayVk *display,
std::vector<vk::GarbageObjectBase> *garbageQueue)
std::vector<vk::GarbageObject> *garbageQueue)
{
if (mImage != nullptr)
{
......
......@@ -36,7 +36,7 @@ class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
// ExternalImageSiblingVk interface
vk::ImageHelper *getImage() const override;
void release(DisplayVk *display, std::vector<vk::GarbageObjectBase> *garbageQueue) override;
void release(DisplayVk *display, std::vector<vk::GarbageObject> *garbageQueue) override;
private:
angle::Result initImpl(DisplayVk *displayVk);
......
......@@ -457,7 +457,7 @@ void DynamicBuffer::releaseBufferListToContext(ContextVk *contextVk,
}
void DynamicBuffer::releaseBufferListToDisplay(DisplayVk *display,
std::vector<GarbageObjectBase> *garbageQueue,
std::vector<GarbageObject> *garbageQueue,
std::vector<BufferHelper *> *buffers)
{
for (BufferHelper *toFree : *buffers)
......@@ -501,7 +501,7 @@ void DynamicBuffer::release(ContextVk *contextVk)
}
}
void DynamicBuffer::release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
void DynamicBuffer::release(DisplayVk *display, std::vector<GarbageObject> *garbageQueue)
{
reset();
......@@ -1310,15 +1310,15 @@ void BufferHelper::release(ContextVk *contextVk)
contextVk->addGarbage(&mDeviceMemory);
}
void BufferHelper::release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
void BufferHelper::release(DisplayVk *display, std::vector<GarbageObject> *garbageQueue)
{
unmap(display->getDevice());
mSize = 0;
mViewFormat = nullptr;
mBuffer.dumpResources(garbageQueue);
mBufferView.dumpResources(garbageQueue);
mDeviceMemory.dumpResources(garbageQueue);
garbageQueue->emplace_back(GetGarbage(&mBuffer));
garbageQueue->emplace_back(GetGarbage(&mBufferView));
garbageQueue->emplace_back(GetGarbage(&mDeviceMemory));
}
bool BufferHelper::needsOnWriteBarrier(VkAccessFlags readAccessType,
......@@ -1571,10 +1571,10 @@ void ImageHelper::releaseImage(ContextVk *contextVk)
contextVk->addGarbage(&mDeviceMemory);
}
void ImageHelper::releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
void ImageHelper::releaseImage(DisplayVk *display, std::vector<GarbageObject> *garbageQueue)
{
mImage.dumpResources(garbageQueue);
mDeviceMemory.dumpResources(garbageQueue);
garbageQueue->emplace_back(GetGarbage(&mImage));
garbageQueue->emplace_back(GetGarbage(&mDeviceMemory));
}
void ImageHelper::releaseStagingBuffer(ContextVk *contextVk)
......@@ -1588,8 +1588,7 @@ void ImageHelper::releaseStagingBuffer(ContextVk *contextVk)
mSubresourceUpdates.clear();
}
void ImageHelper::releaseStagingBuffer(DisplayVk *display,
std::vector<GarbageObjectBase> *garbageQueue)
void ImageHelper::releaseStagingBuffer(DisplayVk *display, std::vector<GarbageObject> *garbageQueue)
{
// Remove updates that never made it to the texture.
for (SubresourceUpdate &update : mSubresourceUpdates)
......@@ -1686,6 +1685,7 @@ void ImageHelper::destroy(VkDevice device)
{
mImage.destroy(device);
mDeviceMemory.destroy(device);
mStagingBuffer.destroy(device);
mCurrentLayout = ImageLayout::Undefined;
mLayerCount = 0;
mLevelCount = 0;
......@@ -1755,12 +1755,6 @@ VkImageAspectFlags ImageHelper::getAspectFlags() const
return GetFormatAspectFlags(mFormat->imageFormat());
}
void ImageHelper::dumpResources(GarbageList *garbageList)
{
mImage.dumpResources(garbageList);
mDeviceMemory.dumpResources(garbageList);
}
VkImageLayout ImageHelper::getCurrentLayout() const
{
return kImageMemoryBarrierData[mCurrentLayout].layout;
......@@ -2692,7 +2686,7 @@ void ImageHelper::SubresourceUpdate::release(ContextVk *contextVk)
}
void ImageHelper::SubresourceUpdate::release(DisplayVk *display,
std::vector<GarbageObjectBase> *garbageQueue)
std::vector<GarbageObject> *garbageQueue)
{
if (updateSource == UpdateSource::Image)
{
......
......@@ -83,7 +83,7 @@ class DynamicBuffer : angle::NonCopyable
// This releases resources when they might currently be in use.
void release(ContextVk *contextVk);
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
void release(DisplayVk *display, std::vector<GarbageObject> *garbageQueue);
// This releases all the buffers that have been allocated since this was last called.
void releaseInFlightBuffers(ContextVk *contextVk);
......@@ -103,7 +103,7 @@ class DynamicBuffer : angle::NonCopyable
angle::Result allocateNewBuffer(ContextVk *contextVk);
void releaseBufferListToContext(ContextVk *contextVk, std::vector<BufferHelper *> *buffers);
void releaseBufferListToDisplay(DisplayVk *display,
std::vector<GarbageObjectBase> *garbageQueue,
std::vector<GarbageObject> *garbageQueue,
std::vector<BufferHelper *> *buffers);
void destroyBufferList(VkDevice device, std::vector<BufferHelper *> *buffers);
......@@ -449,7 +449,7 @@ class BufferHelper final : public CommandGraphResource
void destroy(VkDevice device);
void release(ContextVk *contextVk);
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
void release(DisplayVk *display, std::vector<GarbageObject> *garbageQueue);
bool valid() const { return mBuffer.valid(); }
const Buffer &getBuffer() const { return mBuffer; }
......@@ -704,16 +704,15 @@ class ImageHelper final : public CommandGraphResource
uint32_t layerCount);
void releaseImage(ContextVk *contextVk);
void releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
void releaseImage(DisplayVk *display, std::vector<GarbageObject> *garbageQueue);
void releaseStagingBuffer(ContextVk *contextVk);
void releaseStagingBuffer(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
void releaseStagingBuffer(DisplayVk *display, std::vector<GarbageObject> *garbageQueue);
bool valid() const { return mImage.valid(); }
VkImageAspectFlags getAspectFlags() const;
void destroy(VkDevice device);
void dumpResources(GarbageList *garbageList);
void init2DWeakReference(VkImage handle,
const gl::Extents &glExtents,
......@@ -885,7 +884,7 @@ class ImageHelper final : public CommandGraphResource
SubresourceUpdate(const SubresourceUpdate &other);
void release(ContextVk *contextVk);
void release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue);
void release(DisplayVk *display, std::vector<GarbageObject> *garbageQueue);
const VkImageSubresourceLayers &dstSubresource() const
{
......
......@@ -351,10 +351,10 @@ angle::Result StagingBuffer::init(Context *context, VkDeviceSize size, StagingUs
return angle::Result::Continue;
}
void StagingBuffer::dumpResources(GarbageList *garbageList)
void StagingBuffer::release(ContextVk *contextVk)
{
mBuffer.dumpResources(garbageList);
mDeviceMemory.dumpResources(garbageList);
contextVk->addGarbage(&mBuffer);
contextVk->addGarbage(&mDeviceMemory);
}
angle::Result AllocateBufferMemory(vk::Context *context,
......@@ -435,23 +435,26 @@ gl::TextureType Get2DTextureType(uint32_t layerCount, GLint samples)
}
}
GarbageObjectBase::GarbageObjectBase() : mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE)
GarbageObject::GarbageObject() : mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE) {}
GarbageObject::GarbageObject(HandleType handleType, GarbageHandle handle)
: mHandleType(handleType), mHandle(handle)
{}
GarbageObjectBase::GarbageObjectBase(GarbageObjectBase &&other) : GarbageObjectBase()
GarbageObject::GarbageObject(GarbageObject &&other) : GarbageObject()
{
*this = std::move(other);
}
GarbageObjectBase &GarbageObjectBase::operator=(GarbageObjectBase &&rhs)
GarbageObject &GarbageObject::operator=(GarbageObject &&rhs)
{
std::swap(mHandle, rhs.mHandle);
std::swap(mHandleType, rhs.mHandleType);
return *this;
}
// GarbageObjectBase implementation
void GarbageObjectBase::destroy(VkDevice device)
// GarbageObject implementation
void GarbageObject::destroy(VkDevice device)
{
switch (mHandleType)
{
......
......@@ -226,27 +226,38 @@ class ObjectAndSerial final : angle::NonCopyable
// Reference to a deleted object. The object is due to be destroyed at some point in the future.
// |mHandleType| determines the type of the object and which destroy function should be called.
class GarbageObjectBase
class GarbageObject
{
public:
template <typename ObjectT>
GarbageObjectBase(const ObjectT &object)
: mHandleType(HandleTypeHelper<ObjectT>::kHandleType),
mHandle(reinterpret_cast<VkDevice>(object.getHandle()))
{}
GarbageObjectBase();
GarbageObjectBase(GarbageObjectBase &&other);
GarbageObjectBase &operator=(GarbageObjectBase &&rhs);
GarbageObject();
GarbageObject(GarbageObject &&other);
GarbageObject &operator=(GarbageObject &&rhs);
void destroy(VkDevice device);
template <typename DerivedT, typename HandleT>
static GarbageObject Get(WrappedObject<DerivedT, HandleT> *object)
{
return GarbageObject(HandleTypeHelper<DerivedT>::kHandleType,
reinterpret_cast<GarbageHandle>(object->release()));
}
private:
VK_DEFINE_HANDLE(GarbageHandle)
GarbageObject(HandleType handleType, GarbageHandle handle);
HandleType mHandleType;
VkDevice mHandle;
GarbageHandle mHandle;
};
template <typename T>
GarbageObject GetGarbage(T *obj)
{
return GarbageObject::Get(obj);
}
// A list of garbage objects. Has no object lifetime information.
using GarbageList = std::vector<GarbageObjectBase>;
using GarbageList = std::vector<GarbageObject>;
// A list of garbage objects and the associated serial after which the objects can be destroyed.
using GarbageAndSerial = ObjectAndSerial<GarbageList>;
......@@ -277,6 +288,7 @@ class StagingBuffer final : angle::NonCopyable
{
public:
StagingBuffer();
void release(ContextVk *contextVk);
void destroy(VkDevice device);
angle::Result init(Context *context, VkDeviceSize size, StagingUsage usage);
......@@ -287,8 +299,6 @@ class StagingBuffer final : angle::NonCopyable
const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
size_t getSize() const { return mSize; }
void dumpResources(GarbageList *garbageList);
private:
Buffer mBuffer;
DeviceMemory mDeviceMemory;
......
......@@ -19,46 +19,6 @@ namespace rx
{
namespace vk
{
// Base class for all wrapped vulkan objects. Implements several common helper routines.
template <typename DerivedT, typename HandleT>
class WrappedObject : angle::NonCopyable
{
public:
HandleT getHandle() const { return mHandle; }
bool valid() const { return (mHandle != VK_NULL_HANDLE); }
const HandleT *ptr() const { return &mHandle; }
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()); }
WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
{
other.mHandle = VK_NULL_HANDLE;
}
// Only works to initialize empty objects, since we don't have the device handle.
WrappedObject &operator=(WrappedObject &&other)
{
ASSERT(!valid());
std::swap(mHandle, other.mHandle);
return *this;
}
HandleT mHandle;
};
// Helper macros that apply to all the wrapped object types.
// Unimplemented handle types:
// Instance
......@@ -127,6 +87,43 @@ struct HandleTypeHelper<priv::CommandBuffer>
#undef ANGLE_HANDLE_TYPE_HELPER_FUNC
// Base class for all wrapped vulkan objects. Implements several common helper routines.
template <typename DerivedT, typename HandleT>
class WrappedObject : angle::NonCopyable
{
public:
HandleT getHandle() const { return mHandle; }
bool valid() const { return (mHandle != VK_NULL_HANDLE); }
const HandleT *ptr() const { return &mHandle; }
HandleT release()
{
HandleT handle = mHandle;
mHandle = VK_NULL_HANDLE;
return handle;
}
protected:
WrappedObject() : mHandle(VK_NULL_HANDLE) {}
~WrappedObject() { ASSERT(!valid()); }
WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
{
other.mHandle = VK_NULL_HANDLE;
}
// Only works to initialize empty objects, since we don't have the device handle.
WrappedObject &operator=(WrappedObject &&other)
{
ASSERT(!valid());
std::swap(mHandle, other.mHandle);
return *this;
}
HandleT mHandle;
};
class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
{
public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment