blob: 3fbc63b60c6f025957b8fcea3b025982e44144cd [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
2 * Copyright 2015 Google Inc.
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/gpu/GrBackendSurface.h"
9#include "include/gpu/GrRenderTarget.h"
10#include "include/gpu/vk/GrVkBackendContext.h"
11#include "include/gpu/vk/GrVkExtensions.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "src/gpu/GrRenderTargetProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrShaderCaps.h"
14#include "src/gpu/SkGr.h"
15#include "src/gpu/vk/GrVkCaps.h"
16#include "src/gpu/vk/GrVkInterface.h"
17#include "src/gpu/vk/GrVkTexture.h"
18#include "src/gpu/vk/GrVkUtil.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050019
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040020#ifdef SK_BUILD_FOR_ANDROID
21#include <sys/system_properties.h>
22#endif
23
Greg Daniel164a9f02016-02-22 09:56:40 -050024GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
Greg Daniela0651ac2018-08-08 09:23:18 -040025 VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
Greg Daniel41f0e282019-01-28 13:15:05 -050026 uint32_t instanceVersion, uint32_t physicalDeviceVersion,
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040027 const GrVkExtensions& extensions, GrProtected isProtected)
28 : INHERITED(contextOptions) {
Greg Daniel164a9f02016-02-22 09:56:40 -050029 /**************************************************************************
Brian Salomonf7232642018-09-19 08:58:08 -040030 * GrCaps fields
31 **************************************************************************/
jvanverth62340062016-04-26 08:01:44 -070032 fMipMapSupport = true; // always available in Vulkan
brianosmanf05ab1b2016-05-12 11:01:10 -070033 fSRGBSupport = true; // always available in Vulkan
brianosman88791862016-05-23 10:15:27 -070034 fNPOTTextureTileSupport = true; // always available in Vulkan
Greg Daniel164a9f02016-02-22 09:56:40 -050035 fReuseScratchTextures = true; //TODO: figure this out
36 fGpuTracingSupport = false; //TODO: figure this out
Greg Daniel164a9f02016-02-22 09:56:40 -050037 fOversizedStencilSupport = false; //TODO: figure this out
Chris Dalton1d616352017-05-31 12:51:23 -060038 fInstanceAttribSupport = true;
Greg Daniel164a9f02016-02-22 09:56:40 -050039
Brian Salomon9ff5acb2019-05-08 09:04:47 -040040 fSemaphoreSupport = true; // always available in Vulkan
jvanverth84741b32016-09-30 08:39:02 -070041 fFenceSyncSupport = true; // always available in Vulkan
Greg Daniel691f5e72018-02-28 14:21:34 -050042 fCrossContextTextureSupport = true;
Brian Osman499bf1a2018-09-17 11:32:42 -040043 fHalfFloatVertexAttributeSupport = true;
Greg Daniel164a9f02016-02-22 09:56:40 -050044
Brian Salomon1047a492019-07-02 12:25:21 -040045 // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
46 fReadPixelsRowBytesSupport = true;
47 fWritePixelsRowBytesSupport = true;
48
Brian Salomone05ba5a2019-04-08 11:59:07 -040049 fTransferBufferSupport = true;
Greg Daniel164a9f02016-02-22 09:56:40 -050050
51 fMaxRenderTargetSize = 4096; // minimum required by spec
52 fMaxTextureSize = 4096; // minimum required by spec
Greg Daniel164a9f02016-02-22 09:56:40 -050053
Brian Salomonf7232642018-09-19 08:58:08 -040054 fDynamicStateArrayGeometryProcessorTextureSupport = true;
55
Brian Salomon94efbf52016-11-29 13:43:05 -050056 fShaderCaps.reset(new GrShaderCaps(contextOptions));
Greg Daniel164a9f02016-02-22 09:56:40 -050057
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040058 this->init(contextOptions, vkInterface, physDev, features, physicalDeviceVersion, extensions,
59 isProtected);
Greg Daniel164a9f02016-02-22 09:56:40 -050060}
61
Robert Phillipsbf25d432017-04-07 10:08:53 -040062bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
Greg Daniel46cfbc62019-06-07 11:43:30 -040063 bool* rectsMustMatch, bool* disallowSubrect) const {
Eric Karl74480882017-04-03 14:49:05 -070064 // Vk doesn't use rectsMustMatch or disallowSubrect. Always return false.
65 *rectsMustMatch = false;
66 *disallowSubrect = false;
67
Brian Salomon467921e2017-03-06 16:17:12 -050068 // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
69 // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
70 // render target as well.
Brian Salomon467921e2017-03-06 16:17:12 -050071 desc->fConfig = src->config();
Chris Dalton6ce447a2019-06-23 18:07:38 -060072 if (src->numSamples() > 1 || src->asTextureProxy()) {
Brian Salomon467921e2017-03-06 16:17:12 -050073 desc->fFlags = kRenderTarget_GrSurfaceFlag;
74 } else {
75 // Just going to use CopyImage here
76 desc->fFlags = kNone_GrSurfaceFlags;
77 }
78
79 return true;
80}
81
Greg Daniel5c7b5412019-05-10 11:39:55 -040082static int get_compatible_format_class(GrPixelConfig config) {
83 switch (config) {
84 case kAlpha_8_GrPixelConfig:
85 case kAlpha_8_as_Red_GrPixelConfig:
86 case kGray_8_GrPixelConfig:
87 case kGray_8_as_Red_GrPixelConfig:
88 return 1;
89 case kRGB_565_GrPixelConfig:
90 case kRGBA_4444_GrPixelConfig:
91 case kRG_88_GrPixelConfig:
92 case kAlpha_half_GrPixelConfig:
93 case kAlpha_half_as_Red_GrPixelConfig:
Robert Phillips66a46032019-06-18 08:00:42 -040094 case kR_16_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -040095 return 2;
96 case kRGB_888_GrPixelConfig:
97 return 3;
98 case kRGBA_8888_GrPixelConfig:
99 case kRGB_888X_GrPixelConfig:
100 case kBGRA_8888_GrPixelConfig:
101 case kSRGBA_8888_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -0400102 case kRGBA_1010102_GrPixelConfig:
Robert Phillips66a46032019-06-18 08:00:42 -0400103 case kRG_1616_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -0400104 return 4;
105 case kRGBA_half_GrPixelConfig:
106 case kRGBA_half_Clamped_GrPixelConfig:
107 case kRG_float_GrPixelConfig:
108 return 5;
109 case kRGBA_float_GrPixelConfig:
110 return 6;
111 case kRGB_ETC1_GrPixelConfig:
112 return 7;
113 case kUnknown_GrPixelConfig:
114 case kAlpha_8_as_Alpha_GrPixelConfig:
115 case kGray_8_as_Lum_GrPixelConfig:
116 SK_ABORT("Unsupported Vulkan pixel config");
117 return 0;
Robert Phillips66a46032019-06-18 08:00:42 -0400118
119 // Experimental (for Y416 and mutant P016/P010)
120 case kRGBA_16161616_GrPixelConfig:
121 return 8;
122 case kRG_half_GrPixelConfig:
Robert Phillipsfe18de52019-06-06 17:21:50 -0400123 return 4;
Greg Daniel5c7b5412019-05-10 11:39:55 -0400124 }
125 SK_ABORT("Invalid pixel config");
126 return 0;
127}
128
Greg Daniel46cfbc62019-06-07 11:43:30 -0400129bool GrVkCaps::canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
130 GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
Greg Daniel25af6712018-04-25 10:44:38 -0400131 if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
132 return false;
133 }
134
Greg Daniela51e93c2019-03-25 12:30:45 -0400135 if (dstHasYcbcr || srcHasYcbcr) {
136 return false;
137 }
138
Greg Daniel25af6712018-04-25 10:44:38 -0400139 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
140 // as image usage flags.
Greg Daniel46cfbc62019-06-07 11:43:30 -0400141 if (get_compatible_format_class(srcConfig) != get_compatible_format_class(dstConfig)) {
Greg Daniel25af6712018-04-25 10:44:38 -0400142 return false;
143 }
144
Greg Daniel25af6712018-04-25 10:44:38 -0400145 return true;
146}
147
148bool GrVkCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dstIsLinear,
Greg Daniela51e93c2019-03-25 12:30:45 -0400149 bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt,
150 bool srcIsLinear, bool srcHasYcbcr) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400151
152 VkFormat dstFormat;
153 SkAssertResult(GrPixelConfigToVkFormat(dstConfig, &dstFormat));
154 VkFormat srcFormat;
155 SkAssertResult(GrPixelConfigToVkFormat(srcConfig, &srcFormat));
Greg Daniel25af6712018-04-25 10:44:38 -0400156 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
157 // as image usage flags.
Greg Danielcaa795f2019-05-14 11:54:25 -0400158 if (!this->formatCanBeDstofBlit(dstFormat, dstIsLinear) ||
159 !this->formatCanBeSrcofBlit(srcFormat, srcIsLinear)) {
Greg Daniel25af6712018-04-25 10:44:38 -0400160 return false;
161 }
162
Greg Daniel25af6712018-04-25 10:44:38 -0400163 // We cannot blit images that are multisampled. Will need to figure out if we can blit the
164 // resolved msaa though.
165 if (dstSampleCnt > 1 || srcSampleCnt > 1) {
166 return false;
167 }
168
Greg Daniela51e93c2019-03-25 12:30:45 -0400169 if (dstHasYcbcr || srcHasYcbcr) {
170 return false;
171 }
172
Greg Daniel25af6712018-04-25 10:44:38 -0400173 return true;
174}
175
Greg Daniel46cfbc62019-06-07 11:43:30 -0400176bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
177 GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
Greg Daniel25af6712018-04-25 10:44:38 -0400178 // The src surface must be multisampled.
179 if (srcSampleCnt <= 1) {
180 return false;
181 }
182
183 // The dst must not be multisampled.
184 if (dstSampleCnt > 1) {
185 return false;
186 }
187
188 // Surfaces must have the same format.
189 if (dstConfig != srcConfig) {
190 return false;
191 }
192
Greg Daniela51e93c2019-03-25 12:30:45 -0400193 if (dstHasYcbcr || srcHasYcbcr) {
194 return false;
195 }
196
Greg Daniel25af6712018-04-25 10:44:38 -0400197 return true;
198}
199
Brian Salomonc67c31c2018-12-06 10:00:03 -0500200bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
201 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400202 if (src->isProtected() && !dst->isProtected()) {
203 return false;
204 }
205
Greg Daniel25af6712018-04-25 10:44:38 -0400206 GrPixelConfig dstConfig = dst->config();
207 GrPixelConfig srcConfig = src->config();
208
209 // TODO: Figure out a way to track if we've wrapped a linear texture in a proxy (e.g.
210 // PromiseImage which won't get instantiated right away. Does this need a similar thing like the
211 // tracking of external or rectangle textures in GL? For now we don't create linear textures
212 // internally, and I don't believe anyone is wrapping them.
213 bool srcIsLinear = false;
214 bool dstIsLinear = false;
215
216 int dstSampleCnt = 0;
217 int srcSampleCnt = 0;
218 if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
Greg Danielbe7fc462019-01-03 16:40:42 -0500219 // Copying to or from render targets that wrap a secondary command buffer is not allowed
220 // since they would require us to know the VkImage, which we don't have, as well as need us
221 // to stop and start the VkRenderPass which we don't have access to.
222 if (rtProxy->wrapsVkSecondaryCB()) {
223 return false;
224 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600225 dstSampleCnt = rtProxy->numSamples();
Greg Daniel25af6712018-04-25 10:44:38 -0400226 }
227 if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
Greg Danielbe7fc462019-01-03 16:40:42 -0500228 // Copying to or from render targets that wrap a secondary command buffer is not allowed
229 // since they would require us to know the VkImage, which we don't have, as well as need us
230 // to stop and start the VkRenderPass which we don't have access to.
231 if (rtProxy->wrapsVkSecondaryCB()) {
232 return false;
233 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600234 srcSampleCnt = rtProxy->numSamples();
Greg Daniel25af6712018-04-25 10:44:38 -0400235 }
236 SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
237 SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
238
Greg Daniela51e93c2019-03-25 12:30:45 -0400239 bool dstHasYcbcr = false;
240 if (auto ycbcr = dst->backendFormat().getVkYcbcrConversionInfo()) {
241 if (ycbcr->isValid()) {
242 dstHasYcbcr = true;
243 }
244 }
245
246 bool srcHasYcbcr = false;
247 if (auto ycbcr = src->backendFormat().getVkYcbcrConversionInfo()) {
248 if (ycbcr->isValid()) {
249 srcHasYcbcr = true;
250 }
251 }
252
Greg Daniel46cfbc62019-06-07 11:43:30 -0400253 return this->canCopyImage(dstConfig, dstSampleCnt, dstHasYcbcr,
254 srcConfig, srcSampleCnt, srcHasYcbcr) ||
Greg Daniela51e93c2019-03-25 12:30:45 -0400255 this->canCopyAsBlit(dstConfig, dstSampleCnt, dstIsLinear, dstHasYcbcr,
256 srcConfig, srcSampleCnt, srcIsLinear, srcHasYcbcr) ||
Greg Daniel46cfbc62019-06-07 11:43:30 -0400257 this->canCopyAsResolve(dstConfig, dstSampleCnt, dstHasYcbcr,
258 srcConfig, srcSampleCnt, srcHasYcbcr);
Greg Daniel25af6712018-04-25 10:44:38 -0400259}
260
Greg Daniel7e000222018-12-03 10:08:21 -0500261template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features,
262 VkStructureType type) {
263 // All Vulkan structs that could be part of the features chain will start with the
264 // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
265 // so we can get access to the pNext for the next struct.
266 struct CommonVulkanHeader {
267 VkStructureType sType;
268 void* pNext;
269 };
270
271 void* pNext = features.pNext;
272 while (pNext) {
273 CommonVulkanHeader* header = static_cast<CommonVulkanHeader*>(pNext);
274 if (header->sType == type) {
275 return static_cast<T*>(pNext);
276 }
277 pNext = header->pNext;
278 }
279 return nullptr;
280}
281
Greg Daniel164a9f02016-02-22 09:56:40 -0500282void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
Greg Daniela0651ac2018-08-08 09:23:18 -0400283 VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400284 uint32_t physicalDeviceVersion, const GrVkExtensions& extensions,
285 GrProtected isProtected) {
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000286 VkPhysicalDeviceProperties properties;
287 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
egdanield5e3b9e2016-03-08 12:19:54 -0800288
egdanield5e3b9e2016-03-08 12:19:54 -0800289 VkPhysicalDeviceMemoryProperties memoryProperties;
290 GR_VK_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &memoryProperties));
291
Greg Daniel41f0e282019-01-28 13:15:05 -0500292 SkASSERT(physicalDeviceVersion <= properties.apiVersion);
Greg Danielc0b03d82018-08-03 14:41:15 -0400293
Greg Danielcb324152019-02-25 11:36:53 -0500294 if (extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 1)) {
295 fSupportsSwapchain = true;
296 }
297
Greg Danielc0b03d82018-08-03 14:41:15 -0400298 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
299 extensions.hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
300 fSupportsPhysicalDeviceProperties2 = true;
301 }
302
303 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
304 extensions.hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1)) {
305 fSupportsMemoryRequirements2 = true;
306 }
307
308 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Daniel637c06a2018-09-12 09:44:25 -0400309 extensions.hasExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, 1)) {
310 fSupportsBindMemory2 = true;
311 }
312
313 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Danielc0b03d82018-08-03 14:41:15 -0400314 extensions.hasExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME, 1)) {
315 fSupportsMaintenance1 = true;
316 }
317
318 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
319 extensions.hasExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME, 1)) {
320 fSupportsMaintenance2 = true;
321 }
322
323 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
324 extensions.hasExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME, 1)) {
325 fSupportsMaintenance3 = true;
326 }
327
Greg Daniela9979d12018-08-27 15:56:46 -0400328 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Daniel637c06a2018-09-12 09:44:25 -0400329 (extensions.hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
Greg Daniela9979d12018-08-27 15:56:46 -0400330 this->supportsMemoryRequirements2())) {
331 fSupportsDedicatedAllocation = true;
332 }
333
334 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
335 (extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 1) &&
336 this->supportsPhysicalDeviceProperties2() &&
337 extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, 1) &&
338 this->supportsDedicatedAllocation())) {
339 fSupportsExternalMemory = true;
340 }
341
342#ifdef SK_BUILD_FOR_ANDROID
Greg Daniel637c06a2018-09-12 09:44:25 -0400343 // Currently Adreno devices are not supporting the QUEUE_FAMILY_FOREIGN_EXTENSION, so until they
344 // do we don't explicitly require it here even the spec says it is required.
Greg Daniela9979d12018-08-27 15:56:46 -0400345 if (extensions.hasExtension(
Greg Daniel637c06a2018-09-12 09:44:25 -0400346 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2) &&
347 /* extensions.hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1) &&*/
348 this->supportsExternalMemory() &&
349 this->supportsBindMemory2()) {
Greg Daniela9979d12018-08-27 15:56:46 -0400350 fSupportsAndroidHWBExternalMemory = true;
Greg Daniel637c06a2018-09-12 09:44:25 -0400351 fSupportsAHardwareBufferImages = true;
Greg Daniela9979d12018-08-27 15:56:46 -0400352 }
353#endif
354
Greg Daniel7e000222018-12-03 10:08:21 -0500355 auto ycbcrFeatures =
356 get_extension_feature_struct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
357 features,
358 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
359 if (ycbcrFeatures && ycbcrFeatures->samplerYcbcrConversion &&
360 fSupportsAndroidHWBExternalMemory &&
361 (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
362 (extensions.hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1) &&
363 this->supportsMaintenance1() &&
364 this->supportsBindMemory2() &&
365 this->supportsMemoryRequirements2() &&
366 this->supportsPhysicalDeviceProperties2()))) {
367 fSupportsYcbcrConversion = true;
368 }
369 // We always push back the default GrVkYcbcrConversionInfo so that the case of no conversion
370 // will return a key of 0.
371 fYcbcrInfos.push_back(GrVkYcbcrConversionInfo());
372
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400373 if ((isProtected == GrProtected::kYes) &&
374 (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0))) {
375 fSupportsProtectedMemory = true;
376 fAvoidUpdateBuffers = true;
377 fShouldAlwaysUseDedicatedImageMemory = true;
378 }
379
Greg Daniel313c6952018-08-08 09:24:08 -0400380 this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
Greg Daniel36443602018-08-02 12:51:52 -0400381 this->initShaderCaps(properties, features);
Greg Danielf3b11622018-03-01 15:01:27 -0500382
383 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
384#if defined(SK_CPU_X86)
385 // We need to do this before initing the config table since it uses fSRGBSupport
386 if (kImagination_VkVendor == properties.vendorID) {
387 fSRGBSupport = false;
388 }
389#endif
390 }
391
Chris Dalton8e738a22018-10-05 16:41:44 -0600392 if (kQualcomm_VkVendor == properties.vendorID) {
393 // A "clear" load for the CCPR atlas runs faster on QC than a "discard" load followed by a
394 // scissored clear.
395 // On NVIDIA and Intel, the discard load followed by clear is faster.
396 // TODO: Evaluate on ARM, Imagination, and ATI.
397 fPreferFullscreenClears = true;
398 }
399
Greg Daniel44e69f92019-03-20 11:18:25 -0400400 if (kQualcomm_VkVendor == properties.vendorID || kARM_VkVendor == properties.vendorID) {
401 // On Qualcomm and ARM mapping a gpu buffer and doing both reads and writes to it is slow.
402 // Thus for index and vertex buffers we will force to use a cpu side buffer and then copy
403 // the whole buffer up to the gpu.
Greg Daniel78e6a4c2019-03-19 14:13:36 -0400404 fBufferMapThreshold = SK_MaxS32;
405 }
406
407 if (kQualcomm_VkVendor == properties.vendorID) {
408 // On Qualcomm it looks like using vkCmdUpdateBuffer is slower than using a transfer buffer
409 // even for small sizes.
410 fAvoidUpdateBuffers = true;
411 }
412
Chris Dalton0dffbab2019-03-27 13:08:50 -0600413 if (kARM_VkVendor == properties.vendorID) {
414 // ARM seems to do better with more fine triangles as opposed to using the sample mask.
415 // (At least in our current round rect op.)
416 fPreferTrianglesOverSampleMask = true;
417 }
Greg Daniel78e6a4c2019-03-19 14:13:36 -0400418
Greg Danielcaa795f2019-05-14 11:54:25 -0400419 this->initFormatTable(vkInterface, physDev, properties);
egdaniel8f1dcaa2016-04-01 10:10:45 -0700420 this->initStencilFormat(vkInterface, physDev);
Greg Daniel164a9f02016-02-22 09:56:40 -0500421
Greg Daniel691f5e72018-02-28 14:21:34 -0500422 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
423 this->applyDriverCorrectnessWorkarounds(properties);
egdanielc5ec1402016-03-28 12:14:42 -0700424 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500425
Greg Daniel691f5e72018-02-28 14:21:34 -0500426 this->applyOptionsOverrides(contextOptions);
427 fShaderCaps->applyOptionsOverrides(contextOptions);
428}
429
430void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) {
egdaniel6fa0a912016-09-12 11:51:29 -0700431 if (kQualcomm_VkVendor == properties.vendorID) {
432 fMustDoCopiesFromOrigin = true;
Brian Salomona585fe92019-04-09 14:57:00 -0400433 // Transfer doesn't support this workaround.
434 fTransferBufferSupport = false;
egdaniel6fa0a912016-09-12 11:51:29 -0700435 }
436
Greg Daniel80a08dd2017-01-20 10:45:49 -0500437#if defined(SK_BUILD_FOR_WIN)
Greg Daniel900e5c82018-08-28 10:59:24 -0400438 if (kNvidia_VkVendor == properties.vendorID || kIntel_VkVendor == properties.vendorID) {
Greg Daniel80a08dd2017-01-20 10:45:49 -0500439 fMustSleepOnTearDown = true;
440 }
441#elif defined(SK_BUILD_FOR_ANDROID)
442 if (kImagination_VkVendor == properties.vendorID) {
443 fMustSleepOnTearDown = true;
444 }
445#endif
Greg Danielbce5eb92018-03-01 13:13:44 -0500446
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400447#if defined(SK_BUILD_FOR_ANDROID)
448 // Protected memory features have problems in Android P and earlier.
449 if (fSupportsProtectedMemory && (kQualcomm_VkVendor == properties.vendorID)) {
450 char androidAPIVersion[PROP_VALUE_MAX];
451 int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersion);
452 if (strLength == 0 || atoi(androidAPIVersion) <= 28) {
453 fSupportsProtectedMemory = false;
454 }
455 }
456#endif
457
Greg Danielbce5eb92018-03-01 13:13:44 -0500458 // AMD seems to have issues binding new VkPipelines inside a secondary command buffer.
459 // Current workaround is to use a different secondary command buffer for each new VkPipeline.
460 if (kAMD_VkVendor == properties.vendorID) {
461 fNewCBOnPipelineChange = true;
462 }
463
Greg Danielddc0c602018-06-18 11:26:30 -0400464 // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
465 if (kARM_VkVendor == properties.vendorID) {
466 fShouldAlwaysUseDedicatedImageMemory = true;
467 }
468
Greg Danielbce5eb92018-03-01 13:13:44 -0500469 ////////////////////////////////////////////////////////////////////////////
470 // GrCaps workarounds
471 ////////////////////////////////////////////////////////////////////////////
472
473 if (kARM_VkVendor == properties.vendorID) {
474 fInstanceAttribSupport = false;
Greg Daniel4374e962018-09-28 15:09:47 -0400475 fAvoidWritePixelsFastPath = true; // bugs.skia.org/8064
Greg Danielbce5eb92018-03-01 13:13:44 -0500476 }
477
478 // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32.
479 if (kAMD_VkVendor == properties.vendorID) {
480 fMaxVertexAttributes = SkTMin(fMaxVertexAttributes, 32);
481 }
482
Greg Danielbce5eb92018-03-01 13:13:44 -0500483 ////////////////////////////////////////////////////////////////////////////
484 // GrShaderCaps workarounds
485 ////////////////////////////////////////////////////////////////////////////
486
Greg Danielbce5eb92018-03-01 13:13:44 -0500487 if (kImagination_VkVendor == properties.vendorID) {
488 fShaderCaps->fAtan2ImplementedAsAtanYOverX = true;
489 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500490}
491
492int get_max_sample_count(VkSampleCountFlags flags) {
493 SkASSERT(flags & VK_SAMPLE_COUNT_1_BIT);
494 if (!(flags & VK_SAMPLE_COUNT_2_BIT)) {
495 return 0;
496 }
497 if (!(flags & VK_SAMPLE_COUNT_4_BIT)) {
498 return 2;
499 }
500 if (!(flags & VK_SAMPLE_COUNT_8_BIT)) {
501 return 4;
502 }
503 if (!(flags & VK_SAMPLE_COUNT_16_BIT)) {
504 return 8;
505 }
506 if (!(flags & VK_SAMPLE_COUNT_32_BIT)) {
507 return 16;
508 }
509 if (!(flags & VK_SAMPLE_COUNT_64_BIT)) {
510 return 32;
511 }
512 return 64;
513}
514
Greg Daniel313c6952018-08-08 09:24:08 -0400515void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
516 VkPhysicalDevice physDev,
517 const VkPhysicalDeviceProperties& properties,
jvanverthfd7bd452016-03-25 06:29:52 -0700518 const VkPhysicalDeviceMemoryProperties& memoryProperties,
Greg Daniel313c6952018-08-08 09:24:08 -0400519 const VkPhysicalDeviceFeatures2& features,
520 const GrVkExtensions& extensions) {
Greg Danielc5cc2de2017-03-20 11:40:58 -0400521 // So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no
522 // need for us ever to support that amount, and it makes tests which tests all the vertex
523 // attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if
524 // we ever find that need.
525 static const uint32_t kMaxVertexAttributes = 64;
526 fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
Greg Danielc5cc2de2017-03-20 11:40:58 -0400527
egdanield5e3b9e2016-03-08 12:19:54 -0800528 // We could actually query and get a max size for each config, however maxImageDimension2D will
529 // give the minimum max size across all configs. So for simplicity we will use that for now.
jvanverthe78d4872016-09-27 03:33:05 -0700530 fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
531 fMaxTextureSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
Adrienne Walker724afe82018-05-15 11:36:26 -0700532 if (fDriverBugWorkarounds.max_texture_size_limit_4096) {
533 fMaxTextureSize = SkTMin(fMaxTextureSize, 4096);
534 }
535 // Our render targets are always created with textures as the color
536 // attachment, hence this min:
537 fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
egdanield5e3b9e2016-03-08 12:19:54 -0800538
Chris Dalton2612bae2018-02-22 13:41:37 -0700539 // TODO: check if RT's larger than 4k incur a performance cost on ARM.
540 fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
541
egdanield5e3b9e2016-03-08 12:19:54 -0800542 // Assuming since we will always map in the end to upload the data we might as well just map
543 // from the get go. There is no hard data to suggest this is faster or slower.
cdalton397536c2016-03-25 12:15:03 -0700544 fBufferMapThreshold = 0;
egdanield5e3b9e2016-03-08 12:19:54 -0800545
Brian Salomon105d7c22019-04-16 13:46:14 -0400546 fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;
egdanield5e3b9e2016-03-08 12:19:54 -0800547
egdanield5e3b9e2016-03-08 12:19:54 -0800548 fOversizedStencilSupport = true;
Greg Daniel313c6952018-08-08 09:24:08 -0400549
550 if (extensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2) &&
551 this->supportsPhysicalDeviceProperties2()) {
552
553 VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProps;
554 blendProps.sType =
555 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
556 blendProps.pNext = nullptr;
557
558 VkPhysicalDeviceProperties2 props;
559 props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
560 props.pNext = &blendProps;
561
562 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props));
563
564 if (blendProps.advancedBlendAllOperations == VK_TRUE) {
565 fShaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kAutomatic_AdvBlendEqInteraction;
566
567 auto blendFeatures =
568 get_extension_feature_struct<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(
569 features,
570 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT);
571 if (blendFeatures && blendFeatures->advancedBlendCoherentOperations == VK_TRUE) {
572 fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
573 } else {
574 // TODO: Currently non coherent blends are not supported in our vulkan backend. They
575 // require us to support self dependencies in our render passes.
576 // fBlendEquationSupport = kAdvanced_BlendEquationSupport;
577 }
578 }
579 }
egdanield5e3b9e2016-03-08 12:19:54 -0800580}
581
Greg Daniel36443602018-08-02 12:51:52 -0400582void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
Greg Daniela0651ac2018-08-08 09:23:18 -0400583 const VkPhysicalDeviceFeatures2& features) {
Brian Salomon1edc5b92016-11-29 13:43:46 -0500584 GrShaderCaps* shaderCaps = fShaderCaps.get();
585 shaderCaps->fVersionDeclString = "#version 330\n";
egdaniel3a15fd42016-04-05 11:00:29 -0700586
egdanield5e3b9e2016-03-08 12:19:54 -0800587 // Vulkan is based off ES 3.0 so the following should all be supported
Brian Salomon1edc5b92016-11-29 13:43:46 -0500588 shaderCaps->fUsesPrecisionModifiers = true;
589 shaderCaps->fFlatInterpolationSupport = true;
Brian Salomon41274562017-09-15 09:40:03 -0700590 // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed
591 // to be true with Vulkan as well.
592 shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID;
egdanield5e3b9e2016-03-08 12:19:54 -0800593
594 // GrShaderCaps
595
Brian Salomon1edc5b92016-11-29 13:43:46 -0500596 shaderCaps->fShaderDerivativeSupport = true;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600597
Ethan Nicholas6ac8d362019-01-22 21:43:55 +0000598 // FIXME: http://skbug.com/7733: Disable geometry shaders until Intel/Radeon GMs draw correctly.
599 // shaderCaps->fGeometryShaderSupport =
600 // shaderCaps->fGSInvocationsSupport = features.features.geometryShader;
egdanield632bb42016-03-30 12:06:48 -0700601
Greg Daniela0651ac2018-08-08 09:23:18 -0400602 shaderCaps->fDualSourceBlendingSupport = features.features.dualSrcBlend;
egdanield632bb42016-03-30 12:06:48 -0700603
Brian Salomon1edc5b92016-11-29 13:43:46 -0500604 shaderCaps->fIntegerSupport = true;
Chris Dalton1d616352017-05-31 12:51:23 -0600605 shaderCaps->fVertexIDSupport = true;
Chris Dalton7c7ff032018-03-28 20:09:58 -0600606 shaderCaps->fFPManipulationSupport = true;
cdalton9c3f1432016-03-11 10:07:37 -0800607
cdaltona6b92ad2016-04-11 12:03:08 -0700608 // Assume the minimum precisions mandated by the SPIR-V spec.
Chris Dalton47c8ed32017-11-15 18:27:09 -0700609 shaderCaps->fFloatIs32Bits = true;
610 shaderCaps->fHalfIs32Bits = false;
cdaltona6b92ad2016-04-11 12:03:08 -0700611
Brian Salomon1edc5b92016-11-29 13:43:46 -0500612 shaderCaps->fMaxFragmentSamplers = SkTMin(
613 SkTMin(properties.limits.maxPerStageDescriptorSampledImages,
614 properties.limits.maxPerStageDescriptorSamplers),
615 (uint32_t)INT_MAX);
Greg Daniel164a9f02016-02-22 09:56:40 -0500616}
617
egdaniel8f1dcaa2016-04-01 10:10:45 -0700618bool stencil_format_supported(const GrVkInterface* interface,
619 VkPhysicalDevice physDev,
620 VkFormat format) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500621 VkFormatProperties props;
622 memset(&props, 0, sizeof(VkFormatProperties));
623 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
egdaniel8f1dcaa2016-04-01 10:10:45 -0700624 return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures);
Greg Daniel164a9f02016-02-22 09:56:40 -0500625}
626
egdaniel8f1dcaa2016-04-01 10:10:45 -0700627void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevice physDev) {
628 // List of legal stencil formats (though perhaps not supported on
629 // the particular gpu/driver) from most preferred to least. We are guaranteed to have either
jvanvertha4b0fed2016-04-27 11:42:21 -0700630 // VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D32_SFLOAT_S8_UINT. VK_FORMAT_D32_SFLOAT_S8_UINT
egdaniel8f1dcaa2016-04-01 10:10:45 -0700631 // can optionally have 24 unused bits at the end so we assume the total bits is 64.
Greg Daniel164a9f02016-02-22 09:56:40 -0500632 static const StencilFormat
633 // internal Format stencil bits total bits packed?
634 gS8 = { VK_FORMAT_S8_UINT, 8, 8, false },
egdaniel8f1dcaa2016-04-01 10:10:45 -0700635 gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT, 8, 32, true },
636 gD32S8 = { VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 64, true };
Greg Daniel164a9f02016-02-22 09:56:40 -0500637
egdaniel8f1dcaa2016-04-01 10:10:45 -0700638 if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) {
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400639 fPreferredStencilFormat = gS8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700640 } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) {
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400641 fPreferredStencilFormat = gD24S8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700642 } else {
643 SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT));
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400644 fPreferredStencilFormat = gD32S8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700645 }
646}
647
Greg Danielcaa795f2019-05-14 11:54:25 -0400648static bool format_is_srgb(VkFormat format) {
Robert Phillipsf209e882019-06-25 15:59:50 -0400649 SkASSERT(GrVkFormatIsSupported(format));
650
Greg Danielcaa795f2019-05-14 11:54:25 -0400651 switch (format) {
652 case VK_FORMAT_R8G8B8A8_SRGB:
653 case VK_FORMAT_B8G8R8A8_SRGB:
654 return true;
Greg Danielcaa795f2019-05-14 11:54:25 -0400655 default:
Greg Danielcaa795f2019-05-14 11:54:25 -0400656 return false;
657 }
658}
659
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400660// These are all the valid VkFormats that we support in Skia. They are roughly ordered from most
Greg Danielcaa795f2019-05-14 11:54:25 -0400661// frequently used to least to improve look up times in arrays.
662static constexpr VkFormat kVkFormats[] = {
663 VK_FORMAT_R8G8B8A8_UNORM,
664 VK_FORMAT_R8_UNORM,
665 VK_FORMAT_B8G8R8A8_UNORM,
666 VK_FORMAT_R5G6B5_UNORM_PACK16,
667 VK_FORMAT_R16G16B16A16_SFLOAT,
668 VK_FORMAT_R16_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400669 VK_FORMAT_R8G8B8_UNORM,
670 VK_FORMAT_R8G8_UNORM,
671 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
672 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
Greg Danieleb4a8272019-05-16 16:52:55 -0400673 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
Greg Danielcaa795f2019-05-14 11:54:25 -0400674 VK_FORMAT_R32G32B32A32_SFLOAT,
675 VK_FORMAT_R32G32_SFLOAT,
676 VK_FORMAT_R8G8B8A8_SRGB,
677 VK_FORMAT_B8G8R8A8_SRGB,
Robert Phillipsfe18de52019-06-06 17:21:50 -0400678 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
Robert Phillipsfe18de52019-06-06 17:21:50 -0400679 VK_FORMAT_R16_UNORM,
680 VK_FORMAT_R16G16_UNORM,
Robert Phillips66a46032019-06-18 08:00:42 -0400681 // Experimental (for Y416 and mutant P016/P010)
682 VK_FORMAT_R16G16B16A16_UNORM,
683 VK_FORMAT_R16G16_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400684};
685
686const GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) const {
687 static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
688 "Size of VkFormats array must match static value in header");
689 for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
690 if (kVkFormats[i] == format) {
691 return fFormatTable[i];
692 }
693 }
694 SK_ABORT("Invalid VkFormat");
Greg Daniel52ee5f62019-06-20 13:38:18 -0400695 static const FormatInfo kInvalidFormat;
696 return kInvalidFormat;
Greg Danielcaa795f2019-05-14 11:54:25 -0400697}
698
699void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000700 const VkPhysicalDeviceProperties& properties) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400701 static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
702 "Size of VkFormats array must match static value in header");
703 for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
704 VkFormat format = kVkFormats[i];
705 if (!format_is_srgb(format) || fSRGBSupport) {
706 fFormatTable[i].init(interface, physDev, properties, format);
egdaniel8f1dcaa2016-04-01 10:10:45 -0700707 }
708 }
709}
710
Greg Danielcaa795f2019-05-14 11:54:25 -0400711void GrVkCaps::FormatInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
egdaniel8f1dcaa2016-04-01 10:10:45 -0700712 if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
713 SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
714 *flags = *flags | kTextureable_Flag;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700715
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400716 // Ganesh assumes that all renderable surfaces are also texturable
Greg Danielcaa795f2019-05-14 11:54:25 -0400717 if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400718 *flags = *flags | kRenderable_Flag;
719 }
egdaniel8f1dcaa2016-04-01 10:10:45 -0700720 }
721
722 if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) {
723 *flags = *flags | kBlitSrc_Flag;
724 }
725
726 if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) {
727 *flags = *flags | kBlitDst_Flag;
728 }
729}
730
Greg Danielcaa795f2019-05-14 11:54:25 -0400731void GrVkCaps::FormatInfo::initSampleCounts(const GrVkInterface* interface,
Greg Daniel81e7bf82017-07-19 14:47:42 -0400732 VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000733 const VkPhysicalDeviceProperties& physProps,
Greg Daniel81e7bf82017-07-19 14:47:42 -0400734 VkFormat format) {
735 VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
736 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
737 VK_IMAGE_USAGE_SAMPLED_BIT |
738 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Greg Daniel81e7bf82017-07-19 14:47:42 -0400739 VkImageFormatProperties properties;
740 GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev,
741 format,
742 VK_IMAGE_TYPE_2D,
743 VK_IMAGE_TILING_OPTIMAL,
744 usage,
Brian Osman2b23c4b2018-06-01 12:25:08 -0400745 0, // createFlags
Greg Daniel81e7bf82017-07-19 14:47:42 -0400746 &properties));
747 VkSampleCountFlags flags = properties.sampleCounts;
748 if (flags & VK_SAMPLE_COUNT_1_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400749 fColorSampleCounts.push_back(1);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400750 }
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000751 if (kImagination_VkVendor == physProps.vendorID) {
752 // MSAA does not work on imagination
753 return;
754 }
Greg Daniel81e7bf82017-07-19 14:47:42 -0400755 if (flags & VK_SAMPLE_COUNT_2_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400756 fColorSampleCounts.push_back(2);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400757 }
758 if (flags & VK_SAMPLE_COUNT_4_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400759 fColorSampleCounts.push_back(4);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400760 }
761 if (flags & VK_SAMPLE_COUNT_8_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400762 fColorSampleCounts.push_back(8);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400763 }
764 if (flags & VK_SAMPLE_COUNT_16_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400765 fColorSampleCounts.push_back(16);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400766 }
767 if (flags & VK_SAMPLE_COUNT_32_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400768 fColorSampleCounts.push_back(32);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400769 }
770 if (flags & VK_SAMPLE_COUNT_64_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400771 fColorSampleCounts.push_back(64);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400772 }
773}
774
Greg Danielcaa795f2019-05-14 11:54:25 -0400775void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,
egdaniel8f1dcaa2016-04-01 10:10:45 -0700776 VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000777 const VkPhysicalDeviceProperties& properties,
Greg Danielcaa795f2019-05-14 11:54:25 -0400778 VkFormat format) {
egdaniel8f1dcaa2016-04-01 10:10:45 -0700779 VkFormatProperties props;
780 memset(&props, 0, sizeof(VkFormatProperties));
781 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
Greg Danielcaa795f2019-05-14 11:54:25 -0400782 InitConfigFlags(props.linearTilingFeatures, &fLinearFlags);
783 InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400784 if (fOptimalFlags & kRenderable_Flag) {
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000785 this->initSampleCounts(interface, physDev, properties, format);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400786 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500787}
Greg Daniel81e7bf82017-07-19 14:47:42 -0400788
Robert Phillipsf209e882019-06-25 15:59:50 -0400789bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
790 if (!format.getVkFormat()) {
791 return false;
792 }
793
794 return format_is_srgb(*format.getVkFormat());
795}
796
Greg Daniel2f2caea2019-07-08 14:24:47 -0400797bool GrVkCaps::isFormatTexturable(GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400798 if (!format.getVkFormat()) {
799 return false;
800 }
801
Greg Daniel2f2caea2019-07-08 14:24:47 -0400802 return this->isVkFormatTexturable(*format.getVkFormat());
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400803}
804
Greg Daniel2f2caea2019-07-08 14:24:47 -0400805bool GrVkCaps::isVkFormatTexturable(VkFormat format) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400806 if (!GrVkFormatIsSupported(format)) {
807 return false;
808 }
809
810 const FormatInfo& info = this->getFormatInfo(format);
811 return SkToBool(FormatInfo::kTextureable_Flag & info.fOptimalFlags);
812}
813
814bool GrVkCaps::isConfigTexturable(GrPixelConfig config) const {
815 VkFormat format;
816 if (!GrPixelConfigToVkFormat(config, &format)) {
817 return false;
818 }
Greg Daniel2f2caea2019-07-08 14:24:47 -0400819 return this->isVkFormatTexturable(format);
Robert Phillips39ef2ef2019-05-15 08:45:53 -0400820}
821
822bool GrVkCaps::isFormatRenderable(VkFormat format) const {
823 return this->maxRenderTargetSampleCount(format) > 0;
Greg Danielcaa795f2019-05-14 11:54:25 -0400824}
825
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400826int GrVkCaps::getRenderTargetSampleCount(int requestedCount,
Greg Daniel5c96db82019-07-09 14:06:58 -0400827 GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400828 if (!format.getVkFormat()) {
829 return 0;
830 }
831
832 return this->getRenderTargetSampleCount(requestedCount, *format.getVkFormat());
833}
834
Brian Salomonbdecacf2018-02-02 20:32:49 -0500835int GrVkCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400836 // Currently we don't allow RGB_888X to be renderable because we don't have a way to handle
837 // blends that reference dst alpha when the values in the dst alpha channel are uninitialized.
838 if (config == kRGB_888X_GrPixelConfig) {
839 return 0;
840 }
841
842 VkFormat format;
843 if (!GrPixelConfigToVkFormat(config, &format)) {
844 return 0;
845 }
846
847 return this->getRenderTargetSampleCount(requestedCount, format);
848}
849
850int GrVkCaps::getRenderTargetSampleCount(int requestedCount, VkFormat format) const {
Brian Salomonbdecacf2018-02-02 20:32:49 -0500851 requestedCount = SkTMax(1, requestedCount);
Greg Danielcaa795f2019-05-14 11:54:25 -0400852
853 const FormatInfo& info = this->getFormatInfo(format);
854
855 int count = info.fColorSampleCounts.count();
Brian Salomonbdecacf2018-02-02 20:32:49 -0500856
857 if (!count) {
Greg Daniel81e7bf82017-07-19 14:47:42 -0400858 return 0;
859 }
860
Brian Salomonbdecacf2018-02-02 20:32:49 -0500861 if (1 == requestedCount) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400862 SkASSERT(info.fColorSampleCounts.count() && info.fColorSampleCounts[0] == 1);
Brian Salomonbdecacf2018-02-02 20:32:49 -0500863 return 1;
864 }
865
Greg Daniel81e7bf82017-07-19 14:47:42 -0400866 for (int i = 0; i < count; ++i) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400867 if (info.fColorSampleCounts[i] >= requestedCount) {
868 return info.fColorSampleCounts[i];
Greg Daniel81e7bf82017-07-19 14:47:42 -0400869 }
870 }
Brian Salomonbdecacf2018-02-02 20:32:49 -0500871 return 0;
872}
873
Greg Daniel5c96db82019-07-09 14:06:58 -0400874int GrVkCaps::maxRenderTargetSampleCount(GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400875 if (!format.getVkFormat()) {
876 return 0;
877 }
878
879 return this->maxRenderTargetSampleCount(*format.getVkFormat());
880}
881
Brian Salomonbdecacf2018-02-02 20:32:49 -0500882int GrVkCaps::maxRenderTargetSampleCount(GrPixelConfig config) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400883 // Currently we don't allow RGB_888X to be renderable because we don't have a way to handle
884 // blends that reference dst alpha when the values in the dst alpha channel are uninitialized.
885 if (config == kRGB_888X_GrPixelConfig) {
886 return 0;
887 }
888
889 VkFormat format;
890 if (!GrPixelConfigToVkFormat(config, &format)) {
891 return 0;
892 }
893 return this->maxRenderTargetSampleCount(format);
894}
895
896int GrVkCaps::maxRenderTargetSampleCount(VkFormat format) const {
897 const FormatInfo& info = this->getFormatInfo(format);
898
899 const auto& table = info.fColorSampleCounts;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500900 if (!table.count()) {
901 return 0;
902 }
903 return table[table.count() - 1];
Brian Salomond653cac2018-02-01 13:58:00 -0500904}
905
Brian Salomondc0710f2019-07-01 14:59:32 -0400906GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
907 const GrSurface* surface) const {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400908 if (surface->isProtected()) {
Brian Salomondc0710f2019-07-01 14:59:32 -0400909 return SurfaceReadPixelsSupport::kUnsupported;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400910 }
Greg Daniela51e93c2019-03-25 12:30:45 -0400911 if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
912 // We can't directly read from a VkImage that has a ycbcr sampler.
913 if (tex->ycbcrConversionInfo().isValid()) {
Brian Salomondc0710f2019-07-01 14:59:32 -0400914 return SurfaceReadPixelsSupport::kCopyToTexture2D;
Greg Daniela51e93c2019-03-25 12:30:45 -0400915 }
916 }
Brian Salomondc0710f2019-07-01 14:59:32 -0400917 return SurfaceReadPixelsSupport::kSupported;
Greg Daniela51e93c2019-03-25 12:30:45 -0400918}
919
Brian Salomonc67c31c2018-12-06 10:00:03 -0500920bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
Brian Salomon3d86a192018-02-27 16:46:11 -0500921 if (auto rt = surface->asRenderTarget()) {
Chris Dalton6ce447a2019-06-23 18:07:38 -0600922 return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
Brian Salomon3d86a192018-02-27 16:46:11 -0500923 }
Greg Daniela51e93c2019-03-25 12:30:45 -0400924 // We can't write to a texture that has a ycbcr sampler.
925 if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
926 // We can't directly read from a VkImage that has a ycbcr sampler.
927 if (tex->ycbcrConversionInfo().isValid()) {
928 return false;
929 }
930 }
Brian Salomon3d86a192018-02-27 16:46:11 -0500931 return true;
932}
933
Robert Phillips1e2cb442019-07-02 15:51:28 -0400934// A near clone of format_color_type_valid_pair
935static GrPixelConfig validate_image_info(VkFormat format, GrColorType ct, bool hasYcbcrConversion) {
Greg Daniel14c55c22018-12-04 11:25:03 -0500936 if (format == VK_FORMAT_UNDEFINED) {
937 // If the format is undefined then it is only valid as an external image which requires that
938 // we have a valid VkYcbcrConversion.
939 if (hasYcbcrConversion) {
940 // We don't actually care what the color type or config are since we won't use those
Greg Daniela51e93c2019-03-25 12:30:45 -0400941 // values for external textures. However, for read pixels we will draw to a non ycbcr
942 // texture of this config so we set RGBA here for that.
Brian Salomonf391d0f2018-12-14 09:18:50 -0500943 return kRGBA_8888_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500944 } else {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500945 return kUnknown_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500946 }
947 }
948
949 if (hasYcbcrConversion) {
950 // We only support having a ycbcr conversion for external images.
Brian Salomonf391d0f2018-12-14 09:18:50 -0500951 return kUnknown_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500952 }
953
Greg Danielf5d87582017-12-18 14:48:15 -0500954 switch (ct) {
Robert Phillips1e2cb442019-07-02 15:51:28 -0400955 case GrColorType::kUnknown:
Brian Salomonf391d0f2018-12-14 09:18:50 -0500956 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400957 case GrColorType::kAlpha_8:
Greg Danielf5d87582017-12-18 14:48:15 -0500958 if (VK_FORMAT_R8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500959 return kAlpha_8_as_Red_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500960 }
961 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400962 case GrColorType::kBGR_565:
Greg Danielf5d87582017-12-18 14:48:15 -0500963 if (VK_FORMAT_R5G6B5_UNORM_PACK16 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500964 return kRGB_565_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500965 }
966 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400967 case GrColorType::kABGR_4444:
Greg Danieleb4a8272019-05-16 16:52:55 -0400968 if (VK_FORMAT_B4G4R4A4_UNORM_PACK16 == format ||
969 VK_FORMAT_R4G4B4A4_UNORM_PACK16 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500970 return kRGBA_4444_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500971 }
972 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400973 case GrColorType::kRGBA_8888:
Greg Danielf5d87582017-12-18 14:48:15 -0500974 if (VK_FORMAT_R8G8B8A8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500975 return kRGBA_8888_GrPixelConfig;
Greg Daniele877dce2019-07-11 10:52:43 -0400976 }
977 break;
978 case GrColorType::kRGBA_8888_SRGB:
979 if (VK_FORMAT_R8G8B8A8_SRGB == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500980 return kSRGBA_8888_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500981 }
982 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400983 case GrColorType::kRGB_888x:
Greg Daniel475eb702018-09-28 14:16:50 -0400984 if (VK_FORMAT_R8G8B8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500985 return kRGB_888_GrPixelConfig;
Greg Daniel475eb702018-09-28 14:16:50 -0400986 }
Greg Danielf259b8b2019-02-14 09:03:43 -0500987 if (VK_FORMAT_R8G8B8A8_UNORM == format) {
988 return kRGB_888X_GrPixelConfig;
989 }
Greg Daniel475eb702018-09-28 14:16:50 -0400990 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400991 case GrColorType::kRG_88:
992 if (VK_FORMAT_R8G8_UNORM == format) {
993 return kRG_88_GrPixelConfig;
994 }
995 break;
996 case GrColorType::kBGRA_8888:
Greg Danielf5d87582017-12-18 14:48:15 -0500997 if (VK_FORMAT_B8G8R8A8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500998 return kBGRA_8888_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500999 }
1000 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001001 case GrColorType::kRGBA_1010102:
Brian Osman10fc6fd2018-03-02 11:01:10 -05001002 if (VK_FORMAT_A2B10G10R10_UNORM_PACK32 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001003 return kRGBA_1010102_GrPixelConfig;
Brian Osman10fc6fd2018-03-02 11:01:10 -05001004 }
1005 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001006 case GrColorType::kGray_8:
Greg Danielf5d87582017-12-18 14:48:15 -05001007 if (VK_FORMAT_R8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001008 return kGray_8_as_Red_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001009 }
1010 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001011 case GrColorType::kAlpha_F16:
1012 if (VK_FORMAT_R16_SFLOAT == format) {
Robert Phillips0902c982019-07-16 07:47:56 -04001013 return kAlpha_half_as_Red_GrPixelConfig;
Mike Kleinb70990e2019-02-28 10:03:27 -06001014 }
1015 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001016 case GrColorType::kRGBA_F16:
Greg Danielf5d87582017-12-18 14:48:15 -05001017 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001018 return kRGBA_half_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001019 }
1020 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001021 case GrColorType::kRGBA_F16_Clamped:
1022 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
1023 return kRGBA_half_Clamped_GrPixelConfig;
1024 }
1025 break;
1026 case GrColorType::kRG_F32:
1027 if (VK_FORMAT_R32G32_SFLOAT == format) {
1028 return kRG_float_GrPixelConfig;
1029 }
1030 break;
1031 case GrColorType::kRGBA_F32:
Mike Klein37854712018-06-26 11:43:06 -04001032 if (VK_FORMAT_R32G32B32A32_SFLOAT == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001033 return kRGBA_float_GrPixelConfig;
Mike Klein37854712018-06-26 11:43:06 -04001034 }
1035 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001036 case GrColorType::kR_16:
1037 if (VK_FORMAT_R16_UNORM == format) {
1038 return kR_16_GrPixelConfig;
1039 }
1040 break;
1041 case GrColorType::kRG_1616:
1042 if (VK_FORMAT_R16G16_UNORM == format) {
1043 return kRG_1616_GrPixelConfig;
1044 }
1045 break;
1046 case GrColorType::kRGBA_16161616:
1047 if (VK_FORMAT_R16G16B16A16_UNORM == format) {
1048 return kRGBA_16161616_GrPixelConfig;
1049 }
1050 break;
1051 case GrColorType::kRG_F16:
1052 if (VK_FORMAT_R16G16_SFLOAT == format) {
1053 return kRG_half_GrPixelConfig;
1054 }
1055 break;
Greg Danielf5d87582017-12-18 14:48:15 -05001056 }
1057
Brian Salomonf391d0f2018-12-14 09:18:50 -05001058 return kUnknown_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001059}
1060
Brian Salomonf391d0f2018-12-14 09:18:50 -05001061GrPixelConfig GrVkCaps::validateBackendRenderTarget(const GrBackendRenderTarget& rt,
Robert Phillips1e2cb442019-07-02 15:51:28 -04001062 GrColorType ct) const {
Greg Daniel323fbcf2018-04-10 13:46:30 -04001063 GrVkImageInfo imageInfo;
1064 if (!rt.getVkImageInfo(&imageInfo)) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001065 return kUnknown_GrPixelConfig;
Robert Phillipsfc711a22018-02-13 17:03:00 -05001066 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001067 return validate_image_info(imageInfo.fFormat, ct, imageInfo.fYcbcrConversionInfo.isValid());
Robert Phillipsfc711a22018-02-13 17:03:00 -05001068}
1069
Greg Daniel627d0532019-07-08 16:48:14 -04001070bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
1071 const GrBackendFormat& format) const {
Robert Phillipsc046ff02019-07-01 10:34:03 -04001072 const VkFormat* vkFormat = format.getVkFormat();
1073 const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1074 if (!vkFormat || !ycbcrInfo) {
1075 return false;
1076 }
1077
1078 return kUnknown_GrPixelConfig != validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
1079}
1080
1081
Greg Daniel627d0532019-07-08 16:48:14 -04001082GrPixelConfig GrVkCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
1083 GrColorType ct) const {
Robert Phillipsfc711a22018-02-13 17:03:00 -05001084 const VkFormat* vkFormat = format.getVkFormat();
Greg Daniel14c55c22018-12-04 11:25:03 -05001085 const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1086 if (!vkFormat || !ycbcrInfo) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001087 return kUnknown_GrPixelConfig;
Robert Phillipsfc711a22018-02-13 17:03:00 -05001088 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001089 return validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
Greg Danielfaa095e2017-12-19 13:15:02 -05001090}
Greg Danielf5d87582017-12-18 14:48:15 -05001091
Brian Salomonf391d0f2018-12-14 09:18:50 -05001092static GrPixelConfig get_yuva_config(VkFormat vkFormat) {
Jim Van Verth9bf81202018-10-30 15:53:36 -04001093 switch (vkFormat) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001094 case VK_FORMAT_R8_UNORM:
1095 return kAlpha_8_as_Red_GrPixelConfig;
1096 case VK_FORMAT_R8G8B8A8_UNORM:
1097 return kRGBA_8888_GrPixelConfig;
1098 case VK_FORMAT_R8G8B8_UNORM:
1099 return kRGB_888_GrPixelConfig;
1100 case VK_FORMAT_R8G8_UNORM:
1101 return kRG_88_GrPixelConfig;
1102 case VK_FORMAT_B8G8R8A8_UNORM:
1103 return kBGRA_8888_GrPixelConfig;
Robert Phillips2dd1b472019-03-21 09:00:20 -04001104 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1105 return kRGBA_1010102_GrPixelConfig;
Robert Phillipsfe18de52019-06-06 17:21:50 -04001106 case VK_FORMAT_R16_UNORM:
1107 return kR_16_GrPixelConfig;
1108 case VK_FORMAT_R16G16_UNORM:
1109 return kRG_1616_GrPixelConfig;
Robert Phillips66a46032019-06-18 08:00:42 -04001110 // Experimental (for Y416 and mutant P016/P010)
1111 case VK_FORMAT_R16G16B16A16_UNORM:
1112 return kRGBA_16161616_GrPixelConfig;
1113 case VK_FORMAT_R16G16_SFLOAT:
1114 return kRG_half_GrPixelConfig;
Brian Salomonf391d0f2018-12-14 09:18:50 -05001115 default:
1116 return kUnknown_GrPixelConfig;
Jim Van Verthb7f0b9c2018-10-22 14:12:03 -04001117 }
Jim Van Verthb7f0b9c2018-10-22 14:12:03 -04001118}
1119
Brian Salomonf391d0f2018-12-14 09:18:50 -05001120GrPixelConfig GrVkCaps::getYUVAConfigFromBackendFormat(const GrBackendFormat& format) const {
Jim Van Verth9bf81202018-10-30 15:53:36 -04001121 const VkFormat* vkFormat = format.getVkFormat();
1122 if (!vkFormat) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001123 return kUnknown_GrPixelConfig;
Jim Van Verth9bf81202018-10-30 15:53:36 -04001124 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001125 return get_yuva_config(*vkFormat);
Timothy Liang036fdfe2018-06-28 15:50:36 -04001126}
Greg Daniel4065d452018-11-16 15:43:41 -05001127
Greg Daniele877dce2019-07-11 10:52:43 -04001128GrBackendFormat GrVkCaps::getBackendFormatFromColorType(GrColorType ct) const {
1129 GrPixelConfig config = GrColorTypeToPixelConfig(ct);
Greg Daniel4065d452018-11-16 15:43:41 -05001130 if (config == kUnknown_GrPixelConfig) {
1131 return GrBackendFormat();
1132 }
1133 VkFormat format;
1134 if (!GrPixelConfigToVkFormat(config, &format)) {
1135 return GrBackendFormat();
1136 }
1137 return GrBackendFormat::MakeVk(format);
1138}
Timothy Liang036fdfe2018-06-28 15:50:36 -04001139
Brian Salomonbb8dde82019-06-27 10:52:13 -04001140GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
1141 SkImage::CompressionType compressionType) const {
1142 switch (compressionType) {
1143 case SkImage::kETC1_CompressionType:
1144 return GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
1145 }
1146 SK_ABORT("Invalid compression type");
1147 return {};
1148}
1149
Brian Salomona3e29962019-07-16 11:52:08 -04001150bool GrVkCaps::canClearTextureOnCreation() const { return true; }
1151
Greg Danieleb4a8272019-05-16 16:52:55 -04001152#ifdef SK_DEBUG
1153static bool format_color_type_valid_pair(VkFormat vkFormat, GrColorType colorType) {
1154 switch (colorType) {
1155 case GrColorType::kUnknown:
1156 return false;
1157 case GrColorType::kAlpha_8:
1158 return VK_FORMAT_R8_UNORM == vkFormat;
Greg Daniel48fec762019-06-18 17:06:43 -04001159 case GrColorType::kBGR_565:
Greg Danieleb4a8272019-05-16 16:52:55 -04001160 return VK_FORMAT_R5G6B5_UNORM_PACK16 == vkFormat;
1161 case GrColorType::kABGR_4444:
1162 return VK_FORMAT_B4G4R4A4_UNORM_PACK16 == vkFormat ||
1163 VK_FORMAT_R4G4B4A4_UNORM_PACK16 == vkFormat;
1164 case GrColorType::kRGBA_8888:
Greg Daniele877dce2019-07-11 10:52:43 -04001165 return VK_FORMAT_R8G8B8A8_UNORM == vkFormat;
1166 case GrColorType::kRGBA_8888_SRGB:
1167 return VK_FORMAT_R8G8B8A8_SRGB == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001168 case GrColorType::kRGB_888x:
Brian Salomonbb8dde82019-06-27 10:52:13 -04001169 GR_STATIC_ASSERT(GrCompressionTypeClosestColorType(SkImage::kETC1_CompressionType) ==
1170 GrColorType::kRGB_888x);
1171 return VK_FORMAT_R8G8B8_UNORM == vkFormat || VK_FORMAT_R8G8B8A8_UNORM == vkFormat ||
1172 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001173 case GrColorType::kRG_88:
1174 return VK_FORMAT_R8G8_UNORM == vkFormat;
1175 case GrColorType::kBGRA_8888:
1176 return VK_FORMAT_B8G8R8A8_UNORM == vkFormat || VK_FORMAT_B8G8R8A8_SRGB == vkFormat;
1177 case GrColorType::kRGBA_1010102:
1178 return VK_FORMAT_A2B10G10R10_UNORM_PACK32 == vkFormat;
1179 case GrColorType::kGray_8:
1180 return VK_FORMAT_R8_UNORM == vkFormat;
1181 case GrColorType::kAlpha_F16:
1182 return VK_FORMAT_R16_SFLOAT == vkFormat;
1183 case GrColorType::kRGBA_F16:
1184 return VK_FORMAT_R16G16B16A16_SFLOAT == vkFormat;
1185 case GrColorType::kRGBA_F16_Clamped:
1186 return VK_FORMAT_R16G16B16A16_SFLOAT == vkFormat;
1187 case GrColorType::kRG_F32:
1188 return VK_FORMAT_R32G32_SFLOAT == vkFormat;
1189 case GrColorType::kRGBA_F32:
1190 return VK_FORMAT_R32G32B32A32_SFLOAT == vkFormat;
Robert Phillipsfe18de52019-06-06 17:21:50 -04001191 case GrColorType::kR_16:
1192 return VK_FORMAT_R16_UNORM == vkFormat;
1193 case GrColorType::kRG_1616:
1194 return VK_FORMAT_R16G16_UNORM == vkFormat;
Robert Phillips66a46032019-06-18 08:00:42 -04001195 // Experimental (for Y416 and mutant P016/P010)
1196 case GrColorType::kRGBA_16161616:
1197 return VK_FORMAT_R16G16B16A16_UNORM == vkFormat;
Brian Salomone14cfbe2019-06-24 15:00:58 -04001198 case GrColorType::kRG_F16:
Robert Phillips66a46032019-06-18 08:00:42 -04001199 return VK_FORMAT_R16G16_SFLOAT == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001200 }
Greg Daniel4f71ccc2019-05-17 10:56:46 -04001201 SK_ABORT("Unknown color type");
1202 return false;
Greg Danieleb4a8272019-05-16 16:52:55 -04001203}
1204#endif
1205
1206static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
1207 bool forOutput) {
1208 SkASSERT(format.getVkFormat());
1209 VkFormat vkFormat = *format.getVkFormat();
1210
1211 SkASSERT(format_color_type_valid_pair(vkFormat, colorType));
1212
1213 switch (colorType) {
1214 case GrColorType::kAlpha_8: // fall through
1215 case GrColorType::kAlpha_F16:
1216 if (forOutput) {
1217 return GrSwizzle::AAAA();
1218 } else {
1219 return GrSwizzle::RRRR();
1220 }
1221 case GrColorType::kGray_8:
1222 if (!forOutput) {
1223 return GrSwizzle::RRRA();
1224 }
1225 break;
1226 case GrColorType::kABGR_4444:
1227 if (VK_FORMAT_B4G4R4A4_UNORM_PACK16 == vkFormat) {
1228 return GrSwizzle::BGRA();
1229 }
1230 break;
1231 case GrColorType::kRGB_888x:
1232 if (!forOutput) {
1233 return GrSwizzle::RGB1();
1234 }
1235 default:
1236 return GrSwizzle::RGBA();
1237 }
1238 return GrSwizzle::RGBA();
1239}
1240
1241GrSwizzle GrVkCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1242 return get_swizzle(format, colorType, false);
1243}
1244GrSwizzle GrVkCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1245 return get_swizzle(format, colorType, true);
1246}
1247
Brian Salomon26de56e2019-04-10 12:14:26 -04001248size_t GrVkCaps::onTransferFromOffsetAlignment(GrColorType bufferColorType) const {
Brian Salomona585fe92019-04-09 14:57:00 -04001249 // This GrColorType has 32 bpp but the Vulkan pixel format we use for with may have 24bpp
1250 // (VK_FORMAT_R8G8B8_...) or may be 32 bpp. We don't support post transforming the pixel data
1251 // for transfer-from currently and don't want to have to pass info about the src surface here.
1252 if (bufferColorType == GrColorType::kRGB_888x) {
1253 return false;
1254 }
1255 size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
1256 // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1257 switch (bpp & 0b11) {
Brian Salomon26de56e2019-04-10 12:14:26 -04001258 // bpp is already a multiple of 4.
1259 case 0: return bpp;
1260 // bpp is a multiple of 2 but not 4.
1261 case 2: return 2 * bpp;
1262 // bpp is not a multiple of 2.
1263 default: return 4 * bpp;
Brian Salomona585fe92019-04-09 14:57:00 -04001264 }
Brian Salomona585fe92019-04-09 14:57:00 -04001265}