Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
VulkanResourceProvider.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
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
9
10#include "include/core/SkSpan.h"
34
35#ifdef SK_BUILD_FOR_ANDROID
38#endif
39
40namespace skgpu::graphite {
41
43 SingleOwner* singleOwner,
44 uint32_t recorderID,
45 size_t resourceBudget,
46 sk_sp<Buffer> intrinsicConstantUniformBuffer,
47 sk_sp<Buffer> loadMSAAVertexBuffer)
48 : ResourceProvider(sharedContext, singleOwner, recorderID, resourceBudget)
49 , fIntrinsicUniformBuffer(std::move(intrinsicConstantUniformBuffer))
50 , fLoadMSAAVertexBuffer(std::move(loadMSAAVertexBuffer)) {
51}
52
54 if (fPipelineCache != VK_NULL_HANDLE) {
55 VULKAN_CALL(this->vulkanSharedContext()->interface(),
56 DestroyPipelineCache(this->vulkanSharedContext()->device(),
57 fPipelineCache,
58 nullptr));
59 }
60 if (fMSAALoadVertShaderModule != VK_NULL_HANDLE) {
61 VULKAN_CALL(this->vulkanSharedContext()->interface(),
62 DestroyShaderModule(this->vulkanSharedContext()->device(),
63 fMSAALoadVertShaderModule,
64 nullptr));
65 }
66 if (fMSAALoadFragShaderModule != VK_NULL_HANDLE) {
67 VULKAN_CALL(this->vulkanSharedContext()->interface(),
68 DestroyShaderModule(this->vulkanSharedContext()->device(),
69 fMSAALoadFragShaderModule,
70 nullptr));
71 }
72 if (fMSAALoadPipelineLayout != VK_NULL_HANDLE) {
73 VULKAN_CALL(this->vulkanSharedContext()->interface(),
74 DestroyPipelineLayout(this->vulkanSharedContext()->device(),
75 fMSAALoadPipelineLayout,
76 nullptr));
77 }
78}
79
80const VulkanSharedContext* VulkanResourceProvider::vulkanSharedContext() const {
81 return static_cast<const VulkanSharedContext*>(fSharedContext);
82}
83
85 return VulkanTexture::MakeWrapped(this->vulkanSharedContext(),
86 this,
87 texture.dimensions(),
88 texture.info(),
89 texture.getMutableState(),
90 texture.getVkImage(),
91 /*alloc=*/{}); // Skia does not own wrapped texture memory
92}
93
95 return fIntrinsicUniformBuffer;
96}
97
99 return fLoadMSAAVertexBuffer.get();
100}
101
103 const RuntimeEffectDictionary* runtimeDict,
104 const GraphicsPipelineDesc& pipelineDesc,
105 const RenderPassDesc& renderPassDesc) {
106 auto compatibleRenderPass =
107 this->findOrCreateRenderPass(renderPassDesc, /*compatibleOnly=*/true);
108 return VulkanGraphicsPipeline::Make(this->vulkanSharedContext(),
109 runtimeDict,
110 pipelineDesc,
111 renderPassDesc,
112 compatibleRenderPass,
113 this->pipelineCache());
114}
115
119
121 skgpu::Budgeted budgeted) {
122 return VulkanTexture::Make(this->vulkanSharedContext(), this, size, info, budgeted);
123}
124
127 AccessPattern accessPattern,
128 std::string_view label) {
129 return VulkanBuffer::Make(this->vulkanSharedContext(),
130 size,
131 type,
132 accessPattern,
133 std::move(label));
134}
135
137 return VulkanSampler::Make(this->vulkanSharedContext(),
138 samplerDesc.samplingOptions(),
139 samplerDesc.tileModeX(),
140 samplerDesc.tileModeY());
141}
142
144 const TextureInfo& info) {
145 VulkanTextureInfo vkTexInfo;
146 if (!info.getVulkanTextureInfo(&vkTexInfo)) {
147 return {};
148 }
149 VulkanTexture::CreatedImageInfo createdTextureInfo;
150 if (!VulkanTexture::MakeVkImage(this->vulkanSharedContext(), dimensions, info,
151 &createdTextureInfo)) {
152 return {};
153 }
154 return {dimensions,
155 vkTexInfo,
158 createdTextureInfo.fImage,
159 createdTextureInfo.fMemoryAlloc};
160}
161
162namespace {
163GraphiteResourceKey build_desc_set_key(const SkSpan<DescriptorData>& requestedDescriptors) {
165
166 const int num32DataCnt = requestedDescriptors.size() + 1;
167
169 GraphiteResourceKey::Builder builder(&key, kType, num32DataCnt, Shareable::kNo);
170
171 builder[0] = requestedDescriptors.size();
172 for (int i = 1; i < num32DataCnt; i++) {
173 const auto& currDesc = requestedDescriptors[i - 1];
174 // TODO: Consider making the DescriptorData struct itself just use uint16_t.
175 uint16_t smallerCount = static_cast<uint16_t>(currDesc.count);
176 builder[i] = static_cast<uint8_t>(currDesc.type) << 24 |
177 currDesc.bindingIndex << 16 |
178 smallerCount;
179 }
180 builder.finish();
181 return key;
182}
183
184sk_sp<VulkanDescriptorSet> add_new_desc_set_to_cache(const VulkanSharedContext* context,
186 const GraphiteResourceKey& descSetKey,
187 ResourceCache* resourceCache) {
189 if (!descSet) {
190 return nullptr;
191 }
192 descSet->setKey(descSetKey);
193 resourceCache->insertResource(descSet.get());
194
195 return descSet;
196}
197} // anonymous namespace
198
199sk_sp<VulkanDescriptorSet> VulkanResourceProvider::findOrCreateDescriptorSet(
200 SkSpan<DescriptorData> requestedDescriptors) {
201 if (requestedDescriptors.empty()) {
202 return nullptr;
203 }
204 // Search for available descriptor sets by assembling a key based upon the set's structure.
205 GraphiteResourceKey key = build_desc_set_key(requestedDescriptors);
206 if (auto descSet = fResourceCache->findAndRefResource(key, skgpu::Budgeted::kYes)) {
207 // A non-null resource pointer indicates we have found an available descriptor set.
208 return sk_sp<VulkanDescriptorSet>(static_cast<VulkanDescriptorSet*>(descSet));
209 }
210
211
212 // If we did not find an existing avilable desc set, allocate sets with the appropriate layout
213 // and add them to the cache.
214 VkDescriptorSetLayout layout;
215 const VulkanSharedContext* context = this->vulkanSharedContext();
216 DescriptorDataToVkDescSetLayout(context, requestedDescriptors, &layout);
217 if (!layout) {
218 return nullptr;
219 }
220 auto pool = VulkanDescriptorPool::Make(context, requestedDescriptors, layout);
221 if (!pool) {
222 VULKAN_CALL(context->interface(), DestroyDescriptorSetLayout(context->device(),
223 layout,
224 nullptr));
225 return nullptr;
226 }
227
228 // Start with allocating one descriptor set. If one cannot be successfully created, then we can
229 // return early before attempting to allocate more. Storing a ptr to the first set also
230 // allows us to return that later without having to perform a find operation on the cache once
231 // all the sets are added.
232 auto firstDescSet =
233 add_new_desc_set_to_cache(context, pool, key, fResourceCache.get());
234 if (!firstDescSet) {
235 return nullptr;
236 }
237
238 // Continue to allocate & cache the maximum number of sets so they can be easily accessed as
239 // they're needed.
240 for (int i = 1; i < VulkanDescriptorPool::kMaxNumSets ; i++) {
241 auto descSet =
242 add_new_desc_set_to_cache(context, pool, key, fResourceCache.get());
243 if (!descSet) {
244 SKGPU_LOG_W("Descriptor set allocation %d of %d was unsuccessful; no more sets will be"
245 "allocated from this pool.", i, VulkanDescriptorPool::kMaxNumSets);
246 break;
247 }
248 }
249
250 return firstDescSet;
251}
252
253sk_sp<VulkanRenderPass> VulkanResourceProvider::findOrCreateRenderPassWithKnownKey(
254 const RenderPassDesc& renderPassDesc,
255 bool compatibleOnly,
256 const GraphiteResourceKey& rpKey) {
257 if (Resource* resource =
258 fResourceCache->findAndRefResource(rpKey, skgpu::Budgeted::kYes)) {
259 return sk_sp<VulkanRenderPass>(static_cast<VulkanRenderPass*>(resource));
260 }
261
262 sk_sp<VulkanRenderPass> renderPass =
263 VulkanRenderPass::MakeRenderPass(this->vulkanSharedContext(),
264 renderPassDesc,
265 compatibleOnly);
266 if (!renderPass) {
267 return nullptr;
268 }
269
270 renderPass->setKey(rpKey);
271 fResourceCache->insertResource(renderPass.get());
272
273 return renderPass;
274}
275
276sk_sp<VulkanRenderPass> VulkanResourceProvider::findOrCreateRenderPass(
277 const RenderPassDesc& renderPassDesc, bool compatibleOnly) {
278 GraphiteResourceKey rpKey = VulkanRenderPass::MakeRenderPassKey(renderPassDesc, compatibleOnly);
279
280 return this->findOrCreateRenderPassWithKnownKey(renderPassDesc, compatibleOnly, rpKey);
281}
282
283VkPipelineCache VulkanResourceProvider::pipelineCache() {
284 if (fPipelineCache == VK_NULL_HANDLE) {
285 VkPipelineCacheCreateInfo createInfo;
286 memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
288 createInfo.pNext = nullptr;
289 createInfo.flags = 0;
290 createInfo.initialDataSize = 0;
291 createInfo.pInitialData = nullptr;
293 VULKAN_CALL_RESULT(this->vulkanSharedContext(),
294 result,
295 CreatePipelineCache(this->vulkanSharedContext()->device(),
296 &createInfo,
297 nullptr,
298 &fPipelineCache));
299 if (VK_SUCCESS != result) {
300 fPipelineCache = VK_NULL_HANDLE;
301 }
302 }
303 return fPipelineCache;
304}
305
306sk_sp<VulkanFramebuffer> VulkanResourceProvider::createFramebuffer(
307 const VulkanSharedContext* context,
308 const skia_private::TArray<VkImageView>& attachmentViews,
309 const VulkanRenderPass& renderPass,
310 const int width,
311 const int height) {
312 // TODO: Consider caching these in the future. If we pursue that, it may make more sense to
313 // use a compatible renderpass rather than a full one to make each frame buffer more versatile.
314 VkFramebufferCreateInfo framebufferInfo;
315 memset(&framebufferInfo, 0, sizeof(VkFramebufferCreateInfo));
317 framebufferInfo.pNext = nullptr;
318 framebufferInfo.flags = 0;
319 framebufferInfo.renderPass = renderPass.renderPass();
320 framebufferInfo.attachmentCount = attachmentViews.size();
321 framebufferInfo.pAttachments = attachmentViews.begin();
322 framebufferInfo.width = width;
323 framebufferInfo.height = height;
324 framebufferInfo.layers = 1;
325 return VulkanFramebuffer::Make(context, framebufferInfo);
326}
327
329 SkASSERT(texture.isValid());
331
332 VULKAN_CALL(this->vulkanSharedContext()->interface(),
333 DestroyImage(this->vulkanSharedContext()->device(), texture.getVkImage(),
334 /*VkAllocationCallbacks=*/nullptr));
335
336 // Free the image memory used for the BackendTexture's VkImage.
337 //
338 // How we do this is dependent upon on how the image was allocated (via the memory allocator or
339 // with a direct call to the Vulkan driver) . If the VulkanAlloc's fBackendMemory is != 0, then
340 // that means the allocator was used. Otherwise, a direct driver call was used and we should
341 // free the VkDeviceMemory (fMemory).
342 if (texture.getMemoryAlloc()->fBackendMemory) {
343 skgpu::VulkanMemory::FreeImageMemory(this->vulkanSharedContext()->memoryAllocator(),
344 *(texture.getMemoryAlloc()));
345 } else {
346 SkASSERT(texture.getMemoryAlloc()->fMemory != VK_NULL_HANDLE);
347 VULKAN_CALL(this->vulkanSharedContext()->interface(),
348 FreeMemory(this->vulkanSharedContext()->device(),
349 texture.getMemoryAlloc()->fMemory,
350 nullptr));
351 }
352}
353
356 const VulkanYcbcrConversionInfo& ycbcrInfo) const {
357 if (!ycbcrInfo.isValid()) {
358 return nullptr;
359 }
361 this->vulkanSharedContext(), ycbcrInfo);
362
363 if (Resource* resource = fResourceCache->findAndRefResource(ycbcrConversionKey,
366 static_cast<VulkanSamplerYcbcrConversion*>(resource));
367 }
368
369 auto ycbcrConversion = VulkanSamplerYcbcrConversion::Make(this->vulkanSharedContext(),
370 ycbcrInfo);
371 if (!ycbcrConversion) {
372 return nullptr;
373 }
374
375 ycbcrConversion->setKey(ycbcrConversionKey);
376 fResourceCache->insertResource(ycbcrConversion.get());
377
378 return ycbcrConversion;
379}
380
381sk_sp<VulkanGraphicsPipeline> VulkanResourceProvider::findOrCreateLoadMSAAPipeline(
382 const RenderPassDesc& renderPassDesc) {
383
384 if (!renderPassDesc.fColorResolveAttachment.fTextureInfo.isValid() ||
385 !renderPassDesc.fColorAttachment.fTextureInfo.isValid()) {
386 SKGPU_LOG_E("Loading MSAA from resolve texture requires valid color & resolve attachment");
387 return nullptr;
388 }
389
390 // Check to see if we already have a suitable pipeline that we can use.
391 GraphiteResourceKey renderPassKey =
392 VulkanRenderPass::MakeRenderPassKey(renderPassDesc, /*compatibleOnly=*/true);
393 for (int i = 0; i < fLoadMSAAPipelines.size(); i++) {
394 if (renderPassKey == fLoadMSAAPipelines.at(i).first) {
395 return fLoadMSAAPipelines.at(i).second;
396 }
397 }
398
399 // If any of the load MSAA pipeline creation structures are null then we need to initialize
400 // those before proceeding. If the creation of one of them fails, all are assigned to null, so
401 // we only need to check one of the structures.
402 if (fMSAALoadVertShaderModule == VK_NULL_HANDLE) {
403 SkASSERT(fMSAALoadFragShaderModule == VK_NULL_HANDLE &&
404 fMSAALoadPipelineLayout == VK_NULL_HANDLE);
406 this->vulkanSharedContext(),
407 &fMSAALoadVertShaderModule,
408 &fMSAALoadFragShaderModule,
409 &fMSAALoadShaderStageInfo[0],
410 &fMSAALoadPipelineLayout)) {
411 SKGPU_LOG_E("Failed to initialize MSAA load pipeline creation structure(s)");
412 return nullptr;
413 }
414 }
415
416 sk_sp<VulkanRenderPass> compatibleRenderPass =
417 this->findOrCreateRenderPassWithKnownKey(renderPassDesc,
418 /*compatibleOnly=*/true,
419 renderPassKey);
420 if (!compatibleRenderPass) {
421 SKGPU_LOG_E("Failed to make compatible render pass for loading MSAA");
422 }
423
425 this->vulkanSharedContext(),
426 fMSAALoadVertShaderModule,
427 fMSAALoadFragShaderModule,
428 &fMSAALoadShaderStageInfo[0],
429 fMSAALoadPipelineLayout,
430 compatibleRenderPass,
431 this->pipelineCache(),
432 renderPassDesc.fColorAttachment.fTextureInfo);
433
434 if (!pipeline) {
435 SKGPU_LOG_E("Failed to create MSAA load pipeline");
436 return nullptr;
437 }
438
439 fLoadMSAAPipelines.push_back(std::make_pair(renderPassKey, pipeline));
440 return pipeline;
441}
442
443#ifdef SK_BUILD_FOR_ANDROID
444
446 bool isRenderable,
447 bool isProtectedContent,
448 SkISize dimensions,
449 bool fromAndroidWindow) const {
450
451 const VulkanSharedContext* vkContext = this->vulkanSharedContext();
452 VkDevice device = vkContext->device();
453 const VulkanCaps& vkCaps = vkContext->vulkanCaps();
454
457 if (!skgpu::GetAHardwareBufferProperties(
458 &hwbFormatProps, &hwbProps, vkContext->interface(), hardwareBuffer, device)) {
459 return {};
460 }
461
462 bool importAsExternalFormat = hwbFormatProps.format == VK_FORMAT_UNDEFINED;
463
464 // Start to assemble VulkanTextureInfo which is needed later on to create the VkImage but can
465 // sooner help us query VulkanCaps for certain format feature support.
466 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; // TODO: Query for tiling mode.
467 VkImageCreateFlags imgCreateflags = isProtectedContent ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
469 // When importing as an external format the image usage can only be VK_IMAGE_USAGE_SAMPLED_BIT.
470 if (!importAsExternalFormat) {
472 if (isRenderable) {
473 // Renderable attachments can be used as input attachments if we are loading from MSAA.
475 }
476 }
477 VulkanTextureInfo vkTexInfo { VK_SAMPLE_COUNT_1_BIT,
478 Mipmapped::kNo,
479 imgCreateflags,
480 hwbFormatProps.format,
481 tiling,
482 usageFlags,
485 VulkanYcbcrConversionInfo() };
486
487 if (isRenderable && (importAsExternalFormat || !vkCaps.isRenderable(vkTexInfo))) {
488 SKGPU_LOG_W("Renderable texture requested from an AHardwareBuffer which uses a VkFormat "
489 "that Skia cannot render to (VkFormat: %d).\n", hwbFormatProps.format);
490 return {};
491 }
492
493 if (!importAsExternalFormat && (!vkCaps.isTransferSrc(vkTexInfo) ||
494 !vkCaps.isTransferDst(vkTexInfo) ||
495 !vkCaps.isTexturable(vkTexInfo))) {
496 if (isRenderable) {
497 SKGPU_LOG_W("VkFormat %d is either unfamiliar to Skia or doesn't support the necessary"
498 " format features. Because a renerable texture was requested, we cannot "
499 "fall back to importing with an external format.\n", hwbFormatProps.format);
500 return {};
501 }
502 // If the VkFormat does not support the features we need, then import as an external format.
503 importAsExternalFormat = true;
504 // If we use VkExternalFormatANDROID with an externalFormat != 0, then format must =
505 // VK_FORMAT_UNDEFINED.
506 vkTexInfo.fFormat = VK_FORMAT_UNDEFINED;
507 vkTexInfo.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
508 }
509
510 VulkanYcbcrConversionInfo ycbcrInfo;
511 VkExternalFormatANDROID externalFormat;
513 externalFormat.pNext = nullptr;
514 externalFormat.externalFormat = 0; // If this is zero it is as if we aren't using this struct.
515 if (importAsExternalFormat) {
516 GetYcbcrConversionInfoFromFormatProps(&ycbcrInfo, hwbFormatProps);
517 if (!ycbcrInfo.isValid()) {
518 SKGPU_LOG_W("Failed to create valid YCbCr conversion information from hardware buffer"
519 "format properties.\n");
520 return {};
521 }
522 externalFormat.externalFormat = hwbFormatProps.externalFormat;
523 }
524 const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
526 &externalFormat, // pNext
528 };
529
530 SkASSERT(!(vkTexInfo.fFlags & VK_IMAGE_CREATE_PROTECTED_BIT) ||
531 fSharedContext->isProtected() == Protected::kYes);
532
533 const VkImageCreateInfo imageCreateInfo = {
535 &externalMemoryImageInfo, // pNext
536 vkTexInfo.fFlags, // VkImageCreateFlags
537 VK_IMAGE_TYPE_2D, // VkImageType
538 vkTexInfo.fFormat, // VkFormat
539 { (uint32_t)dimensions.fWidth, (uint32_t)dimensions.fHeight, 1 }, // VkExtent3D
540 1, // mipLevels
541 1, // arrayLayers
542 VK_SAMPLE_COUNT_1_BIT, // samples
543 vkTexInfo.fImageTiling, // VkImageTiling
544 vkTexInfo.fImageUsageFlags, // VkImageUsageFlags
545 vkTexInfo.fSharingMode, // VkSharingMode
546 0, // queueFamilyCount
547 nullptr, // pQueueFamilyIndices
548 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
549 };
550
552 VkImage image;
553 result = VULKAN_CALL(vkContext->interface(),
554 CreateImage(device, &imageCreateInfo, nullptr, &image));
555 if (result != VK_SUCCESS) {
556 return {};
557 }
558
559 const VkPhysicalDeviceMemoryProperties2& phyDevMemProps =
560 vkContext->vulkanCaps().physicalDeviceMemoryProperties2();
561 VulkanAlloc alloc;
562 if (!AllocateAndBindImageMemory(&alloc, image, phyDevMemProps, hwbProps, hardwareBuffer,
563 vkContext->interface(), device)) {
564 VULKAN_CALL(vkContext->interface(), DestroyImage(device, image, nullptr));
565 return {};
566 }
567
568 return { dimensions, vkTexInfo, VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_FOREIGN_EXT,
569 image, alloc};
570}
571
572#endif // SK_BUILD_FOR_ANDROID
573
574} // namespace skgpu::graphite
AutoreleasePool pool
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
struct AHardwareBuffer AHardwareBuffer
#define SKGPU_LOG_E(fmt,...)
Definition Log.h:38
#define SKGPU_LOG_W(fmt,...)
Definition Log.h:40
#define SkASSERT(cond)
Definition SkAssert.h:116
#define VULKAN_CALL(IFACE, X)
#define VULKAN_CALL_RESULT(SHARED_CONTEXT, RESULT, X)
constexpr bool empty() const
Definition SkSpan_impl.h:96
constexpr size_t size() const
Definition SkSpan_impl.h:95
T * get() const
Definition SkRefCnt.h:303
sk_sp< ResourceCache > fResourceCache
static sk_sp< Buffer > Make(const VulkanSharedContext *, size_t, BufferType, AccessPattern, std::string_view label)
static sk_sp< VulkanDescriptorPool > Make(const VulkanSharedContext *, SkSpan< DescriptorData >, VkDescriptorSetLayout)
static sk_sp< VulkanDescriptorSet > Make(const VulkanSharedContext *, const sk_sp< VulkanDescriptorPool > &)
static sk_sp< VulkanFramebuffer > Make(const VulkanSharedContext *, const VkFramebufferCreateInfo &)
static sk_sp< VulkanGraphicsPipeline > Make(const VulkanSharedContext *, const RuntimeEffectDictionary *, const GraphicsPipelineDesc &, const RenderPassDesc &, const sk_sp< VulkanRenderPass > &compatibleRenderPass, VkPipelineCache)
static sk_sp< VulkanGraphicsPipeline > MakeLoadMSAAPipeline(const VulkanSharedContext *, VkShaderModule vsModule, VkShaderModule fsModule, VkPipelineShaderStageCreateInfo *pipelineShaderStages, VkPipelineLayout, sk_sp< VulkanRenderPass > compatibleRenderPass, VkPipelineCache, const TextureInfo &dstColorAttachmentTexInfo)
static bool InitializeMSAALoadPipelineStructs(const VulkanSharedContext *, VkShaderModule *outVertexShaderModule, VkShaderModule *outFragShaderModule, VkPipelineShaderStageCreateInfo *outShaderStageInfo, VkPipelineLayout *outPipelineLayout)
static sk_sp< VulkanRenderPass > MakeRenderPass(const VulkanSharedContext *, const RenderPassDesc &, bool compatibleOnly)
static GraphiteResourceKey MakeRenderPassKey(const RenderPassDesc &, bool compatibleOnly)
sk_sp< Sampler > createSampler(const SamplerDesc &) override
sk_sp< Texture > createWrappedTexture(const BackendTexture &) override
sk_sp< Buffer > createBuffer(size_t size, BufferType type, AccessPattern, std::string_view label) override
sk_sp< VulkanSamplerYcbcrConversion > findOrCreateCompatibleSamplerYcbcrConversion(const VulkanYcbcrConversionInfo &ycbcrInfo) const
void onDeleteBackendTexture(const BackendTexture &) override
BackendTexture onCreateBackendTexture(SkISize dimensions, const TextureInfo &) override
VulkanResourceProvider(SharedContext *sharedContext, SingleOwner *, uint32_t recorderID, size_t resourceBudget, sk_sp< Buffer > intrinsicConstantUniformBuffer, sk_sp< Buffer > loadMSAAVertexBuffer)
sk_sp< Texture > createTexture(SkISize, const TextureInfo &, skgpu::Budgeted) override
sk_sp< GraphicsPipeline > createGraphicsPipeline(const RuntimeEffectDictionary *, const GraphicsPipelineDesc &, const RenderPassDesc &) override
sk_sp< ComputePipeline > createComputePipeline(const ComputePipelineDesc &) override
static GraphiteResourceKey MakeYcbcrConversionKey(const VulkanSharedContext *, const VulkanYcbcrConversionInfo &)
static sk_sp< VulkanSamplerYcbcrConversion > Make(const VulkanSharedContext *, const VulkanYcbcrConversionInfo &)
static sk_sp< VulkanSampler > Make(const VulkanSharedContext *, const SkSamplingOptions &samplingOptions, SkTileMode xTileMode, SkTileMode yTileMode)
static sk_sp< Texture > Make(const VulkanSharedContext *, const VulkanResourceProvider *, SkISize dimensions, const TextureInfo &, skgpu::Budgeted)
static bool MakeVkImage(const VulkanSharedContext *, SkISize dimensions, const TextureInfo &, CreatedImageInfo *outInfo)
static sk_sp< Texture > MakeWrapped(const VulkanSharedContext *, const VulkanResourceProvider *, SkISize dimensions, const TextureInfo &, sk_sp< MutableTextureState >, VkImage, const VulkanAlloc &)
int size() const
Definition SkTArray.h:416
VkDevice device
Definition main.cc:53
sk_sp< SkImage > image
Definition examples.cpp:29
GAsyncResult * result
FlTexture * texture
SK_API uint32_t GetVkQueueFamilyIndex(const MutableTextureState &state)
SK_API VkImageLayout GetVkImageLayout(const MutableTextureState &state)
void FreeImageMemory(VulkanMemoryAllocator *, const VulkanAlloc &alloc)
uint32_t ResourceType
void DescriptorDataToVkDescSetLayout(const VulkanSharedContext *ctxt, const SkSpan< DescriptorData > &requestedDescriptors, VkDescriptorSetLayout *outLayout)
Budgeted
Definition GpuTypes.h:35
Definition ref_ptr.h:256
int32_t height
int32_t width
int32_t fHeight
Definition SkSize.h:18
int32_t fWidth
Definition SkSize.h:17
const VkImageView * pAttachments
VkStructureType sType
VkFramebufferCreateFlags flags
VkPipelineCacheCreateFlags flags
SkTileMode tileModeX() const
SkSamplingOptions samplingOptions() const
SkTileMode tileModeY() const
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_SHARING_MODE_EXCLUSIVE
VkFlags VkImageUsageFlags
@ VK_IMAGE_CREATE_PROTECTED_BIT
VkImageTiling
@ VK_IMAGE_TILING_OPTIMAL
@ VK_IMAGE_ASPECT_COLOR_BIT
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_SAMPLED_BIT
@ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
@ VK_SAMPLE_COUNT_1_BIT
@ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
#define VK_QUEUE_FAMILY_FOREIGN_EXT
@ VK_IMAGE_TYPE_2D
VkFlags VkImageCreateFlags
VkResult
@ VK_SUCCESS
#define VK_NULL_HANDLE
Definition vulkan_core.h:46
@ VK_FORMAT_UNDEFINED
@ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
@ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
@ VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID
@ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
@ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO