blob: 8ba5ade3336b1f349cddcbc6e5efce3cb1ac178f [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
2* Copyright 2016 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#include "GrVkResourceProvider.h"
9
egdaniel8b6394c2016-03-04 07:35:10 -080010#include "GrTextureParams.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050011#include "GrVkCommandBuffer.h"
12#include "GrVkPipeline.h"
13#include "GrVkRenderPass.h"
egdaniel8b6394c2016-03-04 07:35:10 -080014#include "GrVkSampler.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050015#include "GrVkUtil.h"
16
17#ifdef SK_TRACE_VK_RESOURCES
18SkTDynamicHash<GrVkResource, uint32_t> GrVkResource::fTrace;
19SkRandom GrVkResource::fRandom;
20#endif
21
jvanverth03509ea2016-03-02 13:19:47 -080022GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu) : fGpu(gpu)
23 , fPipelineCache(VK_NULL_HANDLE) {
egdaniel22281c12016-03-23 13:49:40 -070024 fPipelineStateCache = new PipelineStateCache(gpu);
Greg Daniel164a9f02016-02-22 09:56:40 -050025}
26
27GrVkResourceProvider::~GrVkResourceProvider() {
28 SkASSERT(0 == fSimpleRenderPasses.count());
jvanverth03509ea2016-03-02 13:19:47 -080029 SkASSERT(VK_NULL_HANDLE == fPipelineCache);
egdaniel22281c12016-03-23 13:49:40 -070030 delete fPipelineStateCache;
jvanverth03509ea2016-03-02 13:19:47 -080031}
32
33void GrVkResourceProvider::init() {
34 VkPipelineCacheCreateInfo createInfo;
35 memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
36 createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
37 createInfo.pNext = nullptr;
38 createInfo.flags = 0;
39 createInfo.initialDataSize = 0;
40 createInfo.pInitialData = nullptr;
41 VkResult result = GR_VK_CALL(fGpu->vkInterface(),
42 CreatePipelineCache(fGpu->device(), &createInfo, nullptr,
43 &fPipelineCache));
44 SkASSERT(VK_SUCCESS == result);
45 if (VK_SUCCESS != result) {
46 fPipelineCache = VK_NULL_HANDLE;
47 }
Greg Daniel164a9f02016-02-22 09:56:40 -050048}
49
50GrVkPipeline* GrVkResourceProvider::createPipeline(const GrPipeline& pipeline,
51 const GrPrimitiveProcessor& primProc,
52 VkPipelineShaderStageCreateInfo* shaderStageInfo,
53 int shaderStageCount,
54 GrPrimitiveType primitiveType,
55 const GrVkRenderPass& renderPass,
56 VkPipelineLayout layout) {
57
58 return GrVkPipeline::Create(fGpu, pipeline, primProc, shaderStageInfo, shaderStageCount,
jvanverth03509ea2016-03-02 13:19:47 -080059 primitiveType, renderPass, layout, fPipelineCache);
Greg Daniel164a9f02016-02-22 09:56:40 -050060}
61
62
63// To create framebuffers, we first need to create a simple RenderPass that is
halcanary9d524f22016-03-29 09:03:52 -070064// only used for framebuffer creation. When we actually render we will create
Greg Daniel164a9f02016-02-22 09:56:40 -050065// RenderPasses as needed that are compatible with the framebuffer.
halcanary9d524f22016-03-29 09:03:52 -070066const GrVkRenderPass*
Greg Daniel164a9f02016-02-22 09:56:40 -050067GrVkResourceProvider::findOrCreateCompatibleRenderPass(const GrVkRenderTarget& target) {
68 for (int i = 0; i < fSimpleRenderPasses.count(); ++i) {
69 GrVkRenderPass* renderPass = fSimpleRenderPasses[i];
70 if (renderPass->isCompatible(target)) {
71 renderPass->ref();
72 return renderPass;
73 }
74 }
75
76 GrVkRenderPass* renderPass = new GrVkRenderPass();
77 renderPass->initSimple(fGpu, target);
78 fSimpleRenderPasses.push_back(renderPass);
79 renderPass->ref();
80 return renderPass;
81}
82
83GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool(
egdanielc2dc1b22016-03-18 13:18:23 -070084 VkDescriptorType type, uint32_t count) {
85 return new GrVkDescriptorPool(fGpu, type, count);
Greg Daniel164a9f02016-02-22 09:56:40 -050086}
87
jvanverth62340062016-04-26 08:01:44 -070088GrVkSampler* GrVkResourceProvider::findOrCreateCompatibleSampler(const GrTextureParams& params,
89 uint32_t mipLevels) {
90 GrVkSampler* sampler = fSamplers.find(GrVkSampler::GenerateKey(params, mipLevels));
egdaniel8b6394c2016-03-04 07:35:10 -080091 if (!sampler) {
jvanverth62340062016-04-26 08:01:44 -070092 sampler = GrVkSampler::Create(fGpu, params, mipLevels);
egdaniel8b6394c2016-03-04 07:35:10 -080093 fSamplers.add(sampler);
94 }
95 SkASSERT(sampler);
96 sampler->ref();
97 return sampler;
98}
99
egdanielaf132772016-03-28 12:39:29 -0700100sk_sp<GrVkPipelineState> GrVkResourceProvider::findOrCreateCompatiblePipelineState(
egdaniel22281c12016-03-23 13:49:40 -0700101 const GrPipeline& pipeline,
102 const GrPrimitiveProcessor& proc,
103 GrPrimitiveType primitiveType,
104 const GrVkRenderPass& renderPass) {
105 return fPipelineStateCache->refPipelineState(pipeline, proc, primitiveType, renderPass);
106}
107
Greg Daniel164a9f02016-02-22 09:56:40 -0500108GrVkCommandBuffer* GrVkResourceProvider::createCommandBuffer() {
109 GrVkCommandBuffer* cmdBuffer = GrVkCommandBuffer::Create(fGpu, fGpu->cmdPool());
110 fActiveCommandBuffers.push_back(cmdBuffer);
111 cmdBuffer->ref();
112 return cmdBuffer;
113}
114
115void GrVkResourceProvider::checkCommandBuffers() {
116 for (int i = fActiveCommandBuffers.count()-1; i >= 0; --i) {
117 if (fActiveCommandBuffers[i]->finished(fGpu)) {
118 fActiveCommandBuffers[i]->unref(fGpu);
119 fActiveCommandBuffers.removeShuffle(i);
120 }
121 }
122}
123
124void GrVkResourceProvider::destroyResources() {
125 // release our current command buffers
126 for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
127 SkASSERT(fActiveCommandBuffers[i]->finished(fGpu));
128 SkASSERT(fActiveCommandBuffers[i]->unique());
129 fActiveCommandBuffers[i]->unref(fGpu);
130 }
131 fActiveCommandBuffers.reset();
132
133 // loop over all render passes to make sure we destroy all the internal VkRenderPasses
134 for (int i = 0; i < fSimpleRenderPasses.count(); ++i) {
135 fSimpleRenderPasses[i]->unref(fGpu);
136 }
137 fSimpleRenderPasses.reset();
138
egdaniel8b6394c2016-03-04 07:35:10 -0800139 // Iterate through all store GrVkSamplers and unref them before resetting the hash.
jvanverth62340062016-04-26 08:01:44 -0700140 SkTDynamicHash<GrVkSampler, uint16_t>::Iter iter(&fSamplers);
egdaniel8b6394c2016-03-04 07:35:10 -0800141 for (; !iter.done(); ++iter) {
142 (*iter).unref(fGpu);
143 }
144 fSamplers.reset();
145
egdaniel22281c12016-03-23 13:49:40 -0700146 fPipelineStateCache->release();
147
Greg Daniel164a9f02016-02-22 09:56:40 -0500148#ifdef SK_TRACE_VK_RESOURCES
149 SkASSERT(0 == GrVkResource::fTrace.count());
150#endif
151
jvanverth03509ea2016-03-02 13:19:47 -0800152 GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr));
153 fPipelineCache = VK_NULL_HANDLE;
Greg Daniel164a9f02016-02-22 09:56:40 -0500154}
155
156void GrVkResourceProvider::abandonResources() {
157 // release our current command buffers
158 for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
159 SkASSERT(fActiveCommandBuffers[i]->finished(fGpu));
160 fActiveCommandBuffers[i]->unrefAndAbandon();
161 }
162 fActiveCommandBuffers.reset();
163
164 for (int i = 0; i < fSimpleRenderPasses.count(); ++i) {
165 fSimpleRenderPasses[i]->unrefAndAbandon();
166 }
167 fSimpleRenderPasses.reset();
168
egdaniel8b6394c2016-03-04 07:35:10 -0800169 // Iterate through all store GrVkSamplers and unrefAndAbandon them before resetting the hash.
jvanverth62340062016-04-26 08:01:44 -0700170 SkTDynamicHash<GrVkSampler, uint16_t>::Iter iter(&fSamplers);
egdaniel8b6394c2016-03-04 07:35:10 -0800171 for (; !iter.done(); ++iter) {
172 (*iter).unrefAndAbandon();
173 }
174 fSamplers.reset();
175
egdaniel22281c12016-03-23 13:49:40 -0700176 fPipelineStateCache->abandon();
177
Greg Daniel164a9f02016-02-22 09:56:40 -0500178#ifdef SK_TRACE_VK_RESOURCES
179 SkASSERT(0 == GrVkResource::fTrace.count());
180#endif
jvanverth03509ea2016-03-02 13:19:47 -0800181 fPipelineCache = VK_NULL_HANDLE;
182}