Always destroy resources instead of simply "abandoning" them in Vulkan backend.

This also now requires that when using a vulkan GrContext, the backing VkDevice,
Queue, and Instance must be alive when the GrContext is first destroyed or
abandoned. Additionally any GrBackendTextures created from the GrContext must
be deleted before destroying or abandoning the GrContext.

Bug: skia:9603
Change-Id: Ibf194d2ffdcddd61e34214d7d59a2d9a33c880e5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/257921
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2019-12-04 15:17:54 -05:00 committed by Skia Commit-Bot
parent 6cc49538b3
commit f0e04f0c31
37 changed files with 60 additions and 336 deletions

View File

@ -7,6 +7,12 @@ This file includes a list of high level updates for each milestone release.
Milestone 80
<Insert new notes here- top is most recent.>
* For Vulkan backend, we now require that the VkDevice, Queue, and Instance outlive
either the destruction or abandoning of the GrContext. Additionally, all
GrBackendTextures created via GrContext::createBackendTexture calls must be deleted
before destroying or abandoning the GrContext.
https://review.skia.org/257921
* Removed SkSize& SkSize::operator=(const SkISize&)
https://review.skia.org/257880

View File

@ -57,6 +57,10 @@ public:
static sk_sp<GrContext> MakeGL(const GrContextOptions&);
static sk_sp<GrContext> MakeGL();
/**
* The Vulkan context (VkQueue, VkDevice, VkInstance) must be kept alive unitl the returned
* GrContext is first destroyed or abandoned.
*/
static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&, const GrContextOptions&);
static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&);
@ -114,6 +118,9 @@ public:
*
* The typical use case for this function is that the underlying 3D context was lost and further
* API calls may crash.
*
* For Vulkan, even if the device becomes lost, the VkQueue, VkDevice, or VkInstance used to
* create the GrContext must be alive before calling abandonContext.
*/
void abandonContext() override;
@ -130,6 +137,9 @@ public:
* The typical use case for this function is that the client is going to destroy the 3D context
* but can't guarantee that GrContext will be destroyed first (perhaps because it may be ref'ed
* elsewhere by either the client or Skia objects).
*
* For Vulkan, even if the device becomes lost, the VkQueue, VkDevice, or VkInstance used to
* create the GrContext must be alive before calling releaseResourcesAndAbandonContext.
*/
virtual void releaseResourcesAndAbandonContext();
@ -385,8 +395,9 @@ public:
* objects outside of Skia proper (i.e., Skia's caching system will not know about them.)
*
* It is the client's responsibility to delete all these objects (using deleteBackendTexture)
* before deleting the GrContext used to create them. Additionally, clients should only
* delete these objects on the thread for which that GrContext is active.
* before deleting the GrContext used to create them. If the backend is Vulkan, the textures must
* be deleted before abandoning the GrContext as well. Additionally, clients should only delete
* these objects on the thread for which that GrContext is active.
*
* The client is responsible for ensuring synchronization between different uses
* of the backend object (i.e., wrapping it in a surface, rendering to it, deleting the

View File

@ -550,7 +550,9 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n
void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
if (this->abandoned() || !backendTex.isValid()) {
// For the Vulkan backend we still must destroy the backend texture when the context is
// abandoned.
if ((this->abandoned() && this->backend() != GrBackendApi::kVulkan) || !backendTex.isValid()) {
return;
}

View File

@ -122,16 +122,6 @@ void GrVkBuffer::vkRelease(const GrVkGpu* gpu) {
VALIDATE();
}
void GrVkBuffer::vkAbandon() {
fResource->unrefAndAbandon();
fResource = nullptr;
if (!fDesc.fDynamic) {
delete[] (unsigned char*)fMapPtr;
}
fMapPtr = nullptr;
VALIDATE();
}
VkAccessFlags buffer_type_to_access_flags(GrVkBuffer::Type type) {
switch (type) {
case GrVkBuffer::kIndex_Type:

View File

@ -20,7 +20,7 @@ class GrVkGpu;
class GrVkBuffer : public SkNoncopyable {
public:
virtual ~GrVkBuffer() {
// either release or abandon should have been called by the owner of this object.
// release should have been called by the owner of this object.
SkASSERT(!fResource);
delete [] (unsigned char*)fMapPtr;
}
@ -95,7 +95,6 @@ protected:
bool vkUpdateData(GrVkGpu* gpu, const void* src, size_t srcSizeInBytes,
bool* createdNewBuffer = nullptr);
void vkAbandon();
void vkRelease(const GrVkGpu* gpu);
private:

View File

@ -53,22 +53,6 @@ void GrVkCommandBuffer::freeGPUData(GrVkGpu* gpu, VkCommandPool cmdPool) const {
this->onFreeGPUData(gpu);
}
void GrVkCommandBuffer::abandonGPUData() const {
SkDEBUGCODE(fResourcesReleased = true;)
for (int i = 0; i < fTrackedResources.count(); ++i) {
fTrackedResources[i]->notifyRemovedFromCommandBuffer();
fTrackedResources[i]->unrefAndAbandon();
}
for (int i = 0; i < fTrackedRecycledResources.count(); ++i) {
fTrackedRecycledResources[i]->notifyRemovedFromCommandBuffer();
// We don't recycle resources when abandoning them.
fTrackedRecycledResources[i]->unrefAndAbandon();
}
this->onAbandonGPUData();
}
void GrVkCommandBuffer::releaseResources(GrVkGpu* gpu) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkDEBUGCODE(fResourcesReleased = true;)
@ -852,13 +836,6 @@ void GrVkPrimaryCommandBuffer::onFreeGPUData(GrVkGpu* gpu) const {
SkASSERT(!fSecondaryCommandBuffers.count());
}
void GrVkPrimaryCommandBuffer::onAbandonGPUData() const {
SkASSERT(!fActiveRenderPass);
for (const auto& buffer : fSecondaryCommandBuffers) {
buffer->abandonGPUData();
}
}
///////////////////////////////////////////////////////////////////////////////
// SecondaryCommandBuffer
////////////////////////////////////////////////////////////////////////////////

View File

@ -114,7 +114,6 @@ public:
void releaseResources(GrVkGpu* gpu);
void freeGPUData(GrVkGpu* gpu, VkCommandPool pool) const;
void abandonGPUData() const;
bool hasWork() const { return fHasWork; }
@ -153,7 +152,6 @@ private:
virtual void onReleaseResources(GrVkGpu* gpu) {}
virtual void onFreeGPUData(GrVkGpu* gpu) const = 0;
virtual void onAbandonGPUData() const = 0;
static constexpr uint32_t kMaxInputBuffers = 2;
@ -302,8 +300,6 @@ private:
void onFreeGPUData(GrVkGpu* gpu) const override;
void onAbandonGPUData() const override;
void onReleaseResources(GrVkGpu* gpu) override;
SkTArray<std::unique_ptr<GrVkSecondaryCommandBuffer>, true> fSecondaryCommandBuffers;
@ -333,8 +329,6 @@ private:
void onFreeGPUData(GrVkGpu* gpu) const override {}
void onAbandonGPUData() const override {}
// Used for accessing fIsActive (on GrVkCommandBuffer)
friend class GrVkPrimaryCommandBuffer;

View File

@ -86,13 +86,6 @@ void GrVkCommandPool::releaseResources(GrVkGpu* gpu) {
fPrimaryCommandBuffer->recycleSecondaryCommandBuffers(this);
}
void GrVkCommandPool::abandonGPUData() const {
fPrimaryCommandBuffer->abandonGPUData();
for (const auto& buffer : fAvailableSecondaryBuffers) {
buffer->abandonGPUData();
}
}
void GrVkCommandPool::freeGPUData(GrVkGpu* gpu) const {
// TODO: having freeGPUData virtual on GrVkResource be const seems like a bad restriction since
// we are changing the internal objects of these classes when it is called. We should go back a

View File

@ -52,8 +52,6 @@ private:
GrVkCommandPool(GrVkGpu* gpu, VkCommandPool commandPool, GrVkPrimaryCommandBuffer*);
void abandonGPUData() const override;
void freeGPUData(GrVkGpu* gpu) const override;
bool fOpen = true;

View File

@ -28,7 +28,3 @@ void GrVkDescriptorSet::onRecycle(GrVkGpu* gpu) const {
gpu->resourceProvider().recycleDescriptorSet(this, fHandle);
}
void GrVkDescriptorSet::abandonGPUData() const {
fPool->unrefAndAbandon();
}

View File

@ -33,7 +33,6 @@ public:
private:
void freeGPUData(GrVkGpu* gpu) const override;
void abandonGPUData() const override;
void onRecycle(GrVkGpu* gpu) const override;
VkDescriptorSet fDescSet;

View File

@ -234,22 +234,6 @@ void GrVkDescriptorSetManager::release(GrVkGpu* gpu) {
fImmutableSamplers.reset();
}
void GrVkDescriptorSetManager::abandon() {
fPoolManager.abandonGPUResources();
for (int i = 0; i < fFreeSets.count(); ++i) {
fFreeSets[i]->unrefAndAbandon();
}
fFreeSets.reset();
for (int i = 0; i < fImmutableSamplers.count(); ++i) {
if (fImmutableSamplers[i]) {
fImmutableSamplers[i]->unrefAndAbandon();
}
}
fImmutableSamplers.reset();
}
bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type,
const GrVkUniformHandler* uniHandler) const {
SkASSERT(uniHandler);
@ -360,10 +344,3 @@ void GrVkDescriptorSetManager::DescriptorPoolManager::freeGPUResources(GrVkGpu*
}
}
void GrVkDescriptorSetManager::DescriptorPoolManager::abandonGPUResources() {
fDescLayout = VK_NULL_HANDLE;
if (fPool) {
fPool->unrefAndAbandon();
fPool = nullptr;
}
}

View File

@ -35,7 +35,6 @@ public:
~GrVkDescriptorSetManager() {}
void abandon();
void release(GrVkGpu* gpu);
VkDescriptorSetLayout layout() const { return fPoolManager.fDescLayout; }
@ -61,7 +60,6 @@ private:
bool getNewDescriptorSet(GrVkGpu* gpu, VkDescriptorSet* ds);
void freeGPUResources(GrVkGpu* gpu);
void abandonGPUResources();
VkDescriptorSetLayout fDescLayout;
VkDescriptorType fDescType;

View File

@ -158,7 +158,6 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
: INHERITED(context)
, fInterface(std::move(interface))
, fMemoryAllocator(backendContext.fMemoryAllocator)
, fInstance(backendContext.fInstance)
, fPhysicalDevice(backendContext.fPhysicalDevice)
, fDevice(backendContext.fDevice)
, fQueue(backendContext.fQueue)
@ -273,17 +272,12 @@ void GrVkGpu::destroyResources() {
// must call this just before we destroy the command pool and VkDevice
fResourceProvider.destroyResources(VK_ERROR_DEVICE_LOST == res);
fMemoryAllocator.reset();
fQueue = VK_NULL_HANDLE;
fDevice = VK_NULL_HANDLE;
fInstance = VK_NULL_HANDLE;
}
GrVkGpu::~GrVkGpu() {
if (!fDisconnected) {
this->destroyResources();
fMemoryAllocator.reset();
}
delete fCompiler;
}
@ -292,25 +286,9 @@ GrVkGpu::~GrVkGpu() {
void GrVkGpu::disconnect(DisconnectType type) {
INHERITED::disconnect(type);
if (!fDisconnected) {
if (DisconnectType::kCleanup == type) {
this->destroyResources();
} else {
if (fCmdPool) {
fCmdPool->unrefAndAbandon();
fCmdPool = nullptr;
}
for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
fSemaphoresToWaitOn[i]->unrefAndAbandon();
}
for (int i = 0; i < fSemaphoresToSignal.count(); ++i) {
fSemaphoresToSignal[i]->unrefAndAbandon();
}
this->destroyResources();
fMemoryAllocator.reset();
// must call this just before we destroy the command pool and VkDevice
fResourceProvider.abandonResources();
fMemoryAllocator.reset();
}
fSemaphoresToWaitOn.reset();
fSemaphoresToSignal.reset();
fCurrentCmdBuffer = nullptr;

View File

@ -275,7 +275,6 @@ private:
sk_sp<GrVkCaps> fVkCaps;
bool fDeviceIsLost = false;
VkInstance fInstance;
VkPhysicalDevice fPhysicalDevice;
VkDevice fDevice;
VkQueue fQueue; // Must be Graphics queue

View File

@ -87,6 +87,7 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags dstStageMask,
bool byRegion, bool releaseFamilyQueue) {
SkASSERT(!gpu->isDeviceLost());
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout);
VkImageLayout currentLayout = this->currentLayout();
@ -227,7 +228,7 @@ void GrVkImage::DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo* info) {
}
GrVkImage::~GrVkImage() {
// should have been released or abandoned first
// should have been released first
SkASSERT(!fResource);
}
@ -248,7 +249,7 @@ void GrVkImage::prepareForExternal(GrVkGpu* gpu) {
}
void GrVkImage::releaseImage(GrVkGpu* gpu) {
if (fInfo.fCurrentQueueFamily != fInitialQueueFamily) {
if (!gpu->isDeviceLost() && fInfo.fCurrentQueueFamily != fInitialQueueFamily) {
// The Vulkan spec is vague on what to put for the dstStageMask here. The spec for image
// memory barrier says the dstStageMask must not be zero. However, in the spec when it talks
// about family queue transfers it says the dstStageMask is ignored and should be set to
@ -264,14 +265,6 @@ void GrVkImage::releaseImage(GrVkGpu* gpu) {
}
}
void GrVkImage::abandonImage() {
if (fResource) {
fResource->removeOwningTexture();
fResource->unrefAndAbandon();
fResource = nullptr;
}
}
void GrVkImage::setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper) {
SkASSERT(fResource);
// Forward the release proc on to GrVkImage::Resource
@ -322,10 +315,6 @@ void GrVkImage::BorrowedResource::freeGPUData(GrVkGpu* gpu) const {
this->invokeReleaseProc();
}
void GrVkImage::BorrowedResource::abandonGPUData() const {
this->invokeReleaseProc();
}
#if GR_TEST_UTILS
void GrVkImage::setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu) {
fInfo.fCurrentQueueFamily = gpu->queueIndex();

View File

@ -157,7 +157,6 @@ public:
protected:
void releaseImage(GrVkGpu* gpu);
void abandonImage();
bool hasResource() const { return fResource; }
GrVkImageInfo fInfo;
@ -225,10 +224,6 @@ private:
private:
void freeGPUData(GrVkGpu* gpu) const override;
void abandonGPUData() const override {
this->invokeReleaseProc();
SkASSERT(!fReleaseHelper);
}
VkImage fImage;
GrVkAlloc fAlloc;
@ -248,7 +243,6 @@ private:
}
private:
void freeGPUData(GrVkGpu* gpu) const override;
void abandonGPUData() const override;
};
Resource* fResource;

View File

@ -69,9 +69,3 @@ void GrVkImageView::freeGPUData(GrVkGpu* gpu) const {
}
}
void GrVkImageView::abandonGPUData() const {
if (fYcbcrConversion) {
fYcbcrConversion->unrefAndAbandon();
}
}

View File

@ -42,7 +42,6 @@ private:
GrVkImageView& operator=(const GrVkImageView&);
void freeGPUData(GrVkGpu* gpu) const override;
void abandonGPUData() const override;
VkImageView fImageView;
GrVkSamplerYcbcrConversion* fYcbcrConversion;

View File

@ -39,12 +39,13 @@ void GrVkIndexBuffer::onRelease() {
if (!this->wasDestroyed()) {
this->vkRelease(this->getVkGpu());
}
INHERITED::onRelease();
}
void GrVkIndexBuffer::onAbandon() {
this->vkAbandon();
if (!this->wasDestroyed()) {
this->vkRelease(this->getVkGpu());
}
INHERITED::onAbandon();
}

View File

@ -80,23 +80,6 @@ void GrVkPipelineState::freeGPUResources(GrVkGpu* gpu) {
}
}
void GrVkPipelineState::abandonGPUResources() {
if (fPipeline) {
fPipeline->unrefAndAbandon();
fPipeline = nullptr;
}
if (fUniformBuffer) {
fUniformBuffer->abandon();
fUniformBuffer.reset();
}
if (fUniformDescriptorSet) {
fUniformDescriptorSet->unrefAndAbandon();
fUniformDescriptorSet = nullptr;
}
}
bool GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu,
const GrRenderTarget* renderTarget,
const GrProgramInfo& programInfo,

View File

@ -68,8 +68,6 @@ public:
void freeGPUResources(GrVkGpu* gpu);
void abandonGPUResources();
private:
void writeUniformBuffers(const GrVkGpu* gpu);

View File

@ -64,14 +64,6 @@ GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
#endif
}
void GrVkResourceProvider::PipelineStateCache::abandon() {
fMap.foreach([](std::unique_ptr<Entry>* e) {
(*e)->fPipelineState->abandonGPUResources();
(*e)->fPipelineState = nullptr;
});
fMap.reset();
}
void GrVkResourceProvider::PipelineStateCache::release() {
fMap.reset();
}

View File

@ -363,35 +363,6 @@ void GrVkRenderTarget::releaseInternalObjects() {
fGrSecondaryCommandBuffers.reset();
}
void GrVkRenderTarget::abandonInternalObjects() {
if (fMSAAImage) {
fMSAAImage->abandonImage();
fMSAAImage.reset();
}
if (fResolveAttachmentView) {
fResolveAttachmentView->unrefAndAbandon();
fResolveAttachmentView = nullptr;
}
if (fColorAttachmentView) {
fColorAttachmentView->unrefAndAbandon();
fColorAttachmentView = nullptr;
}
if (fCachedFramebuffer) {
fCachedFramebuffer->unrefAndAbandon();
fCachedFramebuffer = nullptr;
}
if (fCachedSimpleRenderPass) {
fCachedSimpleRenderPass->unrefAndAbandon();
fCachedSimpleRenderPass = nullptr;
}
for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) {
SkASSERT(fGrSecondaryCommandBuffers[i]);
fGrSecondaryCommandBuffers[i]->abandonGPUData();
}
fGrSecondaryCommandBuffers.reset();
}
void GrVkRenderTarget::onRelease() {
this->releaseInternalObjects();
this->releaseImage(this->getVkGpu());
@ -399,12 +370,11 @@ void GrVkRenderTarget::onRelease() {
}
void GrVkRenderTarget::onAbandon() {
this->abandonInternalObjects();
this->abandonImage();
this->releaseInternalObjects();
this->releaseImage(this->getVkGpu());
GrRenderTarget::onAbandon();
}
GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(), fInfo,

View File

@ -168,7 +168,6 @@ private:
}
void releaseInternalObjects();
void abandonInternalObjects();
const GrVkImageView* fColorAttachmentView;
std::unique_ptr<GrVkImage> fMSAAImage;

View File

@ -32,8 +32,7 @@ class GrVkGpu;
the stack or calling delete) if getRefCnt() > 1.
This is nearly identical to SkRefCntBase. The exceptions are that unref()
takes a GrVkGpu, and any derived classes must implement freeGPUData() and
possibly abandonGPUData().
takes a GrVkGpu, and any derived classes must implement freeGPUData().
*/
class GrVkResource : SkNoncopyable {
@ -134,24 +133,10 @@ public:
}
}
/** Unref without freeing GPU data. Used only when we're abandoning the resource */
void unrefAndAbandon() const {
SkASSERT(this->getRefCnt() > 0);
// A release here acts in place of all releases we "should" have been doing in ref().
int newRefCount = fRefCnt.fetch_add(-1, std::memory_order_acq_rel);
SkASSERT(newRefCount >= 0);
if (newRefCount == 1) {
// Like unique(), the acquire is only needed on success, to make sure
// code in internal_dispose() doesn't happen before the decrement.
this->internal_dispose();
}
}
// Called every time this resource is added to a command buffer.
virtual void notifyAddedToCommandBuffer() const {}
// Called every time this resource is removed from a command buffer (typically because
// the command buffer finished execution on the GPU but also when the command buffer
// is abandoned.)
// the command buffer finished execution on the GPU.)
virtual void notifyRemovedFromCommandBuffer() const {}
#ifdef SK_DEBUG
@ -179,13 +164,6 @@ private:
*/
virtual void freeGPUData(GrVkGpu* gpu) const = 0;
/**
* Called from unrefAndAbandon. Resources should do any necessary cleanup without freeing
* underlying Vk objects. This must be overridden by subclasses that themselves store
* GrVkResources since those resource will need to be unrefed.
*/
virtual void abandonGPUData() const {}
/**
* Called when the ref count goes to 0. Will free Vk resources.
*/
@ -195,22 +173,6 @@ private:
GetTrace()->remove(this);
#endif
#ifdef SK_DEBUG
SkASSERT(0 == this->getRefCnt());
fRefCnt.store(1);
#endif
delete this;
}
/**
* Internal_dispose without freeing Vk resources. Used when we've lost context.
*/
void internal_dispose() const {
this->abandonGPUData();
#ifdef SK_TRACE_VK_RESOURCES
GetTrace()->remove(this);
#endif
#ifdef SK_DEBUG
SkASSERT(0 == this->getRefCnt());
fRefCnt.store(1);

View File

@ -432,66 +432,6 @@ void GrVkResourceProvider::destroyResources(bool deviceLost) {
fAvailableUniformBufferResources.reset();
}
void GrVkResourceProvider::abandonResources() {
SkTaskGroup* taskGroup = fGpu->getContext()->priv().getTaskGroup();
if (taskGroup) {
taskGroup->wait();
}
// Abandon all command pools
for (int i = 0; i < fActiveCommandPools.count(); ++i) {
SkASSERT(fActiveCommandPools[i]->unique());
fActiveCommandPools[i]->unrefAndAbandon();
}
fActiveCommandPools.reset();
for (int i = 0; i < fAvailableCommandPools.count(); ++i) {
SkASSERT(fAvailableCommandPools[i]->unique());
fAvailableCommandPools[i]->unrefAndAbandon();
}
fAvailableCommandPools.reset();
// loop over all render pass sets to make sure we destroy all the internal VkRenderPasses
for (int i = 0; i < fRenderPassArray.count(); ++i) {
fRenderPassArray[i].abandonResources();
}
fRenderPassArray.reset();
for (int i = 0; i < fExternalRenderPasses.count(); ++i) {
fExternalRenderPasses[i]->unrefAndAbandon();
}
fExternalRenderPasses.reset();
// Iterate through all store GrVkSamplers and unrefAndAbandon them before resetting the hash.
SkTDynamicHash<GrVkSampler, GrVkSampler::Key>::Iter iter(&fSamplers);
for (; !iter.done(); ++iter) {
(*iter).unrefAndAbandon();
}
fSamplers.reset();
for (decltype(fYcbcrConversions)::Iter iter(&fYcbcrConversions); !iter.done(); ++iter) {
(*iter).unrefAndAbandon();
}
fYcbcrConversions.reset();
fPipelineStateCache->abandon();
fPipelineCache = VK_NULL_HANDLE;
// We must abandon all command buffers and pipeline states before abandoning the
// GrVkDescriptorSetManagers
for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
fDescriptorSetManagers[i]->abandon();
}
fDescriptorSetManagers.reset();
// release our uniform buffers
for (int i = 0; i < fAvailableUniformBufferResources.count(); ++i) {
SkASSERT(fAvailableUniformBufferResources[i]->unique());
fAvailableUniformBufferResources[i]->unrefAndAbandon();
}
fAvailableUniformBufferResources.reset();
}
void GrVkResourceProvider::backgroundReset(GrVkCommandPool* pool) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkASSERT(pool->unique());
@ -587,11 +527,3 @@ void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources(GrVkGpu* gp
}
}
void GrVkResourceProvider::CompatibleRenderPassSet::abandonResources() {
for (int i = 0; i < fRenderPasses.count(); ++i) {
if (fRenderPasses[i]) {
fRenderPasses[i]->unrefAndAbandon();
fRenderPasses[i] = nullptr;
}
}
}

View File

@ -164,11 +164,6 @@ public:
// before deleting (see section 4.2.4 of the Vulkan spec).
void destroyResources(bool deviceLost);
// Abandon any cached resources. To be used when the context/VkDevice is lost.
// For resource tracing to work properly, this should be called after unrefing all other
// resource usages.
void abandonResources();
void backgroundReset(GrVkCommandPool* pool);
void reset(GrVkCommandPool* pool);
@ -188,7 +183,6 @@ private:
PipelineStateCache(GrVkGpu* gpu);
~PipelineStateCache();
void abandon();
void release();
GrVkPipelineState* refPipelineState(GrRenderTarget*,
const GrProgramInfo&,
@ -234,7 +228,6 @@ private:
const GrVkRenderPass::LoadStoreOps& stencilOps);
void releaseResources(GrVkGpu* gpu);
void abandonResources();
private:
SkSTArray<4, GrVkRenderPass*> fRenderPasses;

View File

@ -120,12 +120,6 @@ void GrVkSampler::freeGPUData(GrVkGpu* gpu) const {
}
}
void GrVkSampler::abandonGPUData() const {
if (fYcbcrConversion) {
fYcbcrConversion->unrefAndAbandon();
}
}
GrVkSampler::Key GrVkSampler::GenerateKey(const GrSamplerState& samplerState,
const GrVkYcbcrConversionInfo& ycbcrInfo) {
return { GrSamplerState::GenerateKey(samplerState),

View File

@ -66,7 +66,6 @@ private:
, fUniqueID(GenID()) {}
void freeGPUData(GrVkGpu* gpu) const override;
void abandonGPUData() const override;
static uint32_t GenID() {
static std::atomic<uint32_t> nextID{1};

View File

@ -81,18 +81,19 @@ size_t GrVkStencilAttachment::onGpuMemorySize() const {
void GrVkStencilAttachment::onRelease() {
GrVkGpu* gpu = this->getVkGpu();
this->releaseImage(gpu);
fStencilView->unref(gpu);
fStencilView = nullptr;
GrStencilAttachment::onRelease();
}
void GrVkStencilAttachment::onAbandon() {
this->abandonImage();
fStencilView->unrefAndAbandon();
GrVkGpu* gpu = this->getVkGpu();
this->releaseImage(gpu);
fStencilView->unref(gpu);
fStencilView = nullptr;
GrStencilAttachment::onAbandon();
}

View File

@ -181,17 +181,13 @@ void GrVkTexture::onAbandon() {
// we create this and don't hand it off, so we should always destroy it
if (fTextureView) {
fTextureView->unrefAndAbandon();
fTextureView->unref(this->getVkGpu());
fTextureView = nullptr;
}
fDescSetCache.foreach ([](std::unique_ptr<DescriptorCacheEntry>* entry) {
(*entry)->fDescriptorSet->unrefAndAbandon();
(*entry)->fDescriptorSet = nullptr;
});
fDescSetCache.reset();
this->abandonImage();
this->releaseImage(this->getVkGpu());
INHERITED::onAbandon();
}

View File

@ -43,12 +43,13 @@ void GrVkTransferBuffer::onRelease() {
if (!this->wasDestroyed()) {
this->vkRelease(this->getVkGpu());
}
INHERITED::onRelease();
}
void GrVkTransferBuffer::onAbandon() {
this->vkAbandon();
if (!this->wasDestroyed()) {
this->vkRelease(this->getVkGpu());
}
INHERITED::onAbandon();
}

View File

@ -33,7 +33,6 @@ public:
return this->vkUpdateData(gpu, src, srcSizeInBytes, createdNewBuffer);
}
void release(const GrVkGpu* gpu) { this->vkRelease(gpu); }
void abandon() { this->vkAbandon(); }
private:
class Resource : public GrVkBuffer::Resource {

View File

@ -43,7 +43,9 @@ void GrVkVertexBuffer::onRelease() {
}
void GrVkVertexBuffer::onAbandon() {
this->vkAbandon();
if (!this->wasDestroyed()) {
this->vkRelease(this->getVkGpu());
}
INHERITED::onAbandon();
}

View File

@ -1604,6 +1604,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceMessagesAfterAbandon, reporter, ctxIn
GrTextureFreedMessage msg{tex, context->priv().contextID()};
SkMessageBus<GrTextureFreedMessage>::Post(msg);
// This doesn't actually do anything but it does trigger us to read messages
context->purgeUnlockedResources(false);
}

View File

@ -86,10 +86,18 @@ void GrContextFactory::abandonContexts() {
if (context.fTestContext) {
auto restore = context.fTestContext->makeCurrentAndAutoRestore();
context.fTestContext->testAbandon();
}
bool requiresEarlyAbandon = (context.fGrContext->backend() == GrBackendApi::kVulkan);
if (requiresEarlyAbandon) {
context.fGrContext->abandonContext();
}
if (context.fTestContext) {
delete(context.fTestContext);
context.fTestContext = nullptr;
}
context.fGrContext->abandonContext();
if (!requiresEarlyAbandon) {
context.fGrContext->abandonContext();
}
context.fAbandoned = true;
}
}
@ -108,11 +116,11 @@ void GrContextFactory::releaseResourcesAndAbandonContexts() {
restore = context.fTestContext->makeCurrentAndAutoRestore();
}
context.fGrContext->releaseResourcesAndAbandonContext();
context.fAbandoned = true;
if (context.fTestContext) {
delete context.fTestContext;
context.fTestContext = nullptr;
}
context.fAbandoned = true;
}
}
}