Don't destroy VkPipelineLayouts until after command buffer recording.

Bug: skia:
Change-Id: I70be1dc6b29db9a9152e008293a7d0a276384011
Reviewed-on: https://skia-review.googlesource.com/135867
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2018-06-19 15:22:01 -04:00 committed by Skia Commit-Bot
parent 53418da8c6
commit 7d918fde03
9 changed files with 125 additions and 27 deletions

View File

@ -582,6 +582,8 @@ skia_vk_sources = [
"$_src/gpu/vk/GrVkMemory.h",
"$_src/gpu/vk/GrVkPipeline.cpp",
"$_src/gpu/vk/GrVkPipeline.h",
"$_src/gpu/vk/GrVkPipelineLayout.cpp",
"$_src/gpu/vk/GrVkPipelineLayout.h",
"$_src/gpu/vk/GrVkPipelineState.cpp",
"$_src/gpu/vk/GrVkPipelineState.h",
"$_src/gpu/vk/GrVkPipelineStateBuilder.cpp",

View File

@ -16,6 +16,7 @@
#include "GrVkPipelineState.h"
#include "GrVkRenderPass.h"
#include "GrVkRenderTarget.h"
#include "GrVkPipelineLayout.h"
#include "GrVkPipelineState.h"
#include "GrVkTransferBuffer.h"
#include "GrVkUtil.h"
@ -49,6 +50,10 @@ void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const {
fTrackedRecycledResources[i]->recycle(const_cast<GrVkGpu*>(gpu));
}
for (int i = 0; i < fTrackedRecordingResources.count(); ++i) {
fTrackedRecordingResources[i]->unref(gpu);
}
GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(),
1, &fCmdBuffer));
@ -64,6 +69,10 @@ void GrVkCommandBuffer::abandonGPUData() const {
// We don't recycle resources when abandoning them.
fTrackedRecycledResources[i]->unrefAndAbandon();
}
for (int i = 0; i < fTrackedRecordingResources.count(); ++i) {
fTrackedRecordingResources[i]->unrefAndAbandon();
}
}
void GrVkCommandBuffer::reset(GrVkGpu* gpu) {
@ -75,15 +84,22 @@ void GrVkCommandBuffer::reset(GrVkGpu* gpu) {
fTrackedRecycledResources[i]->recycle(const_cast<GrVkGpu*>(gpu));
}
for (int i = 0; i < fTrackedRecordingResources.count(); ++i) {
fTrackedRecordingResources[i]->unref(gpu);
}
if (++fNumResets > kNumRewindResetsBeforeFullReset) {
fTrackedResources.reset();
fTrackedRecycledResources.reset();
fTrackedRecordingResources.reset();
fTrackedResources.setReserve(kInitialTrackedResourcesCount);
fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
fTrackedRecordingResources.setReserve(kInitialTrackedResourcesCount);
fNumResets = 0;
} else {
fTrackedResources.rewind();
fTrackedRecycledResources.rewind();
fTrackedRecordingResources.rewind();
}
@ -211,7 +227,7 @@ void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu,
void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
GrVkPipelineState* pipelineState,
VkPipelineLayout layout,
GrVkPipelineLayout* layout,
uint32_t firstSet,
uint32_t setCount,
const VkDescriptorSet* descriptorSets,
@ -220,19 +236,20 @@ void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
SkASSERT(fIsActive);
GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
layout,
layout->layout(),
firstSet,
setCount,
descriptorSets,
dynamicOffsetCount,
dynamicOffsets));
this->addRecordingResource(layout);
pipelineState->addUniformResources(*this);
}
void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
const SkTArray<const GrVkRecycledResource*>& recycled,
const SkTArray<const GrVkResource*>& resources,
VkPipelineLayout layout,
GrVkPipelineLayout* layout,
uint32_t firstSet,
uint32_t setCount,
const VkDescriptorSet* descriptorSets,
@ -241,12 +258,13 @@ void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu,
SkASSERT(fIsActive);
GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
layout,
layout->layout(),
firstSet,
setCount,
descriptorSets,
dynamicOffsetCount,
dynamicOffsets));
this->addRecordingResource(layout);
for (int i = 0; i < recycled.count(); ++i) {
this->addRecycledResource(recycled[i]);
}
@ -378,6 +396,10 @@ void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) {
SkASSERT(fIsActive);
SkASSERT(!fActiveRenderPass);
GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer));
for (int i = 0; i < fTrackedRecordingResources.count(); ++i) {
fTrackedRecordingResources[i]->unref(gpu);
}
fTrackedRecordingResources.rewind();
this->invalidateState();
fIsActive = false;
}

View File

@ -53,7 +53,7 @@ public:
void bindDescriptorSets(const GrVkGpu* gpu,
GrVkPipelineState*,
VkPipelineLayout layout,
GrVkPipelineLayout* layout,
uint32_t firstSet,
uint32_t setCount,
const VkDescriptorSet* descriptorSets,
@ -63,7 +63,7 @@ public:
void bindDescriptorSets(const GrVkGpu* gpu,
const SkTArray<const GrVkRecycledResource*>&,
const SkTArray<const GrVkResource*>&,
VkPipelineLayout layout,
GrVkPipelineLayout* layout,
uint32_t firstSet,
uint32_t setCount,
const VkDescriptorSet* descriptorSets,
@ -102,8 +102,8 @@ public:
uint32_t firstVertex,
uint32_t firstInstance) const;
// Add ref-counted resource that will be tracked and released when this
// command buffer finishes execution
// Add ref-counted resource that will be tracked and released when this command buffer finishes
// execution
void addResource(const GrVkResource* resource) {
resource->ref();
fTrackedResources.append(1, &resource);
@ -116,6 +116,13 @@ public:
fTrackedRecycledResources.append(1, &resource);
}
// Add ref-counted resource that will be tracked and released when this command buffer finishes
// recording.
void addRecordingResource(const GrVkResource* resource) {
resource->ref();
fTrackedRecordingResources.append(1, &resource);
}
void reset(GrVkGpu* gpu);
protected:
@ -126,11 +133,13 @@ protected:
, fNumResets(0) {
fTrackedResources.setReserve(kInitialTrackedResourcesCount);
fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount);
fTrackedRecordingResources.setReserve(kInitialTrackedResourcesCount);
this->invalidateState();
}
SkTDArray<const GrVkResource*> fTrackedResources;
SkTDArray<const GrVkRecycledResource*> fTrackedRecycledResources;
SkTDArray<const GrVkResource*> fTrackedRecordingResources;
// Tracks whether we are in the middle of a command buffer begin/end calls and thus can add
// new commands to the buffer;

View File

@ -17,6 +17,7 @@
#include "GrVkDescriptorSet.h"
#include "GrVkGpu.h"
#include "GrVkImageView.h"
#include "GrVkPipelineLayout.h"
#include "GrVkRenderTarget.h"
#include "GrVkResourceProvider.h"
#include "GrVkSampler.h"
@ -30,7 +31,7 @@
GrVkCopyManager::GrVkCopyManager()
: fVertShaderModule(VK_NULL_HANDLE)
, fFragShaderModule(VK_NULL_HANDLE)
, fPipelineLayout(VK_NULL_HANDLE) {}
, fPipelineLayout(nullptr) {}
GrVkCopyManager::~GrVkCopyManager() {}
@ -114,15 +115,18 @@ bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) {
layoutCreateInfo.pushConstantRangeCount = 0;
layoutCreateInfo.pPushConstantRanges = nullptr;
VkPipelineLayout pipelineLayout;
VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
&layoutCreateInfo,
nullptr,
&fPipelineLayout));
&pipelineLayout));
if (err) {
this->destroyResources(gpu);
return false;
}
fPipelineLayout = new GrVkPipelineLayout(pipelineLayout);
static const float vdata[] = {
0, 0,
0, 1,
@ -169,7 +173,7 @@ bool GrVkCopyManager::copySurfaceAsDraw(GrVkGpu* gpu,
if (VK_NULL_HANDLE == fVertShaderModule) {
SkASSERT(VK_NULL_HANDLE == fFragShaderModule &&
VK_NULL_HANDLE == fPipelineLayout &&
nullptr == fPipelineLayout &&
nullptr == fVertexBuffer.get() &&
nullptr == fUniformBuffer.get());
if (!this->createCopyProgram(gpu)) {
@ -177,12 +181,13 @@ bool GrVkCopyManager::copySurfaceAsDraw(GrVkGpu* gpu,
return false;
}
}
SkASSERT(fPipelineLayout);
GrVkResourceProvider& resourceProv = gpu->resourceProvider();
GrVkCopyPipeline* pipeline = resourceProv.findOrCreateCopyPipeline(rt,
fShaderStageInfo,
fPipelineLayout);
fPipelineLayout->layout());
if (!pipeline) {
return false;
}
@ -412,10 +417,9 @@ void GrVkCopyManager::destroyResources(GrVkGpu* gpu) {
fFragShaderModule = VK_NULL_HANDLE;
}
if (VK_NULL_HANDLE != fPipelineLayout) {
GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout,
nullptr));
fPipelineLayout = VK_NULL_HANDLE;
if (fPipelineLayout) {
fPipelineLayout->unref(gpu);
fPipelineLayout = nullptr;
}
if (fUniformBuffer) {
@ -427,7 +431,10 @@ void GrVkCopyManager::destroyResources(GrVkGpu* gpu) {
void GrVkCopyManager::abandonResources() {
fVertShaderModule = VK_NULL_HANDLE;
fFragShaderModule = VK_NULL_HANDLE;
fPipelineLayout = VK_NULL_HANDLE;
if (fPipelineLayout) {
fPipelineLayout->unrefAndAbandon();
fPipelineLayout = nullptr;
}
if (fUniformBuffer) {
fUniformBuffer->abandon();

View File

@ -16,6 +16,7 @@
class GrSurface;
class GrVkCopyPipeline;
class GrVkGpu;
class GrVkPipelineLayout;
class GrVkUniformBuffer;
class GrVkVertexBuffer;
struct SkIPoint;
@ -45,7 +46,7 @@ private:
VkPipelineShaderStageCreateInfo fShaderStageInfo[2];
GrVkDescriptorSetManager::Handle fSamplerDSHandle;
VkPipelineLayout fPipelineLayout;
GrVkPipelineLayout* fPipelineLayout;
sk_sp<GrVkVertexBuffer> fVertexBuffer;
std::unique_ptr<GrVkUniformBuffer> fUniformBuffer;

View File

@ -0,0 +1,14 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrVkPipelineLayout.h"
#include "GrVkGpu.h"
#include "GrVkUtil.h"
void GrVkPipelineLayout::freeGPUData(const GrVkGpu* gpu) const {
GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout, nullptr));
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrVkPipelineLayout_DEFINED
#define GrVkPipelineLayout_DEFINED
#include "GrTypes.h"
#include "GrVkResource.h"
#include "vk/GrVkDefines.h"
class GrVkPipelineLayout : public GrVkResource {
public:
GrVkPipelineLayout(VkPipelineLayout layout) : fPipelineLayout(layout) {}
VkPipelineLayout layout() const { return fPipelineLayout; }
#ifdef SK_TRACE_VK_RESOURCES
void dumpInfo() const override {
SkDebugf("GrVkPipelineLayout: %d (%d refs)\n", fPipelineLayout, this->getRefCnt());
}
#endif
private:
GrVkPipelineLayout(const GrVkPipelineLayout&);
GrVkPipelineLayout& operator=(const GrVkPipelineLayout&);
void freeGPUData(const GrVkGpu* gpu) const override;
VkPipelineLayout fPipelineLayout;
typedef GrVkResource INHERITED;
};
#endif

View File

@ -19,6 +19,7 @@
#include "GrVkImageView.h"
#include "GrVkMemory.h"
#include "GrVkPipeline.h"
#include "GrVkPipelineLayout.h"
#include "GrVkSampler.h"
#include "GrVkTexelBuffer.h"
#include "GrVkTexture.h"
@ -45,7 +46,7 @@ GrVkPipelineState::GrVkPipelineState(
std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
int fragmentProcessorCnt)
: fPipeline(pipeline)
, fPipelineLayout(layout)
, fPipelineLayout(new GrVkPipelineLayout(layout))
, fUniformDescriptorSet(nullptr)
, fSamplerDescriptorSet(nullptr)
, fTexelBufferDescriptorSet(nullptr)
@ -119,10 +120,8 @@ void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) {
}
if (fPipelineLayout) {
GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(),
fPipelineLayout,
nullptr));
fPipelineLayout = VK_NULL_HANDLE;
fPipelineLayout->unref(gpu);
fPipelineLayout = nullptr;
}
if (fGeometryUniformBuffer) {
@ -153,10 +152,15 @@ void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) {
}
void GrVkPipelineState::abandonGPUResources() {
fPipeline->unrefAndAbandon();
fPipeline = nullptr;
if (fPipeline) {
fPipeline->unrefAndAbandon();
fPipeline = nullptr;
}
fPipelineLayout = VK_NULL_HANDLE;
if (fPipelineLayout) {
fPipelineLayout->unrefAndAbandon();
fPipelineLayout = nullptr;
}
fGeometryUniformBuffer->abandon();
fFragmentUniformBuffer->abandon();

View File

@ -23,6 +23,7 @@ class GrVkDescriptorSet;
class GrVkGpu;
class GrVkImageView;
class GrVkPipeline;
class GrVkPipelineLayout;
class GrVkSampler;
class GrVkUniformBuffer;
@ -125,7 +126,7 @@ private:
// Used for binding DescriptorSets to the command buffer but does not need to survive during
// command buffer execution. Thus this is not need to be a GrVkResource.
VkPipelineLayout fPipelineLayout;
GrVkPipelineLayout* fPipelineLayout;
// The DescriptorSets need to survive until the gpu has finished all draws that use them.
// However, they will only be freed by the descriptor pool. Thus by simply keeping the