blob: bf283fc512a46482cfb1c0f37cc3f2651a0dedef [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
egdaniel778555c2016-05-02 06:50:36 -070022GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu)
23 : fGpu(gpu)
24 , fPipelineCache(VK_NULL_HANDLE)
25 , fUniformDescPool(nullptr)
26 , fCurrentUniformDescCount(0) {
egdaniel22281c12016-03-23 13:49:40 -070027 fPipelineStateCache = new PipelineStateCache(gpu);
Greg Daniel164a9f02016-02-22 09:56:40 -050028}
29
30GrVkResourceProvider::~GrVkResourceProvider() {
31 SkASSERT(0 == fSimpleRenderPasses.count());
jvanverth03509ea2016-03-02 13:19:47 -080032 SkASSERT(VK_NULL_HANDLE == fPipelineCache);
egdaniel22281c12016-03-23 13:49:40 -070033 delete fPipelineStateCache;
jvanverth03509ea2016-03-02 13:19:47 -080034}
35
egdaniel778555c2016-05-02 06:50:36 -070036void GrVkResourceProvider::initUniformDescObjects() {
37 // Create Uniform Buffer Descriptor
38 // The vertex uniform buffer will have binding 0 and the fragment binding 1.
39 VkDescriptorSetLayoutBinding dsUniBindings[2];
40 memset(&dsUniBindings, 0, 2 * sizeof(VkDescriptorSetLayoutBinding));
41 dsUniBindings[0].binding = GrVkUniformHandler::kVertexBinding;
42 dsUniBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
43 dsUniBindings[0].descriptorCount = 1;
44 dsUniBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
45 dsUniBindings[0].pImmutableSamplers = nullptr;
46 dsUniBindings[1].binding = GrVkUniformHandler::kFragBinding;
47 dsUniBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
48 dsUniBindings[1].descriptorCount = 1;
49 dsUniBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
50 dsUniBindings[1].pImmutableSamplers = nullptr;
51
52 VkDescriptorSetLayoutCreateInfo dsUniformLayoutCreateInfo;
53 memset(&dsUniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
54 dsUniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
55 dsUniformLayoutCreateInfo.pNext = nullptr;
56 dsUniformLayoutCreateInfo.flags = 0;
57 dsUniformLayoutCreateInfo.bindingCount = 2;
58 dsUniformLayoutCreateInfo.pBindings = dsUniBindings;
59
60 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreateDescriptorSetLayout(fGpu->device(),
61 &dsUniformLayoutCreateInfo,
62 nullptr,
63 &fUniformDescLayout));
64 fCurrMaxUniDescriptors = kStartNumUniformDescriptors;
65 fUniformDescPool = this->findOrCreateCompatibleDescriptorPool(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
66 fCurrMaxUniDescriptors);
67}
68
jvanverth03509ea2016-03-02 13:19:47 -080069void GrVkResourceProvider::init() {
70 VkPipelineCacheCreateInfo createInfo;
71 memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
72 createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
73 createInfo.pNext = nullptr;
74 createInfo.flags = 0;
75 createInfo.initialDataSize = 0;
76 createInfo.pInitialData = nullptr;
77 VkResult result = GR_VK_CALL(fGpu->vkInterface(),
78 CreatePipelineCache(fGpu->device(), &createInfo, nullptr,
79 &fPipelineCache));
80 SkASSERT(VK_SUCCESS == result);
81 if (VK_SUCCESS != result) {
82 fPipelineCache = VK_NULL_HANDLE;
83 }
egdaniel778555c2016-05-02 06:50:36 -070084
85 this->initUniformDescObjects();
Greg Daniel164a9f02016-02-22 09:56:40 -050086}
87
88GrVkPipeline* GrVkResourceProvider::createPipeline(const GrPipeline& pipeline,
89 const GrPrimitiveProcessor& primProc,
90 VkPipelineShaderStageCreateInfo* shaderStageInfo,
91 int shaderStageCount,
92 GrPrimitiveType primitiveType,
93 const GrVkRenderPass& renderPass,
94 VkPipelineLayout layout) {
95
96 return GrVkPipeline::Create(fGpu, pipeline, primProc, shaderStageInfo, shaderStageCount,
jvanverth03509ea2016-03-02 13:19:47 -080097 primitiveType, renderPass, layout, fPipelineCache);
Greg Daniel164a9f02016-02-22 09:56:40 -050098}
99
100
101// To create framebuffers, we first need to create a simple RenderPass that is
halcanary9d524f22016-03-29 09:03:52 -0700102// only used for framebuffer creation. When we actually render we will create
Greg Daniel164a9f02016-02-22 09:56:40 -0500103// RenderPasses as needed that are compatible with the framebuffer.
halcanary9d524f22016-03-29 09:03:52 -0700104const GrVkRenderPass*
Greg Daniel164a9f02016-02-22 09:56:40 -0500105GrVkResourceProvider::findOrCreateCompatibleRenderPass(const GrVkRenderTarget& target) {
106 for (int i = 0; i < fSimpleRenderPasses.count(); ++i) {
107 GrVkRenderPass* renderPass = fSimpleRenderPasses[i];
108 if (renderPass->isCompatible(target)) {
109 renderPass->ref();
110 return renderPass;
111 }
112 }
113
114 GrVkRenderPass* renderPass = new GrVkRenderPass();
115 renderPass->initSimple(fGpu, target);
116 fSimpleRenderPasses.push_back(renderPass);
117 renderPass->ref();
118 return renderPass;
119}
120
121GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool(
egdanielc2dc1b22016-03-18 13:18:23 -0700122 VkDescriptorType type, uint32_t count) {
123 return new GrVkDescriptorPool(fGpu, type, count);
Greg Daniel164a9f02016-02-22 09:56:40 -0500124}
125
jvanverth62340062016-04-26 08:01:44 -0700126GrVkSampler* GrVkResourceProvider::findOrCreateCompatibleSampler(const GrTextureParams& params,
127 uint32_t mipLevels) {
128 GrVkSampler* sampler = fSamplers.find(GrVkSampler::GenerateKey(params, mipLevels));
egdaniel8b6394c2016-03-04 07:35:10 -0800129 if (!sampler) {
jvanverth62340062016-04-26 08:01:44 -0700130 sampler = GrVkSampler::Create(fGpu, params, mipLevels);
egdaniel8b6394c2016-03-04 07:35:10 -0800131 fSamplers.add(sampler);
132 }
133 SkASSERT(sampler);
134 sampler->ref();
135 return sampler;
136}
137
egdanielaf132772016-03-28 12:39:29 -0700138sk_sp<GrVkPipelineState> GrVkResourceProvider::findOrCreateCompatiblePipelineState(
egdaniel22281c12016-03-23 13:49:40 -0700139 const GrPipeline& pipeline,
140 const GrPrimitiveProcessor& proc,
141 GrPrimitiveType primitiveType,
142 const GrVkRenderPass& renderPass) {
143 return fPipelineStateCache->refPipelineState(pipeline, proc, primitiveType, renderPass);
144}
145
egdaniel778555c2016-05-02 06:50:36 -0700146void GrVkResourceProvider::getUniformDescriptorSet(VkDescriptorSet* ds,
147 const GrVkDescriptorPool** outPool) {
148 fCurrentUniformDescCount += kNumUniformDescPerSet;
149 if (fCurrentUniformDescCount > fCurrMaxUniDescriptors) {
150 fUniformDescPool->unref(fGpu);
151 if (fCurrMaxUniDescriptors < kMaxUniformDescriptors >> 1) {
152 fCurrMaxUniDescriptors = fCurrMaxUniDescriptors << 1;
153 } else {
154 fCurrMaxUniDescriptors = kMaxUniformDescriptors;
155 }
156 fUniformDescPool =
157 this->findOrCreateCompatibleDescriptorPool(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
158 fCurrMaxUniDescriptors);
159 fCurrentUniformDescCount = kNumUniformDescPerSet;
160 }
161 SkASSERT(fUniformDescPool);
162
163 VkDescriptorSetAllocateInfo dsAllocateInfo;
164 memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo));
165 dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
166 dsAllocateInfo.pNext = nullptr;
167 dsAllocateInfo.descriptorPool = fUniformDescPool->descPool();
168 dsAllocateInfo.descriptorSetCount = 1;
169 dsAllocateInfo.pSetLayouts = &fUniformDescLayout;
170 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), AllocateDescriptorSets(fGpu->device(),
171 &dsAllocateInfo,
172 ds));
173 *outPool = fUniformDescPool;
174}
175
Greg Daniel164a9f02016-02-22 09:56:40 -0500176GrVkCommandBuffer* GrVkResourceProvider::createCommandBuffer() {
177 GrVkCommandBuffer* cmdBuffer = GrVkCommandBuffer::Create(fGpu, fGpu->cmdPool());
178 fActiveCommandBuffers.push_back(cmdBuffer);
179 cmdBuffer->ref();
180 return cmdBuffer;
181}
182
183void GrVkResourceProvider::checkCommandBuffers() {
184 for (int i = fActiveCommandBuffers.count()-1; i >= 0; --i) {
185 if (fActiveCommandBuffers[i]->finished(fGpu)) {
186 fActiveCommandBuffers[i]->unref(fGpu);
187 fActiveCommandBuffers.removeShuffle(i);
188 }
189 }
190}
191
192void GrVkResourceProvider::destroyResources() {
193 // release our current command buffers
194 for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
195 SkASSERT(fActiveCommandBuffers[i]->finished(fGpu));
196 SkASSERT(fActiveCommandBuffers[i]->unique());
197 fActiveCommandBuffers[i]->unref(fGpu);
198 }
199 fActiveCommandBuffers.reset();
200
201 // loop over all render passes to make sure we destroy all the internal VkRenderPasses
202 for (int i = 0; i < fSimpleRenderPasses.count(); ++i) {
203 fSimpleRenderPasses[i]->unref(fGpu);
204 }
205 fSimpleRenderPasses.reset();
206
egdaniel8b6394c2016-03-04 07:35:10 -0800207 // Iterate through all store GrVkSamplers and unref them before resetting the hash.
jvanverth62340062016-04-26 08:01:44 -0700208 SkTDynamicHash<GrVkSampler, uint16_t>::Iter iter(&fSamplers);
egdaniel8b6394c2016-03-04 07:35:10 -0800209 for (; !iter.done(); ++iter) {
210 (*iter).unref(fGpu);
211 }
212 fSamplers.reset();
213
egdaniel22281c12016-03-23 13:49:40 -0700214 fPipelineStateCache->release();
215
Greg Daniel164a9f02016-02-22 09:56:40 -0500216#ifdef SK_TRACE_VK_RESOURCES
217 SkASSERT(0 == GrVkResource::fTrace.count());
218#endif
219
jvanverth03509ea2016-03-02 13:19:47 -0800220 GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr));
221 fPipelineCache = VK_NULL_HANDLE;
egdaniel778555c2016-05-02 06:50:36 -0700222
223 if (fUniformDescLayout) {
224 GR_VK_CALL(fGpu->vkInterface(), DestroyDescriptorSetLayout(fGpu->device(),
225 fUniformDescLayout,
226 nullptr));
227 fUniformDescLayout = VK_NULL_HANDLE;
228 }
229 fUniformDescPool->unref(fGpu);
Greg Daniel164a9f02016-02-22 09:56:40 -0500230}
231
232void GrVkResourceProvider::abandonResources() {
233 // release our current command buffers
234 for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
235 SkASSERT(fActiveCommandBuffers[i]->finished(fGpu));
236 fActiveCommandBuffers[i]->unrefAndAbandon();
237 }
238 fActiveCommandBuffers.reset();
239
240 for (int i = 0; i < fSimpleRenderPasses.count(); ++i) {
241 fSimpleRenderPasses[i]->unrefAndAbandon();
242 }
243 fSimpleRenderPasses.reset();
244
egdaniel8b6394c2016-03-04 07:35:10 -0800245 // Iterate through all store GrVkSamplers and unrefAndAbandon them before resetting the hash.
jvanverth62340062016-04-26 08:01:44 -0700246 SkTDynamicHash<GrVkSampler, uint16_t>::Iter iter(&fSamplers);
egdaniel8b6394c2016-03-04 07:35:10 -0800247 for (; !iter.done(); ++iter) {
248 (*iter).unrefAndAbandon();
249 }
250 fSamplers.reset();
251
egdaniel22281c12016-03-23 13:49:40 -0700252 fPipelineStateCache->abandon();
253
Greg Daniel164a9f02016-02-22 09:56:40 -0500254#ifdef SK_TRACE_VK_RESOURCES
255 SkASSERT(0 == GrVkResource::fTrace.count());
256#endif
jvanverth03509ea2016-03-02 13:19:47 -0800257 fPipelineCache = VK_NULL_HANDLE;
egdaniel778555c2016-05-02 06:50:36 -0700258
259 fUniformDescLayout = VK_NULL_HANDLE;
260 fUniformDescPool->unrefAndAbandon();
jvanverth03509ea2016-03-02 13:19:47 -0800261}