xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanTexture.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanTexture.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/MutableTextureState.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanMutableTextureState.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMipmap.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanCaps.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanCommandBuffer.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteTypesPriv.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanResourceProvider.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanSharedContext.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanMemory.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanMutableTextureStatePriv.h"
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
25*c8dee2aaSAndroid Build Coastguard Worker 
MakeVkImage(const VulkanSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,CreatedImageInfo * outInfo)26*c8dee2aaSAndroid Build Coastguard Worker bool VulkanTexture::MakeVkImage(const VulkanSharedContext* sharedContext,
27*c8dee2aaSAndroid Build Coastguard Worker                                 SkISize dimensions,
28*c8dee2aaSAndroid Build Coastguard Worker                                 const TextureInfo& info,
29*c8dee2aaSAndroid Build Coastguard Worker                                 CreatedImageInfo* outInfo) {
30*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(outInfo);
31*c8dee2aaSAndroid Build Coastguard Worker     const VulkanCaps& caps = sharedContext->vulkanCaps();
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker     if (dimensions.isEmpty()) {
34*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Tried to create VkImage with empty dimensions.");
35*c8dee2aaSAndroid Build Coastguard Worker         return false;
36*c8dee2aaSAndroid Build Coastguard Worker     }
37*c8dee2aaSAndroid Build Coastguard Worker     if (dimensions.width() > caps.maxTextureSize() ||
38*c8dee2aaSAndroid Build Coastguard Worker         dimensions.height() > caps.maxTextureSize()) {
39*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Tried to create VkImage with too large a size.");
40*c8dee2aaSAndroid Build Coastguard Worker         return false;
41*c8dee2aaSAndroid Build Coastguard Worker     }
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker     if ((info.isProtected() == Protected::kYes) != caps.protectedSupport()) {
44*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Tried to create %s VkImage in %s Context.",
45*c8dee2aaSAndroid Build Coastguard Worker                     info.isProtected() == Protected::kYes ? "protected" : "unprotected",
46*c8dee2aaSAndroid Build Coastguard Worker                     caps.protectedSupport() ? "protected" : "unprotected");
47*c8dee2aaSAndroid Build Coastguard Worker         return false;
48*c8dee2aaSAndroid Build Coastguard Worker     }
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker     const VulkanTextureSpec spec = TextureInfos::GetVulkanTextureSpec(info);
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     bool isLinear = spec.fImageTiling == VK_IMAGE_TILING_LINEAR;
53*c8dee2aaSAndroid Build Coastguard Worker     VkImageLayout initialLayout = isLinear ? VK_IMAGE_LAYOUT_PREINITIALIZED
54*c8dee2aaSAndroid Build Coastguard Worker                                            : VK_IMAGE_LAYOUT_UNDEFINED;
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker     // Create Image
57*c8dee2aaSAndroid Build Coastguard Worker     VkSampleCountFlagBits vkSamples;
58*c8dee2aaSAndroid Build Coastguard Worker     if (!SampleCountToVkSampleCount(info.numSamples(), &vkSamples)) {
59*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Failed creating VkImage because we could not covert the number of samples: "
60*c8dee2aaSAndroid Build Coastguard Worker                     "%u to a VkSampleCountFlagBits.", info.numSamples());
61*c8dee2aaSAndroid Build Coastguard Worker         return false;
62*c8dee2aaSAndroid Build Coastguard Worker     }
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!isLinear || vkSamples == VK_SAMPLE_COUNT_1_BIT);
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker     VkImageCreateFlags createflags = 0;
67*c8dee2aaSAndroid Build Coastguard Worker     if (info.isProtected() == Protected::kYes && caps.protectedSupport()) {
68*c8dee2aaSAndroid Build Coastguard Worker         createflags |= VK_IMAGE_CREATE_PROTECTED_BIT;
69*c8dee2aaSAndroid Build Coastguard Worker     }
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker     uint32_t numMipLevels = 1;
72*c8dee2aaSAndroid Build Coastguard Worker     if (info.mipmapped() == Mipmapped::kYes) {
73*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
74*c8dee2aaSAndroid Build Coastguard Worker     }
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker     uint32_t width = static_cast<uint32_t>(dimensions.fWidth);
77*c8dee2aaSAndroid Build Coastguard Worker     uint32_t height = static_cast<uint32_t>(dimensions.fHeight);
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     const VkImageCreateInfo imageCreateInfo = {
80*c8dee2aaSAndroid Build Coastguard Worker         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
81*c8dee2aaSAndroid Build Coastguard Worker         nullptr,                             // pNext
82*c8dee2aaSAndroid Build Coastguard Worker         createflags,                         // VkImageCreateFlags
83*c8dee2aaSAndroid Build Coastguard Worker         VK_IMAGE_TYPE_2D,                    // VkImageType
84*c8dee2aaSAndroid Build Coastguard Worker         spec.fFormat,                        // VkFormat
85*c8dee2aaSAndroid Build Coastguard Worker         { width, height, 1 },                // VkExtent3D
86*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels,                        // mipLevels
87*c8dee2aaSAndroid Build Coastguard Worker         1,                                   // arrayLayers
88*c8dee2aaSAndroid Build Coastguard Worker         vkSamples,                           // samples
89*c8dee2aaSAndroid Build Coastguard Worker         spec.fImageTiling,                   // VkImageTiling
90*c8dee2aaSAndroid Build Coastguard Worker         spec.fImageUsageFlags,               // VkImageUsageFlags
91*c8dee2aaSAndroid Build Coastguard Worker         spec.fSharingMode,                   // VkSharingMode
92*c8dee2aaSAndroid Build Coastguard Worker         0,                                   // queueFamilyCount
93*c8dee2aaSAndroid Build Coastguard Worker         nullptr,                             // pQueueFamilyIndices
94*c8dee2aaSAndroid Build Coastguard Worker         initialLayout                        // initialLayout
95*c8dee2aaSAndroid Build Coastguard Worker     };
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker     auto device = sharedContext->device();
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker     VkImage image = VK_NULL_HANDLE;
100*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
101*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL_RESULT(
102*c8dee2aaSAndroid Build Coastguard Worker             sharedContext, result, CreateImage(device, &imageCreateInfo, nullptr, &image));
103*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
104*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Failed call to vkCreateImage with error: %d", result);
105*c8dee2aaSAndroid Build Coastguard Worker         return false;
106*c8dee2aaSAndroid Build Coastguard Worker     }
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker     auto allocator = sharedContext->memoryAllocator();
109*c8dee2aaSAndroid Build Coastguard Worker     bool forceDedicatedMemory = caps.shouldAlwaysUseDedicatedImageMemory();
110*c8dee2aaSAndroid Build Coastguard Worker     bool useLazyAllocation =
111*c8dee2aaSAndroid Build Coastguard Worker             SkToBool(spec.fImageUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT);
112*c8dee2aaSAndroid Build Coastguard Worker 
113*c8dee2aaSAndroid Build Coastguard Worker     auto checkResult = [sharedContext](VkResult result) {
114*c8dee2aaSAndroid Build Coastguard Worker         return sharedContext->checkVkResult(result);
115*c8dee2aaSAndroid Build Coastguard Worker     };
116*c8dee2aaSAndroid Build Coastguard Worker     if (!skgpu::VulkanMemory::AllocImageMemory(allocator,
117*c8dee2aaSAndroid Build Coastguard Worker                                                image,
118*c8dee2aaSAndroid Build Coastguard Worker                                                info.isProtected(),
119*c8dee2aaSAndroid Build Coastguard Worker                                                forceDedicatedMemory,
120*c8dee2aaSAndroid Build Coastguard Worker                                                useLazyAllocation,
121*c8dee2aaSAndroid Build Coastguard Worker                                                checkResult,
122*c8dee2aaSAndroid Build Coastguard Worker                                                &outInfo->fMemoryAlloc)) {
123*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(), DestroyImage(device, image, nullptr));
124*c8dee2aaSAndroid Build Coastguard Worker         return false;
125*c8dee2aaSAndroid Build Coastguard Worker     }
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     if (useLazyAllocation &&
128*c8dee2aaSAndroid Build Coastguard Worker         !SkToBool(outInfo->fMemoryAlloc.fFlags & skgpu::VulkanAlloc::kLazilyAllocated_Flag)) {
129*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Failed allocate lazy vulkan memory when requested");
130*c8dee2aaSAndroid Build Coastguard Worker         skgpu::VulkanMemory::FreeImageMemory(allocator, outInfo->fMemoryAlloc);
131*c8dee2aaSAndroid Build Coastguard Worker         return false;
132*c8dee2aaSAndroid Build Coastguard Worker     }
133*c8dee2aaSAndroid Build Coastguard Worker 
134*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL_RESULT(
135*c8dee2aaSAndroid Build Coastguard Worker             sharedContext,
136*c8dee2aaSAndroid Build Coastguard Worker             result,
137*c8dee2aaSAndroid Build Coastguard Worker             BindImageMemory(
138*c8dee2aaSAndroid Build Coastguard Worker                     device, image, outInfo->fMemoryAlloc.fMemory, outInfo->fMemoryAlloc.fOffset));
139*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
140*c8dee2aaSAndroid Build Coastguard Worker         skgpu::VulkanMemory::FreeImageMemory(allocator, outInfo->fMemoryAlloc);
141*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(), DestroyImage(device, image, nullptr));
142*c8dee2aaSAndroid Build Coastguard Worker         return false;
143*c8dee2aaSAndroid Build Coastguard Worker     }
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker     outInfo->fImage = image;
146*c8dee2aaSAndroid Build Coastguard Worker     outInfo->fMutableState = sk_make_sp<MutableTextureState>(
147*c8dee2aaSAndroid Build Coastguard Worker             skgpu::MutableTextureStates::MakeVulkan(initialLayout, VK_QUEUE_FAMILY_IGNORED));
148*c8dee2aaSAndroid Build Coastguard Worker     return true;
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker 
Make(const VulkanSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,skgpu::Budgeted budgeted,sk_sp<VulkanYcbcrConversion> ycbcrConversion)151*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Texture> VulkanTexture::Make(const VulkanSharedContext* sharedContext,
152*c8dee2aaSAndroid Build Coastguard Worker                                    SkISize dimensions,
153*c8dee2aaSAndroid Build Coastguard Worker                                    const TextureInfo& info,
154*c8dee2aaSAndroid Build Coastguard Worker                                    skgpu::Budgeted budgeted,
155*c8dee2aaSAndroid Build Coastguard Worker                                    sk_sp<VulkanYcbcrConversion> ycbcrConversion) {
156*c8dee2aaSAndroid Build Coastguard Worker     CreatedImageInfo imageInfo;
157*c8dee2aaSAndroid Build Coastguard Worker     if (!MakeVkImage(sharedContext, dimensions, info, &imageInfo)) {
158*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
159*c8dee2aaSAndroid Build Coastguard Worker     }
160*c8dee2aaSAndroid Build Coastguard Worker 
161*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<Texture>(new VulkanTexture(sharedContext,
162*c8dee2aaSAndroid Build Coastguard Worker                                             dimensions,
163*c8dee2aaSAndroid Build Coastguard Worker                                             info,
164*c8dee2aaSAndroid Build Coastguard Worker                                             std::move(imageInfo.fMutableState),
165*c8dee2aaSAndroid Build Coastguard Worker                                             imageInfo.fImage,
166*c8dee2aaSAndroid Build Coastguard Worker                                             imageInfo.fMemoryAlloc,
167*c8dee2aaSAndroid Build Coastguard Worker                                             Ownership::kOwned,
168*c8dee2aaSAndroid Build Coastguard Worker                                             budgeted,
169*c8dee2aaSAndroid Build Coastguard Worker                                             std::move(ycbcrConversion)));
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker 
MakeWrapped(const VulkanSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,sk_sp<MutableTextureState> mutableState,VkImage image,const VulkanAlloc & alloc,sk_sp<VulkanYcbcrConversion> ycbcrConversion)172*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Texture> VulkanTexture::MakeWrapped(const VulkanSharedContext* sharedContext,
173*c8dee2aaSAndroid Build Coastguard Worker                                           SkISize dimensions,
174*c8dee2aaSAndroid Build Coastguard Worker                                           const TextureInfo& info,
175*c8dee2aaSAndroid Build Coastguard Worker                                           sk_sp<MutableTextureState> mutableState,
176*c8dee2aaSAndroid Build Coastguard Worker                                           VkImage image,
177*c8dee2aaSAndroid Build Coastguard Worker                                           const VulkanAlloc& alloc,
178*c8dee2aaSAndroid Build Coastguard Worker                                           sk_sp<VulkanYcbcrConversion> ycbcrConversion) {
179*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<Texture>(new VulkanTexture(sharedContext,
180*c8dee2aaSAndroid Build Coastguard Worker                                             dimensions,
181*c8dee2aaSAndroid Build Coastguard Worker                                             info,
182*c8dee2aaSAndroid Build Coastguard Worker                                             std::move(mutableState),
183*c8dee2aaSAndroid Build Coastguard Worker                                             image,
184*c8dee2aaSAndroid Build Coastguard Worker                                             alloc,
185*c8dee2aaSAndroid Build Coastguard Worker                                             Ownership::kWrapped,
186*c8dee2aaSAndroid Build Coastguard Worker                                             skgpu::Budgeted::kNo,
187*c8dee2aaSAndroid Build Coastguard Worker                                             std::move(ycbcrConversion)));
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker 
vk_format_to_aspect_flags(VkFormat format)190*c8dee2aaSAndroid Build Coastguard Worker VkImageAspectFlags vk_format_to_aspect_flags(VkFormat format) {
191*c8dee2aaSAndroid Build Coastguard Worker     switch (format) {
192*c8dee2aaSAndroid Build Coastguard Worker         case VK_FORMAT_S8_UINT:
193*c8dee2aaSAndroid Build Coastguard Worker             return VK_IMAGE_ASPECT_STENCIL_BIT;
194*c8dee2aaSAndroid Build Coastguard Worker         case VK_FORMAT_D16_UNORM:
195*c8dee2aaSAndroid Build Coastguard Worker             [[fallthrough]];
196*c8dee2aaSAndroid Build Coastguard Worker         case VK_FORMAT_D32_SFLOAT:
197*c8dee2aaSAndroid Build Coastguard Worker             return VK_IMAGE_ASPECT_DEPTH_BIT;
198*c8dee2aaSAndroid Build Coastguard Worker         case VK_FORMAT_D24_UNORM_S8_UINT:
199*c8dee2aaSAndroid Build Coastguard Worker             [[fallthrough]];
200*c8dee2aaSAndroid Build Coastguard Worker         case VK_FORMAT_D32_SFLOAT_S8_UINT:
201*c8dee2aaSAndroid Build Coastguard Worker             return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
202*c8dee2aaSAndroid Build Coastguard Worker         default:
203*c8dee2aaSAndroid Build Coastguard Worker             return VK_IMAGE_ASPECT_COLOR_BIT;
204*c8dee2aaSAndroid Build Coastguard Worker     }
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker 
setImageLayoutAndQueueIndex(VulkanCommandBuffer * cmdBuffer,VkImageLayout newLayout,VkAccessFlags dstAccessMask,VkPipelineStageFlags dstStageMask,bool byRegion,uint32_t newQueueFamilyIndex) const207*c8dee2aaSAndroid Build Coastguard Worker void VulkanTexture::setImageLayoutAndQueueIndex(VulkanCommandBuffer* cmdBuffer,
208*c8dee2aaSAndroid Build Coastguard Worker                                                 VkImageLayout newLayout,
209*c8dee2aaSAndroid Build Coastguard Worker                                                 VkAccessFlags dstAccessMask,
210*c8dee2aaSAndroid Build Coastguard Worker                                                 VkPipelineStageFlags dstStageMask,
211*c8dee2aaSAndroid Build Coastguard Worker                                                 bool byRegion,
212*c8dee2aaSAndroid Build Coastguard Worker                                                 uint32_t newQueueFamilyIndex) const {
213*c8dee2aaSAndroid Build Coastguard Worker 
214*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(newLayout == this->currentLayout() ||
215*c8dee2aaSAndroid Build Coastguard Worker              (VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
216*c8dee2aaSAndroid Build Coastguard Worker               VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout));
217*c8dee2aaSAndroid Build Coastguard Worker     VkImageLayout currentLayout = this->currentLayout();
218*c8dee2aaSAndroid Build Coastguard Worker     uint32_t currentQueueIndex = this->currentQueueFamilyIndex();
219*c8dee2aaSAndroid Build Coastguard Worker 
220*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo textureInfo;
221*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(TextureInfos::GetVulkanTextureInfo(this->textureInfo(), &textureInfo));
222*c8dee2aaSAndroid Build Coastguard Worker     auto sharedContext = static_cast<const VulkanSharedContext*>(this->sharedContext());
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     // Enable the following block on new devices to test that their lazy images stay at 0 memory use
225*c8dee2aaSAndroid Build Coastguard Worker #if 0
226*c8dee2aaSAndroid Build Coastguard Worker     auto device = sharedContext->device();
227*c8dee2aaSAndroid Build Coastguard Worker     if (fAlloc.fFlags & skgpu::VulkanAlloc::kLazilyAllocated_Flag) {
228*c8dee2aaSAndroid Build Coastguard Worker         VkDeviceSize size;
229*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(), GetDeviceMemoryCommitment(device, fAlloc.fMemory, &size));
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Lazy Image. This: %p, image: %d, size: %d\n", this, fImage, size);
232*c8dee2aaSAndroid Build Coastguard Worker     }
233*c8dee2aaSAndroid Build Coastguard Worker #endif
234*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
235*c8dee2aaSAndroid Build Coastguard Worker     if (textureInfo.fSharingMode == VK_SHARING_MODE_CONCURRENT) {
236*c8dee2aaSAndroid Build Coastguard Worker         if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) {
237*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED ||
238*c8dee2aaSAndroid Build Coastguard Worker                      currentQueueIndex == VK_QUEUE_FAMILY_EXTERNAL ||
239*c8dee2aaSAndroid Build Coastguard Worker                      currentQueueIndex == VK_QUEUE_FAMILY_FOREIGN_EXT);
240*c8dee2aaSAndroid Build Coastguard Worker         } else {
241*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
242*c8dee2aaSAndroid Build Coastguard Worker                      newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT);
243*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED);
244*c8dee2aaSAndroid Build Coastguard Worker         }
245*c8dee2aaSAndroid Build Coastguard Worker     } else {
246*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(textureInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE);
247*c8dee2aaSAndroid Build Coastguard Worker         if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED ||
248*c8dee2aaSAndroid Build Coastguard Worker             currentQueueIndex == sharedContext->queueIndex()) {
249*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED ||
250*c8dee2aaSAndroid Build Coastguard Worker                      currentQueueIndex == VK_QUEUE_FAMILY_EXTERNAL ||
251*c8dee2aaSAndroid Build Coastguard Worker                      currentQueueIndex == VK_QUEUE_FAMILY_FOREIGN_EXT ||
252*c8dee2aaSAndroid Build Coastguard Worker                      currentQueueIndex == sharedContext->queueIndex());
253*c8dee2aaSAndroid Build Coastguard Worker         } else if (newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
254*c8dee2aaSAndroid Build Coastguard Worker                    newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT) {
255*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED ||
256*c8dee2aaSAndroid Build Coastguard Worker                      currentQueueIndex == sharedContext->queueIndex());
257*c8dee2aaSAndroid Build Coastguard Worker         }
258*c8dee2aaSAndroid Build Coastguard Worker     }
259*c8dee2aaSAndroid Build Coastguard Worker #endif
260*c8dee2aaSAndroid Build Coastguard Worker 
261*c8dee2aaSAndroid Build Coastguard Worker     if (textureInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
262*c8dee2aaSAndroid Build Coastguard Worker         if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) {
263*c8dee2aaSAndroid Build Coastguard Worker             newQueueFamilyIndex = sharedContext->queueIndex();
264*c8dee2aaSAndroid Build Coastguard Worker         }
265*c8dee2aaSAndroid Build Coastguard Worker         if (currentQueueIndex == VK_QUEUE_FAMILY_IGNORED) {
266*c8dee2aaSAndroid Build Coastguard Worker             currentQueueIndex = sharedContext->queueIndex();
267*c8dee2aaSAndroid Build Coastguard Worker         }
268*c8dee2aaSAndroid Build Coastguard Worker     }
269*c8dee2aaSAndroid Build Coastguard Worker 
270*c8dee2aaSAndroid Build Coastguard Worker     // If the old and new layout are the same and the layout is a read only layout, there is no need
271*c8dee2aaSAndroid Build Coastguard Worker     // to put in a barrier unless we also need to switch queues.
272*c8dee2aaSAndroid Build Coastguard Worker     if (newLayout == currentLayout && currentQueueIndex == newQueueFamilyIndex &&
273*c8dee2aaSAndroid Build Coastguard Worker         (VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == currentLayout ||
274*c8dee2aaSAndroid Build Coastguard Worker          VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == currentLayout ||
275*c8dee2aaSAndroid Build Coastguard Worker          VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == currentLayout)) {
276*c8dee2aaSAndroid Build Coastguard Worker         return;
277*c8dee2aaSAndroid Build Coastguard Worker     }
278*c8dee2aaSAndroid Build Coastguard Worker 
279*c8dee2aaSAndroid Build Coastguard Worker     VkAccessFlags srcAccessMask = VulkanTexture::LayoutToSrcAccessMask(currentLayout);
280*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineStageFlags srcStageMask = VulkanTexture::LayoutToPipelineSrcStageFlags(currentLayout);
281*c8dee2aaSAndroid Build Coastguard Worker 
282*c8dee2aaSAndroid Build Coastguard Worker     VkImageAspectFlags aspectFlags = vk_format_to_aspect_flags(textureInfo.fFormat);
283*c8dee2aaSAndroid Build Coastguard Worker     uint32_t numMipLevels = 1;
284*c8dee2aaSAndroid Build Coastguard Worker     SkISize dimensions = this->dimensions();
285*c8dee2aaSAndroid Build Coastguard Worker     if (this->mipmapped() == Mipmapped::kYes) {
286*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
287*c8dee2aaSAndroid Build Coastguard Worker     }
288*c8dee2aaSAndroid Build Coastguard Worker     VkImageMemoryBarrier imageMemoryBarrier = {
289*c8dee2aaSAndroid Build Coastguard Worker         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
290*c8dee2aaSAndroid Build Coastguard Worker         nullptr,                                         // pNext
291*c8dee2aaSAndroid Build Coastguard Worker         srcAccessMask,                                   // srcAccessMask
292*c8dee2aaSAndroid Build Coastguard Worker         dstAccessMask,                                   // dstAccessMask
293*c8dee2aaSAndroid Build Coastguard Worker         currentLayout,                                   // oldLayout
294*c8dee2aaSAndroid Build Coastguard Worker         newLayout,                                       // newLayout
295*c8dee2aaSAndroid Build Coastguard Worker         currentQueueIndex,                               // srcQueueFamilyIndex
296*c8dee2aaSAndroid Build Coastguard Worker         newQueueFamilyIndex,                             // dstQueueFamilyIndex
297*c8dee2aaSAndroid Build Coastguard Worker         fImage,                                          // image
298*c8dee2aaSAndroid Build Coastguard Worker         { aspectFlags, 0, numMipLevels, 0, 1 }           // subresourceRange
299*c8dee2aaSAndroid Build Coastguard Worker     };
300*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(srcAccessMask == imageMemoryBarrier.srcAccessMask);
301*c8dee2aaSAndroid Build Coastguard Worker     cmdBuffer->addImageMemoryBarrier(this, srcStageMask, dstStageMask, byRegion,
302*c8dee2aaSAndroid Build Coastguard Worker                                      &imageMemoryBarrier);
303*c8dee2aaSAndroid Build Coastguard Worker 
304*c8dee2aaSAndroid Build Coastguard Worker     skgpu::MutableTextureStates::SetVkImageLayout(this->mutableState(), newLayout);
305*c8dee2aaSAndroid Build Coastguard Worker     skgpu::MutableTextureStates::SetVkQueueFamilyIndex(this->mutableState(), newQueueFamilyIndex);
306*c8dee2aaSAndroid Build Coastguard Worker }
307*c8dee2aaSAndroid Build Coastguard Worker 
VulkanTexture(const VulkanSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,sk_sp<MutableTextureState> mutableState,VkImage image,const VulkanAlloc & alloc,Ownership ownership,skgpu::Budgeted budgeted,sk_sp<VulkanYcbcrConversion> ycbcrConversion)308*c8dee2aaSAndroid Build Coastguard Worker VulkanTexture::VulkanTexture(const VulkanSharedContext* sharedContext,
309*c8dee2aaSAndroid Build Coastguard Worker                              SkISize dimensions,
310*c8dee2aaSAndroid Build Coastguard Worker                              const TextureInfo& info,
311*c8dee2aaSAndroid Build Coastguard Worker                              sk_sp<MutableTextureState> mutableState,
312*c8dee2aaSAndroid Build Coastguard Worker                              VkImage image,
313*c8dee2aaSAndroid Build Coastguard Worker                              const VulkanAlloc& alloc,
314*c8dee2aaSAndroid Build Coastguard Worker                              Ownership ownership,
315*c8dee2aaSAndroid Build Coastguard Worker                              skgpu::Budgeted budgeted,
316*c8dee2aaSAndroid Build Coastguard Worker                              sk_sp<VulkanYcbcrConversion> ycbcrConversion)
317*c8dee2aaSAndroid Build Coastguard Worker         : Texture(sharedContext, dimensions, info, std::move(mutableState), ownership, budgeted)
318*c8dee2aaSAndroid Build Coastguard Worker         , fImage(image)
319*c8dee2aaSAndroid Build Coastguard Worker         , fMemoryAlloc(alloc)
320*c8dee2aaSAndroid Build Coastguard Worker         , fYcbcrConversion(std::move(ycbcrConversion)) {}
321*c8dee2aaSAndroid Build Coastguard Worker 
freeGpuData()322*c8dee2aaSAndroid Build Coastguard Worker void VulkanTexture::freeGpuData() {
323*c8dee2aaSAndroid Build Coastguard Worker     // Need to delete any ImageViews first
324*c8dee2aaSAndroid Build Coastguard Worker     fImageViews.clear();
325*c8dee2aaSAndroid Build Coastguard Worker 
326*c8dee2aaSAndroid Build Coastguard Worker     // If the texture is wrapped we don't own this data
327*c8dee2aaSAndroid Build Coastguard Worker     if (this->ownership() != Ownership::kWrapped) {
328*c8dee2aaSAndroid Build Coastguard Worker         auto sharedContext = static_cast<const VulkanSharedContext*>(this->sharedContext());
329*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(),
330*c8dee2aaSAndroid Build Coastguard Worker                     DestroyImage(sharedContext->device(), fImage, nullptr));
331*c8dee2aaSAndroid Build Coastguard Worker         skgpu::VulkanMemory::FreeImageMemory(sharedContext->memoryAllocator(), fMemoryAlloc);
332*c8dee2aaSAndroid Build Coastguard Worker     }
333*c8dee2aaSAndroid Build Coastguard Worker }
334*c8dee2aaSAndroid Build Coastguard Worker 
updateImageLayout(VkImageLayout newLayout)335*c8dee2aaSAndroid Build Coastguard Worker void VulkanTexture::updateImageLayout(VkImageLayout newLayout) {
336*c8dee2aaSAndroid Build Coastguard Worker     skgpu::MutableTextureStates::SetVkImageLayout(this->mutableState(), newLayout);
337*c8dee2aaSAndroid Build Coastguard Worker }
338*c8dee2aaSAndroid Build Coastguard Worker 
currentLayout() const339*c8dee2aaSAndroid Build Coastguard Worker VkImageLayout VulkanTexture::currentLayout() const {
340*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::MutableTextureStates::GetVkImageLayout(this->mutableState());
341*c8dee2aaSAndroid Build Coastguard Worker }
342*c8dee2aaSAndroid Build Coastguard Worker 
currentQueueFamilyIndex() const343*c8dee2aaSAndroid Build Coastguard Worker uint32_t VulkanTexture::currentQueueFamilyIndex() const {
344*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::MutableTextureStates::GetVkQueueFamilyIndex(this->mutableState());
345*c8dee2aaSAndroid Build Coastguard Worker }
346*c8dee2aaSAndroid Build Coastguard Worker 
LayoutToPipelineSrcStageFlags(const VkImageLayout layout)347*c8dee2aaSAndroid Build Coastguard Worker VkPipelineStageFlags VulkanTexture::LayoutToPipelineSrcStageFlags(const VkImageLayout layout) {
348*c8dee2aaSAndroid Build Coastguard Worker     if (VK_IMAGE_LAYOUT_GENERAL == layout) {
349*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
350*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
351*c8dee2aaSAndroid Build Coastguard Worker                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
352*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_TRANSFER_BIT;
353*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
354*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
355*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout ||
356*c8dee2aaSAndroid Build Coastguard Worker                VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout) {
357*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
358*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
359*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
360*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
361*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_HOST_BIT;
362*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout) {
363*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
364*c8dee2aaSAndroid Build Coastguard Worker     }
365*c8dee2aaSAndroid Build Coastguard Worker 
366*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout);
367*c8dee2aaSAndroid Build Coastguard Worker     return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
368*c8dee2aaSAndroid Build Coastguard Worker }
369*c8dee2aaSAndroid Build Coastguard Worker 
LayoutToSrcAccessMask(const VkImageLayout layout)370*c8dee2aaSAndroid Build Coastguard Worker VkAccessFlags VulkanTexture::LayoutToSrcAccessMask(const VkImageLayout layout) {
371*c8dee2aaSAndroid Build Coastguard Worker     // Currently we assume we will never being doing any explict shader writes (this doesn't include
372*c8dee2aaSAndroid Build Coastguard Worker     // color attachment or depth/stencil writes). So we will ignore the
373*c8dee2aaSAndroid Build Coastguard Worker     // VK_MEMORY_OUTPUT_SHADER_WRITE_BIT.
374*c8dee2aaSAndroid Build Coastguard Worker 
375*c8dee2aaSAndroid Build Coastguard Worker     // We can only directly access the host memory if we are in preinitialized or general layout,
376*c8dee2aaSAndroid Build Coastguard Worker     // and the image is linear.
377*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Add check for linear here so we are not always adding host to general, and we should
378*c8dee2aaSAndroid Build Coastguard Worker     //       only be in preinitialized if we are linear
379*c8dee2aaSAndroid Build Coastguard Worker     VkAccessFlags flags = 0;
380*c8dee2aaSAndroid Build Coastguard Worker     if (VK_IMAGE_LAYOUT_GENERAL == layout) {
381*c8dee2aaSAndroid Build Coastguard Worker         flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
382*c8dee2aaSAndroid Build Coastguard Worker                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
383*c8dee2aaSAndroid Build Coastguard Worker                 VK_ACCESS_TRANSFER_WRITE_BIT |
384*c8dee2aaSAndroid Build Coastguard Worker                 VK_ACCESS_HOST_WRITE_BIT;
385*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
386*c8dee2aaSAndroid Build Coastguard Worker         flags = VK_ACCESS_HOST_WRITE_BIT;
387*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
388*c8dee2aaSAndroid Build Coastguard Worker         flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
389*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) {
390*c8dee2aaSAndroid Build Coastguard Worker         flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
391*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
392*c8dee2aaSAndroid Build Coastguard Worker         flags = VK_ACCESS_TRANSFER_WRITE_BIT;
393*c8dee2aaSAndroid Build Coastguard Worker     } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
394*c8dee2aaSAndroid Build Coastguard Worker                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout ||
395*c8dee2aaSAndroid Build Coastguard Worker                VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout) {
396*c8dee2aaSAndroid Build Coastguard Worker         // There are no writes that need to be made available
397*c8dee2aaSAndroid Build Coastguard Worker         flags = 0;
398*c8dee2aaSAndroid Build Coastguard Worker     }
399*c8dee2aaSAndroid Build Coastguard Worker     return flags;
400*c8dee2aaSAndroid Build Coastguard Worker }
401*c8dee2aaSAndroid Build Coastguard Worker 
getImageView(VulkanImageView::Usage usage) const402*c8dee2aaSAndroid Build Coastguard Worker const VulkanImageView* VulkanTexture::getImageView(VulkanImageView::Usage usage) const {
403*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fImageViews.size(); ++i) {
404*c8dee2aaSAndroid Build Coastguard Worker         if (fImageViews[i]->usage() == usage) {
405*c8dee2aaSAndroid Build Coastguard Worker             return fImageViews[i].get();
406*c8dee2aaSAndroid Build Coastguard Worker         }
407*c8dee2aaSAndroid Build Coastguard Worker     }
408*c8dee2aaSAndroid Build Coastguard Worker 
409*c8dee2aaSAndroid Build Coastguard Worker     auto sharedContext = static_cast<const VulkanSharedContext*>(this->sharedContext());
410*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkTexInfo;
411*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(TextureInfos::GetVulkanTextureInfo(this->textureInfo(), &vkTexInfo));
412*c8dee2aaSAndroid Build Coastguard Worker     int miplevels = this->textureInfo().mipmapped() == Mipmapped::kYes
413*c8dee2aaSAndroid Build Coastguard Worker                     ? SkMipmap::ComputeLevelCount(this->dimensions().width(),
414*c8dee2aaSAndroid Build Coastguard Worker                                                   this->dimensions().height()) + 1
415*c8dee2aaSAndroid Build Coastguard Worker                     : 1;
416*c8dee2aaSAndroid Build Coastguard Worker     auto imageView = VulkanImageView::Make(sharedContext,
417*c8dee2aaSAndroid Build Coastguard Worker                                            fImage,
418*c8dee2aaSAndroid Build Coastguard Worker                                            vkTexInfo.fFormat,
419*c8dee2aaSAndroid Build Coastguard Worker                                            usage,
420*c8dee2aaSAndroid Build Coastguard Worker                                            miplevels,
421*c8dee2aaSAndroid Build Coastguard Worker                                            fYcbcrConversion);
422*c8dee2aaSAndroid Build Coastguard Worker     return fImageViews.push_back(std::move(imageView)).get();
423*c8dee2aaSAndroid Build Coastguard Worker }
424*c8dee2aaSAndroid Build Coastguard Worker 
supportsInputAttachmentUsage() const425*c8dee2aaSAndroid Build Coastguard Worker bool VulkanTexture::supportsInputAttachmentUsage() const {
426*c8dee2aaSAndroid Build Coastguard Worker     return (TextureInfos::GetVkUsageFlags(this->textureInfo()) &
427*c8dee2aaSAndroid Build Coastguard Worker             VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
428*c8dee2aaSAndroid Build Coastguard Worker }
429*c8dee2aaSAndroid Build Coastguard Worker 
430*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
431