/src/skia/src/gpu/ganesh/vk/GrVkResourceProvider.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
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 "src/gpu/ganesh/vk/GrVkResourceProvider.h" |
9 | | |
10 | | #include "include/core/SkData.h" |
11 | | #include "include/core/SkString.h" |
12 | | #include "include/gpu/ganesh/GrDirectContext.h" |
13 | | #include "include/gpu/ganesh/GrTypes.h" |
14 | | #include "include/private/base/SkDebug.h" |
15 | | #include "include/private/gpu/ganesh/GrTypesPriv.h" |
16 | | #include "src/core/SkTaskGroup.h" |
17 | | #include "src/core/SkTraceEvent.h" |
18 | | #include "src/gpu/Blend.h" |
19 | | #include "src/gpu/RefCntedCallback.h" |
20 | | #include "src/gpu/ganesh/GrDirectContextPriv.h" |
21 | | #include "src/gpu/ganesh/GrGeometryProcessor.h" |
22 | | #include "src/gpu/ganesh/GrSamplerState.h" |
23 | | #include "src/gpu/ganesh/GrStencilSettings.h" |
24 | | #include "src/gpu/ganesh/vk/GrVkCommandBuffer.h" |
25 | | #include "src/gpu/ganesh/vk/GrVkCommandPool.h" |
26 | | #include "src/gpu/ganesh/vk/GrVkDescriptorPool.h" |
27 | | #include "src/gpu/ganesh/vk/GrVkGpu.h" |
28 | | #include "src/gpu/ganesh/vk/GrVkPipeline.h" |
29 | | #include "src/gpu/ganesh/vk/GrVkRenderTarget.h" |
30 | | #include "src/gpu/ganesh/vk/GrVkUtil.h" |
31 | | |
32 | | #include <algorithm> |
33 | | #include <cstring> |
34 | | |
35 | | class GrProgramInfo; |
36 | | class GrRenderTarget; |
37 | | class GrVkDescriptorSet; |
38 | | |
39 | | GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu) |
40 | 0 | : fGpu(gpu) |
41 | 0 | , fPipelineCache(VK_NULL_HANDLE) { |
42 | 0 | fPipelineStateCache = sk_make_sp<PipelineStateCache>(gpu); |
43 | 0 | } |
44 | | |
45 | 0 | GrVkResourceProvider::~GrVkResourceProvider() { |
46 | 0 | SkASSERT(fRenderPassArray.empty()); |
47 | 0 | SkASSERT(fExternalRenderPasses.empty()); |
48 | 0 | SkASSERT(fMSAALoadPipelines.empty()); |
49 | 0 | SkASSERT(VK_NULL_HANDLE == fPipelineCache); |
50 | 0 | } Unexecuted instantiation: GrVkResourceProvider::~GrVkResourceProvider() Unexecuted instantiation: GrVkResourceProvider::~GrVkResourceProvider() |
51 | | |
52 | 0 | VkPipelineCache GrVkResourceProvider::pipelineCache() { |
53 | 0 | if (fPipelineCache == VK_NULL_HANDLE) { |
54 | 0 | TRACE_EVENT0("skia.shaders", "CreatePipelineCache-GrVkResourceProvider"); |
55 | 0 | VkPipelineCacheCreateInfo createInfo; |
56 | 0 | memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo)); |
57 | 0 | createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; |
58 | 0 | createInfo.pNext = nullptr; |
59 | 0 | createInfo.flags = 0; |
60 | |
|
61 | 0 | auto persistentCache = fGpu->getContext()->priv().getPersistentCache(); |
62 | 0 | sk_sp<SkData> cached; |
63 | 0 | if (persistentCache) { |
64 | 0 | uint32_t key = GrVkGpu::kPipelineCache_PersistentCacheKeyType; |
65 | 0 | sk_sp<SkData> keyData = SkData::MakeWithoutCopy(&key, sizeof(uint32_t)); |
66 | 0 | cached = persistentCache->load(*keyData); |
67 | 0 | } |
68 | 0 | bool usedCached = false; |
69 | 0 | if (cached) { |
70 | 0 | const uint32_t* cacheHeader = (const uint32_t*)cached->data(); |
71 | 0 | if (cacheHeader[1] == VK_PIPELINE_CACHE_HEADER_VERSION_ONE) { |
72 | | // For version one of the header, the total header size is 16 bytes plus |
73 | | // VK_UUID_SIZE bytes. See Section 9.6 (Pipeline Cache) in the vulkan spec to see |
74 | | // the breakdown of these bytes. |
75 | 0 | SkASSERT(cacheHeader[0] == 16 + VK_UUID_SIZE); |
76 | 0 | const VkPhysicalDeviceProperties& devProps = fGpu->physicalDeviceProperties(); |
77 | 0 | const uint8_t* supportedPipelineCacheUUID = devProps.pipelineCacheUUID; |
78 | 0 | if (cacheHeader[2] == devProps.vendorID && cacheHeader[3] == devProps.deviceID && |
79 | 0 | !memcmp(&cacheHeader[4], supportedPipelineCacheUUID, VK_UUID_SIZE)) { |
80 | 0 | createInfo.initialDataSize = cached->size(); |
81 | 0 | createInfo.pInitialData = cached->data(); |
82 | 0 | usedCached = true; |
83 | 0 | } |
84 | 0 | } |
85 | 0 | } |
86 | 0 | if (!usedCached) { |
87 | 0 | createInfo.initialDataSize = 0; |
88 | 0 | createInfo.pInitialData = nullptr; |
89 | 0 | } |
90 | |
|
91 | 0 | VkResult result; |
92 | 0 | GR_VK_CALL_RESULT(fGpu, result, CreatePipelineCache(fGpu->device(), &createInfo, nullptr, |
93 | 0 | &fPipelineCache)); |
94 | 0 | if (VK_SUCCESS != result) { |
95 | 0 | fPipelineCache = VK_NULL_HANDLE; |
96 | 0 | } |
97 | 0 | } |
98 | 0 | return fPipelineCache; |
99 | 0 | } Unexecuted instantiation: GrVkResourceProvider::pipelineCache() Unexecuted instantiation: GrVkResourceProvider::pipelineCache() |
100 | | |
101 | 0 | void GrVkResourceProvider::init() { |
102 | | // Init uniform descriptor objects |
103 | 0 | GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateUniformManager(fGpu); |
104 | 0 | fDescriptorSetManagers.emplace_back(dsm); |
105 | 0 | SkASSERT(1 == fDescriptorSetManagers.size()); |
106 | 0 | fUniformDSHandle = GrVkDescriptorSetManager::Handle(0); |
107 | 0 | dsm = GrVkDescriptorSetManager::CreateInputManager(fGpu); |
108 | 0 | fDescriptorSetManagers.emplace_back(dsm); |
109 | 0 | SkASSERT(2 == fDescriptorSetManagers.size()); |
110 | 0 | fInputDSHandle = GrVkDescriptorSetManager::Handle(1); |
111 | 0 | } Unexecuted instantiation: GrVkResourceProvider::init() Unexecuted instantiation: GrVkResourceProvider::init() |
112 | | |
113 | | sk_sp<const GrVkPipeline> GrVkResourceProvider::makePipeline( |
114 | | const GrProgramInfo& programInfo, |
115 | | VkPipelineShaderStageCreateInfo* shaderStageInfo, |
116 | | int shaderStageCount, |
117 | | VkRenderPass compatibleRenderPass, |
118 | | VkPipelineLayout layout, |
119 | 0 | uint32_t subpass) { |
120 | 0 | return GrVkPipeline::Make(fGpu, programInfo, shaderStageInfo, shaderStageCount, |
121 | 0 | compatibleRenderPass, layout, this->pipelineCache(), subpass); |
122 | 0 | } |
123 | | |
124 | | // To create framebuffers, we first need to create a simple RenderPass that is |
125 | | // only used for framebuffer creation. When we actually render we will create |
126 | | // RenderPasses as needed that are compatible with the framebuffer. |
127 | | const GrVkRenderPass* |
128 | | GrVkResourceProvider::findCompatibleRenderPass(GrVkRenderTarget* target, |
129 | | CompatibleRPHandle* compatibleHandle, |
130 | | bool withResolve, |
131 | | bool withStencil, |
132 | | SelfDependencyFlags selfDepFlags, |
133 | 0 | LoadFromResolve loadFromResolve) { |
134 | | // Get attachment information from render target. This includes which attachments the render |
135 | | // target has (color, stencil) and the attachments format and sample count. |
136 | 0 | GrVkRenderPass::AttachmentFlags attachmentFlags; |
137 | 0 | GrVkRenderPass::AttachmentsDescriptor attachmentsDesc; |
138 | 0 | if (!target->getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags, |
139 | 0 | withResolve, withStencil)) { |
140 | 0 | return nullptr; |
141 | 0 | } |
142 | | |
143 | 0 | return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, selfDepFlags, |
144 | 0 | loadFromResolve, compatibleHandle); |
145 | 0 | } |
146 | | |
147 | | const GrVkRenderPass* |
148 | | GrVkResourceProvider::findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor* desc, |
149 | | GrVkRenderPass::AttachmentFlags attachmentFlags, |
150 | | SelfDependencyFlags selfDepFlags, |
151 | | LoadFromResolve loadFromResolve, |
152 | 0 | CompatibleRPHandle* compatibleHandle) { |
153 | 0 | for (int i = 0; i < fRenderPassArray.size(); ++i) { |
154 | 0 | if (fRenderPassArray[i].isCompatible(*desc, attachmentFlags, selfDepFlags, |
155 | 0 | loadFromResolve)) { |
156 | 0 | const GrVkRenderPass* renderPass = fRenderPassArray[i].getCompatibleRenderPass(); |
157 | 0 | renderPass->ref(); |
158 | 0 | if (compatibleHandle) { |
159 | 0 | *compatibleHandle = CompatibleRPHandle(i); |
160 | 0 | } |
161 | 0 | return renderPass; |
162 | 0 | } |
163 | 0 | } |
164 | | |
165 | 0 | GrVkRenderPass* renderPass = GrVkRenderPass::CreateSimple(fGpu, desc, attachmentFlags, |
166 | 0 | selfDepFlags, loadFromResolve); |
167 | 0 | if (!renderPass) { |
168 | 0 | return nullptr; |
169 | 0 | } |
170 | 0 | fRenderPassArray.emplace_back(renderPass); |
171 | |
|
172 | 0 | if (compatibleHandle) { |
173 | 0 | *compatibleHandle = CompatibleRPHandle(fRenderPassArray.size() - 1); |
174 | 0 | } |
175 | 0 | return renderPass; |
176 | 0 | } |
177 | | |
178 | | const GrVkRenderPass* GrVkResourceProvider::findCompatibleExternalRenderPass( |
179 | 0 | VkRenderPass renderPass, uint32_t colorAttachmentIndex) { |
180 | 0 | for (int i = 0; i < fExternalRenderPasses.size(); ++i) { |
181 | 0 | if (fExternalRenderPasses[i]->isCompatibleExternalRP(renderPass)) { |
182 | 0 | fExternalRenderPasses[i]->ref(); |
183 | | #ifdef SK_DEBUG |
184 | | uint32_t cachedColorIndex; |
185 | 0 | SkASSERT(fExternalRenderPasses[i]->colorAttachmentIndex(&cachedColorIndex)); |
186 | 0 | SkASSERT(cachedColorIndex == colorAttachmentIndex); |
187 | | #endif |
188 | 0 | return fExternalRenderPasses[i]; |
189 | 0 | } |
190 | 0 | } |
191 | | |
192 | 0 | const GrVkRenderPass* newRenderPass = new GrVkRenderPass(fGpu, renderPass, |
193 | 0 | colorAttachmentIndex); |
194 | 0 | fExternalRenderPasses.push_back(newRenderPass); |
195 | 0 | newRenderPass->ref(); |
196 | 0 | return newRenderPass; |
197 | 0 | } Unexecuted instantiation: GrVkResourceProvider::findCompatibleExternalRenderPass(VkRenderPass_T*, unsigned int) Unexecuted instantiation: GrVkResourceProvider::findCompatibleExternalRenderPass(VkRenderPass_T*, unsigned int) |
198 | | |
199 | | const GrVkRenderPass* GrVkResourceProvider::findRenderPass( |
200 | | GrVkRenderTarget* target, |
201 | | const GrVkRenderPass::LoadStoreOps& colorOps, |
202 | | const GrVkRenderPass::LoadStoreOps& resolveOps, |
203 | | const GrVkRenderPass::LoadStoreOps& stencilOps, |
204 | | CompatibleRPHandle* compatibleHandle, |
205 | | bool withResolve, |
206 | | bool withStencil, |
207 | | SelfDependencyFlags selfDepFlags, |
208 | 0 | LoadFromResolve loadFromResolve) { |
209 | 0 | GrVkResourceProvider::CompatibleRPHandle tempRPHandle; |
210 | 0 | GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle |
211 | 0 | : &tempRPHandle; |
212 | 0 | *pRPHandle = target->compatibleRenderPassHandle(withResolve, withStencil, selfDepFlags, |
213 | 0 | loadFromResolve); |
214 | 0 | if (!pRPHandle->isValid()) { |
215 | 0 | return nullptr; |
216 | 0 | } |
217 | | |
218 | 0 | return this->findRenderPass(*pRPHandle, colorOps, resolveOps, stencilOps); |
219 | 0 | } |
220 | | |
221 | | const GrVkRenderPass* |
222 | | GrVkResourceProvider::findRenderPass(const CompatibleRPHandle& compatibleHandle, |
223 | | const GrVkRenderPass::LoadStoreOps& colorOps, |
224 | | const GrVkRenderPass::LoadStoreOps& resolveOps, |
225 | 0 | const GrVkRenderPass::LoadStoreOps& stencilOps) { |
226 | 0 | SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.size()); |
227 | 0 | CompatibleRenderPassSet& compatibleSet = fRenderPassArray[compatibleHandle.toIndex()]; |
228 | 0 | const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu, |
229 | 0 | colorOps, |
230 | 0 | resolveOps, |
231 | 0 | stencilOps); |
232 | 0 | if (!renderPass) { |
233 | 0 | return nullptr; |
234 | 0 | } |
235 | 0 | renderPass->ref(); |
236 | 0 | return renderPass; |
237 | 0 | } Unexecuted instantiation: GrVkResourceProvider::findRenderPass(GrResourceHandle<GrVkResourceProvider::CompatibleRPHandleKind> const&, GrVkRenderPass::LoadStoreOps const&, GrVkRenderPass::LoadStoreOps const&, GrVkRenderPass::LoadStoreOps const&) Unexecuted instantiation: GrVkResourceProvider::findRenderPass(GrResourceHandle<GrVkResourceProvider::CompatibleRPHandleKind> const&, GrVkRenderPass::LoadStoreOps const&, GrVkRenderPass::LoadStoreOps const&, GrVkRenderPass::LoadStoreOps const&) |
238 | | |
239 | | GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool( |
240 | 0 | VkDescriptorType type, uint32_t count) { |
241 | 0 | return GrVkDescriptorPool::Create(fGpu, type, count); |
242 | 0 | } |
243 | | |
244 | | GrVkSampler* GrVkResourceProvider::findOrCreateCompatibleSampler( |
245 | 0 | GrSamplerState params, const skgpu::VulkanYcbcrConversionInfo& ycbcrInfo) { |
246 | 0 | GrVkSampler* sampler = fSamplers.find(GrVkSampler::GenerateKey(params, ycbcrInfo)); |
247 | 0 | if (!sampler) { |
248 | 0 | sampler = GrVkSampler::Create(fGpu, params, ycbcrInfo); |
249 | 0 | if (!sampler) { |
250 | 0 | return nullptr; |
251 | 0 | } |
252 | 0 | fSamplers.add(sampler); |
253 | 0 | } |
254 | 0 | SkASSERT(sampler); |
255 | 0 | sampler->ref(); |
256 | 0 | return sampler; |
257 | 0 | } Unexecuted instantiation: GrVkResourceProvider::findOrCreateCompatibleSampler(GrSamplerState, skgpu::VulkanYcbcrConversionInfo const&) Unexecuted instantiation: GrVkResourceProvider::findOrCreateCompatibleSampler(GrSamplerState, skgpu::VulkanYcbcrConversionInfo const&) |
258 | | |
259 | | GrVkSamplerYcbcrConversion* GrVkResourceProvider::findOrCreateCompatibleSamplerYcbcrConversion( |
260 | 0 | const skgpu::VulkanYcbcrConversionInfo& ycbcrInfo) { |
261 | 0 | GrVkSamplerYcbcrConversion* ycbcrConversion = |
262 | 0 | fYcbcrConversions.find(GrVkSamplerYcbcrConversion::GenerateKey(ycbcrInfo)); |
263 | 0 | if (!ycbcrConversion) { |
264 | 0 | ycbcrConversion = GrVkSamplerYcbcrConversion::Create(fGpu, ycbcrInfo); |
265 | 0 | if (!ycbcrConversion) { |
266 | 0 | return nullptr; |
267 | 0 | } |
268 | 0 | fYcbcrConversions.add(ycbcrConversion); |
269 | 0 | } |
270 | 0 | SkASSERT(ycbcrConversion); |
271 | 0 | ycbcrConversion->ref(); |
272 | 0 | return ycbcrConversion; |
273 | 0 | } Unexecuted instantiation: GrVkResourceProvider::findOrCreateCompatibleSamplerYcbcrConversion(skgpu::VulkanYcbcrConversionInfo const&) Unexecuted instantiation: GrVkResourceProvider::findOrCreateCompatibleSamplerYcbcrConversion(skgpu::VulkanYcbcrConversionInfo const&) |
274 | | |
275 | | GrVkPipelineState* GrVkResourceProvider::findOrCreateCompatiblePipelineState( |
276 | | GrRenderTarget* renderTarget, |
277 | | const GrProgramInfo& programInfo, |
278 | | VkRenderPass compatibleRenderPass, |
279 | 0 | bool overrideSubpassForResolveLoad) { |
280 | 0 | return fPipelineStateCache->findOrCreatePipelineState(renderTarget, programInfo, |
281 | 0 | compatibleRenderPass, |
282 | 0 | overrideSubpassForResolveLoad); |
283 | 0 | } |
284 | | |
285 | | GrVkPipelineState* GrVkResourceProvider::findOrCreateCompatiblePipelineState( |
286 | | const GrProgramDesc& desc, |
287 | | const GrProgramInfo& programInfo, |
288 | | VkRenderPass compatibleRenderPass, |
289 | 0 | GrThreadSafePipelineBuilder::Stats::ProgramCacheResult* stat) { |
290 | |
|
291 | 0 | auto tmp = fPipelineStateCache->findOrCreatePipelineState(desc, programInfo, |
292 | 0 | compatibleRenderPass, stat); |
293 | 0 | if (!tmp) { |
294 | 0 | fPipelineStateCache->stats()->incNumPreCompilationFailures(); |
295 | 0 | } else { |
296 | 0 | fPipelineStateCache->stats()->incNumPreProgramCacheResult(*stat); |
297 | 0 | } |
298 | |
|
299 | 0 | return tmp; |
300 | 0 | } |
301 | | |
302 | | sk_sp<const GrVkPipeline> GrVkResourceProvider::findOrCreateMSAALoadPipeline( |
303 | | const GrVkRenderPass& renderPass, |
304 | | int numSamples, |
305 | | VkPipelineShaderStageCreateInfo* shaderStageInfo, |
306 | 0 | VkPipelineLayout pipelineLayout) { |
307 | | // Find or Create a compatible pipeline |
308 | 0 | sk_sp<const GrVkPipeline> pipeline; |
309 | 0 | for (int i = 0; i < fMSAALoadPipelines.size() && !pipeline; ++i) { |
310 | 0 | if (fMSAALoadPipelines[i].fRenderPass->isCompatible(renderPass)) { |
311 | 0 | pipeline = fMSAALoadPipelines[i].fPipeline; |
312 | 0 | } |
313 | 0 | } |
314 | 0 | if (!pipeline) { |
315 | 0 | pipeline = GrVkPipeline::Make( |
316 | 0 | fGpu, |
317 | 0 | /*vertexAttribs=*/GrGeometryProcessor::AttributeSet(), |
318 | 0 | /*instanceAttribs=*/GrGeometryProcessor::AttributeSet(), |
319 | 0 | GrPrimitiveType::kTriangleStrip, |
320 | 0 | kTopLeft_GrSurfaceOrigin, |
321 | 0 | GrStencilSettings(), |
322 | 0 | numSamples, |
323 | 0 | /*isHWantialiasState=*/false, |
324 | 0 | skgpu::BlendInfo(), |
325 | 0 | /*isWireframe=*/false, |
326 | 0 | /*useConservativeRaster=*/false, |
327 | 0 | /*subpass=*/0, |
328 | 0 | shaderStageInfo, |
329 | 0 | /*shaderStageCount=*/2, |
330 | 0 | renderPass.vkRenderPass(), |
331 | 0 | pipelineLayout, |
332 | 0 | /*ownsLayout=*/false, |
333 | 0 | this->pipelineCache()); |
334 | 0 | if (!pipeline) { |
335 | 0 | return nullptr; |
336 | 0 | } |
337 | 0 | fMSAALoadPipelines.push_back({pipeline, &renderPass}); |
338 | 0 | } |
339 | 0 | SkASSERT(pipeline); |
340 | 0 | return pipeline; |
341 | 0 | } Unexecuted instantiation: GrVkResourceProvider::findOrCreateMSAALoadPipeline(GrVkRenderPass const&, int, VkPipelineShaderStageCreateInfo*, VkPipelineLayout_T*) Unexecuted instantiation: GrVkResourceProvider::findOrCreateMSAALoadPipeline(GrVkRenderPass const&, int, VkPipelineShaderStageCreateInfo*, VkPipelineLayout_T*) |
342 | | |
343 | | void GrVkResourceProvider::getZeroSamplerDescriptorSetHandle( |
344 | 0 | GrVkDescriptorSetManager::Handle* handle) { |
345 | 0 | SkASSERT(handle); |
346 | 0 | for (int i = 0; i < fDescriptorSetManagers.size(); ++i) { |
347 | 0 | if (fDescriptorSetManagers[i]->isZeroSampler()) { |
348 | 0 | *handle = GrVkDescriptorSetManager::Handle(i); |
349 | 0 | return; |
350 | 0 | } |
351 | 0 | } |
352 | | |
353 | 0 | GrVkDescriptorSetManager* dsm = |
354 | 0 | GrVkDescriptorSetManager::CreateZeroSamplerManager(fGpu); |
355 | 0 | fDescriptorSetManagers.emplace_back(dsm); |
356 | 0 | *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.size() - 1); |
357 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getZeroSamplerDescriptorSetHandle(GrResourceHandle<GrVkDescriptorSetManager::HandleKind>*) Unexecuted instantiation: GrVkResourceProvider::getZeroSamplerDescriptorSetHandle(GrResourceHandle<GrVkDescriptorSetManager::HandleKind>*) |
358 | | |
359 | | void GrVkResourceProvider::getSamplerDescriptorSetHandle(VkDescriptorType type, |
360 | | const GrVkUniformHandler& uniformHandler, |
361 | 0 | GrVkDescriptorSetManager::Handle* handle) { |
362 | 0 | SkASSERT(handle); |
363 | 0 | SkASSERT(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == type || |
364 | 0 | VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == type); |
365 | 0 | for (int i = 0; i < fDescriptorSetManagers.size(); ++i) { |
366 | 0 | if (fDescriptorSetManagers[i]->isCompatible(type, &uniformHandler)) { |
367 | 0 | *handle = GrVkDescriptorSetManager::Handle(i); |
368 | 0 | return; |
369 | 0 | } |
370 | 0 | } |
371 | | |
372 | 0 | GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateSamplerManager(fGpu, type, |
373 | 0 | uniformHandler); |
374 | 0 | fDescriptorSetManagers.emplace_back(dsm); |
375 | 0 | *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.size() - 1); |
376 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getSamplerDescriptorSetHandle(VkDescriptorType, GrVkUniformHandler const&, GrResourceHandle<GrVkDescriptorSetManager::HandleKind>*) Unexecuted instantiation: GrVkResourceProvider::getSamplerDescriptorSetHandle(VkDescriptorType, GrVkUniformHandler const&, GrResourceHandle<GrVkDescriptorSetManager::HandleKind>*) |
377 | | |
378 | 0 | VkDescriptorSetLayout GrVkResourceProvider::getUniformDSLayout() const { |
379 | 0 | SkASSERT(fUniformDSHandle.isValid()); |
380 | 0 | return fDescriptorSetManagers[fUniformDSHandle.toIndex()]->layout(); |
381 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getUniformDSLayout() const Unexecuted instantiation: GrVkResourceProvider::getUniformDSLayout() const |
382 | | |
383 | 0 | VkDescriptorSetLayout GrVkResourceProvider::getInputDSLayout() const { |
384 | 0 | SkASSERT(fInputDSHandle.isValid()); |
385 | 0 | return fDescriptorSetManagers[fInputDSHandle.toIndex()]->layout(); |
386 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getInputDSLayout() const Unexecuted instantiation: GrVkResourceProvider::getInputDSLayout() const |
387 | | |
388 | | VkDescriptorSetLayout GrVkResourceProvider::getSamplerDSLayout( |
389 | 0 | const GrVkDescriptorSetManager::Handle& handle) const { |
390 | 0 | SkASSERT(handle.isValid()); |
391 | 0 | return fDescriptorSetManagers[handle.toIndex()]->layout(); |
392 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getSamplerDSLayout(GrResourceHandle<GrVkDescriptorSetManager::HandleKind> const&) const Unexecuted instantiation: GrVkResourceProvider::getSamplerDSLayout(GrResourceHandle<GrVkDescriptorSetManager::HandleKind> const&) const |
393 | | |
394 | 0 | const GrVkDescriptorSet* GrVkResourceProvider::getUniformDescriptorSet() { |
395 | 0 | SkASSERT(fUniformDSHandle.isValid()); |
396 | 0 | return fDescriptorSetManagers[fUniformDSHandle.toIndex()]->getDescriptorSet(fGpu, |
397 | 0 | fUniformDSHandle); |
398 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getUniformDescriptorSet() Unexecuted instantiation: GrVkResourceProvider::getUniformDescriptorSet() |
399 | | |
400 | 0 | const GrVkDescriptorSet* GrVkResourceProvider::getInputDescriptorSet() { |
401 | 0 | SkASSERT(fInputDSHandle.isValid()); |
402 | 0 | return fDescriptorSetManagers[fInputDSHandle.toIndex()]->getDescriptorSet(fGpu, fInputDSHandle); |
403 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getInputDescriptorSet() Unexecuted instantiation: GrVkResourceProvider::getInputDescriptorSet() |
404 | | |
405 | | const GrVkDescriptorSet* GrVkResourceProvider::getSamplerDescriptorSet( |
406 | 0 | const GrVkDescriptorSetManager::Handle& handle) { |
407 | 0 | SkASSERT(handle.isValid()); |
408 | 0 | return fDescriptorSetManagers[handle.toIndex()]->getDescriptorSet(fGpu, handle); |
409 | 0 | } Unexecuted instantiation: GrVkResourceProvider::getSamplerDescriptorSet(GrResourceHandle<GrVkDescriptorSetManager::HandleKind> const&) Unexecuted instantiation: GrVkResourceProvider::getSamplerDescriptorSet(GrResourceHandle<GrVkDescriptorSetManager::HandleKind> const&) |
410 | | |
411 | | void GrVkResourceProvider::recycleDescriptorSet(const GrVkDescriptorSet* descSet, |
412 | 0 | const GrVkDescriptorSetManager::Handle& handle) { |
413 | 0 | SkASSERT(descSet); |
414 | 0 | SkASSERT(handle.isValid()); |
415 | 0 | int managerIdx = handle.toIndex(); |
416 | 0 | SkASSERT(managerIdx < fDescriptorSetManagers.size()); |
417 | 0 | fDescriptorSetManagers[managerIdx]->recycleDescriptorSet(descSet); |
418 | 0 | } Unexecuted instantiation: GrVkResourceProvider::recycleDescriptorSet(GrVkDescriptorSet const*, GrResourceHandle<GrVkDescriptorSetManager::HandleKind> const&) Unexecuted instantiation: GrVkResourceProvider::recycleDescriptorSet(GrVkDescriptorSet const*, GrResourceHandle<GrVkDescriptorSetManager::HandleKind> const&) |
419 | | |
420 | 0 | GrVkCommandPool* GrVkResourceProvider::findOrCreateCommandPool() { |
421 | 0 | GrVkCommandPool* result; |
422 | 0 | if (!fAvailableCommandPools.empty()) { |
423 | 0 | result = fAvailableCommandPools.back(); |
424 | 0 | fAvailableCommandPools.pop_back(); |
425 | 0 | } else { |
426 | 0 | result = GrVkCommandPool::Create(fGpu); |
427 | 0 | if (!result) { |
428 | 0 | return nullptr; |
429 | 0 | } |
430 | 0 | } |
431 | 0 | SkASSERT(result->unique()); |
432 | 0 | SkDEBUGCODE( |
433 | 0 | for (const GrVkCommandPool* pool : fActiveCommandPools) { |
434 | 0 | SkASSERT(pool != result); |
435 | 0 | } |
436 | 0 | for (const GrVkCommandPool* pool : fAvailableCommandPools) { |
437 | 0 | SkASSERT(pool != result); |
438 | 0 | } |
439 | 0 | ) |
440 | 0 | fActiveCommandPools.push_back(result); |
441 | 0 | result->ref(); |
442 | 0 | return result; |
443 | 0 | } Unexecuted instantiation: GrVkResourceProvider::findOrCreateCommandPool() Unexecuted instantiation: GrVkResourceProvider::findOrCreateCommandPool() |
444 | | |
445 | 0 | void GrVkResourceProvider::checkCommandBuffers() { |
446 | | // When resetting a command buffer it can trigger client provided procs (e.g. release or |
447 | | // finished) to be called. During these calls the client could trigger us to abandon the vk |
448 | | // context, e.g. if we are in a DEVICE_LOST state. When we abandon the vk context we will |
449 | | // unref all the fActiveCommandPools and reset the array. Since this can happen in the middle |
450 | | // of the loop here, we need to additionally check that fActiveCommandPools still has pools on |
451 | | // each iteration. |
452 | | // |
453 | | // TODO: We really need to have a more robust way to protect us from client proc calls that |
454 | | // happen in the middle of us doing work. This may be just one of many potential pitfalls that |
455 | | // could happen from the client triggering GrDirectContext changes during a proc call. |
456 | 0 | for (int i = fActiveCommandPools.size() - 1; !fActiveCommandPools.empty() && i >= 0; --i) { |
457 | 0 | GrVkCommandPool* pool = fActiveCommandPools[i]; |
458 | 0 | if (!pool->isOpen()) { |
459 | 0 | GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer(); |
460 | 0 | if (buffer->finished(fGpu)) { |
461 | 0 | fActiveCommandPools.removeShuffle(i); |
462 | 0 | SkASSERT(pool->unique()); |
463 | 0 | pool->reset(fGpu); |
464 | | // After resetting the pool (specifically releasing the pool's resources) we may |
465 | | // have called a client callback proc which may have disconnected the GrVkGpu. In |
466 | | // that case we do not want to push the pool back onto the cache, but instead just |
467 | | // drop the pool. |
468 | 0 | if (fGpu->disconnected()) { |
469 | 0 | pool->unref(); |
470 | 0 | return; |
471 | 0 | } |
472 | 0 | fAvailableCommandPools.push_back(pool); |
473 | 0 | } |
474 | 0 | } |
475 | 0 | } |
476 | 0 | } Unexecuted instantiation: GrVkResourceProvider::checkCommandBuffers() Unexecuted instantiation: GrVkResourceProvider::checkCommandBuffers() |
477 | | |
478 | 0 | void GrVkResourceProvider::forceSyncAllCommandBuffers() { |
479 | 0 | for (int i = fActiveCommandPools.size() - 1; !fActiveCommandPools.empty() && i >= 0; --i) { |
480 | 0 | GrVkCommandPool* pool = fActiveCommandPools[i]; |
481 | 0 | if (!pool->isOpen()) { |
482 | 0 | GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer(); |
483 | 0 | buffer->forceSync(fGpu); |
484 | 0 | } |
485 | 0 | } |
486 | 0 | } |
487 | | |
488 | | void GrVkResourceProvider::addFinishedProcToActiveCommandBuffers( |
489 | 0 | sk_sp<skgpu::RefCntedCallback> finishedCallback) { |
490 | 0 | for (int i = 0; i < fActiveCommandPools.size(); ++i) { |
491 | 0 | GrVkCommandPool* pool = fActiveCommandPools[i]; |
492 | 0 | GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer(); |
493 | 0 | buffer->addFinishedProc(finishedCallback); |
494 | 0 | } |
495 | 0 | } |
496 | | |
497 | 0 | void GrVkResourceProvider::destroyResources() { |
498 | 0 | SkTaskGroup* taskGroup = fGpu->getContext()->priv().getTaskGroup(); |
499 | 0 | if (taskGroup) { |
500 | 0 | taskGroup->wait(); |
501 | 0 | } |
502 | | |
503 | | // Release all msaa load pipelines |
504 | 0 | fMSAALoadPipelines.clear(); |
505 | | |
506 | | // loop over all render pass sets to make sure we destroy all the internal VkRenderPasses |
507 | 0 | for (int i = 0; i < fRenderPassArray.size(); ++i) { |
508 | 0 | fRenderPassArray[i].releaseResources(); |
509 | 0 | } |
510 | 0 | fRenderPassArray.clear(); |
511 | |
|
512 | 0 | for (int i = 0; i < fExternalRenderPasses.size(); ++i) { |
513 | 0 | fExternalRenderPasses[i]->unref(); |
514 | 0 | } |
515 | 0 | fExternalRenderPasses.clear(); |
516 | | |
517 | | // Iterate through all store GrVkSamplers and unref them before resetting the hash table. |
518 | 0 | fSamplers.foreach([&](auto* elt) { elt->unref(); }); |
519 | 0 | fSamplers.reset(); |
520 | |
|
521 | 0 | fYcbcrConversions.foreach([&](auto* elt) { elt->unref(); }); |
522 | 0 | fYcbcrConversions.reset(); |
523 | |
|
524 | 0 | fPipelineStateCache->release(); |
525 | |
|
526 | 0 | GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr)); |
527 | 0 | fPipelineCache = VK_NULL_HANDLE; |
528 | |
|
529 | 0 | for (GrVkCommandPool* pool : fActiveCommandPools) { |
530 | 0 | SkASSERT(pool->unique()); |
531 | 0 | pool->unref(); |
532 | 0 | } |
533 | 0 | fActiveCommandPools.clear(); |
534 | |
|
535 | 0 | for (GrVkCommandPool* pool : fAvailableCommandPools) { |
536 | 0 | SkASSERT(pool->unique()); |
537 | 0 | pool->unref(); |
538 | 0 | } |
539 | 0 | fAvailableCommandPools.clear(); |
540 | | |
541 | | // We must release/destroy all command buffers and pipeline states before releasing the |
542 | | // GrVkDescriptorSetManagers. Additionally, we must release all uniform buffers since they hold |
543 | | // refs to GrVkDescriptorSets. |
544 | 0 | for (int i = 0; i < fDescriptorSetManagers.size(); ++i) { |
545 | 0 | fDescriptorSetManagers[i]->release(fGpu); |
546 | 0 | } |
547 | 0 | fDescriptorSetManagers.clear(); |
548 | |
|
549 | 0 | } Unexecuted instantiation: GrVkResourceProvider::destroyResources() Unexecuted instantiation: GrVkResourceProvider::destroyResources() |
550 | | |
551 | 0 | void GrVkResourceProvider::releaseUnlockedBackendObjects() { |
552 | 0 | for (GrVkCommandPool* pool : fAvailableCommandPools) { |
553 | 0 | SkASSERT(pool->unique()); |
554 | 0 | pool->unref(); |
555 | 0 | } |
556 | 0 | fAvailableCommandPools.clear(); |
557 | 0 | } Unexecuted instantiation: GrVkResourceProvider::releaseUnlockedBackendObjects() Unexecuted instantiation: GrVkResourceProvider::releaseUnlockedBackendObjects() |
558 | | |
559 | 0 | void GrVkResourceProvider::storePipelineCacheData(size_t maxSize) { |
560 | 0 | if (this->pipelineCache() == VK_NULL_HANDLE) { |
561 | 0 | return; |
562 | 0 | } |
563 | 0 | size_t dataSize = 0; |
564 | 0 | VkResult result; |
565 | 0 | GR_VK_CALL_RESULT(fGpu, result, GetPipelineCacheData(fGpu->device(), this->pipelineCache(), |
566 | 0 | &dataSize, nullptr)); |
567 | 0 | if (result != VK_SUCCESS) { |
568 | 0 | return; |
569 | 0 | } |
570 | | |
571 | 0 | dataSize = std::min(dataSize, maxSize); |
572 | |
|
573 | 0 | std::unique_ptr<uint8_t[]> data(new uint8_t[dataSize]); |
574 | |
|
575 | 0 | GR_VK_CALL_RESULT_NOCHECK( |
576 | 0 | fGpu, |
577 | 0 | result, |
578 | 0 | GetPipelineCacheData( |
579 | 0 | fGpu->device(), this->pipelineCache(), &dataSize, (void*)data.get())); |
580 | 0 | fGpu->checkVkResult(result); |
581 | 0 | if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) { |
582 | 0 | SkDebugf("%s: vkGetPipelineCacheData: failed vulkan call (%d)", __func__, result); |
583 | 0 | return; |
584 | 0 | } |
585 | | |
586 | 0 | uint32_t key = GrVkGpu::kPipelineCache_PersistentCacheKeyType; |
587 | 0 | sk_sp<SkData> keyData = SkData::MakeWithoutCopy(&key, sizeof(uint32_t)); |
588 | |
|
589 | 0 | fGpu->getContext()->priv().getPersistentCache()->store( |
590 | 0 | *keyData, *SkData::MakeWithoutCopy(data.get(), dataSize), SkString("VkPipelineCache")); |
591 | 0 | } Unexecuted instantiation: GrVkResourceProvider::storePipelineCacheData(unsigned long) Unexecuted instantiation: GrVkResourceProvider::storePipelineCacheData(unsigned long) |
592 | | |
593 | | //////////////////////////////////////////////////////////////////////////////// |
594 | | |
595 | | GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(GrVkRenderPass* renderPass) |
596 | 0 | : fLastReturnedIndex(0) { |
597 | 0 | renderPass->ref(); |
598 | 0 | fRenderPasses.push_back(renderPass); |
599 | 0 | } |
600 | | |
601 | | bool GrVkResourceProvider::CompatibleRenderPassSet::isCompatible( |
602 | | const GrVkRenderPass::AttachmentsDescriptor& attachmentsDescriptor, |
603 | | GrVkRenderPass::AttachmentFlags attachmentFlags, |
604 | | SelfDependencyFlags selfDepFlags, |
605 | 0 | LoadFromResolve loadFromResolve) const { |
606 | | // The first GrVkRenderpass should always exists since we create the basic load store |
607 | | // render pass on create |
608 | 0 | SkASSERT(fRenderPasses[0]); |
609 | 0 | return fRenderPasses[0]->isCompatible(attachmentsDescriptor, attachmentFlags, selfDepFlags, |
610 | 0 | loadFromResolve); |
611 | 0 | } Unexecuted instantiation: GrVkResourceProvider::CompatibleRenderPassSet::isCompatible(GrVkRenderPass::AttachmentsDescriptor const&, GrVkRenderPass::AttachmentFlags, GrVkRenderPass::SelfDependencyFlags, GrVkRenderPass::LoadFromResolve) const Unexecuted instantiation: GrVkResourceProvider::CompatibleRenderPassSet::isCompatible(GrVkRenderPass::AttachmentsDescriptor const&, GrVkRenderPass::AttachmentFlags, GrVkRenderPass::SelfDependencyFlags, GrVkRenderPass::LoadFromResolve) const |
612 | | |
613 | | GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass( |
614 | | GrVkGpu* gpu, |
615 | | const GrVkRenderPass::LoadStoreOps& colorOps, |
616 | | const GrVkRenderPass::LoadStoreOps& resolveOps, |
617 | 0 | const GrVkRenderPass::LoadStoreOps& stencilOps) { |
618 | 0 | for (int i = 0; i < fRenderPasses.size(); ++i) { |
619 | 0 | int idx = (i + fLastReturnedIndex) % fRenderPasses.size(); |
620 | 0 | if (fRenderPasses[idx]->equalLoadStoreOps(colorOps, resolveOps, stencilOps)) { |
621 | 0 | fLastReturnedIndex = idx; |
622 | 0 | return fRenderPasses[idx]; |
623 | 0 | } |
624 | 0 | } |
625 | 0 | GrVkRenderPass* renderPass = GrVkRenderPass::Create(gpu, *this->getCompatibleRenderPass(), |
626 | 0 | colorOps, resolveOps, stencilOps); |
627 | 0 | if (!renderPass) { |
628 | 0 | return nullptr; |
629 | 0 | } |
630 | 0 | fRenderPasses.push_back(renderPass); |
631 | 0 | fLastReturnedIndex = fRenderPasses.size() - 1; |
632 | 0 | return renderPass; |
633 | 0 | } |
634 | | |
635 | 0 | void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources() { |
636 | 0 | for (int i = 0; i < fRenderPasses.size(); ++i) { |
637 | 0 | if (fRenderPasses[i]) { |
638 | 0 | fRenderPasses[i]->unref(); |
639 | 0 | fRenderPasses[i] = nullptr; |
640 | 0 | } |
641 | 0 | } |
642 | 0 | } |
643 | | |