xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanCaps.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/VulkanCaps.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextureCompressionType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/ContextOptions.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/TextureInfo.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanExtensions.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanTypes.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextUtils.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/GraphicsPipelineDesc.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/GraphiteResourceKey.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RenderPassDesc.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RendererProvider.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RuntimeEffectDictionary.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteTypesPriv.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanRenderPass.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanSharedContext.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanYcbcrConversion.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanUtilsPriv.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLUtil.h"
29*c8dee2aaSAndroid Build Coastguard Worker 
30*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
31*c8dee2aaSAndroid Build Coastguard Worker #include <sys/system_properties.h>
32*c8dee2aaSAndroid Build Coastguard Worker #endif
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
35*c8dee2aaSAndroid Build Coastguard Worker 
VulkanCaps(const ContextOptions & contextOptions,const skgpu::VulkanInterface * vkInterface,VkPhysicalDevice physDev,uint32_t physicalDeviceVersion,const VkPhysicalDeviceFeatures2 * features,const skgpu::VulkanExtensions * extensions,Protected isProtected)36*c8dee2aaSAndroid Build Coastguard Worker VulkanCaps::VulkanCaps(const ContextOptions& contextOptions,
37*c8dee2aaSAndroid Build Coastguard Worker                        const skgpu::VulkanInterface* vkInterface,
38*c8dee2aaSAndroid Build Coastguard Worker                        VkPhysicalDevice physDev,
39*c8dee2aaSAndroid Build Coastguard Worker                        uint32_t physicalDeviceVersion,
40*c8dee2aaSAndroid Build Coastguard Worker                        const VkPhysicalDeviceFeatures2* features,
41*c8dee2aaSAndroid Build Coastguard Worker                        const skgpu::VulkanExtensions* extensions,
42*c8dee2aaSAndroid Build Coastguard Worker                        Protected isProtected)
43*c8dee2aaSAndroid Build Coastguard Worker         : Caps() {
44*c8dee2aaSAndroid Build Coastguard Worker     this->init(contextOptions, vkInterface, physDev, physicalDeviceVersion, features, extensions,
45*c8dee2aaSAndroid Build Coastguard Worker                isProtected);
46*c8dee2aaSAndroid Build Coastguard Worker }
47*c8dee2aaSAndroid Build Coastguard Worker 
~VulkanCaps()48*c8dee2aaSAndroid Build Coastguard Worker VulkanCaps::~VulkanCaps() {}
49*c8dee2aaSAndroid Build Coastguard Worker 
init(const ContextOptions & contextOptions,const skgpu::VulkanInterface * vkInterface,VkPhysicalDevice physDev,uint32_t physicalDeviceVersion,const VkPhysicalDeviceFeatures2 * features,const skgpu::VulkanExtensions * extensions,Protected isProtected)50*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::init(const ContextOptions& contextOptions,
51*c8dee2aaSAndroid Build Coastguard Worker                       const skgpu::VulkanInterface* vkInterface,
52*c8dee2aaSAndroid Build Coastguard Worker                       VkPhysicalDevice physDev,
53*c8dee2aaSAndroid Build Coastguard Worker                       uint32_t physicalDeviceVersion,
54*c8dee2aaSAndroid Build Coastguard Worker                       const VkPhysicalDeviceFeatures2* features,
55*c8dee2aaSAndroid Build Coastguard Worker                       const skgpu::VulkanExtensions* extensions,
56*c8dee2aaSAndroid Build Coastguard Worker                       Protected isProtected) {
57*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceProperties physDevProperties;
58*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &physDevProperties));
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
61*c8dee2aaSAndroid Build Coastguard Worker     this->setDeviceName(physDevProperties.deviceName);
62*c8dee2aaSAndroid Build Coastguard Worker #endif
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     // Graphite requires Vulkan version 1.1 or later, which always has protected support.
65*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected == Protected::kYes) {
66*c8dee2aaSAndroid Build Coastguard Worker         fProtectedSupport = true;
67*c8dee2aaSAndroid Build Coastguard Worker         fShouldAlwaysUseDedicatedImageMemory = true;
68*c8dee2aaSAndroid Build Coastguard Worker     }
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker     fPhysicalDeviceMemoryProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
71*c8dee2aaSAndroid Build Coastguard Worker     fPhysicalDeviceMemoryProperties2.pNext = nullptr;
72*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL(vkInterface,
73*c8dee2aaSAndroid Build Coastguard Worker                 GetPhysicalDeviceMemoryProperties2(physDev, &fPhysicalDeviceMemoryProperties2));
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker     // We could actually query and get a max size for each config, however maxImageDimension2D will
76*c8dee2aaSAndroid Build Coastguard Worker     // give the minimum max size across all configs. So for simplicity we will use that for now.
77*c8dee2aaSAndroid Build Coastguard Worker     fMaxTextureSize = std::min(physDevProperties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     fRequiredUniformBufferAlignment = physDevProperties.limits.minUniformBufferOffsetAlignment;
80*c8dee2aaSAndroid Build Coastguard Worker     fRequiredStorageBufferAlignment =  physDevProperties.limits.minStorageBufferOffsetAlignment;
81*c8dee2aaSAndroid Build Coastguard Worker     fRequiredTransferBufferAlignment = 4;
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker     // Unlike D3D, WebGPU, and Metal, the Vulkan NDC coordinate space is aligned with the top-left
84*c8dee2aaSAndroid Build Coastguard Worker     // Y-down coordinate space of the viewport.
85*c8dee2aaSAndroid Build Coastguard Worker     fNDCYAxisPointsDown = true;
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fUniformBufferLayout = Layout::kStd140;
88*c8dee2aaSAndroid Build Coastguard Worker     // We can enable std430 and ensure no array stride mismatch in functions because all bound
89*c8dee2aaSAndroid Build Coastguard Worker     // buffers will either be a UBO or SSBO, depending on if storage buffers are enabled or not.
90*c8dee2aaSAndroid Build Coastguard Worker     // Although intrinsic uniforms always use uniform buffers, they do not contain any arrays.
91*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fStorageBufferLayout = Layout::kStd430;
92*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fSeparateTextureAndSamplerBinding = false;
93*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fDistinctIndexRanges = false;
94*c8dee2aaSAndroid Build Coastguard Worker 
95*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fIntrinsicBufferBinding =
96*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kIntrinsicUniformBufferIndex;
97*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fRenderStepBufferBinding =
98*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kRenderStepUniformBufferIndex;
99*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fPaintParamsBufferBinding =
100*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kPaintUniformBufferIndex;
101*c8dee2aaSAndroid Build Coastguard Worker     fResourceBindingReqs.fGradientBufferBinding =
102*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kGradientBufferIndex;
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker     // TODO(b/353983969): Enable storage buffers once perf regressions are addressed.
105*c8dee2aaSAndroid Build Coastguard Worker     fStorageBufferSupport = false;
106*c8dee2aaSAndroid Build Coastguard Worker 
107*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
108*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &deviceMemoryProperties));
109*c8dee2aaSAndroid Build Coastguard Worker     fSupportsMemorylessAttachments = false;
110*c8dee2aaSAndroid Build Coastguard Worker     VkMemoryPropertyFlags requiredLazyFlags = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
111*c8dee2aaSAndroid Build Coastguard Worker     if (fProtectedSupport) {
112*c8dee2aaSAndroid Build Coastguard Worker         // If we have a protected context we can only use memoryless images if they also support
113*c8dee2aaSAndroid Build Coastguard Worker         // being protected. With current devices we don't actually expect this combination to be
114*c8dee2aaSAndroid Build Coastguard Worker         // supported, but this at least covers us for future devices that may allow it.
115*c8dee2aaSAndroid Build Coastguard Worker         requiredLazyFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
116*c8dee2aaSAndroid Build Coastguard Worker     }
117*c8dee2aaSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; ++i) {
118*c8dee2aaSAndroid Build Coastguard Worker         const uint32_t& supportedFlags = deviceMemoryProperties.memoryTypes[i].propertyFlags;
119*c8dee2aaSAndroid Build Coastguard Worker         if ((supportedFlags & requiredLazyFlags) == requiredLazyFlags) {
120*c8dee2aaSAndroid Build Coastguard Worker             fSupportsMemorylessAttachments = true;
121*c8dee2aaSAndroid Build Coastguard Worker         }
122*c8dee2aaSAndroid Build Coastguard Worker     }
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_UNIX
125*c8dee2aaSAndroid Build Coastguard Worker     if (kNvidia_VkVendor == physDevProperties.vendorID) {
126*c8dee2aaSAndroid Build Coastguard Worker         // On NVIDIA linux we see a big perf regression when not using dedicated image allocations.
127*c8dee2aaSAndroid Build Coastguard Worker         fShouldAlwaysUseDedicatedImageMemory = true;
128*c8dee2aaSAndroid Build Coastguard Worker     }
129*c8dee2aaSAndroid Build Coastguard Worker #endif
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker     if (physDevProperties.vendorID == kNvidia_VkVendor ||
132*c8dee2aaSAndroid Build Coastguard Worker         physDevProperties.vendorID == kAMD_VkVendor) {
133*c8dee2aaSAndroid Build Coastguard Worker         // On discrete GPUs, it can be faster to read gpu-only memory compared to memory that is
134*c8dee2aaSAndroid Build Coastguard Worker         // also mappable on the host.
135*c8dee2aaSAndroid Build Coastguard Worker         fGpuOnlyBuffersMorePerformant = true;
136*c8dee2aaSAndroid Build Coastguard Worker 
137*c8dee2aaSAndroid Build Coastguard Worker         // On discrete GPUs we try to use special DEVICE_LOCAL and HOST_VISIBLE memory for our
138*c8dee2aaSAndroid Build Coastguard Worker         // cpu write, gpu read buffers. This memory is not ideal to be kept persistently mapped.
139*c8dee2aaSAndroid Build Coastguard Worker         // Some discrete GPUs do not expose this special memory, however we still disable
140*c8dee2aaSAndroid Build Coastguard Worker         // persistently mapped buffers for all of them since most GPUs with updated drivers do
141*c8dee2aaSAndroid Build Coastguard Worker         // expose it. If this becomes an issue we can try to be more fine grained.
142*c8dee2aaSAndroid Build Coastguard Worker         fShouldPersistentlyMapCpuToGpuBuffers = false;
143*c8dee2aaSAndroid Build Coastguard Worker     }
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker     if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
146*c8dee2aaSAndroid Build Coastguard Worker         this->applyDriverCorrectnessWorkarounds(physDevProperties);
147*c8dee2aaSAndroid Build Coastguard Worker     }
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     if (physDevProperties.vendorID == kAMD_VkVendor) {
150*c8dee2aaSAndroid Build Coastguard Worker         // AMD advertises support for MAX_UINT vertex attributes but in reality only supports 32.
151*c8dee2aaSAndroid Build Coastguard Worker         fMaxVertexAttributes = 32;
152*c8dee2aaSAndroid Build Coastguard Worker     } else {
153*c8dee2aaSAndroid Build Coastguard Worker         fMaxVertexAttributes = physDevProperties.limits.maxVertexInputAttributes;
154*c8dee2aaSAndroid Build Coastguard Worker     }
155*c8dee2aaSAndroid Build Coastguard Worker     fMaxUniformBufferRange = physDevProperties.limits.maxUniformBufferRange;
156*c8dee2aaSAndroid Build Coastguard Worker     fMaxStorageBufferRange = physDevProperties.limits.maxStorageBufferRange;
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
159*c8dee2aaSAndroid Build Coastguard Worker     if (extensions->hasExtension(
160*c8dee2aaSAndroid Build Coastguard Worker             VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2)) {
161*c8dee2aaSAndroid Build Coastguard Worker         fSupportsAHardwareBufferImages = true;
162*c8dee2aaSAndroid Build Coastguard Worker     }
163*c8dee2aaSAndroid Build Coastguard Worker #endif
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     // Determine whether the client enabled certain physical device features.
166*c8dee2aaSAndroid Build Coastguard Worker     if (features) {
167*c8dee2aaSAndroid Build Coastguard Worker         auto ycbcrFeatures =
168*c8dee2aaSAndroid Build Coastguard Worker                 skgpu::GetExtensionFeatureStruct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
169*c8dee2aaSAndroid Build Coastguard Worker                         *features,
170*c8dee2aaSAndroid Build Coastguard Worker                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
171*c8dee2aaSAndroid Build Coastguard Worker         if (ycbcrFeatures && ycbcrFeatures->samplerYcbcrConversion) {
172*c8dee2aaSAndroid Build Coastguard Worker             fSupportsYcbcrConversion = true;
173*c8dee2aaSAndroid Build Coastguard Worker         }
174*c8dee2aaSAndroid Build Coastguard Worker     }
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker     if (extensions->hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) {
177*c8dee2aaSAndroid Build Coastguard Worker         fSupportsDeviceFaultInfo = true;
178*c8dee2aaSAndroid Build Coastguard Worker     }
179*c8dee2aaSAndroid Build Coastguard Worker 
180*c8dee2aaSAndroid Build Coastguard Worker     // TODO(skia:14639): We must force std430 array stride when using SSBOs since SPIR-V generation
181*c8dee2aaSAndroid Build Coastguard Worker     // cannot handle mixed array strides being passed into functions.
182*c8dee2aaSAndroid Build Coastguard Worker     fShaderCaps->fForceStd430ArrayLayout =
183*c8dee2aaSAndroid Build Coastguard Worker             fStorageBufferSupport && fResourceBindingReqs.fStorageBufferLayout == Layout::kStd430;
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker     if (features && features->features.dualSrcBlend) {
186*c8dee2aaSAndroid Build Coastguard Worker         fShaderCaps->fDualSourceBlendingSupport = true;
187*c8dee2aaSAndroid Build Coastguard Worker     }
188*c8dee2aaSAndroid Build Coastguard Worker 
189*c8dee2aaSAndroid Build Coastguard Worker     // Note that format table initialization should be performed at the end of this method to ensure
190*c8dee2aaSAndroid Build Coastguard Worker     // all capability determinations are completed prior to populating the format tables.
191*c8dee2aaSAndroid Build Coastguard Worker     this->initFormatTable(vkInterface, physDev, physDevProperties);
192*c8dee2aaSAndroid Build Coastguard Worker     this->initDepthStencilFormatTable(vkInterface, physDev, physDevProperties);
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     this->finishInitialization(contextOptions);
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker 
applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties & properties)197*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) {
198*c8dee2aaSAndroid Build Coastguard Worker     // By default, we initialize the Android API version to 0 since we consider certain things
199*c8dee2aaSAndroid Build Coastguard Worker     // "fixed" only once above a certain version. This way, we default to enabling the workarounds.
200*c8dee2aaSAndroid Build Coastguard Worker     int androidAPIVersion = 0;
201*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_ANDROID)
202*c8dee2aaSAndroid Build Coastguard Worker     char androidAPIVersionStr[PROP_VALUE_MAX];
203*c8dee2aaSAndroid Build Coastguard Worker     int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersionStr);
204*c8dee2aaSAndroid Build Coastguard Worker     // Defaults to zero since most checks care if it is greater than a specific value. So this will
205*c8dee2aaSAndroid Build Coastguard Worker     // just default to it being less.
206*c8dee2aaSAndroid Build Coastguard Worker     androidAPIVersion = (strLength == 0) ? 0 : atoi(androidAPIVersionStr);
207*c8dee2aaSAndroid Build Coastguard Worker #endif
208*c8dee2aaSAndroid Build Coastguard Worker 
209*c8dee2aaSAndroid Build Coastguard Worker     // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
210*c8dee2aaSAndroid Build Coastguard Worker     if (kARM_VkVendor == properties.vendorID && androidAPIVersion <= 28) {
211*c8dee2aaSAndroid Build Coastguard Worker         fShouldAlwaysUseDedicatedImageMemory = true;
212*c8dee2aaSAndroid Build Coastguard Worker     }
213*c8dee2aaSAndroid Build Coastguard Worker 
214*c8dee2aaSAndroid Build Coastguard Worker     // On Qualcomm the gpu resolves an area larger than the render pass bounds when using
215*c8dee2aaSAndroid Build Coastguard Worker     // discardable msaa attachments. This causes the resolve to resolve uninitialized data from the
216*c8dee2aaSAndroid Build Coastguard Worker     // msaa image into the resolve image. This was reproed on a Pixel4 using the DstReadShuffle GM
217*c8dee2aaSAndroid Build Coastguard Worker     // where the top half of the GM would drop out. In Ganesh we had also seen this on Arm devices,
218*c8dee2aaSAndroid Build Coastguard Worker     // but the issue hasn't appeared yet in Graphite. It may just have occured on older Arm drivers
219*c8dee2aaSAndroid Build Coastguard Worker     // that we don't even test any more. This also occurs on swiftshader: b/303705884 in Ganesh, but
220*c8dee2aaSAndroid Build Coastguard Worker     // we aren't currently testing that in Graphite yet so leaving that off the workaround for now
221*c8dee2aaSAndroid Build Coastguard Worker     // until we run into it.
222*c8dee2aaSAndroid Build Coastguard Worker     if (kQualcomm_VkVendor == properties.vendorID) {
223*c8dee2aaSAndroid Build Coastguard Worker         fMustLoadFullImageForMSAA = true;
224*c8dee2aaSAndroid Build Coastguard Worker     }
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker 
227*c8dee2aaSAndroid Build Coastguard Worker // These are all the valid VkFormats that we support in Skia. They are roughly ordered from most
228*c8dee2aaSAndroid Build Coastguard Worker // frequently used to least to improve look up times in arrays.
229*c8dee2aaSAndroid Build Coastguard Worker static constexpr VkFormat kVkFormats[] = {
230*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R8G8B8A8_UNORM,
231*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R8_UNORM,
232*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_B8G8R8A8_UNORM,
233*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R5G6B5_UNORM_PACK16,
234*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R16G16B16A16_SFLOAT,
235*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R16_SFLOAT,
236*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R8G8B8_UNORM,
237*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R8G8_UNORM,
238*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_A2B10G10R10_UNORM_PACK32,
239*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_A2R10G10B10_UNORM_PACK32,
240*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_B4G4R4A4_UNORM_PACK16,
241*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R4G4B4A4_UNORM_PACK16,
242*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R8G8B8A8_SRGB,
243*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
244*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_BC1_RGB_UNORM_BLOCK,
245*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
246*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R16_UNORM,
247*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R16G16_UNORM,
248*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
249*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
250*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R16G16B16A16_UNORM,
251*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_R16G16_SFLOAT,
252*c8dee2aaSAndroid Build Coastguard Worker };
253*c8dee2aaSAndroid Build Coastguard Worker // These are all the valid depth/stencil formats that we support in Skia.
254*c8dee2aaSAndroid Build Coastguard Worker static constexpr VkFormat kDepthStencilVkFormats[] = {
255*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_S8_UINT,
256*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_D16_UNORM,
257*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_D32_SFLOAT,
258*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_D24_UNORM_S8_UINT,
259*c8dee2aaSAndroid Build Coastguard Worker     VK_FORMAT_D32_SFLOAT_S8_UINT,
260*c8dee2aaSAndroid Build Coastguard Worker };
261*c8dee2aaSAndroid Build Coastguard Worker 
getDefaultSampledTextureInfo(SkColorType ct,Mipmapped mipmapped,Protected isProtected,Renderable isRenderable) const262*c8dee2aaSAndroid Build Coastguard Worker TextureInfo VulkanCaps::getDefaultSampledTextureInfo(SkColorType ct,
263*c8dee2aaSAndroid Build Coastguard Worker                                                      Mipmapped mipmapped,
264*c8dee2aaSAndroid Build Coastguard Worker                                                      Protected isProtected,
265*c8dee2aaSAndroid Build Coastguard Worker                                                      Renderable isRenderable) const {
266*c8dee2aaSAndroid Build Coastguard Worker     VkFormat format = this->getFormatFromColorType(ct);
267*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& formatInfo = this->getFormatInfo(format);
268*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int defaultSampleCount = 1;
269*c8dee2aaSAndroid Build Coastguard Worker     if ((isProtected == Protected::kYes && !this->protectedSupport()) ||
270*c8dee2aaSAndroid Build Coastguard Worker         !formatInfo.isTexturable(VK_IMAGE_TILING_OPTIMAL) ||
271*c8dee2aaSAndroid Build Coastguard Worker         (isRenderable == Renderable::kYes &&
272*c8dee2aaSAndroid Build Coastguard Worker          !formatInfo.isRenderable(VK_IMAGE_TILING_OPTIMAL, defaultSampleCount)) ) {
273*c8dee2aaSAndroid Build Coastguard Worker         return {};
274*c8dee2aaSAndroid Build Coastguard Worker     }
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo info;
277*c8dee2aaSAndroid Build Coastguard Worker     info.fSampleCount = defaultSampleCount;
278*c8dee2aaSAndroid Build Coastguard Worker     info.fMipmapped = mipmapped;
279*c8dee2aaSAndroid Build Coastguard Worker     info.fFlags = (isProtected == Protected::kYes) ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
280*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = format;
281*c8dee2aaSAndroid Build Coastguard Worker     info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
282*c8dee2aaSAndroid Build Coastguard Worker     info.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
283*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
284*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_TRANSFER_DST_BIT;
285*c8dee2aaSAndroid Build Coastguard Worker     if (isRenderable == Renderable::kYes) {
286*c8dee2aaSAndroid Build Coastguard Worker         // We make all renderable images support being used as input attachment
287*c8dee2aaSAndroid Build Coastguard Worker         info.fImageUsageFlags = info.fImageUsageFlags |
288*c8dee2aaSAndroid Build Coastguard Worker                                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
289*c8dee2aaSAndroid Build Coastguard Worker                                 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
290*c8dee2aaSAndroid Build Coastguard Worker     }
291*c8dee2aaSAndroid Build Coastguard Worker     info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
292*c8dee2aaSAndroid Build Coastguard Worker     info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
293*c8dee2aaSAndroid Build Coastguard Worker 
294*c8dee2aaSAndroid Build Coastguard Worker     return TextureInfos::MakeVulkan(info);
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker 
getTextureInfoForSampledCopy(const TextureInfo & textureInfo,Mipmapped mipmapped) const297*c8dee2aaSAndroid Build Coastguard Worker TextureInfo VulkanCaps::getTextureInfoForSampledCopy(const TextureInfo& textureInfo,
298*c8dee2aaSAndroid Build Coastguard Worker                                                      Mipmapped mipmapped) const {
299*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo info;
300*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(textureInfo, &info)) {
301*c8dee2aaSAndroid Build Coastguard Worker         return {};
302*c8dee2aaSAndroid Build Coastguard Worker     }
303*c8dee2aaSAndroid Build Coastguard Worker 
304*c8dee2aaSAndroid Build Coastguard Worker     info.fSampleCount = 1;
305*c8dee2aaSAndroid Build Coastguard Worker     info.fMipmapped = mipmapped;
306*c8dee2aaSAndroid Build Coastguard Worker     info.fFlags =
307*c8dee2aaSAndroid Build Coastguard Worker             (textureInfo.isProtected() == Protected::kYes) ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
308*c8dee2aaSAndroid Build Coastguard Worker     info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
309*c8dee2aaSAndroid Build Coastguard Worker     info.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
310*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_TRANSFER_DST_BIT;
311*c8dee2aaSAndroid Build Coastguard Worker     info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
312*c8dee2aaSAndroid Build Coastguard Worker 
313*c8dee2aaSAndroid Build Coastguard Worker     return TextureInfos::MakeVulkan(info);
314*c8dee2aaSAndroid Build Coastguard Worker }
315*c8dee2aaSAndroid Build Coastguard Worker 
316*c8dee2aaSAndroid Build Coastguard Worker namespace {
format_from_compression(SkTextureCompressionType compression)317*c8dee2aaSAndroid Build Coastguard Worker VkFormat format_from_compression(SkTextureCompressionType compression) {
318*c8dee2aaSAndroid Build Coastguard Worker     switch (compression) {
319*c8dee2aaSAndroid Build Coastguard Worker         case SkTextureCompressionType::kETC2_RGB8_UNORM:
320*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
321*c8dee2aaSAndroid Build Coastguard Worker         case SkTextureCompressionType::kBC1_RGB8_UNORM:
322*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
323*c8dee2aaSAndroid Build Coastguard Worker         case SkTextureCompressionType::kBC1_RGBA8_UNORM:
324*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
325*c8dee2aaSAndroid Build Coastguard Worker         default:
326*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_UNDEFINED;
327*c8dee2aaSAndroid Build Coastguard Worker     }
328*c8dee2aaSAndroid Build Coastguard Worker }
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker 
getDefaultCompressedTextureInfo(SkTextureCompressionType compression,Mipmapped mipmapped,Protected isProtected) const331*c8dee2aaSAndroid Build Coastguard Worker TextureInfo VulkanCaps::getDefaultCompressedTextureInfo(SkTextureCompressionType compression,
332*c8dee2aaSAndroid Build Coastguard Worker                                                         Mipmapped mipmapped,
333*c8dee2aaSAndroid Build Coastguard Worker                                                         Protected isProtected) const {
334*c8dee2aaSAndroid Build Coastguard Worker     VkFormat format = format_from_compression(compression);
335*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& formatInfo = this->getFormatInfo(format);
336*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int defaultSampleCount = 1;
337*c8dee2aaSAndroid Build Coastguard Worker     if ((isProtected == Protected::kYes && !this->protectedSupport()) ||
338*c8dee2aaSAndroid Build Coastguard Worker         !formatInfo.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
339*c8dee2aaSAndroid Build Coastguard Worker         return {};
340*c8dee2aaSAndroid Build Coastguard Worker     }
341*c8dee2aaSAndroid Build Coastguard Worker 
342*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo info;
343*c8dee2aaSAndroid Build Coastguard Worker     info.fSampleCount = defaultSampleCount;
344*c8dee2aaSAndroid Build Coastguard Worker     info.fMipmapped = mipmapped;
345*c8dee2aaSAndroid Build Coastguard Worker     info.fFlags = (isProtected == Protected::kYes) ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
346*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = format;
347*c8dee2aaSAndroid Build Coastguard Worker     info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
348*c8dee2aaSAndroid Build Coastguard Worker     info.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
349*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
350*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_TRANSFER_DST_BIT;
351*c8dee2aaSAndroid Build Coastguard Worker     info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
352*c8dee2aaSAndroid Build Coastguard Worker     info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
353*c8dee2aaSAndroid Build Coastguard Worker 
354*c8dee2aaSAndroid Build Coastguard Worker     return TextureInfos::MakeVulkan(info);
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker 
getDefaultMSAATextureInfo(const TextureInfo & singleSampledInfo,Discardable discardable) const357*c8dee2aaSAndroid Build Coastguard Worker TextureInfo VulkanCaps::getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo,
358*c8dee2aaSAndroid Build Coastguard Worker                                                   Discardable discardable) const {
359*c8dee2aaSAndroid Build Coastguard Worker     if (fDefaultMSAASamples <= 1) {
360*c8dee2aaSAndroid Build Coastguard Worker         return {};
361*c8dee2aaSAndroid Build Coastguard Worker     }
362*c8dee2aaSAndroid Build Coastguard Worker 
363*c8dee2aaSAndroid Build Coastguard Worker     const VkFormat singleSpecFormat = TextureInfos::GetVkFormat(singleSampledInfo);
364*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& formatInfo = this->getFormatInfo(singleSpecFormat);
365*c8dee2aaSAndroid Build Coastguard Worker     if ((singleSampledInfo.isProtected() == Protected::kYes && !this->protectedSupport()) ||
366*c8dee2aaSAndroid Build Coastguard Worker         !formatInfo.isRenderable(VK_IMAGE_TILING_OPTIMAL, fDefaultMSAASamples)) {
367*c8dee2aaSAndroid Build Coastguard Worker         return {};
368*c8dee2aaSAndroid Build Coastguard Worker     }
369*c8dee2aaSAndroid Build Coastguard Worker 
370*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo info;
371*c8dee2aaSAndroid Build Coastguard Worker     info.fSampleCount = fDefaultMSAASamples;
372*c8dee2aaSAndroid Build Coastguard Worker     info.fMipmapped = Mipmapped::kNo;
373*c8dee2aaSAndroid Build Coastguard Worker     info.fFlags = (singleSampledInfo.isProtected() == Protected::kYes) ?
374*c8dee2aaSAndroid Build Coastguard Worker         VK_IMAGE_CREATE_PROTECTED_BIT : 0;
375*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = singleSpecFormat;
376*c8dee2aaSAndroid Build Coastguard Worker     info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
377*c8dee2aaSAndroid Build Coastguard Worker 
378*c8dee2aaSAndroid Build Coastguard Worker     /**
379*c8dee2aaSAndroid Build Coastguard Worker      * Graphite, unlike ganesh, does not require a dedicated MSAA attachment on every surface.
380*c8dee2aaSAndroid Build Coastguard Worker      * MSAA textures now get resolved within the scope of a render pass, which can be done simply
381*c8dee2aaSAndroid Build Coastguard Worker      * with the color attachment usage flag. So we no longer require transfer src/dst usage flags.
382*c8dee2aaSAndroid Build Coastguard Worker     */
383*c8dee2aaSAndroid Build Coastguard Worker     VkImageUsageFlags flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
384*c8dee2aaSAndroid Build Coastguard Worker     if (discardable == Discardable::kYes && fSupportsMemorylessAttachments) {
385*c8dee2aaSAndroid Build Coastguard Worker         flags = flags | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
386*c8dee2aaSAndroid Build Coastguard Worker     }
387*c8dee2aaSAndroid Build Coastguard Worker 
388*c8dee2aaSAndroid Build Coastguard Worker     info.fImageUsageFlags = flags;
389*c8dee2aaSAndroid Build Coastguard Worker     info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
390*c8dee2aaSAndroid Build Coastguard Worker     info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
391*c8dee2aaSAndroid Build Coastguard Worker 
392*c8dee2aaSAndroid Build Coastguard Worker     return TextureInfos::MakeVulkan(info);
393*c8dee2aaSAndroid Build Coastguard Worker }
394*c8dee2aaSAndroid Build Coastguard Worker 
getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags> flags,uint32_t sampleCount,Protected isProtected) const395*c8dee2aaSAndroid Build Coastguard Worker TextureInfo VulkanCaps::getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags> flags,
396*c8dee2aaSAndroid Build Coastguard Worker                                                           uint32_t sampleCount,
397*c8dee2aaSAndroid Build Coastguard Worker                                                           Protected isProtected) const {
398*c8dee2aaSAndroid Build Coastguard Worker     VkFormat format = this->getFormatFromDepthStencilFlags(flags);
399*c8dee2aaSAndroid Build Coastguard Worker     const DepthStencilFormatInfo& formatInfo = this->getDepthStencilFormatInfo(format);
400*c8dee2aaSAndroid Build Coastguard Worker     if ( (isProtected == Protected::kYes && !this->protectedSupport()) ||
401*c8dee2aaSAndroid Build Coastguard Worker          !formatInfo.isDepthStencilSupported(formatInfo.fFormatProperties.optimalTilingFeatures) ||
402*c8dee2aaSAndroid Build Coastguard Worker          !formatInfo.fSupportedSampleCounts.isSampleCountSupported(sampleCount)) {
403*c8dee2aaSAndroid Build Coastguard Worker         return {};
404*c8dee2aaSAndroid Build Coastguard Worker     }
405*c8dee2aaSAndroid Build Coastguard Worker 
406*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo info;
407*c8dee2aaSAndroid Build Coastguard Worker     info.fSampleCount = sampleCount;
408*c8dee2aaSAndroid Build Coastguard Worker     info.fMipmapped = Mipmapped::kNo;
409*c8dee2aaSAndroid Build Coastguard Worker     info.fFlags = (isProtected == Protected::kYes) ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
410*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = format;
411*c8dee2aaSAndroid Build Coastguard Worker     info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
412*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Passing in a discardable flag to this method, and if true, add the TRANSIENT bit.
413*c8dee2aaSAndroid Build Coastguard Worker     info.fImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
414*c8dee2aaSAndroid Build Coastguard Worker     info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
415*c8dee2aaSAndroid Build Coastguard Worker     info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
416*c8dee2aaSAndroid Build Coastguard Worker 
417*c8dee2aaSAndroid Build Coastguard Worker     return TextureInfos::MakeVulkan(info);
418*c8dee2aaSAndroid Build Coastguard Worker }
419*c8dee2aaSAndroid Build Coastguard Worker 
getDefaultStorageTextureInfo(SkColorType colorType) const420*c8dee2aaSAndroid Build Coastguard Worker TextureInfo VulkanCaps::getDefaultStorageTextureInfo(SkColorType colorType) const {
421*c8dee2aaSAndroid Build Coastguard Worker     VkFormat format = this->getFormatFromColorType(colorType);
422*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& formatInfo = this->getFormatInfo(format);
423*c8dee2aaSAndroid Build Coastguard Worker     if (!formatInfo.isTexturable(VK_IMAGE_TILING_OPTIMAL) ||
424*c8dee2aaSAndroid Build Coastguard Worker         !formatInfo.isStorage(VK_IMAGE_TILING_OPTIMAL)) {
425*c8dee2aaSAndroid Build Coastguard Worker         return {};
426*c8dee2aaSAndroid Build Coastguard Worker     }
427*c8dee2aaSAndroid Build Coastguard Worker 
428*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo info;
429*c8dee2aaSAndroid Build Coastguard Worker     info.fSampleCount = 1;
430*c8dee2aaSAndroid Build Coastguard Worker     info.fMipmapped = Mipmapped::kNo;
431*c8dee2aaSAndroid Build Coastguard Worker     info.fFlags = 0;
432*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = format;
433*c8dee2aaSAndroid Build Coastguard Worker     info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
434*c8dee2aaSAndroid Build Coastguard Worker     // Storage textures are currently always sampleable from a shader
435*c8dee2aaSAndroid Build Coastguard Worker     info.fImageUsageFlags = VK_IMAGE_USAGE_STORAGE_BIT |
436*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_SAMPLED_BIT |
437*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
438*c8dee2aaSAndroid Build Coastguard Worker     info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
439*c8dee2aaSAndroid Build Coastguard Worker     info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
440*c8dee2aaSAndroid Build Coastguard Worker 
441*c8dee2aaSAndroid Build Coastguard Worker     return TextureInfos::MakeVulkan(info);
442*c8dee2aaSAndroid Build Coastguard Worker }
443*c8dee2aaSAndroid Build Coastguard Worker 
channelMask(const TextureInfo & textureInfo) const444*c8dee2aaSAndroid Build Coastguard Worker uint32_t VulkanCaps::channelMask(const TextureInfo& textureInfo) const {
445*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::VkFormatChannels(TextureInfos::GetVkFormat(textureInfo));
446*c8dee2aaSAndroid Build Coastguard Worker }
447*c8dee2aaSAndroid Build Coastguard Worker 
initFormatTable(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties)448*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::initFormatTable(const skgpu::VulkanInterface* interface,
449*c8dee2aaSAndroid Build Coastguard Worker                                  VkPhysicalDevice physDev,
450*c8dee2aaSAndroid Build Coastguard Worker                                  const VkPhysicalDeviceProperties& properties) {
451*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(kVkFormats) == VulkanCaps::kNumVkFormats,
452*c8dee2aaSAndroid Build Coastguard Worker                   "Size of VkFormats array must match static value in header");
453*c8dee2aaSAndroid Build Coastguard Worker 
454*c8dee2aaSAndroid Build Coastguard Worker     std::fill_n(fColorTypeToFormatTable, kSkColorTypeCnt, VK_FORMAT_UNDEFINED);
455*c8dee2aaSAndroid Build Coastguard Worker 
456*c8dee2aaSAndroid Build Coastguard Worker     // Go through all the formats and init their support surface and data ColorTypes.
457*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R8G8B8A8_UNORM
458*c8dee2aaSAndroid Build Coastguard Worker     {
459*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
460*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
461*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
462*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
463*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 2;
464*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
465*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
466*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
467*c8dee2aaSAndroid Build Coastguard Worker             {
468*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGBA_8888_SkColorType;
469*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
470*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
471*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
472*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
473*c8dee2aaSAndroid Build Coastguard Worker             }
474*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
475*c8dee2aaSAndroid Build Coastguard Worker             {
476*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
477*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
478*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
479*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
480*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
481*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
482*c8dee2aaSAndroid Build Coastguard Worker             }
483*c8dee2aaSAndroid Build Coastguard Worker         }
484*c8dee2aaSAndroid Build Coastguard Worker     }
485*c8dee2aaSAndroid Build Coastguard Worker 
486*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R8_UNORM
487*c8dee2aaSAndroid Build Coastguard Worker     {
488*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R8_UNORM;
489*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
490*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
491*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
492*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 3;
493*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
494*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
495*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8_UNORM, Surface: kR_8
496*c8dee2aaSAndroid Build Coastguard Worker             {
497*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kR8_unorm_SkColorType;
498*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
499*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
500*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
501*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
502*c8dee2aaSAndroid Build Coastguard Worker             }
503*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8_UNORM, Surface: kAlpha_8
504*c8dee2aaSAndroid Build Coastguard Worker             {
505*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kAlpha_8_SkColorType;
506*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
507*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
508*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
509*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
510*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
511*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
512*c8dee2aaSAndroid Build Coastguard Worker             }
513*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8_UNORM, Surface: kGray_8
514*c8dee2aaSAndroid Build Coastguard Worker             {
515*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kGray_8_SkColorType;
516*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
517*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
518*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
519*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
520*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
521*c8dee2aaSAndroid Build Coastguard Worker             }
522*c8dee2aaSAndroid Build Coastguard Worker         }
523*c8dee2aaSAndroid Build Coastguard Worker     }
524*c8dee2aaSAndroid Build Coastguard Worker 
525*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_B8G8R8A8_UNORM
526*c8dee2aaSAndroid Build Coastguard Worker     {
527*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
528*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
529*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
530*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
531*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
532*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
533*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
534*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
535*c8dee2aaSAndroid Build Coastguard Worker             {
536*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kBGRA_8888_SkColorType;
537*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
538*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
539*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
540*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
541*c8dee2aaSAndroid Build Coastguard Worker             }
542*c8dee2aaSAndroid Build Coastguard Worker         }
543*c8dee2aaSAndroid Build Coastguard Worker     }
544*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R5G6B5_UNORM_PACK16
545*c8dee2aaSAndroid Build Coastguard Worker     {
546*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R5G6B5_UNORM_PACK16;
547*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
548*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
549*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
550*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
551*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
552*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
553*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R5G6B5_UNORM_PACK16, Surface: kRGB_565_SkColorType
554*c8dee2aaSAndroid Build Coastguard Worker             {
555*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_565_SkColorType;
556*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
557*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
558*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
559*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
560*c8dee2aaSAndroid Build Coastguard Worker             }
561*c8dee2aaSAndroid Build Coastguard Worker         }
562*c8dee2aaSAndroid Build Coastguard Worker     }
563*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R16G16B16A16_SFLOAT
564*c8dee2aaSAndroid Build Coastguard Worker     {
565*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT;
566*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
567*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
568*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
569*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 2;
570*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
571*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
572*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: kRGBA_F16_SkColorType
573*c8dee2aaSAndroid Build Coastguard Worker             {
574*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGBA_F16_SkColorType;
575*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
576*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
577*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
578*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
579*c8dee2aaSAndroid Build Coastguard Worker             }
580*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: kRGB_F16F16F16x_SkColorType
581*c8dee2aaSAndroid Build Coastguard Worker             {
582*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_F16F16F16x_SkColorType;
583*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
584*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
585*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
586*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
587*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
588*c8dee2aaSAndroid Build Coastguard Worker             }
589*c8dee2aaSAndroid Build Coastguard Worker         }
590*c8dee2aaSAndroid Build Coastguard Worker     }
591*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R16_SFLOAT
592*c8dee2aaSAndroid Build Coastguard Worker     {
593*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R16_SFLOAT;
594*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
595*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
596*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
597*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
598*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
599*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
600*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16_SFLOAT, Surface: kAlpha_F16
601*c8dee2aaSAndroid Build Coastguard Worker             {
602*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kA16_float_SkColorType;
603*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
604*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
605*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
606*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
607*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
608*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
609*c8dee2aaSAndroid Build Coastguard Worker             }
610*c8dee2aaSAndroid Build Coastguard Worker         }
611*c8dee2aaSAndroid Build Coastguard Worker     }
612*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R8G8B8_UNORM
613*c8dee2aaSAndroid Build Coastguard Worker     {
614*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R8G8B8_UNORM;
615*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
616*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
617*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
618*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
619*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
620*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
621*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8G8B8_UNORM, Surface: kRGB_888x
622*c8dee2aaSAndroid Build Coastguard Worker             {
623*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
624*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
625*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
626*c8dee2aaSAndroid Build Coastguard Worker                 // This SkColorType is a lie, but we don't have a kRGB_888_SkColorType. The Vulkan
627*c8dee2aaSAndroid Build Coastguard Worker                 // format is 3 bpp so we must manualy convert to/from this and kRGB_888x when doing
628*c8dee2aaSAndroid Build Coastguard Worker                 // transfers. We signal this need for manual conversions in the
629*c8dee2aaSAndroid Build Coastguard Worker                 // supportedRead/WriteColorType calls.
630*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = SkColorType::kRGB_888x_SkColorType;
631*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
632*c8dee2aaSAndroid Build Coastguard Worker             }
633*c8dee2aaSAndroid Build Coastguard Worker         }
634*c8dee2aaSAndroid Build Coastguard Worker     }
635*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R8G8_UNORM
636*c8dee2aaSAndroid Build Coastguard Worker     {
637*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R8G8_UNORM;
638*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
639*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
640*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
641*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
642*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
643*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
644*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8G8_UNORM, Surface: kR8G8_unorm
645*c8dee2aaSAndroid Build Coastguard Worker             {
646*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kR8G8_unorm_SkColorType;
647*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
648*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
649*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
650*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
651*c8dee2aaSAndroid Build Coastguard Worker             }
652*c8dee2aaSAndroid Build Coastguard Worker         }
653*c8dee2aaSAndroid Build Coastguard Worker     }
654*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32
655*c8dee2aaSAndroid Build Coastguard Worker     {
656*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
657*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
658*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
659*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
660*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 2;
661*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
662*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
663*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGBA_1010102
664*c8dee2aaSAndroid Build Coastguard Worker             {
665*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGBA_1010102_SkColorType;
666*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
667*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
668*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
669*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
670*c8dee2aaSAndroid Build Coastguard Worker             }
671*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGB_101010x
672*c8dee2aaSAndroid Build Coastguard Worker             {
673*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_101010x_SkColorType;
674*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
675*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
676*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
677*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
678*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
679*c8dee2aaSAndroid Build Coastguard Worker             }
680*c8dee2aaSAndroid Build Coastguard Worker         }
681*c8dee2aaSAndroid Build Coastguard Worker     }
682*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32
683*c8dee2aaSAndroid Build Coastguard Worker     {
684*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
685*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
686*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
687*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
688*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
689*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
690*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
691*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kBGRA_1010102
692*c8dee2aaSAndroid Build Coastguard Worker             {
693*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kBGRA_1010102_SkColorType;
694*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
695*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
696*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
697*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
698*c8dee2aaSAndroid Build Coastguard Worker             }
699*c8dee2aaSAndroid Build Coastguard Worker         }
700*c8dee2aaSAndroid Build Coastguard Worker     }
701*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16
702*c8dee2aaSAndroid Build Coastguard Worker     {
703*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
704*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
705*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
706*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
707*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
708*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
709*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
710*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16, Surface: kARGB_4444_SkColorType
711*c8dee2aaSAndroid Build Coastguard Worker             {
712*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kARGB_4444_SkColorType;
713*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
714*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
715*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
716*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
717*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle::BGRA();
718*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fWriteSwizzle = skgpu::Swizzle::BGRA();
719*c8dee2aaSAndroid Build Coastguard Worker             }
720*c8dee2aaSAndroid Build Coastguard Worker         }
721*c8dee2aaSAndroid Build Coastguard Worker     }
722*c8dee2aaSAndroid Build Coastguard Worker 
723*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16
724*c8dee2aaSAndroid Build Coastguard Worker     {
725*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
726*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
727*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
728*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
729*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
730*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
731*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
732*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16, Surface: kARGB_4444_SkColorType
733*c8dee2aaSAndroid Build Coastguard Worker             {
734*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kARGB_4444_SkColorType;
735*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
736*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
737*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
738*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
739*c8dee2aaSAndroid Build Coastguard Worker             }
740*c8dee2aaSAndroid Build Coastguard Worker         }
741*c8dee2aaSAndroid Build Coastguard Worker     }
742*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R8G8B8A8_SRGB
743*c8dee2aaSAndroid Build Coastguard Worker     {
744*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R8G8B8A8_SRGB;
745*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
746*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
747*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
748*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
749*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
750*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
751*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R8G8B8A8_SRGB, Surface: kRGBA_8888_SRGB
752*c8dee2aaSAndroid Build Coastguard Worker             {
753*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kSRGBA_8888_SkColorType;
754*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
755*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
756*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
757*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
758*c8dee2aaSAndroid Build Coastguard Worker             }
759*c8dee2aaSAndroid Build Coastguard Worker         }
760*c8dee2aaSAndroid Build Coastguard Worker     }
761*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R16_UNORM
762*c8dee2aaSAndroid Build Coastguard Worker     {
763*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R16_UNORM;
764*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
765*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
766*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
767*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
768*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
769*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
770*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16_UNORM, Surface: kAlpha_16
771*c8dee2aaSAndroid Build Coastguard Worker             {
772*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kA16_unorm_SkColorType;
773*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
774*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
775*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
776*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
777*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
778*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
779*c8dee2aaSAndroid Build Coastguard Worker             }
780*c8dee2aaSAndroid Build Coastguard Worker         }
781*c8dee2aaSAndroid Build Coastguard Worker     }
782*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R16G16_UNORM
783*c8dee2aaSAndroid Build Coastguard Worker     {
784*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R16G16_UNORM;
785*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
786*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
787*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
788*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
789*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
790*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
791*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16G16_UNORM, Surface: kRG_1616
792*c8dee2aaSAndroid Build Coastguard Worker             {
793*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kR16G16_unorm_SkColorType;
794*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
795*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
796*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
797*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
798*c8dee2aaSAndroid Build Coastguard Worker             }
799*c8dee2aaSAndroid Build Coastguard Worker         }
800*c8dee2aaSAndroid Build Coastguard Worker     }
801*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R16G16B16A16_UNORM
802*c8dee2aaSAndroid Build Coastguard Worker     {
803*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R16G16B16A16_UNORM;
804*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
805*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
806*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
807*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
808*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
809*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
810*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
811*c8dee2aaSAndroid Build Coastguard Worker             {
812*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kR16G16B16A16_unorm_SkColorType;
813*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
814*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
815*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
816*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
817*c8dee2aaSAndroid Build Coastguard Worker             }
818*c8dee2aaSAndroid Build Coastguard Worker         }
819*c8dee2aaSAndroid Build Coastguard Worker     }
820*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_R16G16_SFLOAT
821*c8dee2aaSAndroid Build Coastguard Worker     {
822*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_R16G16_SFLOAT;
823*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
824*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
825*c8dee2aaSAndroid Build Coastguard Worker          if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
826*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
827*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
828*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
829*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_R16G16_SFLOAT, Surface: kRG_F16
830*c8dee2aaSAndroid Build Coastguard Worker             {
831*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kR16G16_float_SkColorType;
832*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
833*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
834*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
835*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
836*c8dee2aaSAndroid Build Coastguard Worker             }
837*c8dee2aaSAndroid Build Coastguard Worker         }
838*c8dee2aaSAndroid Build Coastguard Worker     }
839*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
840*c8dee2aaSAndroid Build Coastguard Worker     {
841*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
842*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
843*c8dee2aaSAndroid Build Coastguard Worker         if (fSupportsYcbcrConversion) {
844*c8dee2aaSAndroid Build Coastguard Worker             info.init(interface, physDev, properties, format);
845*c8dee2aaSAndroid Build Coastguard Worker         }
846*c8dee2aaSAndroid Build Coastguard Worker         if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
847*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
848*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
849*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
850*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, Surface: kRGB_888x
851*c8dee2aaSAndroid Build Coastguard Worker             {
852*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
853*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
854*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
855*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
856*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
857*c8dee2aaSAndroid Build Coastguard Worker             }
858*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(info.fIsWrappedOnly = true;)
859*c8dee2aaSAndroid Build Coastguard Worker         }
860*c8dee2aaSAndroid Build Coastguard Worker     }
861*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
862*c8dee2aaSAndroid Build Coastguard Worker     {
863*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
864*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
865*c8dee2aaSAndroid Build Coastguard Worker         if (fSupportsYcbcrConversion) {
866*c8dee2aaSAndroid Build Coastguard Worker             info.init(interface, physDev, properties, format);
867*c8dee2aaSAndroid Build Coastguard Worker         }
868*c8dee2aaSAndroid Build Coastguard Worker         if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
869*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
870*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
871*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
872*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, Surface: kRGB_888x
873*c8dee2aaSAndroid Build Coastguard Worker             {
874*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
875*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
876*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
877*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
878*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
879*c8dee2aaSAndroid Build Coastguard Worker             }
880*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(info.fIsWrappedOnly = true;)
881*c8dee2aaSAndroid Build Coastguard Worker         }
882*c8dee2aaSAndroid Build Coastguard Worker     }
883*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
884*c8dee2aaSAndroid Build Coastguard Worker     {
885*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
886*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
887*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
888*c8dee2aaSAndroid Build Coastguard Worker         if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
889*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
890*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
891*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
892*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, Surface: kRGB_888x
893*c8dee2aaSAndroid Build Coastguard Worker             {
894*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
895*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
896*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
897*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
898*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
899*c8dee2aaSAndroid Build Coastguard Worker             }
900*c8dee2aaSAndroid Build Coastguard Worker         }
901*c8dee2aaSAndroid Build Coastguard Worker     }
902*c8dee2aaSAndroid Build Coastguard Worker 
903*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_BC1_RGB_UNORM_BLOCK
904*c8dee2aaSAndroid Build Coastguard Worker     {
905*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_BC1_RGB_UNORM_BLOCK;
906*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
907*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
908*c8dee2aaSAndroid Build Coastguard Worker         if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
909*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
910*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
911*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
912*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_BC1_RGB_UNORM_BLOCK, Surface: kRGB_888x
913*c8dee2aaSAndroid Build Coastguard Worker             {
914*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
915*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
916*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
917*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
918*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
919*c8dee2aaSAndroid Build Coastguard Worker             }
920*c8dee2aaSAndroid Build Coastguard Worker         }
921*c8dee2aaSAndroid Build Coastguard Worker     }
922*c8dee2aaSAndroid Build Coastguard Worker 
923*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_BC1_RGBA_UNORM_BLOCK
924*c8dee2aaSAndroid Build Coastguard Worker     {
925*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
926*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getFormatInfo(format);
927*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
928*c8dee2aaSAndroid Build Coastguard Worker         if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
929*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfoCount = 1;
930*c8dee2aaSAndroid Build Coastguard Worker             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
931*c8dee2aaSAndroid Build Coastguard Worker             int ctIdx = 0;
932*c8dee2aaSAndroid Build Coastguard Worker             // Format: VK_FORMAT_BC1_RGBA_UNORM_BLOCK, Surface: kRGB_888x
933*c8dee2aaSAndroid Build Coastguard Worker             {
934*c8dee2aaSAndroid Build Coastguard Worker                 constexpr SkColorType ct = SkColorType::kRGBA_8888_SkColorType;
935*c8dee2aaSAndroid Build Coastguard Worker                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
936*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fColorType = ct;
937*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fTransferColorType = ct;
938*c8dee2aaSAndroid Build Coastguard Worker                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
939*c8dee2aaSAndroid Build Coastguard Worker             }
940*c8dee2aaSAndroid Build Coastguard Worker         }
941*c8dee2aaSAndroid Build Coastguard Worker     }
942*c8dee2aaSAndroid Build Coastguard Worker 
943*c8dee2aaSAndroid Build Coastguard Worker     ////////////////////////////////////////////////////////////////////////////
944*c8dee2aaSAndroid Build Coastguard Worker     // Map SkColorType (used for creating Surfaces) to VkFormats. The order in which the formats are
945*c8dee2aaSAndroid Build Coastguard Worker     // passed into the setColorType function indicates the priority in selecting which format we use
946*c8dee2aaSAndroid Build Coastguard Worker     // for a given SkColorType.
947*c8dee2aaSAndroid Build Coastguard Worker     typedef SkColorType ct;
948*c8dee2aaSAndroid Build Coastguard Worker 
949*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kAlpha_8_SkColorType,            { VK_FORMAT_R8_UNORM });
950*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGB_565_SkColorType,            { VK_FORMAT_R5G6B5_UNORM_PACK16 });
951*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kARGB_4444_SkColorType,          { VK_FORMAT_R4G4B4A4_UNORM_PACK16,
952*c8dee2aaSAndroid Build Coastguard Worker                                                               VK_FORMAT_B4G4R4A4_UNORM_PACK16 });
953*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGBA_8888_SkColorType,          { VK_FORMAT_R8G8B8A8_UNORM });
954*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kSRGBA_8888_SkColorType,         { VK_FORMAT_R8G8B8A8_SRGB });
955*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGB_888x_SkColorType,           { VK_FORMAT_R8G8B8_UNORM,
956*c8dee2aaSAndroid Build Coastguard Worker                                                               VK_FORMAT_R8G8B8A8_UNORM });
957*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kR8G8_unorm_SkColorType,         { VK_FORMAT_R8G8_UNORM });
958*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kBGRA_8888_SkColorType,          { VK_FORMAT_B8G8R8A8_UNORM });
959*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGBA_1010102_SkColorType,       { VK_FORMAT_A2B10G10R10_UNORM_PACK32 });
960*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kBGRA_1010102_SkColorType,       { VK_FORMAT_A2R10G10B10_UNORM_PACK32 });
961*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGB_101010x_SkColorType,        { VK_FORMAT_A2B10G10R10_UNORM_PACK32 });
962*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kGray_8_SkColorType,             { VK_FORMAT_R8_UNORM });
963*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kA16_float_SkColorType,          { VK_FORMAT_R16_SFLOAT });
964*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGBA_F16_SkColorType,           { VK_FORMAT_R16G16B16A16_SFLOAT });
965*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kRGB_F16F16F16x_SkColorType,     { VK_FORMAT_R16G16B16A16_SFLOAT });
966*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kA16_unorm_SkColorType,          { VK_FORMAT_R16_UNORM });
967*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kR16G16_unorm_SkColorType,       { VK_FORMAT_R16G16_UNORM });
968*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kR16G16B16A16_unorm_SkColorType, { VK_FORMAT_R16G16B16A16_UNORM });
969*c8dee2aaSAndroid Build Coastguard Worker     this->setColorType(ct::kR16G16_float_SkColorType,       { VK_FORMAT_R16G16_SFLOAT });
970*c8dee2aaSAndroid Build Coastguard Worker }
971*c8dee2aaSAndroid Build Coastguard Worker 
972*c8dee2aaSAndroid Build Coastguard Worker namespace {
set_ds_flags_to_format(VkFormat & slot,VkFormat format)973*c8dee2aaSAndroid Build Coastguard Worker void set_ds_flags_to_format(VkFormat& slot, VkFormat format) {
974*c8dee2aaSAndroid Build Coastguard Worker     if (slot == VK_FORMAT_UNDEFINED) {
975*c8dee2aaSAndroid Build Coastguard Worker         slot = format;
976*c8dee2aaSAndroid Build Coastguard Worker     }
977*c8dee2aaSAndroid Build Coastguard Worker }
978*c8dee2aaSAndroid Build Coastguard Worker } // namespace
979*c8dee2aaSAndroid Build Coastguard Worker 
initDepthStencilFormatTable(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties)980*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::initDepthStencilFormatTable(const skgpu::VulkanInterface* interface,
981*c8dee2aaSAndroid Build Coastguard Worker                                              VkPhysicalDevice physDev,
982*c8dee2aaSAndroid Build Coastguard Worker                                              const VkPhysicalDeviceProperties& properties) {
983*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(kDepthStencilVkFormats) == VulkanCaps::kNumDepthStencilVkFormats,
984*c8dee2aaSAndroid Build Coastguard Worker                   "Size of DepthStencilVkFormats array must match static value in header");
985*c8dee2aaSAndroid Build Coastguard Worker 
986*c8dee2aaSAndroid Build Coastguard Worker     using DSFlags = SkEnumBitMask<DepthStencilFlags>;
987*c8dee2aaSAndroid Build Coastguard Worker     constexpr DSFlags stencilFlags = DepthStencilFlags::kStencil;
988*c8dee2aaSAndroid Build Coastguard Worker     constexpr DSFlags depthFlags = DepthStencilFlags::kDepth;
989*c8dee2aaSAndroid Build Coastguard Worker     constexpr DSFlags dsFlags = DepthStencilFlags::kDepthStencil;
990*c8dee2aaSAndroid Build Coastguard Worker 
991*c8dee2aaSAndroid Build Coastguard Worker     std::fill_n(fDepthStencilFlagsToFormatTable, kNumDepthStencilFlags, VK_FORMAT_UNDEFINED);
992*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_S8_UINT
993*c8dee2aaSAndroid Build Coastguard Worker     {
994*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_S8_UINT;
995*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getDepthStencilFormatInfo(format);
996*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
997*c8dee2aaSAndroid Build Coastguard Worker         if (info.fFormatProperties.optimalTilingFeatures &
998*c8dee2aaSAndroid Build Coastguard Worker             VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
999*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[stencilFlags.value()], format);
1000*c8dee2aaSAndroid Build Coastguard Worker         }
1001*c8dee2aaSAndroid Build Coastguard Worker     }
1002*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_D16_UNORM
1003*c8dee2aaSAndroid Build Coastguard Worker     {
1004*c8dee2aaSAndroid Build Coastguard Worker         // Qualcomm drivers will report OUT_OF_HOST_MEMORY when binding memory to a VkImage with
1005*c8dee2aaSAndroid Build Coastguard Worker         // D16_UNORM in a protected context. Using D32_SFLOAT succeeds, so clearly it's not actually
1006*c8dee2aaSAndroid Build Coastguard Worker         // out of memory. D16_UNORM appears to function correctly in unprotected contexts.
1007*c8dee2aaSAndroid Build Coastguard Worker         const bool disableD16InProtected = this->protectedSupport() &&
1008*c8dee2aaSAndroid Build Coastguard Worker                                            kQualcomm_VkVendor == properties.vendorID;
1009*c8dee2aaSAndroid Build Coastguard Worker         if (!disableD16InProtected) {
1010*c8dee2aaSAndroid Build Coastguard Worker             constexpr VkFormat format = VK_FORMAT_D16_UNORM;
1011*c8dee2aaSAndroid Build Coastguard Worker             auto& info = this->getDepthStencilFormatInfo(format);
1012*c8dee2aaSAndroid Build Coastguard Worker             info.init(interface, physDev, properties, format);
1013*c8dee2aaSAndroid Build Coastguard Worker             if (info.fFormatProperties.optimalTilingFeatures &
1014*c8dee2aaSAndroid Build Coastguard Worker                 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1015*c8dee2aaSAndroid Build Coastguard Worker                 set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[depthFlags.value()], format);
1016*c8dee2aaSAndroid Build Coastguard Worker             }
1017*c8dee2aaSAndroid Build Coastguard Worker         }
1018*c8dee2aaSAndroid Build Coastguard Worker     }
1019*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_D32_SFLOAT
1020*c8dee2aaSAndroid Build Coastguard Worker     {
1021*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_D32_SFLOAT;
1022*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getDepthStencilFormatInfo(format);
1023*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
1024*c8dee2aaSAndroid Build Coastguard Worker         if (info.fFormatProperties.optimalTilingFeatures &
1025*c8dee2aaSAndroid Build Coastguard Worker             VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1026*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[depthFlags.value()], format);
1027*c8dee2aaSAndroid Build Coastguard Worker         }
1028*c8dee2aaSAndroid Build Coastguard Worker     }
1029*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_D24_UNORM_S8_UINT
1030*c8dee2aaSAndroid Build Coastguard Worker     {
1031*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_D24_UNORM_S8_UINT;
1032*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getDepthStencilFormatInfo(format);
1033*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
1034*c8dee2aaSAndroid Build Coastguard Worker         if (info.fFormatProperties.optimalTilingFeatures &
1035*c8dee2aaSAndroid Build Coastguard Worker             VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1036*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[stencilFlags.value()], format);
1037*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[depthFlags.value()], format);
1038*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[dsFlags.value()], format);
1039*c8dee2aaSAndroid Build Coastguard Worker         }
1040*c8dee2aaSAndroid Build Coastguard Worker     }
1041*c8dee2aaSAndroid Build Coastguard Worker     // Format: VK_FORMAT_D32_SFLOAT_S8_UINT
1042*c8dee2aaSAndroid Build Coastguard Worker     {
1043*c8dee2aaSAndroid Build Coastguard Worker         constexpr VkFormat format = VK_FORMAT_D32_SFLOAT_S8_UINT;
1044*c8dee2aaSAndroid Build Coastguard Worker         auto& info = this->getDepthStencilFormatInfo(format);
1045*c8dee2aaSAndroid Build Coastguard Worker         info.init(interface, physDev, properties, format);
1046*c8dee2aaSAndroid Build Coastguard Worker         if (info.fFormatProperties.optimalTilingFeatures &
1047*c8dee2aaSAndroid Build Coastguard Worker             VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1048*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[stencilFlags.value()], format);
1049*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[depthFlags.value()], format);
1050*c8dee2aaSAndroid Build Coastguard Worker             set_ds_flags_to_format(fDepthStencilFlagsToFormatTable[dsFlags.value()], format);
1051*c8dee2aaSAndroid Build Coastguard Worker         }
1052*c8dee2aaSAndroid Build Coastguard Worker     }
1053*c8dee2aaSAndroid Build Coastguard Worker }
1054*c8dee2aaSAndroid Build Coastguard Worker 
initSampleCounts(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & physProps,VkFormat format,VkImageUsageFlags usage)1055*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::SupportedSampleCounts::initSampleCounts(const skgpu::VulkanInterface* interface,
1056*c8dee2aaSAndroid Build Coastguard Worker         VkPhysicalDevice physDev,
1057*c8dee2aaSAndroid Build Coastguard Worker         const VkPhysicalDeviceProperties& physProps,
1058*c8dee2aaSAndroid Build Coastguard Worker         VkFormat format,
1059*c8dee2aaSAndroid Build Coastguard Worker         VkImageUsageFlags usage) {
1060*c8dee2aaSAndroid Build Coastguard Worker     VkImageFormatProperties properties;
1061*c8dee2aaSAndroid Build Coastguard Worker 
1062*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
1063*c8dee2aaSAndroid Build Coastguard Worker     // VULKAN_CALL_RESULT requires a VulkanSharedContext for tracking DEVICE_LOST, but VulkanCaps
1064*c8dee2aaSAndroid Build Coastguard Worker     // are initialized before a VulkanSharedContext is available. The _NOCHECK variant only requires
1065*c8dee2aaSAndroid Build Coastguard Worker     // a VulkanInterface, so we can use that and log failures manually.
1066*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL_RESULT_NOCHECK(interface,
1067*c8dee2aaSAndroid Build Coastguard Worker                                result,
1068*c8dee2aaSAndroid Build Coastguard Worker                                GetPhysicalDeviceImageFormatProperties(physDev,
1069*c8dee2aaSAndroid Build Coastguard Worker                                                                       format,
1070*c8dee2aaSAndroid Build Coastguard Worker                                                                       VK_IMAGE_TYPE_2D,
1071*c8dee2aaSAndroid Build Coastguard Worker                                                                       VK_IMAGE_TILING_OPTIMAL,
1072*c8dee2aaSAndroid Build Coastguard Worker                                                                       usage,
1073*c8dee2aaSAndroid Build Coastguard Worker                                                                       0,  // createFlags
1074*c8dee2aaSAndroid Build Coastguard Worker                                                                       &properties));
1075*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
1076*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_W("Vulkan call GetPhysicalDeviceImageFormatProperties failed: %d", result);
1077*c8dee2aaSAndroid Build Coastguard Worker         return;
1078*c8dee2aaSAndroid Build Coastguard Worker     }
1079*c8dee2aaSAndroid Build Coastguard Worker 
1080*c8dee2aaSAndroid Build Coastguard Worker     VkSampleCountFlags flags = properties.sampleCounts;
1081*c8dee2aaSAndroid Build Coastguard Worker     if (flags & VK_SAMPLE_COUNT_1_BIT) {
1082*c8dee2aaSAndroid Build Coastguard Worker         fSampleCounts.push_back(1);
1083*c8dee2aaSAndroid Build Coastguard Worker     }
1084*c8dee2aaSAndroid Build Coastguard Worker     if (kImagination_VkVendor == physProps.vendorID) {
1085*c8dee2aaSAndroid Build Coastguard Worker         // MSAA does not work on imagination
1086*c8dee2aaSAndroid Build Coastguard Worker         return;
1087*c8dee2aaSAndroid Build Coastguard Worker     }
1088*c8dee2aaSAndroid Build Coastguard Worker     if (kIntel_VkVendor == physProps.vendorID) {
1089*c8dee2aaSAndroid Build Coastguard Worker         // MSAA doesn't work well on Intel GPUs chromium:527565, chromium:983926
1090*c8dee2aaSAndroid Build Coastguard Worker         return;
1091*c8dee2aaSAndroid Build Coastguard Worker     }
1092*c8dee2aaSAndroid Build Coastguard Worker     if (flags & VK_SAMPLE_COUNT_2_BIT) {
1093*c8dee2aaSAndroid Build Coastguard Worker         fSampleCounts.push_back(2);
1094*c8dee2aaSAndroid Build Coastguard Worker     }
1095*c8dee2aaSAndroid Build Coastguard Worker     if (flags & VK_SAMPLE_COUNT_4_BIT) {
1096*c8dee2aaSAndroid Build Coastguard Worker         fSampleCounts.push_back(4);
1097*c8dee2aaSAndroid Build Coastguard Worker     }
1098*c8dee2aaSAndroid Build Coastguard Worker     if (flags & VK_SAMPLE_COUNT_8_BIT) {
1099*c8dee2aaSAndroid Build Coastguard Worker         fSampleCounts.push_back(8);
1100*c8dee2aaSAndroid Build Coastguard Worker     }
1101*c8dee2aaSAndroid Build Coastguard Worker     if (flags & VK_SAMPLE_COUNT_16_BIT) {
1102*c8dee2aaSAndroid Build Coastguard Worker         fSampleCounts.push_back(16);
1103*c8dee2aaSAndroid Build Coastguard Worker     }
1104*c8dee2aaSAndroid Build Coastguard Worker     // Standard sample locations are not defined for more than 16 samples, and we don't need more
1105*c8dee2aaSAndroid Build Coastguard Worker     // than 16. Omit 32 and 64.
1106*c8dee2aaSAndroid Build Coastguard Worker }
1107*c8dee2aaSAndroid Build Coastguard Worker 
isSampleCountSupported(int requestedCount) const1108*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::SupportedSampleCounts::isSampleCountSupported(int requestedCount) const {
1109*c8dee2aaSAndroid Build Coastguard Worker     requestedCount = std::max(1, requestedCount);
1110*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fSampleCounts.size(); i++) {
1111*c8dee2aaSAndroid Build Coastguard Worker         if (fSampleCounts[i] == requestedCount) {
1112*c8dee2aaSAndroid Build Coastguard Worker             return true;
1113*c8dee2aaSAndroid Build Coastguard Worker         } else if (requestedCount < fSampleCounts[i]) {
1114*c8dee2aaSAndroid Build Coastguard Worker             return false;
1115*c8dee2aaSAndroid Build Coastguard Worker         }
1116*c8dee2aaSAndroid Build Coastguard Worker     }
1117*c8dee2aaSAndroid Build Coastguard Worker     return false;
1118*c8dee2aaSAndroid Build Coastguard Worker }
1119*c8dee2aaSAndroid Build Coastguard Worker 
1120*c8dee2aaSAndroid Build Coastguard Worker 
1121*c8dee2aaSAndroid Build Coastguard Worker namespace {
is_texturable(VkFormatFeatureFlags flags)1122*c8dee2aaSAndroid Build Coastguard Worker bool is_texturable(VkFormatFeatureFlags flags) {
1123*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & flags) &&
1124*c8dee2aaSAndroid Build Coastguard Worker            SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & flags);
1125*c8dee2aaSAndroid Build Coastguard Worker }
1126*c8dee2aaSAndroid Build Coastguard Worker 
is_renderable(VkFormatFeatureFlags flags)1127*c8dee2aaSAndroid Build Coastguard Worker bool is_renderable(VkFormatFeatureFlags flags) {
1128*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & flags);
1129*c8dee2aaSAndroid Build Coastguard Worker }
1130*c8dee2aaSAndroid Build Coastguard Worker 
is_storage(VkFormatFeatureFlags flags)1131*c8dee2aaSAndroid Build Coastguard Worker bool is_storage(VkFormatFeatureFlags flags) {
1132*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT & flags);
1133*c8dee2aaSAndroid Build Coastguard Worker }
1134*c8dee2aaSAndroid Build Coastguard Worker 
is_transfer_src(VkFormatFeatureFlags flags)1135*c8dee2aaSAndroid Build Coastguard Worker bool is_transfer_src(VkFormatFeatureFlags flags) {
1136*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & flags);
1137*c8dee2aaSAndroid Build Coastguard Worker }
1138*c8dee2aaSAndroid Build Coastguard Worker 
is_transfer_dst(VkFormatFeatureFlags flags)1139*c8dee2aaSAndroid Build Coastguard Worker bool is_transfer_dst(VkFormatFeatureFlags flags) {
1140*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & flags);
1141*c8dee2aaSAndroid Build Coastguard Worker }
1142*c8dee2aaSAndroid Build Coastguard Worker }
1143*c8dee2aaSAndroid Build Coastguard Worker 
init(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties,VkFormat format)1144*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::FormatInfo::init(const skgpu::VulkanInterface* interface,
1145*c8dee2aaSAndroid Build Coastguard Worker                                   VkPhysicalDevice physDev,
1146*c8dee2aaSAndroid Build Coastguard Worker                                   const VkPhysicalDeviceProperties& properties,
1147*c8dee2aaSAndroid Build Coastguard Worker                                   VkFormat format) {
1148*c8dee2aaSAndroid Build Coastguard Worker     memset(&fFormatProperties, 0, sizeof(VkFormatProperties));
1149*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &fFormatProperties));
1150*c8dee2aaSAndroid Build Coastguard Worker 
1151*c8dee2aaSAndroid Build Coastguard Worker     if (is_renderable(fFormatProperties.optimalTilingFeatures)) {
1152*c8dee2aaSAndroid Build Coastguard Worker         // We make all renderable images support being used as input attachment
1153*c8dee2aaSAndroid Build Coastguard Worker         VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1154*c8dee2aaSAndroid Build Coastguard Worker                                        VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1155*c8dee2aaSAndroid Build Coastguard Worker                                        VK_IMAGE_USAGE_SAMPLED_BIT |
1156*c8dee2aaSAndroid Build Coastguard Worker                                        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1157*c8dee2aaSAndroid Build Coastguard Worker                                        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1158*c8dee2aaSAndroid Build Coastguard Worker         this->fSupportedSampleCounts.initSampleCounts(interface, physDev, properties, format,
1159*c8dee2aaSAndroid Build Coastguard Worker                                                       usageFlags);
1160*c8dee2aaSAndroid Build Coastguard Worker     }
1161*c8dee2aaSAndroid Build Coastguard Worker }
1162*c8dee2aaSAndroid Build Coastguard Worker 
isTexturable(VkImageTiling imageTiling) const1163*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::FormatInfo::isTexturable(VkImageTiling imageTiling) const {
1164*c8dee2aaSAndroid Build Coastguard Worker     switch (imageTiling) {
1165*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_OPTIMAL:
1166*c8dee2aaSAndroid Build Coastguard Worker             return is_texturable(fFormatProperties.optimalTilingFeatures);
1167*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_LINEAR:
1168*c8dee2aaSAndroid Build Coastguard Worker             return is_texturable(fFormatProperties.linearTilingFeatures);
1169*c8dee2aaSAndroid Build Coastguard Worker         default:
1170*c8dee2aaSAndroid Build Coastguard Worker             return false;
1171*c8dee2aaSAndroid Build Coastguard Worker     }
1172*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
1173*c8dee2aaSAndroid Build Coastguard Worker }
1174*c8dee2aaSAndroid Build Coastguard Worker 
isRenderable(VkImageTiling imageTiling,uint32_t sampleCount) const1175*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::FormatInfo::isRenderable(VkImageTiling imageTiling,
1176*c8dee2aaSAndroid Build Coastguard Worker                                           uint32_t sampleCount) const {
1177*c8dee2aaSAndroid Build Coastguard Worker     if (!fSupportedSampleCounts.isSampleCountSupported(sampleCount)) {
1178*c8dee2aaSAndroid Build Coastguard Worker         return false;
1179*c8dee2aaSAndroid Build Coastguard Worker     }
1180*c8dee2aaSAndroid Build Coastguard Worker     switch (imageTiling) {
1181*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_OPTIMAL:
1182*c8dee2aaSAndroid Build Coastguard Worker             return is_renderable(fFormatProperties.optimalTilingFeatures);
1183*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_LINEAR:
1184*c8dee2aaSAndroid Build Coastguard Worker             return is_renderable(fFormatProperties.linearTilingFeatures);
1185*c8dee2aaSAndroid Build Coastguard Worker         default:
1186*c8dee2aaSAndroid Build Coastguard Worker             return false;
1187*c8dee2aaSAndroid Build Coastguard Worker     }
1188*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
1189*c8dee2aaSAndroid Build Coastguard Worker }
1190*c8dee2aaSAndroid Build Coastguard Worker 
isStorage(VkImageTiling imageTiling) const1191*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::FormatInfo::isStorage(VkImageTiling imageTiling) const {
1192*c8dee2aaSAndroid Build Coastguard Worker     switch (imageTiling) {
1193*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_OPTIMAL:
1194*c8dee2aaSAndroid Build Coastguard Worker             return is_storage(fFormatProperties.optimalTilingFeatures);
1195*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_LINEAR:
1196*c8dee2aaSAndroid Build Coastguard Worker             return is_storage(fFormatProperties.linearTilingFeatures);
1197*c8dee2aaSAndroid Build Coastguard Worker         default:
1198*c8dee2aaSAndroid Build Coastguard Worker             return false;
1199*c8dee2aaSAndroid Build Coastguard Worker     }
1200*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
1201*c8dee2aaSAndroid Build Coastguard Worker }
1202*c8dee2aaSAndroid Build Coastguard Worker 
isTransferSrc(VkImageTiling imageTiling) const1203*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::FormatInfo::isTransferSrc(VkImageTiling imageTiling) const {
1204*c8dee2aaSAndroid Build Coastguard Worker     switch (imageTiling) {
1205*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_OPTIMAL:
1206*c8dee2aaSAndroid Build Coastguard Worker             return is_transfer_src(fFormatProperties.optimalTilingFeatures);
1207*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_LINEAR:
1208*c8dee2aaSAndroid Build Coastguard Worker             return is_transfer_src(fFormatProperties.linearTilingFeatures);
1209*c8dee2aaSAndroid Build Coastguard Worker         default:
1210*c8dee2aaSAndroid Build Coastguard Worker             return false;
1211*c8dee2aaSAndroid Build Coastguard Worker     }
1212*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
1213*c8dee2aaSAndroid Build Coastguard Worker }
1214*c8dee2aaSAndroid Build Coastguard Worker 
isTransferDst(VkImageTiling imageTiling) const1215*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::FormatInfo::isTransferDst(VkImageTiling imageTiling) const {
1216*c8dee2aaSAndroid Build Coastguard Worker     switch (imageTiling) {
1217*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_OPTIMAL:
1218*c8dee2aaSAndroid Build Coastguard Worker             return is_transfer_dst(fFormatProperties.optimalTilingFeatures);
1219*c8dee2aaSAndroid Build Coastguard Worker         case VK_IMAGE_TILING_LINEAR:
1220*c8dee2aaSAndroid Build Coastguard Worker             return is_transfer_dst(fFormatProperties.linearTilingFeatures);
1221*c8dee2aaSAndroid Build Coastguard Worker         default:
1222*c8dee2aaSAndroid Build Coastguard Worker             return false;
1223*c8dee2aaSAndroid Build Coastguard Worker     }
1224*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
1225*c8dee2aaSAndroid Build Coastguard Worker }
1226*c8dee2aaSAndroid Build Coastguard Worker 
setColorType(SkColorType colorType,std::initializer_list<VkFormat> formats)1227*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::setColorType(SkColorType colorType, std::initializer_list<VkFormat> formats) {
1228*c8dee2aaSAndroid Build Coastguard Worker     int idx = static_cast<int>(colorType);
1229*c8dee2aaSAndroid Build Coastguard Worker     for (auto it = formats.begin(); it != formats.end(); ++it) {
1230*c8dee2aaSAndroid Build Coastguard Worker         const auto& info = this->getFormatInfo(*it);
1231*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1232*c8dee2aaSAndroid Build Coastguard Worker             if (info.fColorTypeInfos[i].fColorType == colorType) {
1233*c8dee2aaSAndroid Build Coastguard Worker                 fColorTypeToFormatTable[idx] = *it;
1234*c8dee2aaSAndroid Build Coastguard Worker                 return;
1235*c8dee2aaSAndroid Build Coastguard Worker             }
1236*c8dee2aaSAndroid Build Coastguard Worker         }
1237*c8dee2aaSAndroid Build Coastguard Worker     }
1238*c8dee2aaSAndroid Build Coastguard Worker }
1239*c8dee2aaSAndroid Build Coastguard Worker 
getFormatFromColorType(SkColorType colorType) const1240*c8dee2aaSAndroid Build Coastguard Worker VkFormat VulkanCaps::getFormatFromColorType(SkColorType colorType) const {
1241*c8dee2aaSAndroid Build Coastguard Worker     int idx = static_cast<int>(colorType);
1242*c8dee2aaSAndroid Build Coastguard Worker     return fColorTypeToFormatTable[idx];
1243*c8dee2aaSAndroid Build Coastguard Worker }
1244*c8dee2aaSAndroid Build Coastguard Worker 
getFormatInfo(VkFormat format)1245*c8dee2aaSAndroid Build Coastguard Worker VulkanCaps::FormatInfo& VulkanCaps::getFormatInfo(VkFormat format) {
1246*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(kVkFormats) == VulkanCaps::kNumVkFormats,
1247*c8dee2aaSAndroid Build Coastguard Worker                   "Size of VkFormats array must match static value in header");
1248*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kVkFormats); ++i) {
1249*c8dee2aaSAndroid Build Coastguard Worker         if (kVkFormats[i] == format) {
1250*c8dee2aaSAndroid Build Coastguard Worker             return fFormatTable[i];
1251*c8dee2aaSAndroid Build Coastguard Worker         }
1252*c8dee2aaSAndroid Build Coastguard Worker     }
1253*c8dee2aaSAndroid Build Coastguard Worker     static FormatInfo kInvalidFormat;
1254*c8dee2aaSAndroid Build Coastguard Worker     return kInvalidFormat;
1255*c8dee2aaSAndroid Build Coastguard Worker }
1256*c8dee2aaSAndroid Build Coastguard Worker 
getFormatInfo(VkFormat format) const1257*c8dee2aaSAndroid Build Coastguard Worker const VulkanCaps::FormatInfo& VulkanCaps::getFormatInfo(VkFormat format) const {
1258*c8dee2aaSAndroid Build Coastguard Worker     VulkanCaps* nonConstThis = const_cast<VulkanCaps*>(this);
1259*c8dee2aaSAndroid Build Coastguard Worker     return nonConstThis->getFormatInfo(format);
1260*c8dee2aaSAndroid Build Coastguard Worker }
1261*c8dee2aaSAndroid Build Coastguard Worker 
init(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties,VkFormat format)1262*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::DepthStencilFormatInfo::init(const skgpu::VulkanInterface* interface,
1263*c8dee2aaSAndroid Build Coastguard Worker                                              VkPhysicalDevice physDev,
1264*c8dee2aaSAndroid Build Coastguard Worker                                              const VkPhysicalDeviceProperties& properties,
1265*c8dee2aaSAndroid Build Coastguard Worker                                              VkFormat format) {
1266*c8dee2aaSAndroid Build Coastguard Worker     memset(&fFormatProperties, 0, sizeof(VkFormatProperties));
1267*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &fFormatProperties));
1268*c8dee2aaSAndroid Build Coastguard Worker 
1269*c8dee2aaSAndroid Build Coastguard Worker     if (this->isDepthStencilSupported(fFormatProperties.optimalTilingFeatures)) {
1270*c8dee2aaSAndroid Build Coastguard Worker         VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1271*c8dee2aaSAndroid Build Coastguard Worker         fSupportedSampleCounts.initSampleCounts(interface, physDev, properties, format, usageFlags);
1272*c8dee2aaSAndroid Build Coastguard Worker     }
1273*c8dee2aaSAndroid Build Coastguard Worker }
1274*c8dee2aaSAndroid Build Coastguard Worker 
isDepthStencilSupported(VkFormatFeatureFlags flags) const1275*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::DepthStencilFormatInfo::isDepthStencilSupported(VkFormatFeatureFlags flags) const {
1276*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & flags);
1277*c8dee2aaSAndroid Build Coastguard Worker }
1278*c8dee2aaSAndroid Build Coastguard Worker 
getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags> & flags) const1279*c8dee2aaSAndroid Build Coastguard Worker VkFormat VulkanCaps::getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags>& flags)
1280*c8dee2aaSAndroid Build Coastguard Worker         const {
1281*c8dee2aaSAndroid Build Coastguard Worker     return fDepthStencilFlagsToFormatTable[flags.value()];
1282*c8dee2aaSAndroid Build Coastguard Worker }
1283*c8dee2aaSAndroid Build Coastguard Worker 
getDepthStencilFormatInfo(VkFormat format)1284*c8dee2aaSAndroid Build Coastguard Worker VulkanCaps::DepthStencilFormatInfo& VulkanCaps::getDepthStencilFormatInfo(VkFormat format) {
1285*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(kDepthStencilVkFormats) == VulkanCaps::kNumDepthStencilVkFormats,
1286*c8dee2aaSAndroid Build Coastguard Worker                   "Size of VkFormats array must match static value in header");
1287*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kDepthStencilVkFormats); ++i) {
1288*c8dee2aaSAndroid Build Coastguard Worker         if (kVkFormats[i] == format) {
1289*c8dee2aaSAndroid Build Coastguard Worker             return fDepthStencilFormatTable[i];
1290*c8dee2aaSAndroid Build Coastguard Worker         }
1291*c8dee2aaSAndroid Build Coastguard Worker     }
1292*c8dee2aaSAndroid Build Coastguard Worker     static DepthStencilFormatInfo kInvalidFormat;
1293*c8dee2aaSAndroid Build Coastguard Worker     return kInvalidFormat;
1294*c8dee2aaSAndroid Build Coastguard Worker }
1295*c8dee2aaSAndroid Build Coastguard Worker 
getDepthStencilFormatInfo(VkFormat format) const1296*c8dee2aaSAndroid Build Coastguard Worker const VulkanCaps::DepthStencilFormatInfo& VulkanCaps::getDepthStencilFormatInfo(VkFormat format)
1297*c8dee2aaSAndroid Build Coastguard Worker         const {
1298*c8dee2aaSAndroid Build Coastguard Worker     VulkanCaps* nonConstThis = const_cast<VulkanCaps*>(this);
1299*c8dee2aaSAndroid Build Coastguard Worker     return nonConstThis->getDepthStencilFormatInfo(format);
1300*c8dee2aaSAndroid Build Coastguard Worker }
1301*c8dee2aaSAndroid Build Coastguard Worker 
getColorTypeInfo(SkColorType ct,const TextureInfo & textureInfo) const1302*c8dee2aaSAndroid Build Coastguard Worker const Caps::ColorTypeInfo* VulkanCaps::getColorTypeInfo(SkColorType ct,
1303*c8dee2aaSAndroid Build Coastguard Worker                                                         const TextureInfo& textureInfo) const {
1304*c8dee2aaSAndroid Build Coastguard Worker     VkFormat vkFormat = TextureInfos::GetVkFormat(textureInfo);
1305*c8dee2aaSAndroid Build Coastguard Worker     if (vkFormat == VK_FORMAT_UNDEFINED) {
1306*c8dee2aaSAndroid Build Coastguard Worker         // If VkFormat is undefined but there is a valid YCbCr conversion associated with the
1307*c8dee2aaSAndroid Build Coastguard Worker         // texture, then we know we are using an external format and can return color type
1308*c8dee2aaSAndroid Build Coastguard Worker         // info representative of external format color information.
1309*c8dee2aaSAndroid Build Coastguard Worker         return TextureInfos::GetVulkanYcbcrConversionInfo(textureInfo).isValid()
1310*c8dee2aaSAndroid Build Coastguard Worker                        ? &fExternalFormatColorTypeInfo
1311*c8dee2aaSAndroid Build Coastguard Worker                        : nullptr;
1312*c8dee2aaSAndroid Build Coastguard Worker     }
1313*c8dee2aaSAndroid Build Coastguard Worker 
1314*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkFormat);
1315*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1316*c8dee2aaSAndroid Build Coastguard Worker         const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i];
1317*c8dee2aaSAndroid Build Coastguard Worker         if (ctInfo.fColorType == ct) {
1318*c8dee2aaSAndroid Build Coastguard Worker             return &ctInfo;
1319*c8dee2aaSAndroid Build Coastguard Worker         }
1320*c8dee2aaSAndroid Build Coastguard Worker     }
1321*c8dee2aaSAndroid Build Coastguard Worker 
1322*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
1323*c8dee2aaSAndroid Build Coastguard Worker }
1324*c8dee2aaSAndroid Build Coastguard Worker 
onIsTexturable(const TextureInfo & texInfo) const1325*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::onIsTexturable(const TextureInfo& texInfo) const {
1326*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1327*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(texInfo, &vkInfo)) {
1328*c8dee2aaSAndroid Build Coastguard Worker         return false;
1329*c8dee2aaSAndroid Build Coastguard Worker     }
1330*c8dee2aaSAndroid Build Coastguard Worker     return this->isTexturable(vkInfo);
1331*c8dee2aaSAndroid Build Coastguard Worker }
1332*c8dee2aaSAndroid Build Coastguard Worker 
isTexturable(const VulkanTextureInfo & vkInfo) const1333*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::isTexturable(const VulkanTextureInfo& vkInfo) const {
1334*c8dee2aaSAndroid Build Coastguard Worker     // All images using external formats are required to be able to be sampled per Vulkan spec.
1335*c8dee2aaSAndroid Build Coastguard Worker     // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkAndroidHardwareBufferFormatPropertiesANDROID.html#_description
1336*c8dee2aaSAndroid Build Coastguard Worker     if (vkInfo.fFormat == VK_FORMAT_UNDEFINED && vkInfo.fYcbcrConversionInfo.isValid()) {
1337*c8dee2aaSAndroid Build Coastguard Worker         return true;
1338*c8dee2aaSAndroid Build Coastguard Worker     }
1339*c8dee2aaSAndroid Build Coastguard Worker 
1340*c8dee2aaSAndroid Build Coastguard Worker     // Otherwise, we are working with a known format and can simply reference the format table info.
1341*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1342*c8dee2aaSAndroid Build Coastguard Worker     return info.isTexturable(vkInfo.fImageTiling);
1343*c8dee2aaSAndroid Build Coastguard Worker }
1344*c8dee2aaSAndroid Build Coastguard Worker 
isRenderable(const TextureInfo & texInfo) const1345*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::isRenderable(const TextureInfo& texInfo) const {
1346*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1347*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(texInfo, &vkInfo)) {
1348*c8dee2aaSAndroid Build Coastguard Worker         return false;
1349*c8dee2aaSAndroid Build Coastguard Worker     }
1350*c8dee2aaSAndroid Build Coastguard Worker     return this->isRenderable(vkInfo);
1351*c8dee2aaSAndroid Build Coastguard Worker }
1352*c8dee2aaSAndroid Build Coastguard Worker 
isRenderable(const VulkanTextureInfo & vkInfo) const1353*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::isRenderable(const VulkanTextureInfo& vkInfo) const {
1354*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1355*c8dee2aaSAndroid Build Coastguard Worker     return info.isRenderable(vkInfo.fImageTiling, vkInfo.fSampleCount);
1356*c8dee2aaSAndroid Build Coastguard Worker }
1357*c8dee2aaSAndroid Build Coastguard Worker 
isStorage(const TextureInfo & texInfo) const1358*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::isStorage(const TextureInfo& texInfo) const {
1359*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1360*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(texInfo, &vkInfo)) {
1361*c8dee2aaSAndroid Build Coastguard Worker         return false;
1362*c8dee2aaSAndroid Build Coastguard Worker     }
1363*c8dee2aaSAndroid Build Coastguard Worker 
1364*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1365*c8dee2aaSAndroid Build Coastguard Worker     return info.isStorage(vkInfo.fImageTiling);
1366*c8dee2aaSAndroid Build Coastguard Worker }
1367*c8dee2aaSAndroid Build Coastguard Worker 
isTransferSrc(const VulkanTextureInfo & vkInfo) const1368*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::isTransferSrc(const VulkanTextureInfo& vkInfo) const {
1369*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1370*c8dee2aaSAndroid Build Coastguard Worker     return info.isTransferSrc(vkInfo.fImageTiling);
1371*c8dee2aaSAndroid Build Coastguard Worker }
1372*c8dee2aaSAndroid Build Coastguard Worker 
isTransferDst(const VulkanTextureInfo & vkInfo) const1373*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::isTransferDst(const VulkanTextureInfo& vkInfo) const {
1374*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1375*c8dee2aaSAndroid Build Coastguard Worker     return info.isTransferDst(vkInfo.fImageTiling);
1376*c8dee2aaSAndroid Build Coastguard Worker }
1377*c8dee2aaSAndroid Build Coastguard Worker 
supportsWritePixels(const TextureInfo & texInfo) const1378*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::supportsWritePixels(const TextureInfo& texInfo) const {
1379*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1380*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(texInfo, &vkInfo)) {
1381*c8dee2aaSAndroid Build Coastguard Worker         return false;
1382*c8dee2aaSAndroid Build Coastguard Worker     }
1383*c8dee2aaSAndroid Build Coastguard Worker 
1384*c8dee2aaSAndroid Build Coastguard Worker     // Can't write if it needs a YCbCr sampler
1385*c8dee2aaSAndroid Build Coastguard Worker     if (VkFormatNeedsYcbcrSampler(vkInfo.fFormat)) {
1386*c8dee2aaSAndroid Build Coastguard Worker         return false;
1387*c8dee2aaSAndroid Build Coastguard Worker     }
1388*c8dee2aaSAndroid Build Coastguard Worker 
1389*c8dee2aaSAndroid Build Coastguard Worker     if (vkInfo.fSampleCount > 1) {
1390*c8dee2aaSAndroid Build Coastguard Worker         return false;
1391*c8dee2aaSAndroid Build Coastguard Worker     }
1392*c8dee2aaSAndroid Build Coastguard Worker 
1393*c8dee2aaSAndroid Build Coastguard Worker     if (!SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
1394*c8dee2aaSAndroid Build Coastguard Worker         return false;
1395*c8dee2aaSAndroid Build Coastguard Worker     }
1396*c8dee2aaSAndroid Build Coastguard Worker 
1397*c8dee2aaSAndroid Build Coastguard Worker     return true;
1398*c8dee2aaSAndroid Build Coastguard Worker }
1399*c8dee2aaSAndroid Build Coastguard Worker 
supportsReadPixels(const TextureInfo & texInfo) const1400*c8dee2aaSAndroid Build Coastguard Worker bool VulkanCaps::supportsReadPixels(const TextureInfo& texInfo) const {
1401*c8dee2aaSAndroid Build Coastguard Worker     if (texInfo.isProtected() == Protected::kYes) {
1402*c8dee2aaSAndroid Build Coastguard Worker         return false;
1403*c8dee2aaSAndroid Build Coastguard Worker     }
1404*c8dee2aaSAndroid Build Coastguard Worker 
1405*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1406*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(texInfo, &vkInfo)) {
1407*c8dee2aaSAndroid Build Coastguard Worker         return false;
1408*c8dee2aaSAndroid Build Coastguard Worker     }
1409*c8dee2aaSAndroid Build Coastguard Worker 
1410*c8dee2aaSAndroid Build Coastguard Worker     // Can't read if it needs a YCbCr sampler
1411*c8dee2aaSAndroid Build Coastguard Worker     if (VkFormatNeedsYcbcrSampler(vkInfo.fFormat)) {
1412*c8dee2aaSAndroid Build Coastguard Worker         return false;
1413*c8dee2aaSAndroid Build Coastguard Worker     }
1414*c8dee2aaSAndroid Build Coastguard Worker 
1415*c8dee2aaSAndroid Build Coastguard Worker     if (VkFormatIsCompressed(vkInfo.fFormat)) {
1416*c8dee2aaSAndroid Build Coastguard Worker         return false;
1417*c8dee2aaSAndroid Build Coastguard Worker     }
1418*c8dee2aaSAndroid Build Coastguard Worker 
1419*c8dee2aaSAndroid Build Coastguard Worker     if (vkInfo.fSampleCount > 1) {
1420*c8dee2aaSAndroid Build Coastguard Worker         return false;
1421*c8dee2aaSAndroid Build Coastguard Worker     }
1422*c8dee2aaSAndroid Build Coastguard Worker 
1423*c8dee2aaSAndroid Build Coastguard Worker     if (!SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) {
1424*c8dee2aaSAndroid Build Coastguard Worker         return false;
1425*c8dee2aaSAndroid Build Coastguard Worker     }
1426*c8dee2aaSAndroid Build Coastguard Worker 
1427*c8dee2aaSAndroid Build Coastguard Worker     return true;
1428*c8dee2aaSAndroid Build Coastguard Worker }
1429*c8dee2aaSAndroid Build Coastguard Worker 
supportedWritePixelsColorType(SkColorType dstColorType,const TextureInfo & dstTextureInfo,SkColorType srcColorType) const1430*c8dee2aaSAndroid Build Coastguard Worker std::pair<SkColorType, bool /*isRGBFormat*/> VulkanCaps::supportedWritePixelsColorType(
1431*c8dee2aaSAndroid Build Coastguard Worker         SkColorType dstColorType,
1432*c8dee2aaSAndroid Build Coastguard Worker         const TextureInfo& dstTextureInfo,
1433*c8dee2aaSAndroid Build Coastguard Worker         SkColorType srcColorType) const {
1434*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1435*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(dstTextureInfo, &vkInfo)) {
1436*c8dee2aaSAndroid Build Coastguard Worker         return {kUnknown_SkColorType, false};
1437*c8dee2aaSAndroid Build Coastguard Worker     }
1438*c8dee2aaSAndroid Build Coastguard Worker 
1439*c8dee2aaSAndroid Build Coastguard Worker     // Can't write to YCbCr formats
1440*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Can't write to external formats, either
1441*c8dee2aaSAndroid Build Coastguard Worker     if (VkFormatNeedsYcbcrSampler(vkInfo.fFormat)) {
1442*c8dee2aaSAndroid Build Coastguard Worker         return {kUnknown_SkColorType, false};
1443*c8dee2aaSAndroid Build Coastguard Worker     }
1444*c8dee2aaSAndroid Build Coastguard Worker 
1445*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1446*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1447*c8dee2aaSAndroid Build Coastguard Worker         const auto& ctInfo = info.fColorTypeInfos[i];
1448*c8dee2aaSAndroid Build Coastguard Worker         if (ctInfo.fColorType == dstColorType) {
1449*c8dee2aaSAndroid Build Coastguard Worker             return {ctInfo.fTransferColorType, vkInfo.fFormat == VK_FORMAT_R8G8B8_UNORM};
1450*c8dee2aaSAndroid Build Coastguard Worker         }
1451*c8dee2aaSAndroid Build Coastguard Worker     }
1452*c8dee2aaSAndroid Build Coastguard Worker 
1453*c8dee2aaSAndroid Build Coastguard Worker     return {kUnknown_SkColorType, false};
1454*c8dee2aaSAndroid Build Coastguard Worker }
1455*c8dee2aaSAndroid Build Coastguard Worker 
supportedReadPixelsColorType(SkColorType srcColorType,const TextureInfo & srcTextureInfo,SkColorType dstColorType) const1456*c8dee2aaSAndroid Build Coastguard Worker std::pair<SkColorType, bool /*isRGBFormat*/> VulkanCaps::supportedReadPixelsColorType(
1457*c8dee2aaSAndroid Build Coastguard Worker         SkColorType srcColorType,
1458*c8dee2aaSAndroid Build Coastguard Worker         const TextureInfo& srcTextureInfo,
1459*c8dee2aaSAndroid Build Coastguard Worker         SkColorType dstColorType) const {
1460*c8dee2aaSAndroid Build Coastguard Worker     VulkanTextureInfo vkInfo;
1461*c8dee2aaSAndroid Build Coastguard Worker     if (!TextureInfos::GetVulkanTextureInfo(srcTextureInfo, &vkInfo)) {
1462*c8dee2aaSAndroid Build Coastguard Worker         return {kUnknown_SkColorType, false};
1463*c8dee2aaSAndroid Build Coastguard Worker     }
1464*c8dee2aaSAndroid Build Coastguard Worker 
1465*c8dee2aaSAndroid Build Coastguard Worker     // Can't read from YCbCr formats
1466*c8dee2aaSAndroid Build Coastguard Worker     // TODO: external formats?
1467*c8dee2aaSAndroid Build Coastguard Worker     if (VkFormatNeedsYcbcrSampler(vkInfo.fFormat)) {
1468*c8dee2aaSAndroid Build Coastguard Worker         return {kUnknown_SkColorType, false};
1469*c8dee2aaSAndroid Build Coastguard Worker     }
1470*c8dee2aaSAndroid Build Coastguard Worker 
1471*c8dee2aaSAndroid Build Coastguard Worker     // TODO: handle compressed formats
1472*c8dee2aaSAndroid Build Coastguard Worker     if (VkFormatIsCompressed(vkInfo.fFormat)) {
1473*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->isTexturable(vkInfo));
1474*c8dee2aaSAndroid Build Coastguard Worker         return {kUnknown_SkColorType, false};
1475*c8dee2aaSAndroid Build Coastguard Worker     }
1476*c8dee2aaSAndroid Build Coastguard Worker 
1477*c8dee2aaSAndroid Build Coastguard Worker     const FormatInfo& info = this->getFormatInfo(vkInfo.fFormat);
1478*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1479*c8dee2aaSAndroid Build Coastguard Worker         const auto& ctInfo = info.fColorTypeInfos[i];
1480*c8dee2aaSAndroid Build Coastguard Worker         if (ctInfo.fColorType == srcColorType) {
1481*c8dee2aaSAndroid Build Coastguard Worker             return {ctInfo.fTransferColorType, vkInfo.fFormat == VK_FORMAT_R8G8B8_UNORM};
1482*c8dee2aaSAndroid Build Coastguard Worker         }
1483*c8dee2aaSAndroid Build Coastguard Worker     }
1484*c8dee2aaSAndroid Build Coastguard Worker 
1485*c8dee2aaSAndroid Build Coastguard Worker     return {kUnknown_SkColorType, false};
1486*c8dee2aaSAndroid Build Coastguard Worker }
1487*c8dee2aaSAndroid Build Coastguard Worker 
makeGraphicsPipelineKey(const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc) const1488*c8dee2aaSAndroid Build Coastguard Worker UniqueKey VulkanCaps::makeGraphicsPipelineKey(const GraphicsPipelineDesc& pipelineDesc,
1489*c8dee2aaSAndroid Build Coastguard Worker                                               const RenderPassDesc& renderPassDesc) const {
1490*c8dee2aaSAndroid Build Coastguard Worker     UniqueKey pipelineKey;
1491*c8dee2aaSAndroid Build Coastguard Worker     {
1492*c8dee2aaSAndroid Build Coastguard Worker         static const skgpu::UniqueKey::Domain kGraphicsPipelineDomain =
1493*c8dee2aaSAndroid Build Coastguard Worker             UniqueKey::GenerateDomain();
1494*c8dee2aaSAndroid Build Coastguard Worker 
1495*c8dee2aaSAndroid Build Coastguard Worker         VulkanRenderPass::VulkanRenderPassMetaData rpMetaData {renderPassDesc};
1496*c8dee2aaSAndroid Build Coastguard Worker 
1497*c8dee2aaSAndroid Build Coastguard Worker         // Reserve 3 uint32s for the render step id, paint id, and write swizzle.
1498*c8dee2aaSAndroid Build Coastguard Worker         static constexpr int kUint32sNeededForPipelineInfo = 3;
1499*c8dee2aaSAndroid Build Coastguard Worker         // The uint32s needed for a RenderPass is variable number, so consult rpMetaData to
1500*c8dee2aaSAndroid Build Coastguard Worker         // determine how many to reserve.
1501*c8dee2aaSAndroid Build Coastguard Worker         UniqueKey::Builder builder(&pipelineKey,
1502*c8dee2aaSAndroid Build Coastguard Worker                                    kGraphicsPipelineDomain,
1503*c8dee2aaSAndroid Build Coastguard Worker                                    kUint32sNeededForPipelineInfo + rpMetaData.fUint32DataCnt,
1504*c8dee2aaSAndroid Build Coastguard Worker                                    "GraphicsPipeline");
1505*c8dee2aaSAndroid Build Coastguard Worker 
1506*c8dee2aaSAndroid Build Coastguard Worker         int idx = 0;
1507*c8dee2aaSAndroid Build Coastguard Worker         // Add GraphicsPipelineDesc information
1508*c8dee2aaSAndroid Build Coastguard Worker         builder[idx++] = pipelineDesc.renderStepID();
1509*c8dee2aaSAndroid Build Coastguard Worker         builder[idx++] = pipelineDesc.paintParamsID().asUInt();
1510*c8dee2aaSAndroid Build Coastguard Worker         // Add RenderPass info relevant for pipeline creation that's not captured in RenderPass keys
1511*c8dee2aaSAndroid Build Coastguard Worker         builder[idx++] = renderPassDesc.fWriteSwizzle.asKey();
1512*c8dee2aaSAndroid Build Coastguard Worker         // Add RenderPassDesc information
1513*c8dee2aaSAndroid Build Coastguard Worker         VulkanRenderPass::AddRenderPassInfoToKey(rpMetaData, builder, idx, /*compatibleOnly=*/true);
1514*c8dee2aaSAndroid Build Coastguard Worker 
1515*c8dee2aaSAndroid Build Coastguard Worker         builder.finish();
1516*c8dee2aaSAndroid Build Coastguard Worker     }
1517*c8dee2aaSAndroid Build Coastguard Worker 
1518*c8dee2aaSAndroid Build Coastguard Worker     return pipelineKey;
1519*c8dee2aaSAndroid Build Coastguard Worker }
1520*c8dee2aaSAndroid Build Coastguard Worker 
makeSamplerKey(const SamplerDesc & samplerDesc) const1521*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey VulkanCaps::makeSamplerKey(const SamplerDesc& samplerDesc) const {
1522*c8dee2aaSAndroid Build Coastguard Worker     GraphiteResourceKey samplerKey;
1523*c8dee2aaSAndroid Build Coastguard Worker     const SkSpan<const uint32_t>& samplerData = samplerDesc.asSpan();
1524*c8dee2aaSAndroid Build Coastguard Worker     static const ResourceType kSamplerType = GraphiteResourceKey::GenerateResourceType();
1525*c8dee2aaSAndroid Build Coastguard Worker     // Non-format ycbcr and sampler information are guaranteed to fit within one uint32, so the size
1526*c8dee2aaSAndroid Build Coastguard Worker     // of the returned span accurately captures the quantity of uint32s needed whether the sampler
1527*c8dee2aaSAndroid Build Coastguard Worker     // is immutable or not.
1528*c8dee2aaSAndroid Build Coastguard Worker     GraphiteResourceKey::Builder builder(&samplerKey, kSamplerType, samplerData.size(),
1529*c8dee2aaSAndroid Build Coastguard Worker                                          Shareable::kYes);
1530*c8dee2aaSAndroid Build Coastguard Worker 
1531*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < samplerData.size(); i++) {
1532*c8dee2aaSAndroid Build Coastguard Worker         builder[i] = samplerData[i];
1533*c8dee2aaSAndroid Build Coastguard Worker     }
1534*c8dee2aaSAndroid Build Coastguard Worker 
1535*c8dee2aaSAndroid Build Coastguard Worker     builder.finish();
1536*c8dee2aaSAndroid Build Coastguard Worker     return samplerKey;
1537*c8dee2aaSAndroid Build Coastguard Worker }
1538*c8dee2aaSAndroid Build Coastguard Worker 
buildKeyForTexture(SkISize dimensions,const TextureInfo & info,ResourceType type,Shareable shareable,GraphiteResourceKey * key) const1539*c8dee2aaSAndroid Build Coastguard Worker void VulkanCaps::buildKeyForTexture(SkISize dimensions,
1540*c8dee2aaSAndroid Build Coastguard Worker                                     const TextureInfo& info,
1541*c8dee2aaSAndroid Build Coastguard Worker                                     ResourceType type,
1542*c8dee2aaSAndroid Build Coastguard Worker                                     Shareable shareable,
1543*c8dee2aaSAndroid Build Coastguard Worker                                     GraphiteResourceKey* key) const {
1544*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!dimensions.isEmpty());
1545*c8dee2aaSAndroid Build Coastguard Worker 
1546*c8dee2aaSAndroid Build Coastguard Worker     const VulkanTextureSpec vkSpec = TextureInfos::GetVulkanTextureSpec(info);
1547*c8dee2aaSAndroid Build Coastguard Worker     // We expect that the VkFormat enum is at most a 32-bit value.
1548*c8dee2aaSAndroid Build Coastguard Worker     static_assert(VK_FORMAT_MAX_ENUM == 0x7FFFFFFF);
1549*c8dee2aaSAndroid Build Coastguard Worker     // We should either be using a known VkFormat or have a valid ycbcr conversion.
1550*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(vkSpec.fFormat != VK_FORMAT_UNDEFINED || vkSpec.fYcbcrConversionInfo.isValid());
1551*c8dee2aaSAndroid Build Coastguard Worker 
1552*c8dee2aaSAndroid Build Coastguard Worker     uint32_t format = static_cast<uint32_t>(vkSpec.fFormat);
1553*c8dee2aaSAndroid Build Coastguard Worker     uint32_t samples = SamplesToKey(info.numSamples());
1554*c8dee2aaSAndroid Build Coastguard Worker     // We don't have to key the number of mip levels because it is inherit in the combination of
1555*c8dee2aaSAndroid Build Coastguard Worker     // isMipped and dimensions.
1556*c8dee2aaSAndroid Build Coastguard Worker     bool isMipped = info.mipmapped() == Mipmapped::kYes;
1557*c8dee2aaSAndroid Build Coastguard Worker     Protected isProtected = info.isProtected();
1558*c8dee2aaSAndroid Build Coastguard Worker 
1559*c8dee2aaSAndroid Build Coastguard Worker     // Confirm all the below parts of the key can fit in a single uint32_t. The sum of the shift
1560*c8dee2aaSAndroid Build Coastguard Worker     // amounts in the asserts must be less than or equal to 32. vkSpec.fFlags will go into its
1561*c8dee2aaSAndroid Build Coastguard Worker     // own 32-bit block.
1562*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(samples                            < (1u << 3));  // sample key is first 3 bits
1563*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(static_cast<uint32_t>(isMipped)    < (1u << 1));  // isMapped is 4th bit
1564*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(static_cast<uint32_t>(isProtected) < (1u << 1));  // isProtected is 5th bit
1565*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(vkSpec.fImageTiling                < (1u << 1));  // imageTiling is 6th bit
1566*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(vkSpec.fSharingMode                < (1u << 1));  // sharingMode is 7th bit
1567*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(vkSpec.fAspectMask                 < (1u << 11)); // aspectMask is bits 8 - 19
1568*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(vkSpec.fImageUsageFlags            < (1u << 12)); // imageUsageFlags are bits 20-32
1569*c8dee2aaSAndroid Build Coastguard Worker 
1570*c8dee2aaSAndroid Build Coastguard Worker     // We need two uint32_ts for dimensions, 1 for format, and 2 for the rest of the information.
1571*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int kNum32DataCntNoYcbcr =  2 + 1 + 2;
1572*c8dee2aaSAndroid Build Coastguard Worker     int num32DataCnt = kNum32DataCntNoYcbcr;
1573*c8dee2aaSAndroid Build Coastguard Worker 
1574*c8dee2aaSAndroid Build Coastguard Worker     // If a texture w/ an external format is being used, that information must also be appended.
1575*c8dee2aaSAndroid Build Coastguard Worker     const VulkanYcbcrConversionInfo& ycbcrInfo = TextureInfos::GetVulkanYcbcrConversionInfo(info);
1576*c8dee2aaSAndroid Build Coastguard Worker     num32DataCnt += ycbcrPackaging::numInt32sNeeded(ycbcrInfo);
1577*c8dee2aaSAndroid Build Coastguard Worker 
1578*c8dee2aaSAndroid Build Coastguard Worker     GraphiteResourceKey::Builder builder(key, type, num32DataCnt, shareable);
1579*c8dee2aaSAndroid Build Coastguard Worker 
1580*c8dee2aaSAndroid Build Coastguard Worker     int i = 0;
1581*c8dee2aaSAndroid Build Coastguard Worker     builder[i++] = dimensions.width();
1582*c8dee2aaSAndroid Build Coastguard Worker     builder[i++] = dimensions.height();
1583*c8dee2aaSAndroid Build Coastguard Worker 
1584*c8dee2aaSAndroid Build Coastguard Worker     if (ycbcrInfo.isValid()) {
1585*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(ycbcrInfo.fFormat != VK_FORMAT_UNDEFINED || ycbcrInfo.fExternalFormat != 0);
1586*c8dee2aaSAndroid Build Coastguard Worker         bool useExternalFormat = ycbcrInfo.fFormat == VK_FORMAT_UNDEFINED;
1587*c8dee2aaSAndroid Build Coastguard Worker         builder[i++] = ycbcrPackaging::nonFormatInfoAsUInt32(ycbcrInfo);
1588*c8dee2aaSAndroid Build Coastguard Worker         if (useExternalFormat) {
1589*c8dee2aaSAndroid Build Coastguard Worker             builder[i++] = (uint32_t)ycbcrInfo.fExternalFormat;
1590*c8dee2aaSAndroid Build Coastguard Worker             builder[i++] = (uint32_t)(ycbcrInfo.fExternalFormat >> 32);
1591*c8dee2aaSAndroid Build Coastguard Worker         } else {
1592*c8dee2aaSAndroid Build Coastguard Worker             builder[i++] =  ycbcrInfo.fFormat;
1593*c8dee2aaSAndroid Build Coastguard Worker         }
1594*c8dee2aaSAndroid Build Coastguard Worker     } else {
1595*c8dee2aaSAndroid Build Coastguard Worker         builder[i++] = format;
1596*c8dee2aaSAndroid Build Coastguard Worker     }
1597*c8dee2aaSAndroid Build Coastguard Worker 
1598*c8dee2aaSAndroid Build Coastguard Worker     builder[i++] = (static_cast<uint32_t>(vkSpec.fFlags));
1599*c8dee2aaSAndroid Build Coastguard Worker     builder[i++] = (samples                                            << 0 ) |
1600*c8dee2aaSAndroid Build Coastguard Worker                    (static_cast<uint32_t>(isMipped)                    << 3 ) |
1601*c8dee2aaSAndroid Build Coastguard Worker                    (static_cast<uint32_t>(isProtected)                 << 4 ) |
1602*c8dee2aaSAndroid Build Coastguard Worker                    (static_cast<uint32_t>(vkSpec.fImageTiling)         << 5 ) |
1603*c8dee2aaSAndroid Build Coastguard Worker                    (static_cast<uint32_t>(vkSpec.fSharingMode)         << 6 ) |
1604*c8dee2aaSAndroid Build Coastguard Worker                    (static_cast<uint32_t>(vkSpec.fAspectMask)          << 7 ) |
1605*c8dee2aaSAndroid Build Coastguard Worker                    (static_cast<uint32_t>(vkSpec.fImageUsageFlags)     << 19);
1606*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(i == num32DataCnt);
1607*c8dee2aaSAndroid Build Coastguard Worker }
1608*c8dee2aaSAndroid Build Coastguard Worker 
getImmutableSamplerInfo(const TextureProxy * proxy) const1609*c8dee2aaSAndroid Build Coastguard Worker ImmutableSamplerInfo VulkanCaps::getImmutableSamplerInfo(const TextureProxy* proxy) const {
1610*c8dee2aaSAndroid Build Coastguard Worker     if (proxy) {
1611*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::VulkanYcbcrConversionInfo& ycbcrConversionInfo =
1612*c8dee2aaSAndroid Build Coastguard Worker                 TextureInfos::GetVulkanYcbcrConversionInfo(proxy->textureInfo());
1613*c8dee2aaSAndroid Build Coastguard Worker 
1614*c8dee2aaSAndroid Build Coastguard Worker         if (ycbcrConversionInfo.isValid()) {
1615*c8dee2aaSAndroid Build Coastguard Worker             ImmutableSamplerInfo immutableSamplerInfo;
1616*c8dee2aaSAndroid Build Coastguard Worker             // ycbcrConversionInfo's fFormat being VK_FORMAT_UNDEFINED indicates we are using an
1617*c8dee2aaSAndroid Build Coastguard Worker             // external format rather than a known VkFormat.
1618*c8dee2aaSAndroid Build Coastguard Worker             immutableSamplerInfo.fFormat = ycbcrConversionInfo.fFormat == VK_FORMAT_UNDEFINED
1619*c8dee2aaSAndroid Build Coastguard Worker                     ? ycbcrConversionInfo.fExternalFormat
1620*c8dee2aaSAndroid Build Coastguard Worker                     : ycbcrConversionInfo.fFormat;
1621*c8dee2aaSAndroid Build Coastguard Worker             immutableSamplerInfo.fNonFormatYcbcrConversionInfo =
1622*c8dee2aaSAndroid Build Coastguard Worker                     ycbcrPackaging::nonFormatInfoAsUInt32(ycbcrConversionInfo);
1623*c8dee2aaSAndroid Build Coastguard Worker             return immutableSamplerInfo;
1624*c8dee2aaSAndroid Build Coastguard Worker         }
1625*c8dee2aaSAndroid Build Coastguard Worker     }
1626*c8dee2aaSAndroid Build Coastguard Worker 
1627*c8dee2aaSAndroid Build Coastguard Worker     // If the proxy is null or the YCbCr conversion for that proxy is invalid, then return a
1628*c8dee2aaSAndroid Build Coastguard Worker     // default ImmutableSamplerInfo struct.
1629*c8dee2aaSAndroid Build Coastguard Worker     return {};
1630*c8dee2aaSAndroid Build Coastguard Worker }
1631*c8dee2aaSAndroid Build Coastguard Worker 
1632*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
1633