1 /*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/graphite/vk/VulkanCaps.h"
9
10 #include "include/gpu/graphite/ContextOptions.h"
11 #include "include/gpu/graphite/TextureInfo.h"
12 #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
13 #include "include/gpu/vk/VulkanExtensions.h"
14 #include "src/gpu/ganesh/TestFormatColorTypeCombination.h"
15 #include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
16
17 #ifdef SK_BUILD_FOR_ANDROID
18 #include <sys/system_properties.h>
19 #endif
20
21 namespace skgpu::graphite {
22
VulkanCaps(const skgpu::VulkanInterface * vkInterface,VkPhysicalDevice physDev,uint32_t physicalDeviceVersion,const skgpu::VulkanExtensions * extensions,const ContextOptions & contextOptions)23 VulkanCaps::VulkanCaps(const skgpu::VulkanInterface* vkInterface,
24 VkPhysicalDevice physDev,
25 uint32_t physicalDeviceVersion,
26 const skgpu::VulkanExtensions* extensions,
27 const ContextOptions& contextOptions)
28 : Caps() {
29 this->init(vkInterface, physDev, physicalDeviceVersion, extensions, contextOptions);
30 }
31
~VulkanCaps()32 VulkanCaps::~VulkanCaps() {}
33
init(const skgpu::VulkanInterface * vkInterface,VkPhysicalDevice physDev,uint32_t physicalDeviceVersion,const skgpu::VulkanExtensions * extensions,const ContextOptions & contextOptions)34 void VulkanCaps::init(const skgpu::VulkanInterface* vkInterface,
35 VkPhysicalDevice physDev,
36 uint32_t physicalDeviceVersion,
37 const skgpu::VulkanExtensions* extensions,
38 const ContextOptions& contextOptions) {
39 VkPhysicalDeviceProperties physDevProperties;
40 VULKAN_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &physDevProperties));
41
42 // Graphite requires Vulkan version 1.1 or later, which has protected support.
43 fProtectedSupport = true;
44
45 // Enable the use of memoryless attachments for tiler GPUs (ARM Mali and Qualcomm Adreno).
46 if (physDevProperties.vendorID == kARM_VkVendor ||
47 physDevProperties.vendorID == kQualcomm_VkVendor) {
48 fSupportsMemorylessAttachments = true;
49 }
50
51 #ifdef SK_BUILD_FOR_UNIX
52 if (kNvidia_VkVendor == physDevProperties.vendorID) {
53 // On NVIDIA linux we see a big perf regression when not using dedicated image allocations.
54 fShouldAlwaysUseDedicatedImageMemory = true;
55 }
56 #endif
57
58 if (physDevProperties.vendorID == kNvidia_VkVendor ||
59 physDevProperties.vendorID == kAMD_VkVendor) {
60 // On discrete GPUs, it can be faster to read gpu-only memory compared to memory that is
61 // also mappable on the host.
62 fGpuOnlyBuffersMorePerformant = true;
63
64 // On discrete GPUs we try to use special DEVICE_LOCAL and HOST_VISIBLE memory for our
65 // cpu write, gpu read buffers. This memory is not ideal to be kept persistently mapped.
66 // Some discrete GPUs do not expose this special memory, however we still disable
67 // persistently mapped buffers for all of them since most GPUs with updated drivers do
68 // expose it. If this becomes an issue we can try to be more fine grained.
69 fShouldPersistentlyMapCpuToGpuBuffers = false;
70 }
71
72 this->initFormatTable(vkInterface, physDev, physDevProperties);
73 this->initDepthStencilFormatTable(vkInterface, physDev, physDevProperties);
74
75 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
76 this->applyDriverCorrectnessWorkarounds(physDevProperties);
77 }
78 }
79
applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties & properties)80 void VulkanCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) {
81 // By default, we initialize the Android API version to 0 since we consider certain things
82 // "fixed" only once above a certain version. This way, we default to enabling the workarounds.
83 int androidAPIVersion = 0;
84 #if defined(SK_BUILD_FOR_ANDROID)
85 char androidAPIVersionStr[PROP_VALUE_MAX];
86 int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersionStr);
87 // Defaults to zero since most checks care if it is greater than a specific value. So this will
88 // just default to it being less.
89 androidAPIVersion = (strLength == 0) ? 0 : atoi(androidAPIVersionStr);
90 #endif
91
92 // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
93 if (kARM_VkVendor == properties.vendorID && androidAPIVersion <= 28) {
94 fShouldAlwaysUseDedicatedImageMemory = true;
95 }
96 }
97
98 // These are all the valid VkFormats that we support in Skia. They are roughly ordered from most
99 // frequently used to least to improve look up times in arrays.
100 static constexpr VkFormat kVkFormats[] = {
101 VK_FORMAT_R8G8B8A8_UNORM,
102 VK_FORMAT_R8_UNORM,
103 VK_FORMAT_B8G8R8A8_UNORM,
104 VK_FORMAT_R5G6B5_UNORM_PACK16,
105 VK_FORMAT_R16G16B16A16_SFLOAT,
106 VK_FORMAT_R16_SFLOAT,
107 VK_FORMAT_R8G8B8_UNORM,
108 VK_FORMAT_R8G8_UNORM,
109 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
110 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
111 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
112 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
113 VK_FORMAT_R8G8B8A8_SRGB,
114 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
115 VK_FORMAT_BC1_RGB_UNORM_BLOCK,
116 VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
117 VK_FORMAT_R16_UNORM,
118 VK_FORMAT_R16G16_UNORM,
119 VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
120 VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
121 VK_FORMAT_R16G16B16A16_UNORM,
122 VK_FORMAT_R16G16_SFLOAT,
123 };
124 // These are all the valid depth/stencil formats that we support in Skia.
125 static constexpr VkFormat kDepthStencilVkFormats[] = {
126 VK_FORMAT_S8_UINT,
127 VK_FORMAT_D24_UNORM_S8_UINT,
128 VK_FORMAT_D32_SFLOAT_S8_UINT,
129 };
130
getDefaultSampledTextureInfo(SkColorType ct,Mipmapped mipmapped,Protected isProtected,Renderable isRenderable) const131 TextureInfo VulkanCaps::getDefaultSampledTextureInfo(SkColorType ct,
132 Mipmapped mipmapped,
133 Protected isProtected,
134 Renderable isRenderable) const {
135 VkFormat format = this->getFormatFromColorType(ct);
136 const FormatInfo& formatInfo = this->getFormatInfo(format);
137 static constexpr int defaultSampleCount = 1;
138 if ((isProtected == Protected::kYes && !this->protectedSupport()) ||
139 !formatInfo.isTexturable(VK_IMAGE_TILING_OPTIMAL) ||
140 (isRenderable == Renderable::kYes &&
141 !formatInfo.isRenderable(VK_IMAGE_TILING_OPTIMAL, defaultSampleCount)) ) {
142 return {};
143 }
144
145 VulkanTextureInfo info;
146 info.fSampleCount = defaultSampleCount;
147 info.fMipmapped = mipmapped;
148 info.fFlags = (isProtected == Protected::kYes) ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
149 info.fFormat = format;
150 info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
151 info.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
152 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
153 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
154 if (isRenderable == Renderable::kYes) {
155 info.fImageUsageFlags = info.fImageUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
156 }
157 info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
158 info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
159
160 return info;
161 }
162
getDefaultMSAATextureInfo(const TextureInfo & singleSampledInfo,Discardable discardable) const163 TextureInfo VulkanCaps::getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo,
164 Discardable discardable) const {
165 const VkFormat singleSpecFormat = singleSampledInfo.vulkanTextureSpec().fFormat;
166 const FormatInfo& formatInfo = this->getFormatInfo(singleSpecFormat);
167 if ((singleSampledInfo.isProtected() == Protected::kYes && !this->protectedSupport()) ||
168 !formatInfo.isRenderable(VK_IMAGE_TILING_OPTIMAL, this->defaultMSAASamples())) {
169 return {};
170 }
171
172 VulkanTextureInfo info;
173 info.fSampleCount = this->defaultMSAASamples();
174 info.fMipmapped = Mipmapped::kNo;
175 info.fFlags = (singleSampledInfo.isProtected() == Protected::kYes) ?
176 VK_IMAGE_CREATE_PROTECTED_BIT : 0;
177 info.fFormat = singleSpecFormat;
178 info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
179
180 /**
181 * Graphite, unlike ganesh, does not require a dedicated MSAA attachment on every surface.
182 * MSAA textures now get resolved within the scope of a render pass, which can be done simply
183 * with the color attachment usage flag. So we no longer require transfer src/dst usage flags.
184 */
185 VkImageUsageFlags flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
186 if (discardable == Discardable::kYes && fSupportsMemorylessAttachments) {
187 flags = flags | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
188 }
189
190 info.fImageUsageFlags = flags;
191 info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
192 info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
193
194 return info;
195 }
196
getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags> flags,uint32_t sampleCount,Protected isProtected) const197 TextureInfo VulkanCaps::getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags> flags,
198 uint32_t sampleCount,
199 Protected isProtected) const {
200 VkFormat format = getFormatFromDepthStencilFlags(flags);
201 const DepthStencilFormatInfo& formatInfo = this->getDepthStencilFormatInfo(format);
202 if ( (isProtected == Protected::kYes && !this->protectedSupport()) ||
203 !formatInfo.isDepthStencilSupported(formatInfo.fFormatProperties.optimalTilingFeatures) ||
204 !formatInfo.fSupportedSampleCounts.isSampleCountSupported(sampleCount)) {
205 return {};
206 }
207
208 VulkanTextureInfo info;
209 info.fSampleCount = sampleCount;
210 info.fMipmapped = Mipmapped::kNo;
211 info.fFlags = (isProtected == Protected::kYes) ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
212 info.fFormat = format;
213 info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
214 // TODO: Passing in a discardable flag to this method, and if true, add the TRANSIENT bit.
215 info.fImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
216 info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
217 info.fAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
218
219 return info;
220 }
221
initFormatTable(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties)222 void VulkanCaps::initFormatTable(const skgpu::VulkanInterface* interface,
223 VkPhysicalDevice physDev,
224 const VkPhysicalDeviceProperties& properties) {
225 static_assert(std::size(kVkFormats) == VulkanCaps::kNumVkFormats,
226 "Size of VkFormats array must match static value in header");
227
228 std::fill_n(fColorTypeToFormatTable, kSkColorTypeCnt, VK_FORMAT_UNDEFINED);
229
230 // Go through all the formats and init their support surface and data ColorTypes.
231 // Format: VK_FORMAT_R8G8B8A8_UNORM
232 {
233 constexpr VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
234 auto& info = this->getFormatInfo(format);
235 info.init(interface, physDev, properties, format);
236 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
237 info.fColorTypeInfoCount = 2;
238 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
239 int ctIdx = 0;
240 // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
241 {
242 constexpr SkColorType ct = SkColorType::kRGBA_8888_SkColorType;
243 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
244 ctInfo.fColorType = ct;
245 ctInfo.fTransferColorType = ct;
246 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
247 }
248 // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
249 {
250 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
251 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
252 ctInfo.fColorType = ct;
253 ctInfo.fTransferColorType = ct;
254 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
255 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
256 }
257 }
258 }
259
260 // Format: VK_FORMAT_R8_UNORM
261 {
262 constexpr VkFormat format = VK_FORMAT_R8_UNORM;
263 auto& info = this->getFormatInfo(format);
264 info.init(interface, physDev, properties, format);
265 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
266 info.fColorTypeInfoCount = 3;
267 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
268 int ctIdx = 0;
269 // Format: VK_FORMAT_R8_UNORM, Surface: kR_8
270 {
271 constexpr SkColorType ct = SkColorType::kR8_unorm_SkColorType;
272 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
273 ctInfo.fColorType = ct;
274 ctInfo.fTransferColorType = ct;
275 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
276 }
277 // Format: VK_FORMAT_R8_UNORM, Surface: kAlpha_8
278 {
279 constexpr SkColorType ct = SkColorType::kAlpha_8_SkColorType;
280 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
281 ctInfo.fColorType = ct;
282 ctInfo.fTransferColorType = ct;
283 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
284 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
285 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
286 }
287 // Format: VK_FORMAT_R8_UNORM, Surface: kGray_8
288 {
289 constexpr SkColorType ct = SkColorType::kGray_8_SkColorType;
290 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
291 ctInfo.fColorType = ct;
292 ctInfo.fTransferColorType = ct;
293 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
294 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
295 }
296 }
297 }
298
299 // Format: VK_FORMAT_B8G8R8A8_UNORM
300 {
301 constexpr VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
302 auto& info = this->getFormatInfo(format);
303 info.init(interface, physDev, properties, format);
304 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
305 info.fColorTypeInfoCount = 1;
306 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
307 int ctIdx = 0;
308 // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
309 {
310 constexpr SkColorType ct = SkColorType::kBGRA_8888_SkColorType;
311 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
312 ctInfo.fColorType = ct;
313 ctInfo.fTransferColorType = ct;
314 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
315 }
316 }
317 }
318 // Format: VK_FORMAT_R5G6B5_UNORM_PACK16
319 {
320 constexpr VkFormat format = VK_FORMAT_R5G6B5_UNORM_PACK16;
321 auto& info = this->getFormatInfo(format);
322 info.init(interface, physDev, properties, format);
323 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
324 info.fColorTypeInfoCount = 1;
325 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
326 int ctIdx = 0;
327 // Format: VK_FORMAT_R5G6B5_UNORM_PACK16, Surface: kRGB_565_SkColorType
328 {
329 constexpr SkColorType ct = SkColorType::kRGB_565_SkColorType;
330 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
331 ctInfo.fColorType = ct;
332 ctInfo.fTransferColorType = ct;
333 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
334 }
335 }
336 }
337 // Format: VK_FORMAT_R16G16B16A16_SFLOAT
338 {
339 constexpr VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT;
340 auto& info = this->getFormatInfo(format);
341 info.init(interface, physDev, properties, format);
342 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
343 info.fColorTypeInfoCount = 2;
344 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
345 int ctIdx = 0;
346 // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: SkColorType::kRGBA_F16_SkColorType
347 {
348 constexpr SkColorType ct = SkColorType::kRGBA_F16_SkColorType;
349 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
350 ctInfo.fColorType = ct;
351 ctInfo.fTransferColorType = ct;
352 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
353 }
354 }
355 }
356 // Format: VK_FORMAT_R16_SFLOAT
357 {
358 constexpr VkFormat format = VK_FORMAT_R16_SFLOAT;
359 auto& info = this->getFormatInfo(format);
360 info.init(interface, physDev, properties, format);
361 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
362 info.fColorTypeInfoCount = 1;
363 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
364 int ctIdx = 0;
365 // Format: VK_FORMAT_R16_SFLOAT, Surface: kAlpha_F16
366 {
367 constexpr SkColorType ct = SkColorType::kA16_float_SkColorType;
368 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
369 ctInfo.fColorType = ct;
370 ctInfo.fTransferColorType = ct;
371 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
372 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
373 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
374 }
375 }
376 }
377 // Format: VK_FORMAT_R8G8B8_UNORM
378 {
379 constexpr VkFormat format = VK_FORMAT_R8G8B8_UNORM;
380 auto& info = this->getFormatInfo(format);
381 info.init(interface, physDev, properties, format);
382 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
383 info.fColorTypeInfoCount = 1;
384 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
385 int ctIdx = 0;
386 // Format: VK_FORMAT_R8G8B8_UNORM, Surface: kRGB_888x
387 {
388 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
389 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
390 ctInfo.fColorType = ct;
391 // The Vulkan format is 3 bpp so we must convert to/from that when transferring.
392 ctInfo.fTransferColorType = SkColorType::kRGB_888x_SkColorType;
393 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
394 }
395 }
396 }
397 // Format: VK_FORMAT_R8G8_UNORM
398 {
399 constexpr VkFormat format = VK_FORMAT_R8G8_UNORM;
400 auto& info = this->getFormatInfo(format);
401 info.init(interface, physDev, properties, format);
402 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
403 info.fColorTypeInfoCount = 1;
404 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
405 int ctIdx = 0;
406 // Format: VK_FORMAT_R8G8_UNORM, Surface: kR8G8_unorm
407 {
408 constexpr SkColorType ct = SkColorType::kR8G8_unorm_SkColorType;
409 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
410 ctInfo.fColorType = ct;
411 ctInfo.fTransferColorType = ct;
412 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
413 }
414 }
415 }
416 // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32
417 {
418 constexpr VkFormat format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
419 auto& info = this->getFormatInfo(format);
420 info.init(interface, physDev, properties, format);
421 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
422 info.fColorTypeInfoCount = 1;
423 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
424 int ctIdx = 0;
425 // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGBA_1010102
426 {
427 constexpr SkColorType ct = SkColorType::kRGBA_1010102_SkColorType;
428 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
429 ctInfo.fColorType = ct;
430 ctInfo.fTransferColorType = ct;
431 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
432 }
433 }
434 }
435 // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32
436 {
437 constexpr VkFormat format = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
438 auto& info = this->getFormatInfo(format);
439 info.init(interface, physDev, properties, format);
440 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
441 info.fColorTypeInfoCount = 1;
442 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
443 int ctIdx = 0;
444 // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kBGRA_1010102
445 {
446 constexpr SkColorType ct = SkColorType::kBGRA_1010102_SkColorType;
447 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
448 ctInfo.fColorType = ct;
449 ctInfo.fTransferColorType = ct;
450 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
451 }
452 }
453 }
454 // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16
455 {
456 constexpr VkFormat format = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
457 auto& info = this->getFormatInfo(format);
458 info.init(interface, physDev, properties, format);
459 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
460 info.fColorTypeInfoCount = 1;
461 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
462 int ctIdx = 0;
463 // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16, Surface: kARGB_4444_SkColorType
464 {
465 constexpr SkColorType ct = SkColorType::kARGB_4444_SkColorType;
466 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
467 ctInfo.fColorType = ct;
468 ctInfo.fTransferColorType = ct;
469 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
470 ctInfo.fReadSwizzle = skgpu::Swizzle::BGRA();
471 ctInfo.fWriteSwizzle = skgpu::Swizzle::BGRA();
472 }
473 }
474 }
475
476 // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16
477 {
478 constexpr VkFormat format = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
479 auto& info = this->getFormatInfo(format);
480 info.init(interface, physDev, properties, format);
481 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
482 info.fColorTypeInfoCount = 1;
483 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
484 int ctIdx = 0;
485 // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16, Surface: kARGB_4444_SkColorType
486 {
487 constexpr SkColorType ct = SkColorType::kARGB_4444_SkColorType;
488 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
489 ctInfo.fColorType = ct;
490 ctInfo.fTransferColorType = ct;
491 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
492 }
493 }
494 }
495 // Format: VK_FORMAT_R8G8B8A8_SRGB
496 {
497 constexpr VkFormat format = VK_FORMAT_R8G8B8A8_SRGB;
498 auto& info = this->getFormatInfo(format);
499 info.init(interface, physDev, properties, format);
500 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
501 info.fColorTypeInfoCount = 1;
502 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
503 int ctIdx = 0;
504 // Format: VK_FORMAT_R8G8B8A8_SRGB, Surface: kRGBA_8888_SRGB
505 {
506 constexpr SkColorType ct = SkColorType::kSRGBA_8888_SkColorType;
507 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
508 ctInfo.fColorType = ct;
509 ctInfo.fTransferColorType = ct;
510 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
511 }
512 }
513 }
514 // Format: VK_FORMAT_R16_UNORM
515 {
516 constexpr VkFormat format = VK_FORMAT_R16_UNORM;
517 auto& info = this->getFormatInfo(format);
518 info.init(interface, physDev, properties, format);
519 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
520 info.fColorTypeInfoCount = 1;
521 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
522 int ctIdx = 0;
523 // Format: VK_FORMAT_R16_UNORM, Surface: kAlpha_16
524 {
525 constexpr SkColorType ct = SkColorType::kA16_unorm_SkColorType;
526 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
527 ctInfo.fColorType = ct;
528 ctInfo.fTransferColorType = ct;
529 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
530 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
531 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
532 }
533 }
534 }
535 // Format: VK_FORMAT_R16G16_UNORM
536 {
537 constexpr VkFormat format = VK_FORMAT_R16G16_UNORM;
538 auto& info = this->getFormatInfo(format);
539 info.init(interface, physDev, properties, format);
540 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
541 info.fColorTypeInfoCount = 1;
542 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
543 int ctIdx = 0;
544 // Format: VK_FORMAT_R16G16_UNORM, Surface: kRG_1616
545 {
546 constexpr SkColorType ct = SkColorType::kR16G16_unorm_SkColorType;
547 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
548 ctInfo.fColorType = ct;
549 ctInfo.fTransferColorType = ct;
550 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
551 }
552 }
553 }
554 // Format: VK_FORMAT_R16G16B16A16_UNORM
555 {
556 constexpr VkFormat format = VK_FORMAT_R16G16B16A16_UNORM;
557 auto& info = this->getFormatInfo(format);
558 info.init(interface, physDev, properties, format);
559 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
560 info.fColorTypeInfoCount = 1;
561 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
562 int ctIdx = 0;
563 // Format: VK_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
564 {
565 constexpr SkColorType ct = SkColorType::kR16G16B16A16_unorm_SkColorType;
566 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
567 ctInfo.fColorType = ct;
568 ctInfo.fTransferColorType = ct;
569 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
570 }
571 }
572 }
573 // Format: VK_FORMAT_R16G16_SFLOAT
574 {
575 constexpr VkFormat format = VK_FORMAT_R16G16_SFLOAT;
576 auto& info = this->getFormatInfo(format);
577 info.init(interface, physDev, properties, format);
578 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
579 info.fColorTypeInfoCount = 1;
580 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
581 int ctIdx = 0;
582 // Format: VK_FORMAT_R16G16_SFLOAT, Surface: kRG_F16
583 {
584 constexpr SkColorType ct = SkColorType::kR16G16_float_SkColorType;
585 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
586 ctInfo.fColorType = ct;
587 ctInfo.fTransferColorType = ct;
588 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
589 }
590 }
591 }
592 // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
593 {
594 constexpr VkFormat format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
595 auto& info = this->getFormatInfo(format);
596 if (fSupportsYcbcrConversion) {
597 info.init(interface, physDev, properties, format);
598 SkDEBUGCODE(info.fIsWrappedOnly = true;)
599 }
600 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
601 info.fColorTypeInfoCount = 1;
602 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
603 int ctIdx = 0;
604 // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, Surface: kRGB_888x
605 {
606 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
607 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
608 ctInfo.fColorType = ct;
609 ctInfo.fTransferColorType = ct;
610 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
611 }
612 }
613 }
614 // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
615 {
616 constexpr VkFormat format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
617 auto& info = this->getFormatInfo(format);
618 if (fSupportsYcbcrConversion) {
619 info.init(interface, physDev, properties, format);
620 SkDEBUGCODE(info.fIsWrappedOnly = true;)
621 }
622 if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) {
623 info.fColorTypeInfoCount = 1;
624 info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
625 int ctIdx = 0;
626 // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, Surface: kRGB_888x
627 {
628 constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType;
629 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
630 ctInfo.fColorType = ct;
631 ctInfo.fTransferColorType = ct;
632 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
633 }
634 }
635 }
636 // Format: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
637 {
638 constexpr VkFormat format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
639 auto& info = this->getFormatInfo(format);
640 info.init(interface, physDev, properties, format);
641 // Setting this to texel block size
642 // No supported SkColorType.
643 }
644
645 // Format: VK_FORMAT_BC1_RGB_UNORM_BLOCK
646 {
647 constexpr VkFormat format = VK_FORMAT_BC1_RGB_UNORM_BLOCK;
648 auto& info = this->getFormatInfo(format);
649 info.init(interface, physDev, properties, format);
650 // Setting this to texel block size
651 // No supported SkColorType.
652 }
653
654 // Format: VK_FORMAT_BC1_RGBA_UNORM_BLOCK
655 {
656 constexpr VkFormat format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
657 auto& info = this->getFormatInfo(format);
658 info.init(interface, physDev, properties, format);
659 // Setting this to texel block size
660 // No supported SkColorType.
661 }
662
663 ////////////////////////////////////////////////////////////////////////////
664 // Map SkColorType (used for creating Surfaces) to VkFormats. The order in which the formats are
665 // passed into the setColorType function indicates the priority in selecting which format we use
666 // for a given SkColorType.
667 typedef SkColorType ct;
668
669 this->setColorType(ct::kAlpha_8_SkColorType, { VK_FORMAT_R8_UNORM });
670 this->setColorType(ct::kRGB_565_SkColorType, { VK_FORMAT_R5G6B5_UNORM_PACK16 });
671 this->setColorType(ct::kARGB_4444_SkColorType, { VK_FORMAT_R4G4B4A4_UNORM_PACK16,
672 VK_FORMAT_B4G4R4A4_UNORM_PACK16 });
673 this->setColorType(ct::kRGBA_8888_SkColorType, { VK_FORMAT_R8G8B8A8_UNORM });
674 this->setColorType(ct::kSRGBA_8888_SkColorType, { VK_FORMAT_R8G8B8A8_SRGB });
675 this->setColorType(ct::kRGB_888x_SkColorType, { VK_FORMAT_R8G8B8_UNORM,
676 VK_FORMAT_R8G8B8A8_UNORM });
677 this->setColorType(ct::kR8G8_unorm_SkColorType, { VK_FORMAT_R8G8_UNORM });
678 this->setColorType(ct::kBGRA_8888_SkColorType, { VK_FORMAT_B8G8R8A8_UNORM });
679 this->setColorType(ct::kRGBA_1010102_SkColorType, { VK_FORMAT_A2B10G10R10_UNORM_PACK32 });
680 this->setColorType(ct::kBGRA_1010102_SkColorType, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 });
681 this->setColorType(ct::kGray_8_SkColorType, { VK_FORMAT_R8_UNORM });
682 this->setColorType(ct::kA16_float_SkColorType, { VK_FORMAT_R16_SFLOAT });
683 this->setColorType(ct::kRGBA_F16_SkColorType, { VK_FORMAT_R16G16B16A16_SFLOAT });
684 this->setColorType(ct::kA16_unorm_SkColorType, { VK_FORMAT_R16_UNORM });
685 this->setColorType(ct::kR16G16_unorm_SkColorType, { VK_FORMAT_R16G16_UNORM });
686 this->setColorType(ct::kR16G16B16A16_unorm_SkColorType, { VK_FORMAT_R16G16B16A16_UNORM });
687 this->setColorType(ct::kR16G16_float_SkColorType, { VK_FORMAT_R16G16_SFLOAT });
688 }
689
initDepthStencilFormatTable(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties)690 void VulkanCaps::initDepthStencilFormatTable(const skgpu::VulkanInterface* interface,
691 VkPhysicalDevice physDev,
692 const VkPhysicalDeviceProperties& properties) {
693 static_assert(std::size(kDepthStencilVkFormats) == VulkanCaps::kNumDepthStencilVkFormats,
694 "Size of DepthStencilVkFormats array must match static value in header");
695
696 std::fill_n(fDepthStencilFlagsToFormatTable, kNumDepthStencilFlags, VK_FORMAT_UNDEFINED);
697 // Format: VK_FORMAT_S8_UINT
698 {
699 constexpr VkFormat format = VK_FORMAT_S8_UINT;
700 auto& info = this->getDepthStencilFormatInfo(format);
701 info.init(interface, physDev, properties, format);
702 }
703 // Format: VK_FORMAT_D24_UNORM_S8_UINT
704 {
705 constexpr VkFormat format = VK_FORMAT_D24_UNORM_S8_UINT;
706 auto& info = this->getDepthStencilFormatInfo(format);
707 info.init(interface, physDev, properties, format);
708 }
709 // Format: VK_FORMAT_D32_SFLOAT_S8_UINT
710 {
711 constexpr VkFormat format = VK_FORMAT_D32_SFLOAT_S8_UINT;
712 auto& info = this->getDepthStencilFormatInfo(format);
713 info.init(interface, physDev, properties, format);
714 }
715 }
716
initSampleCounts(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & physProps,VkFormat format,VkImageUsageFlags usage)717 void VulkanCaps::SupportedSampleCounts::initSampleCounts(const skgpu::VulkanInterface* interface,
718 VkPhysicalDevice physDev,
719 const VkPhysicalDeviceProperties& physProps,
720 VkFormat format,
721 VkImageUsageFlags usage) {
722 VkImageFormatProperties properties;
723
724 VkResult result;
725 VULKAN_CALL_RESULT(interface, result,
726 GetPhysicalDeviceImageFormatProperties(physDev,
727 format,
728 VK_IMAGE_TYPE_2D,
729 VK_IMAGE_TILING_OPTIMAL,
730 usage,
731 0, // createFlags
732 &properties));
733 if (result != VK_SUCCESS) {
734 SKGPU_LOG_W("Vulkan call GetPhysicalDeviceImageFormatProperties failed");
735 return;
736 }
737
738 VkSampleCountFlags flags = properties.sampleCounts;
739 if (flags & VK_SAMPLE_COUNT_1_BIT) {
740 fSampleCounts.push_back(1);
741 }
742 if (kImagination_VkVendor == physProps.vendorID) {
743 // MSAA does not work on imagination
744 return;
745 }
746 if (kIntel_VkVendor == physProps.vendorID) {
747 // MSAA doesn't work well on Intel GPUs chromium:527565, chromium:983926
748 return;
749 }
750 if (flags & VK_SAMPLE_COUNT_2_BIT) {
751 fSampleCounts.push_back(2);
752 }
753 if (flags & VK_SAMPLE_COUNT_4_BIT) {
754 fSampleCounts.push_back(4);
755 }
756 if (flags & VK_SAMPLE_COUNT_8_BIT) {
757 fSampleCounts.push_back(8);
758 }
759 if (flags & VK_SAMPLE_COUNT_16_BIT) {
760 fSampleCounts.push_back(16);
761 }
762 // Standard sample locations are not defined for more than 16 samples, and we don't need more
763 // than 16. Omit 32 and 64.
764 }
765
isSampleCountSupported(int requestedCount) const766 bool VulkanCaps::SupportedSampleCounts::isSampleCountSupported(int requestedCount) const {
767 requestedCount = std::max(1, requestedCount);
768 for (int i = 0; i < fSampleCounts.size(); i++) {
769 if (fSampleCounts[i] == requestedCount) {
770 return true;
771 } else if (requestedCount < fSampleCounts[i]) {
772 return false;
773 }
774 }
775 return false;
776 }
777
init(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties,VkFormat format)778 void VulkanCaps::FormatInfo::init(const skgpu::VulkanInterface* interface,
779 VkPhysicalDevice physDev,
780 const VkPhysicalDeviceProperties& properties,
781 VkFormat format) {
782 memset(&fFormatProperties, 0, sizeof(VkFormatProperties));
783 VULKAN_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &fFormatProperties));
784
785 if (this->isRenderable(fFormatProperties.optimalTilingFeatures)) {
786 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
787 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
788 VK_IMAGE_USAGE_SAMPLED_BIT |
789 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
790 this->fSupportedSampleCounts.initSampleCounts(interface, physDev, properties, format,
791 usageFlags);
792 }
793 }
794
isTexturable(VkImageTiling imageTiling) const795 bool VulkanCaps::FormatInfo::isTexturable(VkImageTiling imageTiling) const {
796 switch (imageTiling) {
797 case VK_IMAGE_TILING_OPTIMAL:
798 return this->isTexturable(fFormatProperties.optimalTilingFeatures);
799 case VK_IMAGE_TILING_LINEAR:
800 return this->isTexturable(fFormatProperties.linearTilingFeatures);
801 default:
802 return false;
803 }
804 SkUNREACHABLE;
805 }
806
isRenderable(VkImageTiling imageTiling,uint32_t sampleCount) const807 bool VulkanCaps::FormatInfo::isRenderable(VkImageTiling imageTiling,
808 uint32_t sampleCount) const {
809 if (!fSupportedSampleCounts.isSampleCountSupported(sampleCount)) {
810 return false;
811 }
812 switch (imageTiling) {
813 case VK_IMAGE_TILING_OPTIMAL:
814 return this->isRenderable(fFormatProperties.optimalTilingFeatures);
815 case VK_IMAGE_TILING_LINEAR:
816 return this->isRenderable(fFormatProperties.linearTilingFeatures);
817 default:
818 return false;
819 }
820 SkUNREACHABLE;
821 }
822
isTexturable(VkFormatFeatureFlags flags) const823 bool VulkanCaps::FormatInfo::isTexturable(VkFormatFeatureFlags flags) const {
824 return SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & flags) &&
825 SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & flags);
826 }
827
isRenderable(VkFormatFeatureFlags flags) const828 bool VulkanCaps::FormatInfo::isRenderable(VkFormatFeatureFlags flags) const {
829 return SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & flags);
830 }
831
setColorType(SkColorType colorType,std::initializer_list<VkFormat> formats)832 void VulkanCaps::setColorType(SkColorType colorType, std::initializer_list<VkFormat> formats) {
833 #ifdef SK_DEBUG
834 // If any format's FormatInfo claims support for the passed-in colorType, ensure that format is
835 // included in the provided formats list.
836 for (size_t i = 0; i < kNumVkFormats; ++i) {
837 const auto& formatInfo = fFormatTable[i];
838 for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
839 const auto& ctInfo = formatInfo.fColorTypeInfos[j];
840 if (ctInfo.fColorType == colorType && !formatInfo.fIsWrappedOnly) {
841 bool found = false;
842 for (auto it = formats.begin(); it != formats.end(); ++it) {
843 if (kVkFormats[i] == *it) {
844 found = true;
845 }
846 }
847 SkASSERT(found);
848 }
849 }
850 }
851 #endif
852 int idx = static_cast<int>(colorType);
853 for (auto it = formats.begin(); it != formats.end(); ++it) {
854 const auto& info = this->getFormatInfo(*it);
855 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
856 if (info.fColorTypeInfos[i].fColorType == colorType) {
857 fColorTypeToFormatTable[idx] = *it;
858 return;
859 }
860 }
861 }
862 }
863
getFormatFromColorType(SkColorType colorType) const864 VkFormat VulkanCaps::getFormatFromColorType(SkColorType colorType) const {
865 int idx = static_cast<int>(colorType);
866 return fColorTypeToFormatTable[idx];
867 }
868
getFormatInfo(VkFormat format)869 VulkanCaps::FormatInfo& VulkanCaps::getFormatInfo(VkFormat format) {
870 static_assert(std::size(kVkFormats) == VulkanCaps::kNumVkFormats,
871 "Size of VkFormats array must match static value in header");
872 for (size_t i = 0; i < std::size(kVkFormats); ++i) {
873 if (kVkFormats[i] == format) {
874 return fFormatTable[i];
875 }
876 }
877 static FormatInfo kInvalidFormat;
878 return kInvalidFormat;
879 }
880
getFormatInfo(VkFormat format) const881 const VulkanCaps::FormatInfo& VulkanCaps::getFormatInfo(VkFormat format) const {
882 VulkanCaps* nonConstThis = const_cast<VulkanCaps*>(this);
883 return nonConstThis->getFormatInfo(format);
884 }
885
init(const skgpu::VulkanInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties,VkFormat format)886 void VulkanCaps::DepthStencilFormatInfo::init(const skgpu::VulkanInterface* interface,
887 VkPhysicalDevice physDev,
888 const VkPhysicalDeviceProperties& properties,
889 VkFormat format) {
890 memset(&fFormatProperties, 0, sizeof(VkFormatProperties));
891 VULKAN_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &fFormatProperties));
892
893 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
894 fSupportedSampleCounts.initSampleCounts(interface, physDev, properties, format, usageFlags);
895 }
896
isDepthStencilSupported(VkFormatFeatureFlags flags) const897 bool VulkanCaps::DepthStencilFormatInfo::isDepthStencilSupported(VkFormatFeatureFlags flags) const {
898 return SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & flags);
899 }
900
getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags> & flags) const901 VkFormat VulkanCaps::getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags>& flags)
902 const {
903 int idx = static_cast<int>(flags);
904 return fDepthStencilFlagsToFormatTable[idx];
905 }
906
getDepthStencilFormatInfo(VkFormat format)907 VulkanCaps::DepthStencilFormatInfo& VulkanCaps::getDepthStencilFormatInfo(VkFormat format) {
908 static_assert(std::size(kDepthStencilVkFormats) == VulkanCaps::kNumDepthStencilVkFormats,
909 "Size of VkFormats array must match static value in header");
910 for (size_t i = 0; i < std::size(kDepthStencilVkFormats); ++i) {
911 if (kVkFormats[i] == format) {
912 return fDepthStencilFormatTable[i];
913 }
914 }
915 static DepthStencilFormatInfo kInvalidFormat;
916 return kInvalidFormat;
917 }
918
getDepthStencilFormatInfo(VkFormat format) const919 const VulkanCaps::DepthStencilFormatInfo& VulkanCaps::getDepthStencilFormatInfo(VkFormat format)
920 const {
921 VulkanCaps* nonConstThis = const_cast<VulkanCaps*>(this);
922 return nonConstThis->getDepthStencilFormatInfo(format);
923 }
924 } // namespace skgpu::graphite
925
926