Coverage Report

Created: 2024-05-20 07:14

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