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:
parent
6cc49538b3
commit
f0e04f0c31
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -52,8 +52,6 @@ private:
|
||||
|
||||
GrVkCommandPool(GrVkGpu* gpu, VkCommandPool commandPool, GrVkPrimaryCommandBuffer*);
|
||||
|
||||
void abandonGPUData() const override;
|
||||
|
||||
void freeGPUData(GrVkGpu* gpu) const override;
|
||||
|
||||
bool fOpen = true;
|
||||
|
@ -28,7 +28,3 @@ void GrVkDescriptorSet::onRecycle(GrVkGpu* gpu) const {
|
||||
gpu->resourceProvider().recycleDescriptorSet(this, fHandle);
|
||||
}
|
||||
|
||||
void GrVkDescriptorSet::abandonGPUData() const {
|
||||
fPool->unrefAndAbandon();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@ public:
|
||||
|
||||
private:
|
||||
void freeGPUData(GrVkGpu* gpu) const override;
|
||||
void abandonGPUData() const override;
|
||||
void onRecycle(GrVkGpu* gpu) const override;
|
||||
|
||||
VkDescriptorSet fDescSet;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -275,7 +275,6 @@ private:
|
||||
sk_sp<GrVkCaps> fVkCaps;
|
||||
bool fDeviceIsLost = false;
|
||||
|
||||
VkInstance fInstance;
|
||||
VkPhysicalDevice fPhysicalDevice;
|
||||
VkDevice fDevice;
|
||||
VkQueue fQueue; // Must be Graphics queue
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -69,9 +69,3 @@ void GrVkImageView::freeGPUData(GrVkGpu* gpu) const {
|
||||
}
|
||||
}
|
||||
|
||||
void GrVkImageView::abandonGPUData() const {
|
||||
if (fYcbcrConversion) {
|
||||
fYcbcrConversion->unrefAndAbandon();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ private:
|
||||
GrVkImageView& operator=(const GrVkImageView&);
|
||||
|
||||
void freeGPUData(GrVkGpu* gpu) const override;
|
||||
void abandonGPUData() const override;
|
||||
|
||||
VkImageView fImageView;
|
||||
GrVkSamplerYcbcrConversion* fYcbcrConversion;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -68,8 +68,6 @@ public:
|
||||
|
||||
void freeGPUResources(GrVkGpu* gpu);
|
||||
|
||||
void abandonGPUResources();
|
||||
|
||||
private:
|
||||
void writeUniformBuffers(const GrVkGpu* gpu);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -168,7 +168,6 @@ private:
|
||||
}
|
||||
|
||||
void releaseInternalObjects();
|
||||
void abandonInternalObjects();
|
||||
|
||||
const GrVkImageView* fColorAttachmentView;
|
||||
std::unique_ptr<GrVkImage> fMSAAImage;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -43,7 +43,9 @@ void GrVkVertexBuffer::onRelease() {
|
||||
}
|
||||
|
||||
void GrVkVertexBuffer::onAbandon() {
|
||||
this->vkAbandon();
|
||||
if (!this->wasDestroyed()) {
|
||||
this->vkRelease(this->getVkGpu());
|
||||
}
|
||||
INHERITED::onAbandon();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user