blob: 355373bcf40bab61bff73ff4f18fc089ba243854 [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"
Brian Osman7fbb3632019-07-19 11:38:57 -040014#include "src/gpu/GrUtil.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/SkGr.h"
16#include "src/gpu/vk/GrVkCaps.h"
17#include "src/gpu/vk/GrVkInterface.h"
18#include "src/gpu/vk/GrVkTexture.h"
19#include "src/gpu/vk/GrVkUtil.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050020
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040021#ifdef SK_BUILD_FOR_ANDROID
22#include <sys/system_properties.h>
23#endif
24
Greg Daniel164a9f02016-02-22 09:56:40 -050025GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
Greg Daniela0651ac2018-08-08 09:23:18 -040026 VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
Greg Daniel41f0e282019-01-28 13:15:05 -050027 uint32_t instanceVersion, uint32_t physicalDeviceVersion,
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040028 const GrVkExtensions& extensions, GrProtected isProtected)
29 : INHERITED(contextOptions) {
Greg Daniel164a9f02016-02-22 09:56:40 -050030 /**************************************************************************
Brian Salomonf7232642018-09-19 08:58:08 -040031 * GrCaps fields
32 **************************************************************************/
jvanverth62340062016-04-26 08:01:44 -070033 fMipMapSupport = true; // always available in Vulkan
brianosmanf05ab1b2016-05-12 11:01:10 -070034 fSRGBSupport = true; // always available in Vulkan
brianosman88791862016-05-23 10:15:27 -070035 fNPOTTextureTileSupport = true; // always available in Vulkan
Greg Daniel164a9f02016-02-22 09:56:40 -050036 fReuseScratchTextures = true; //TODO: figure this out
37 fGpuTracingSupport = false; //TODO: figure this out
Greg Daniel164a9f02016-02-22 09:56:40 -050038 fOversizedStencilSupport = false; //TODO: figure this out
Chris Dalton1d616352017-05-31 12:51:23 -060039 fInstanceAttribSupport = true;
Greg Daniel164a9f02016-02-22 09:56:40 -050040
Brian Salomon9ff5acb2019-05-08 09:04:47 -040041 fSemaphoreSupport = true; // always available in Vulkan
jvanverth84741b32016-09-30 08:39:02 -070042 fFenceSyncSupport = true; // always available in Vulkan
Greg Daniel691f5e72018-02-28 14:21:34 -050043 fCrossContextTextureSupport = true;
Brian Osman499bf1a2018-09-17 11:32:42 -040044 fHalfFloatVertexAttributeSupport = true;
Greg Daniel164a9f02016-02-22 09:56:40 -050045
Brian Salomon1047a492019-07-02 12:25:21 -040046 // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
47 fReadPixelsRowBytesSupport = true;
48 fWritePixelsRowBytesSupport = true;
49
Brian Salomone05ba5a2019-04-08 11:59:07 -040050 fTransferBufferSupport = true;
Greg Daniel164a9f02016-02-22 09:56:40 -050051
52 fMaxRenderTargetSize = 4096; // minimum required by spec
53 fMaxTextureSize = 4096; // minimum required by spec
Greg Daniel164a9f02016-02-22 09:56:40 -050054
Brian Salomonf7232642018-09-19 08:58:08 -040055 fDynamicStateArrayGeometryProcessorTextureSupport = true;
56
Brian Salomon94efbf52016-11-29 13:43:05 -050057 fShaderCaps.reset(new GrShaderCaps(contextOptions));
Greg Daniel164a9f02016-02-22 09:56:40 -050058
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040059 this->init(contextOptions, vkInterface, physDev, features, physicalDeviceVersion, extensions,
60 isProtected);
Greg Daniel164a9f02016-02-22 09:56:40 -050061}
62
Greg Daniel5c7b5412019-05-10 11:39:55 -040063static int get_compatible_format_class(GrPixelConfig config) {
64 switch (config) {
65 case kAlpha_8_GrPixelConfig:
66 case kAlpha_8_as_Red_GrPixelConfig:
67 case kGray_8_GrPixelConfig:
68 case kGray_8_as_Red_GrPixelConfig:
69 return 1;
70 case kRGB_565_GrPixelConfig:
71 case kRGBA_4444_GrPixelConfig:
72 case kRG_88_GrPixelConfig:
73 case kAlpha_half_GrPixelConfig:
74 case kAlpha_half_as_Red_GrPixelConfig:
Robert Phillips66a46032019-06-18 08:00:42 -040075 case kR_16_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -040076 return 2;
77 case kRGB_888_GrPixelConfig:
78 return 3;
79 case kRGBA_8888_GrPixelConfig:
80 case kRGB_888X_GrPixelConfig:
81 case kBGRA_8888_GrPixelConfig:
82 case kSRGBA_8888_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -040083 case kRGBA_1010102_GrPixelConfig:
Robert Phillips66a46032019-06-18 08:00:42 -040084 case kRG_1616_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -040085 return 4;
86 case kRGBA_half_GrPixelConfig:
87 case kRGBA_half_Clamped_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -040088 return 5;
89 case kRGBA_float_GrPixelConfig:
90 return 6;
91 case kRGB_ETC1_GrPixelConfig:
92 return 7;
93 case kUnknown_GrPixelConfig:
94 case kAlpha_8_as_Alpha_GrPixelConfig:
95 case kGray_8_as_Lum_GrPixelConfig:
96 SK_ABORT("Unsupported Vulkan pixel config");
97 return 0;
Robert Phillips66a46032019-06-18 08:00:42 -040098
99 // Experimental (for Y416 and mutant P016/P010)
100 case kRGBA_16161616_GrPixelConfig:
101 return 8;
102 case kRG_half_GrPixelConfig:
Robert Phillipsfe18de52019-06-06 17:21:50 -0400103 return 4;
Greg Daniel5c7b5412019-05-10 11:39:55 -0400104 }
105 SK_ABORT("Invalid pixel config");
106 return 0;
107}
108
Greg Daniel46cfbc62019-06-07 11:43:30 -0400109bool GrVkCaps::canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
110 GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
Greg Daniel25af6712018-04-25 10:44:38 -0400111 if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
112 return false;
113 }
114
Greg Daniela51e93c2019-03-25 12:30:45 -0400115 if (dstHasYcbcr || srcHasYcbcr) {
116 return false;
117 }
118
Greg Daniel25af6712018-04-25 10:44:38 -0400119 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
120 // as image usage flags.
Greg Daniel46cfbc62019-06-07 11:43:30 -0400121 if (get_compatible_format_class(srcConfig) != get_compatible_format_class(dstConfig)) {
Greg Daniel25af6712018-04-25 10:44:38 -0400122 return false;
123 }
124
Greg Daniel25af6712018-04-25 10:44:38 -0400125 return true;
126}
127
128bool GrVkCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dstIsLinear,
Greg Daniela51e93c2019-03-25 12:30:45 -0400129 bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt,
130 bool srcIsLinear, bool srcHasYcbcr) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400131
132 VkFormat dstFormat;
133 SkAssertResult(GrPixelConfigToVkFormat(dstConfig, &dstFormat));
134 VkFormat srcFormat;
135 SkAssertResult(GrPixelConfigToVkFormat(srcConfig, &srcFormat));
Greg Daniel25af6712018-04-25 10:44:38 -0400136 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
137 // as image usage flags.
Greg Danielcaa795f2019-05-14 11:54:25 -0400138 if (!this->formatCanBeDstofBlit(dstFormat, dstIsLinear) ||
139 !this->formatCanBeSrcofBlit(srcFormat, srcIsLinear)) {
Greg Daniel25af6712018-04-25 10:44:38 -0400140 return false;
141 }
142
Greg Daniel25af6712018-04-25 10:44:38 -0400143 // We cannot blit images that are multisampled. Will need to figure out if we can blit the
144 // resolved msaa though.
145 if (dstSampleCnt > 1 || srcSampleCnt > 1) {
146 return false;
147 }
148
Greg Daniela51e93c2019-03-25 12:30:45 -0400149 if (dstHasYcbcr || srcHasYcbcr) {
150 return false;
151 }
152
Greg Daniel25af6712018-04-25 10:44:38 -0400153 return true;
154}
155
Greg Daniel46cfbc62019-06-07 11:43:30 -0400156bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
157 GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
Greg Daniel25af6712018-04-25 10:44:38 -0400158 // The src surface must be multisampled.
159 if (srcSampleCnt <= 1) {
160 return false;
161 }
162
163 // The dst must not be multisampled.
164 if (dstSampleCnt > 1) {
165 return false;
166 }
167
168 // Surfaces must have the same format.
169 if (dstConfig != srcConfig) {
170 return false;
171 }
172
Greg Daniela51e93c2019-03-25 12:30:45 -0400173 if (dstHasYcbcr || srcHasYcbcr) {
174 return false;
175 }
176
Greg Daniel25af6712018-04-25 10:44:38 -0400177 return true;
178}
179
Brian Salomonc67c31c2018-12-06 10:00:03 -0500180bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
181 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400182 if (src->isProtected() && !dst->isProtected()) {
183 return false;
184 }
185
Greg Daniel25af6712018-04-25 10:44:38 -0400186 GrPixelConfig dstConfig = dst->config();
187 GrPixelConfig srcConfig = src->config();
188
189 // TODO: Figure out a way to track if we've wrapped a linear texture in a proxy (e.g.
190 // PromiseImage which won't get instantiated right away. Does this need a similar thing like the
191 // tracking of external or rectangle textures in GL? For now we don't create linear textures
192 // internally, and I don't believe anyone is wrapping them.
193 bool srcIsLinear = false;
194 bool dstIsLinear = false;
195
196 int dstSampleCnt = 0;
197 int srcSampleCnt = 0;
198 if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
Greg Danielbe7fc462019-01-03 16:40:42 -0500199 // Copying to or from render targets that wrap a secondary command buffer is not allowed
200 // since they would require us to know the VkImage, which we don't have, as well as need us
201 // to stop and start the VkRenderPass which we don't have access to.
202 if (rtProxy->wrapsVkSecondaryCB()) {
203 return false;
204 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600205 dstSampleCnt = rtProxy->numSamples();
Greg Daniel25af6712018-04-25 10:44:38 -0400206 }
207 if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
Greg Danielbe7fc462019-01-03 16:40:42 -0500208 // Copying to or from render targets that wrap a secondary command buffer is not allowed
209 // since they would require us to know the VkImage, which we don't have, as well as need us
210 // to stop and start the VkRenderPass which we don't have access to.
211 if (rtProxy->wrapsVkSecondaryCB()) {
212 return false;
213 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600214 srcSampleCnt = rtProxy->numSamples();
Greg Daniel25af6712018-04-25 10:44:38 -0400215 }
216 SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
217 SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
218
Greg Daniela51e93c2019-03-25 12:30:45 -0400219 bool dstHasYcbcr = false;
220 if (auto ycbcr = dst->backendFormat().getVkYcbcrConversionInfo()) {
221 if (ycbcr->isValid()) {
222 dstHasYcbcr = true;
223 }
224 }
225
226 bool srcHasYcbcr = false;
227 if (auto ycbcr = src->backendFormat().getVkYcbcrConversionInfo()) {
228 if (ycbcr->isValid()) {
229 srcHasYcbcr = true;
230 }
231 }
232
Greg Daniel46cfbc62019-06-07 11:43:30 -0400233 return this->canCopyImage(dstConfig, dstSampleCnt, dstHasYcbcr,
234 srcConfig, srcSampleCnt, srcHasYcbcr) ||
Greg Daniela51e93c2019-03-25 12:30:45 -0400235 this->canCopyAsBlit(dstConfig, dstSampleCnt, dstIsLinear, dstHasYcbcr,
236 srcConfig, srcSampleCnt, srcIsLinear, srcHasYcbcr) ||
Greg Daniel46cfbc62019-06-07 11:43:30 -0400237 this->canCopyAsResolve(dstConfig, dstSampleCnt, dstHasYcbcr,
238 srcConfig, srcSampleCnt, srcHasYcbcr);
Greg Daniel25af6712018-04-25 10:44:38 -0400239}
240
Greg Daniel7e000222018-12-03 10:08:21 -0500241template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features,
242 VkStructureType type) {
243 // All Vulkan structs that could be part of the features chain will start with the
244 // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
245 // so we can get access to the pNext for the next struct.
246 struct CommonVulkanHeader {
247 VkStructureType sType;
248 void* pNext;
249 };
250
251 void* pNext = features.pNext;
252 while (pNext) {
253 CommonVulkanHeader* header = static_cast<CommonVulkanHeader*>(pNext);
254 if (header->sType == type) {
255 return static_cast<T*>(pNext);
256 }
257 pNext = header->pNext;
258 }
259 return nullptr;
260}
261
Greg Daniel164a9f02016-02-22 09:56:40 -0500262void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
Greg Daniela0651ac2018-08-08 09:23:18 -0400263 VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400264 uint32_t physicalDeviceVersion, const GrVkExtensions& extensions,
265 GrProtected isProtected) {
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000266 VkPhysicalDeviceProperties properties;
267 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
egdanield5e3b9e2016-03-08 12:19:54 -0800268
egdanield5e3b9e2016-03-08 12:19:54 -0800269 VkPhysicalDeviceMemoryProperties memoryProperties;
270 GR_VK_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &memoryProperties));
271
Greg Daniel41f0e282019-01-28 13:15:05 -0500272 SkASSERT(physicalDeviceVersion <= properties.apiVersion);
Greg Danielc0b03d82018-08-03 14:41:15 -0400273
Greg Danielcb324152019-02-25 11:36:53 -0500274 if (extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 1)) {
275 fSupportsSwapchain = true;
276 }
277
Greg Danielc0b03d82018-08-03 14:41:15 -0400278 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
279 extensions.hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
280 fSupportsPhysicalDeviceProperties2 = true;
281 }
282
283 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
284 extensions.hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1)) {
285 fSupportsMemoryRequirements2 = true;
286 }
287
288 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Daniel637c06a2018-09-12 09:44:25 -0400289 extensions.hasExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, 1)) {
290 fSupportsBindMemory2 = true;
291 }
292
293 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Danielc0b03d82018-08-03 14:41:15 -0400294 extensions.hasExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME, 1)) {
295 fSupportsMaintenance1 = true;
296 }
297
298 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
299 extensions.hasExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME, 1)) {
300 fSupportsMaintenance2 = true;
301 }
302
303 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
304 extensions.hasExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME, 1)) {
305 fSupportsMaintenance3 = true;
306 }
307
Greg Daniela9979d12018-08-27 15:56:46 -0400308 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Daniel637c06a2018-09-12 09:44:25 -0400309 (extensions.hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
Greg Daniela9979d12018-08-27 15:56:46 -0400310 this->supportsMemoryRequirements2())) {
311 fSupportsDedicatedAllocation = true;
312 }
313
314 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
315 (extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 1) &&
316 this->supportsPhysicalDeviceProperties2() &&
317 extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, 1) &&
318 this->supportsDedicatedAllocation())) {
319 fSupportsExternalMemory = true;
320 }
321
322#ifdef SK_BUILD_FOR_ANDROID
Greg Daniel637c06a2018-09-12 09:44:25 -0400323 // Currently Adreno devices are not supporting the QUEUE_FAMILY_FOREIGN_EXTENSION, so until they
324 // do we don't explicitly require it here even the spec says it is required.
Greg Daniela9979d12018-08-27 15:56:46 -0400325 if (extensions.hasExtension(
Greg Daniel637c06a2018-09-12 09:44:25 -0400326 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2) &&
327 /* extensions.hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1) &&*/
328 this->supportsExternalMemory() &&
329 this->supportsBindMemory2()) {
Greg Daniela9979d12018-08-27 15:56:46 -0400330 fSupportsAndroidHWBExternalMemory = true;
Greg Daniel637c06a2018-09-12 09:44:25 -0400331 fSupportsAHardwareBufferImages = true;
Greg Daniela9979d12018-08-27 15:56:46 -0400332 }
333#endif
334
Greg Daniel7e000222018-12-03 10:08:21 -0500335 auto ycbcrFeatures =
336 get_extension_feature_struct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
337 features,
338 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
339 if (ycbcrFeatures && ycbcrFeatures->samplerYcbcrConversion &&
340 fSupportsAndroidHWBExternalMemory &&
341 (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
342 (extensions.hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1) &&
343 this->supportsMaintenance1() &&
344 this->supportsBindMemory2() &&
345 this->supportsMemoryRequirements2() &&
346 this->supportsPhysicalDeviceProperties2()))) {
347 fSupportsYcbcrConversion = true;
348 }
349 // We always push back the default GrVkYcbcrConversionInfo so that the case of no conversion
350 // will return a key of 0.
351 fYcbcrInfos.push_back(GrVkYcbcrConversionInfo());
352
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400353 if ((isProtected == GrProtected::kYes) &&
354 (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0))) {
355 fSupportsProtectedMemory = true;
356 fAvoidUpdateBuffers = true;
357 fShouldAlwaysUseDedicatedImageMemory = true;
358 }
359
Greg Daniel313c6952018-08-08 09:24:08 -0400360 this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
Greg Daniel36443602018-08-02 12:51:52 -0400361 this->initShaderCaps(properties, features);
Greg Danielf3b11622018-03-01 15:01:27 -0500362
363 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
364#if defined(SK_CPU_X86)
365 // We need to do this before initing the config table since it uses fSRGBSupport
366 if (kImagination_VkVendor == properties.vendorID) {
367 fSRGBSupport = false;
368 }
369#endif
370 }
371
Chris Dalton8e738a22018-10-05 16:41:44 -0600372 if (kQualcomm_VkVendor == properties.vendorID) {
373 // A "clear" load for the CCPR atlas runs faster on QC than a "discard" load followed by a
374 // scissored clear.
375 // On NVIDIA and Intel, the discard load followed by clear is faster.
376 // TODO: Evaluate on ARM, Imagination, and ATI.
377 fPreferFullscreenClears = true;
378 }
379
Greg Daniel44e69f92019-03-20 11:18:25 -0400380 if (kQualcomm_VkVendor == properties.vendorID || kARM_VkVendor == properties.vendorID) {
381 // On Qualcomm and ARM mapping a gpu buffer and doing both reads and writes to it is slow.
382 // Thus for index and vertex buffers we will force to use a cpu side buffer and then copy
383 // the whole buffer up to the gpu.
Greg Daniel78e6a4c2019-03-19 14:13:36 -0400384 fBufferMapThreshold = SK_MaxS32;
385 }
386
387 if (kQualcomm_VkVendor == properties.vendorID) {
388 // On Qualcomm it looks like using vkCmdUpdateBuffer is slower than using a transfer buffer
389 // even for small sizes.
390 fAvoidUpdateBuffers = true;
391 }
392
Chris Dalton0dffbab2019-03-27 13:08:50 -0600393 if (kARM_VkVendor == properties.vendorID) {
394 // ARM seems to do better with more fine triangles as opposed to using the sample mask.
395 // (At least in our current round rect op.)
396 fPreferTrianglesOverSampleMask = true;
397 }
Greg Daniel78e6a4c2019-03-19 14:13:36 -0400398
Greg Danielcaa795f2019-05-14 11:54:25 -0400399 this->initFormatTable(vkInterface, physDev, properties);
egdaniel8f1dcaa2016-04-01 10:10:45 -0700400 this->initStencilFormat(vkInterface, physDev);
Greg Daniel164a9f02016-02-22 09:56:40 -0500401
Greg Daniel691f5e72018-02-28 14:21:34 -0500402 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
403 this->applyDriverCorrectnessWorkarounds(properties);
egdanielc5ec1402016-03-28 12:14:42 -0700404 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500405
Greg Daniel691f5e72018-02-28 14:21:34 -0500406 this->applyOptionsOverrides(contextOptions);
407 fShaderCaps->applyOptionsOverrides(contextOptions);
408}
409
410void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) {
egdaniel6fa0a912016-09-12 11:51:29 -0700411 if (kQualcomm_VkVendor == properties.vendorID) {
412 fMustDoCopiesFromOrigin = true;
Brian Salomona585fe92019-04-09 14:57:00 -0400413 // Transfer doesn't support this workaround.
414 fTransferBufferSupport = false;
egdaniel6fa0a912016-09-12 11:51:29 -0700415 }
416
Greg Daniel80a08dd2017-01-20 10:45:49 -0500417#if defined(SK_BUILD_FOR_WIN)
Greg Daniel900e5c82018-08-28 10:59:24 -0400418 if (kNvidia_VkVendor == properties.vendorID || kIntel_VkVendor == properties.vendorID) {
Greg Daniel80a08dd2017-01-20 10:45:49 -0500419 fMustSleepOnTearDown = true;
420 }
421#elif defined(SK_BUILD_FOR_ANDROID)
422 if (kImagination_VkVendor == properties.vendorID) {
423 fMustSleepOnTearDown = true;
424 }
425#endif
Greg Danielbce5eb92018-03-01 13:13:44 -0500426
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400427#if defined(SK_BUILD_FOR_ANDROID)
428 // Protected memory features have problems in Android P and earlier.
429 if (fSupportsProtectedMemory && (kQualcomm_VkVendor == properties.vendorID)) {
430 char androidAPIVersion[PROP_VALUE_MAX];
431 int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersion);
432 if (strLength == 0 || atoi(androidAPIVersion) <= 28) {
433 fSupportsProtectedMemory = false;
434 }
435 }
436#endif
437
Greg Danielbce5eb92018-03-01 13:13:44 -0500438 // AMD seems to have issues binding new VkPipelines inside a secondary command buffer.
439 // Current workaround is to use a different secondary command buffer for each new VkPipeline.
440 if (kAMD_VkVendor == properties.vendorID) {
441 fNewCBOnPipelineChange = true;
442 }
443
Greg Danielddc0c602018-06-18 11:26:30 -0400444 // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
445 if (kARM_VkVendor == properties.vendorID) {
446 fShouldAlwaysUseDedicatedImageMemory = true;
447 }
448
Greg Danielbce5eb92018-03-01 13:13:44 -0500449 ////////////////////////////////////////////////////////////////////////////
450 // GrCaps workarounds
451 ////////////////////////////////////////////////////////////////////////////
452
453 if (kARM_VkVendor == properties.vendorID) {
454 fInstanceAttribSupport = false;
Greg Daniel4374e962018-09-28 15:09:47 -0400455 fAvoidWritePixelsFastPath = true; // bugs.skia.org/8064
Greg Danielbce5eb92018-03-01 13:13:44 -0500456 }
457
458 // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32.
459 if (kAMD_VkVendor == properties.vendorID) {
460 fMaxVertexAttributes = SkTMin(fMaxVertexAttributes, 32);
461 }
462
Greg Danielbce5eb92018-03-01 13:13:44 -0500463 ////////////////////////////////////////////////////////////////////////////
464 // GrShaderCaps workarounds
465 ////////////////////////////////////////////////////////////////////////////
466
Greg Danielbce5eb92018-03-01 13:13:44 -0500467 if (kImagination_VkVendor == properties.vendorID) {
468 fShaderCaps->fAtan2ImplementedAsAtanYOverX = true;
469 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500470}
471
472int get_max_sample_count(VkSampleCountFlags flags) {
473 SkASSERT(flags & VK_SAMPLE_COUNT_1_BIT);
474 if (!(flags & VK_SAMPLE_COUNT_2_BIT)) {
475 return 0;
476 }
477 if (!(flags & VK_SAMPLE_COUNT_4_BIT)) {
478 return 2;
479 }
480 if (!(flags & VK_SAMPLE_COUNT_8_BIT)) {
481 return 4;
482 }
483 if (!(flags & VK_SAMPLE_COUNT_16_BIT)) {
484 return 8;
485 }
486 if (!(flags & VK_SAMPLE_COUNT_32_BIT)) {
487 return 16;
488 }
489 if (!(flags & VK_SAMPLE_COUNT_64_BIT)) {
490 return 32;
491 }
492 return 64;
493}
494
Greg Daniel313c6952018-08-08 09:24:08 -0400495void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
496 VkPhysicalDevice physDev,
497 const VkPhysicalDeviceProperties& properties,
jvanverthfd7bd452016-03-25 06:29:52 -0700498 const VkPhysicalDeviceMemoryProperties& memoryProperties,
Greg Daniel313c6952018-08-08 09:24:08 -0400499 const VkPhysicalDeviceFeatures2& features,
500 const GrVkExtensions& extensions) {
Greg Danielc5cc2de2017-03-20 11:40:58 -0400501 // So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no
502 // need for us ever to support that amount, and it makes tests which tests all the vertex
503 // attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if
504 // we ever find that need.
505 static const uint32_t kMaxVertexAttributes = 64;
506 fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
Greg Danielc5cc2de2017-03-20 11:40:58 -0400507
egdanield5e3b9e2016-03-08 12:19:54 -0800508 // We could actually query and get a max size for each config, however maxImageDimension2D will
509 // give the minimum max size across all configs. So for simplicity we will use that for now.
jvanverthe78d4872016-09-27 03:33:05 -0700510 fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
511 fMaxTextureSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
Adrienne Walker724afe82018-05-15 11:36:26 -0700512 if (fDriverBugWorkarounds.max_texture_size_limit_4096) {
513 fMaxTextureSize = SkTMin(fMaxTextureSize, 4096);
514 }
515 // Our render targets are always created with textures as the color
516 // attachment, hence this min:
517 fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
egdanield5e3b9e2016-03-08 12:19:54 -0800518
Chris Dalton2612bae2018-02-22 13:41:37 -0700519 // TODO: check if RT's larger than 4k incur a performance cost on ARM.
520 fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
521
egdanield5e3b9e2016-03-08 12:19:54 -0800522 // Assuming since we will always map in the end to upload the data we might as well just map
523 // from the get go. There is no hard data to suggest this is faster or slower.
cdalton397536c2016-03-25 12:15:03 -0700524 fBufferMapThreshold = 0;
egdanield5e3b9e2016-03-08 12:19:54 -0800525
Brian Salomon105d7c22019-04-16 13:46:14 -0400526 fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;
egdanield5e3b9e2016-03-08 12:19:54 -0800527
egdanield5e3b9e2016-03-08 12:19:54 -0800528 fOversizedStencilSupport = true;
Greg Daniel313c6952018-08-08 09:24:08 -0400529
530 if (extensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2) &&
531 this->supportsPhysicalDeviceProperties2()) {
532
533 VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProps;
534 blendProps.sType =
535 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
536 blendProps.pNext = nullptr;
537
538 VkPhysicalDeviceProperties2 props;
539 props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
540 props.pNext = &blendProps;
541
542 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props));
543
544 if (blendProps.advancedBlendAllOperations == VK_TRUE) {
545 fShaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kAutomatic_AdvBlendEqInteraction;
546
547 auto blendFeatures =
548 get_extension_feature_struct<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(
549 features,
550 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT);
551 if (blendFeatures && blendFeatures->advancedBlendCoherentOperations == VK_TRUE) {
552 fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
553 } else {
554 // TODO: Currently non coherent blends are not supported in our vulkan backend. They
555 // require us to support self dependencies in our render passes.
556 // fBlendEquationSupport = kAdvanced_BlendEquationSupport;
557 }
558 }
559 }
egdanield5e3b9e2016-03-08 12:19:54 -0800560}
561
Greg Daniel36443602018-08-02 12:51:52 -0400562void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
Greg Daniela0651ac2018-08-08 09:23:18 -0400563 const VkPhysicalDeviceFeatures2& features) {
Brian Salomon1edc5b92016-11-29 13:43:46 -0500564 GrShaderCaps* shaderCaps = fShaderCaps.get();
565 shaderCaps->fVersionDeclString = "#version 330\n";
egdaniel3a15fd42016-04-05 11:00:29 -0700566
egdanield5e3b9e2016-03-08 12:19:54 -0800567 // Vulkan is based off ES 3.0 so the following should all be supported
Brian Salomon1edc5b92016-11-29 13:43:46 -0500568 shaderCaps->fUsesPrecisionModifiers = true;
569 shaderCaps->fFlatInterpolationSupport = true;
Brian Salomon41274562017-09-15 09:40:03 -0700570 // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed
571 // to be true with Vulkan as well.
572 shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID;
egdanield5e3b9e2016-03-08 12:19:54 -0800573
574 // GrShaderCaps
575
Brian Salomon1edc5b92016-11-29 13:43:46 -0500576 shaderCaps->fShaderDerivativeSupport = true;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600577
Ethan Nicholas6ac8d362019-01-22 21:43:55 +0000578 // FIXME: http://skbug.com/7733: Disable geometry shaders until Intel/Radeon GMs draw correctly.
579 // shaderCaps->fGeometryShaderSupport =
580 // shaderCaps->fGSInvocationsSupport = features.features.geometryShader;
egdanield632bb42016-03-30 12:06:48 -0700581
Greg Daniela0651ac2018-08-08 09:23:18 -0400582 shaderCaps->fDualSourceBlendingSupport = features.features.dualSrcBlend;
egdanield632bb42016-03-30 12:06:48 -0700583
Brian Salomon1edc5b92016-11-29 13:43:46 -0500584 shaderCaps->fIntegerSupport = true;
Chris Dalton1d616352017-05-31 12:51:23 -0600585 shaderCaps->fVertexIDSupport = true;
Chris Dalton7c7ff032018-03-28 20:09:58 -0600586 shaderCaps->fFPManipulationSupport = true;
cdalton9c3f1432016-03-11 10:07:37 -0800587
cdaltona6b92ad2016-04-11 12:03:08 -0700588 // Assume the minimum precisions mandated by the SPIR-V spec.
Chris Dalton47c8ed32017-11-15 18:27:09 -0700589 shaderCaps->fFloatIs32Bits = true;
590 shaderCaps->fHalfIs32Bits = false;
cdaltona6b92ad2016-04-11 12:03:08 -0700591
Brian Salomon1edc5b92016-11-29 13:43:46 -0500592 shaderCaps->fMaxFragmentSamplers = SkTMin(
593 SkTMin(properties.limits.maxPerStageDescriptorSampledImages,
594 properties.limits.maxPerStageDescriptorSamplers),
595 (uint32_t)INT_MAX);
Greg Daniel164a9f02016-02-22 09:56:40 -0500596}
597
egdaniel8f1dcaa2016-04-01 10:10:45 -0700598bool stencil_format_supported(const GrVkInterface* interface,
599 VkPhysicalDevice physDev,
600 VkFormat format) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500601 VkFormatProperties props;
602 memset(&props, 0, sizeof(VkFormatProperties));
603 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
egdaniel8f1dcaa2016-04-01 10:10:45 -0700604 return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures);
Greg Daniel164a9f02016-02-22 09:56:40 -0500605}
606
egdaniel8f1dcaa2016-04-01 10:10:45 -0700607void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevice physDev) {
608 // List of legal stencil formats (though perhaps not supported on
609 // the particular gpu/driver) from most preferred to least. We are guaranteed to have either
jvanvertha4b0fed2016-04-27 11:42:21 -0700610 // 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 -0700611 // can optionally have 24 unused bits at the end so we assume the total bits is 64.
Greg Daniel164a9f02016-02-22 09:56:40 -0500612 static const StencilFormat
613 // internal Format stencil bits total bits packed?
614 gS8 = { VK_FORMAT_S8_UINT, 8, 8, false },
egdaniel8f1dcaa2016-04-01 10:10:45 -0700615 gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT, 8, 32, true },
616 gD32S8 = { VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 64, true };
Greg Daniel164a9f02016-02-22 09:56:40 -0500617
egdaniel8f1dcaa2016-04-01 10:10:45 -0700618 if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) {
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400619 fPreferredStencilFormat = gS8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700620 } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) {
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400621 fPreferredStencilFormat = gD24S8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700622 } else {
623 SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT));
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400624 fPreferredStencilFormat = gD32S8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700625 }
626}
627
Greg Danielcaa795f2019-05-14 11:54:25 -0400628static bool format_is_srgb(VkFormat format) {
Robert Phillipsf209e882019-06-25 15:59:50 -0400629 SkASSERT(GrVkFormatIsSupported(format));
630
Greg Danielcaa795f2019-05-14 11:54:25 -0400631 switch (format) {
632 case VK_FORMAT_R8G8B8A8_SRGB:
Greg Danielcaa795f2019-05-14 11:54:25 -0400633 return true;
Greg Danielcaa795f2019-05-14 11:54:25 -0400634 default:
Greg Danielcaa795f2019-05-14 11:54:25 -0400635 return false;
636 }
637}
638
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400639// These are all the valid VkFormats that we support in Skia. They are roughly ordered from most
Greg Danielcaa795f2019-05-14 11:54:25 -0400640// frequently used to least to improve look up times in arrays.
641static constexpr VkFormat kVkFormats[] = {
642 VK_FORMAT_R8G8B8A8_UNORM,
643 VK_FORMAT_R8_UNORM,
644 VK_FORMAT_B8G8R8A8_UNORM,
645 VK_FORMAT_R5G6B5_UNORM_PACK16,
646 VK_FORMAT_R16G16B16A16_SFLOAT,
647 VK_FORMAT_R16_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400648 VK_FORMAT_R8G8B8_UNORM,
649 VK_FORMAT_R8G8_UNORM,
650 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
651 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
Greg Danieleb4a8272019-05-16 16:52:55 -0400652 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
Greg Danielcaa795f2019-05-14 11:54:25 -0400653 VK_FORMAT_R32G32B32A32_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400654 VK_FORMAT_R8G8B8A8_SRGB,
Robert Phillipsfe18de52019-06-06 17:21:50 -0400655 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
Robert Phillipsfe18de52019-06-06 17:21:50 -0400656 VK_FORMAT_R16_UNORM,
657 VK_FORMAT_R16G16_UNORM,
Robert Phillips66a46032019-06-18 08:00:42 -0400658 // Experimental (for Y416 and mutant P016/P010)
659 VK_FORMAT_R16G16B16A16_UNORM,
660 VK_FORMAT_R16G16_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400661};
662
663const GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) const {
664 static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
665 "Size of VkFormats array must match static value in header");
666 for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
667 if (kVkFormats[i] == format) {
668 return fFormatTable[i];
669 }
670 }
671 SK_ABORT("Invalid VkFormat");
Greg Daniel52ee5f62019-06-20 13:38:18 -0400672 static const FormatInfo kInvalidFormat;
673 return kInvalidFormat;
Greg Danielcaa795f2019-05-14 11:54:25 -0400674}
675
676void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000677 const VkPhysicalDeviceProperties& properties) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400678 static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
679 "Size of VkFormats array must match static value in header");
680 for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
681 VkFormat format = kVkFormats[i];
682 if (!format_is_srgb(format) || fSRGBSupport) {
683 fFormatTable[i].init(interface, physDev, properties, format);
egdaniel8f1dcaa2016-04-01 10:10:45 -0700684 }
685 }
686}
687
Greg Danielcaa795f2019-05-14 11:54:25 -0400688void GrVkCaps::FormatInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
egdaniel8f1dcaa2016-04-01 10:10:45 -0700689 if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
690 SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
691 *flags = *flags | kTextureable_Flag;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700692
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400693 // Ganesh assumes that all renderable surfaces are also texturable
Greg Danielcaa795f2019-05-14 11:54:25 -0400694 if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400695 *flags = *flags | kRenderable_Flag;
696 }
egdaniel8f1dcaa2016-04-01 10:10:45 -0700697 }
698
699 if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) {
700 *flags = *flags | kBlitSrc_Flag;
701 }
702
703 if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) {
704 *flags = *flags | kBlitDst_Flag;
705 }
706}
707
Greg Danielcaa795f2019-05-14 11:54:25 -0400708void GrVkCaps::FormatInfo::initSampleCounts(const GrVkInterface* interface,
Greg Daniel81e7bf82017-07-19 14:47:42 -0400709 VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000710 const VkPhysicalDeviceProperties& physProps,
Greg Daniel81e7bf82017-07-19 14:47:42 -0400711 VkFormat format) {
712 VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
713 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
714 VK_IMAGE_USAGE_SAMPLED_BIT |
715 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Greg Daniel81e7bf82017-07-19 14:47:42 -0400716 VkImageFormatProperties properties;
717 GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev,
718 format,
719 VK_IMAGE_TYPE_2D,
720 VK_IMAGE_TILING_OPTIMAL,
721 usage,
Brian Osman2b23c4b2018-06-01 12:25:08 -0400722 0, // createFlags
Greg Daniel81e7bf82017-07-19 14:47:42 -0400723 &properties));
724 VkSampleCountFlags flags = properties.sampleCounts;
725 if (flags & VK_SAMPLE_COUNT_1_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400726 fColorSampleCounts.push_back(1);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400727 }
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000728 if (kImagination_VkVendor == physProps.vendorID) {
729 // MSAA does not work on imagination
730 return;
731 }
Brian Osman7fbb3632019-07-19 11:38:57 -0400732 if (kIntel_VkVendor == physProps.vendorID) {
733 // MSAA on Intel before Gen 9 is slow and/or buggy
734 if (GrGetIntelGpuFamily(physProps.deviceID) < kFirstGen9_IntelGpuFamily) {
735 return;
736 }
737 }
Greg Daniel81e7bf82017-07-19 14:47:42 -0400738 if (flags & VK_SAMPLE_COUNT_2_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400739 fColorSampleCounts.push_back(2);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400740 }
741 if (flags & VK_SAMPLE_COUNT_4_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400742 fColorSampleCounts.push_back(4);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400743 }
744 if (flags & VK_SAMPLE_COUNT_8_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400745 fColorSampleCounts.push_back(8);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400746 }
747 if (flags & VK_SAMPLE_COUNT_16_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400748 fColorSampleCounts.push_back(16);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400749 }
750 if (flags & VK_SAMPLE_COUNT_32_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400751 fColorSampleCounts.push_back(32);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400752 }
753 if (flags & VK_SAMPLE_COUNT_64_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -0400754 fColorSampleCounts.push_back(64);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400755 }
756}
757
Greg Danielcaa795f2019-05-14 11:54:25 -0400758void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,
egdaniel8f1dcaa2016-04-01 10:10:45 -0700759 VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000760 const VkPhysicalDeviceProperties& properties,
Greg Danielcaa795f2019-05-14 11:54:25 -0400761 VkFormat format) {
egdaniel8f1dcaa2016-04-01 10:10:45 -0700762 VkFormatProperties props;
763 memset(&props, 0, sizeof(VkFormatProperties));
764 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
Greg Danielcaa795f2019-05-14 11:54:25 -0400765 InitConfigFlags(props.linearTilingFeatures, &fLinearFlags);
766 InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400767 if (fOptimalFlags & kRenderable_Flag) {
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000768 this->initSampleCounts(interface, physDev, properties, format);
Greg Daniel81e7bf82017-07-19 14:47:42 -0400769 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500770}
Greg Daniel81e7bf82017-07-19 14:47:42 -0400771
Robert Phillipsf209e882019-06-25 15:59:50 -0400772bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
773 if (!format.getVkFormat()) {
774 return false;
775 }
776
777 return format_is_srgb(*format.getVkFormat());
778}
779
Greg Daniel2f2caea2019-07-08 14:24:47 -0400780bool GrVkCaps::isFormatTexturable(GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400781 if (!format.getVkFormat()) {
782 return false;
783 }
784
Greg Daniel2f2caea2019-07-08 14:24:47 -0400785 return this->isVkFormatTexturable(*format.getVkFormat());
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400786}
787
Greg Daniel2f2caea2019-07-08 14:24:47 -0400788bool GrVkCaps::isVkFormatTexturable(VkFormat format) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400789 if (!GrVkFormatIsSupported(format)) {
790 return false;
791 }
792
793 const FormatInfo& info = this->getFormatInfo(format);
794 return SkToBool(FormatInfo::kTextureable_Flag & info.fOptimalFlags);
795}
796
797bool GrVkCaps::isConfigTexturable(GrPixelConfig config) const {
798 VkFormat format;
799 if (!GrPixelConfigToVkFormat(config, &format)) {
800 return false;
801 }
Greg Daniel2f2caea2019-07-08 14:24:47 -0400802 return this->isVkFormatTexturable(format);
Robert Phillips39ef2ef2019-05-15 08:45:53 -0400803}
804
805bool GrVkCaps::isFormatRenderable(VkFormat format) const {
806 return this->maxRenderTargetSampleCount(format) > 0;
Greg Danielcaa795f2019-05-14 11:54:25 -0400807}
808
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400809int GrVkCaps::getRenderTargetSampleCount(int requestedCount,
Greg Daniel5c96db82019-07-09 14:06:58 -0400810 GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400811 if (!format.getVkFormat()) {
812 return 0;
813 }
814
815 return this->getRenderTargetSampleCount(requestedCount, *format.getVkFormat());
816}
817
Brian Salomonbdecacf2018-02-02 20:32:49 -0500818int GrVkCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400819 // Currently we don't allow RGB_888X to be renderable because we don't have a way to handle
820 // blends that reference dst alpha when the values in the dst alpha channel are uninitialized.
821 if (config == kRGB_888X_GrPixelConfig) {
822 return 0;
823 }
824
825 VkFormat format;
826 if (!GrPixelConfigToVkFormat(config, &format)) {
827 return 0;
828 }
829
830 return this->getRenderTargetSampleCount(requestedCount, format);
831}
832
833int GrVkCaps::getRenderTargetSampleCount(int requestedCount, VkFormat format) const {
Brian Salomonbdecacf2018-02-02 20:32:49 -0500834 requestedCount = SkTMax(1, requestedCount);
Greg Danielcaa795f2019-05-14 11:54:25 -0400835
836 const FormatInfo& info = this->getFormatInfo(format);
837
838 int count = info.fColorSampleCounts.count();
Brian Salomonbdecacf2018-02-02 20:32:49 -0500839
840 if (!count) {
Greg Daniel81e7bf82017-07-19 14:47:42 -0400841 return 0;
842 }
843
Brian Salomonbdecacf2018-02-02 20:32:49 -0500844 if (1 == requestedCount) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400845 SkASSERT(info.fColorSampleCounts.count() && info.fColorSampleCounts[0] == 1);
Brian Salomonbdecacf2018-02-02 20:32:49 -0500846 return 1;
847 }
848
Greg Daniel81e7bf82017-07-19 14:47:42 -0400849 for (int i = 0; i < count; ++i) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400850 if (info.fColorSampleCounts[i] >= requestedCount) {
851 return info.fColorSampleCounts[i];
Greg Daniel81e7bf82017-07-19 14:47:42 -0400852 }
853 }
Brian Salomonbdecacf2018-02-02 20:32:49 -0500854 return 0;
855}
856
Greg Daniel5c96db82019-07-09 14:06:58 -0400857int GrVkCaps::maxRenderTargetSampleCount(GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400858 if (!format.getVkFormat()) {
859 return 0;
860 }
861
862 return this->maxRenderTargetSampleCount(*format.getVkFormat());
863}
864
Brian Salomonbdecacf2018-02-02 20:32:49 -0500865int GrVkCaps::maxRenderTargetSampleCount(GrPixelConfig config) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400866 // Currently we don't allow RGB_888X to be renderable because we don't have a way to handle
867 // blends that reference dst alpha when the values in the dst alpha channel are uninitialized.
868 if (config == kRGB_888X_GrPixelConfig) {
869 return 0;
870 }
871
872 VkFormat format;
873 if (!GrPixelConfigToVkFormat(config, &format)) {
874 return 0;
875 }
876 return this->maxRenderTargetSampleCount(format);
877}
878
879int GrVkCaps::maxRenderTargetSampleCount(VkFormat format) const {
880 const FormatInfo& info = this->getFormatInfo(format);
881
882 const auto& table = info.fColorSampleCounts;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500883 if (!table.count()) {
884 return 0;
885 }
886 return table[table.count() - 1];
Brian Salomond653cac2018-02-01 13:58:00 -0500887}
888
Brian Salomondc0710f2019-07-01 14:59:32 -0400889GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
890 const GrSurface* surface) const {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400891 if (surface->isProtected()) {
Brian Salomondc0710f2019-07-01 14:59:32 -0400892 return SurfaceReadPixelsSupport::kUnsupported;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400893 }
Greg Daniela51e93c2019-03-25 12:30:45 -0400894 if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
895 // We can't directly read from a VkImage that has a ycbcr sampler.
896 if (tex->ycbcrConversionInfo().isValid()) {
Brian Salomondc0710f2019-07-01 14:59:32 -0400897 return SurfaceReadPixelsSupport::kCopyToTexture2D;
Greg Daniela51e93c2019-03-25 12:30:45 -0400898 }
Greg Daniel00fb7242019-07-18 14:28:01 -0400899 // We can't directly read from a compressed format
900 SkImage::CompressionType compressionType;
901 if (GrVkFormatToCompressionType(tex->imageFormat(), &compressionType)) {
902 return SurfaceReadPixelsSupport::kCopyToTexture2D;
903 }
Greg Daniela51e93c2019-03-25 12:30:45 -0400904 }
Brian Salomondc0710f2019-07-01 14:59:32 -0400905 return SurfaceReadPixelsSupport::kSupported;
Greg Daniela51e93c2019-03-25 12:30:45 -0400906}
907
Brian Salomonc67c31c2018-12-06 10:00:03 -0500908bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
Brian Salomon3d86a192018-02-27 16:46:11 -0500909 if (auto rt = surface->asRenderTarget()) {
Chris Dalton6ce447a2019-06-23 18:07:38 -0600910 return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
Brian Salomon3d86a192018-02-27 16:46:11 -0500911 }
Greg Daniela51e93c2019-03-25 12:30:45 -0400912 // We can't write to a texture that has a ycbcr sampler.
913 if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
914 // We can't directly read from a VkImage that has a ycbcr sampler.
915 if (tex->ycbcrConversionInfo().isValid()) {
916 return false;
917 }
918 }
Brian Salomon3d86a192018-02-27 16:46:11 -0500919 return true;
920}
921
Robert Phillips1e2cb442019-07-02 15:51:28 -0400922// A near clone of format_color_type_valid_pair
923static GrPixelConfig validate_image_info(VkFormat format, GrColorType ct, bool hasYcbcrConversion) {
Greg Daniel14c55c22018-12-04 11:25:03 -0500924 if (format == VK_FORMAT_UNDEFINED) {
925 // If the format is undefined then it is only valid as an external image which requires that
926 // we have a valid VkYcbcrConversion.
927 if (hasYcbcrConversion) {
928 // 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 -0400929 // values for external textures. However, for read pixels we will draw to a non ycbcr
930 // texture of this config so we set RGBA here for that.
Brian Salomonf391d0f2018-12-14 09:18:50 -0500931 return kRGBA_8888_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500932 } else {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500933 return kUnknown_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500934 }
935 }
936
937 if (hasYcbcrConversion) {
938 // We only support having a ycbcr conversion for external images.
Brian Salomonf391d0f2018-12-14 09:18:50 -0500939 return kUnknown_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500940 }
941
Greg Danielf5d87582017-12-18 14:48:15 -0500942 switch (ct) {
Robert Phillips1e2cb442019-07-02 15:51:28 -0400943 case GrColorType::kUnknown:
Brian Salomonf391d0f2018-12-14 09:18:50 -0500944 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400945 case GrColorType::kAlpha_8:
Greg Danielf5d87582017-12-18 14:48:15 -0500946 if (VK_FORMAT_R8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500947 return kAlpha_8_as_Red_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500948 }
949 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400950 case GrColorType::kBGR_565:
Greg Danielf5d87582017-12-18 14:48:15 -0500951 if (VK_FORMAT_R5G6B5_UNORM_PACK16 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500952 return kRGB_565_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500953 }
954 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400955 case GrColorType::kABGR_4444:
Greg Danieleb4a8272019-05-16 16:52:55 -0400956 if (VK_FORMAT_B4G4R4A4_UNORM_PACK16 == format ||
957 VK_FORMAT_R4G4B4A4_UNORM_PACK16 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500958 return kRGBA_4444_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500959 }
960 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400961 case GrColorType::kRGBA_8888:
Greg Danielf5d87582017-12-18 14:48:15 -0500962 if (VK_FORMAT_R8G8B8A8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500963 return kRGBA_8888_GrPixelConfig;
Greg Daniele877dce2019-07-11 10:52:43 -0400964 }
965 break;
966 case GrColorType::kRGBA_8888_SRGB:
967 if (VK_FORMAT_R8G8B8A8_SRGB == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500968 return kSRGBA_8888_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500969 }
970 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400971 case GrColorType::kRGB_888x:
Greg Daniel475eb702018-09-28 14:16:50 -0400972 if (VK_FORMAT_R8G8B8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500973 return kRGB_888_GrPixelConfig;
Greg Daniel475eb702018-09-28 14:16:50 -0400974 }
Greg Danielf259b8b2019-02-14 09:03:43 -0500975 if (VK_FORMAT_R8G8B8A8_UNORM == format) {
976 return kRGB_888X_GrPixelConfig;
977 }
Greg Daniel475eb702018-09-28 14:16:50 -0400978 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400979 case GrColorType::kRG_88:
980 if (VK_FORMAT_R8G8_UNORM == format) {
981 return kRG_88_GrPixelConfig;
982 }
983 break;
984 case GrColorType::kBGRA_8888:
Greg Danielf5d87582017-12-18 14:48:15 -0500985 if (VK_FORMAT_B8G8R8A8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500986 return kBGRA_8888_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500987 }
988 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400989 case GrColorType::kRGBA_1010102:
Brian Osman10fc6fd2018-03-02 11:01:10 -0500990 if (VK_FORMAT_A2B10G10R10_UNORM_PACK32 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500991 return kRGBA_1010102_GrPixelConfig;
Brian Osman10fc6fd2018-03-02 11:01:10 -0500992 }
993 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400994 case GrColorType::kGray_8:
Greg Danielf5d87582017-12-18 14:48:15 -0500995 if (VK_FORMAT_R8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -0500996 return kGray_8_as_Red_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -0500997 }
998 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -0400999 case GrColorType::kAlpha_F16:
1000 if (VK_FORMAT_R16_SFLOAT == format) {
Robert Phillips0902c982019-07-16 07:47:56 -04001001 return kAlpha_half_as_Red_GrPixelConfig;
Mike Kleinb70990e2019-02-28 10:03:27 -06001002 }
1003 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001004 case GrColorType::kRGBA_F16:
Greg Danielf5d87582017-12-18 14:48:15 -05001005 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001006 return kRGBA_half_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001007 }
1008 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001009 case GrColorType::kRGBA_F16_Clamped:
1010 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
1011 return kRGBA_half_Clamped_GrPixelConfig;
1012 }
1013 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001014 case GrColorType::kRGBA_F32:
Mike Klein37854712018-06-26 11:43:06 -04001015 if (VK_FORMAT_R32G32B32A32_SFLOAT == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001016 return kRGBA_float_GrPixelConfig;
Mike Klein37854712018-06-26 11:43:06 -04001017 }
1018 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001019 case GrColorType::kR_16:
1020 if (VK_FORMAT_R16_UNORM == format) {
1021 return kR_16_GrPixelConfig;
1022 }
1023 break;
1024 case GrColorType::kRG_1616:
1025 if (VK_FORMAT_R16G16_UNORM == format) {
1026 return kRG_1616_GrPixelConfig;
1027 }
1028 break;
1029 case GrColorType::kRGBA_16161616:
1030 if (VK_FORMAT_R16G16B16A16_UNORM == format) {
1031 return kRGBA_16161616_GrPixelConfig;
1032 }
1033 break;
1034 case GrColorType::kRG_F16:
1035 if (VK_FORMAT_R16G16_SFLOAT == format) {
1036 return kRG_half_GrPixelConfig;
1037 }
1038 break;
Greg Danielf5d87582017-12-18 14:48:15 -05001039 }
1040
Brian Salomonf391d0f2018-12-14 09:18:50 -05001041 return kUnknown_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001042}
1043
Brian Salomonf391d0f2018-12-14 09:18:50 -05001044GrPixelConfig GrVkCaps::validateBackendRenderTarget(const GrBackendRenderTarget& rt,
Robert Phillips1e2cb442019-07-02 15:51:28 -04001045 GrColorType ct) const {
Greg Daniel323fbcf2018-04-10 13:46:30 -04001046 GrVkImageInfo imageInfo;
1047 if (!rt.getVkImageInfo(&imageInfo)) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001048 return kUnknown_GrPixelConfig;
Robert Phillipsfc711a22018-02-13 17:03:00 -05001049 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001050 return validate_image_info(imageInfo.fFormat, ct, imageInfo.fYcbcrConversionInfo.isValid());
Robert Phillipsfc711a22018-02-13 17:03:00 -05001051}
1052
Greg Daniel627d0532019-07-08 16:48:14 -04001053bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
1054 const GrBackendFormat& format) const {
Robert Phillipsc046ff02019-07-01 10:34:03 -04001055 const VkFormat* vkFormat = format.getVkFormat();
1056 const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1057 if (!vkFormat || !ycbcrInfo) {
1058 return false;
1059 }
1060
1061 return kUnknown_GrPixelConfig != validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
1062}
1063
1064
Greg Daniel627d0532019-07-08 16:48:14 -04001065GrPixelConfig GrVkCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
1066 GrColorType ct) const {
Robert Phillipsfc711a22018-02-13 17:03:00 -05001067 const VkFormat* vkFormat = format.getVkFormat();
Greg Daniel14c55c22018-12-04 11:25:03 -05001068 const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1069 if (!vkFormat || !ycbcrInfo) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001070 return kUnknown_GrPixelConfig;
Robert Phillipsfc711a22018-02-13 17:03:00 -05001071 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001072 return validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
Greg Danielfaa095e2017-12-19 13:15:02 -05001073}
Greg Danielf5d87582017-12-18 14:48:15 -05001074
Brian Salomonf391d0f2018-12-14 09:18:50 -05001075static GrPixelConfig get_yuva_config(VkFormat vkFormat) {
Jim Van Verth9bf81202018-10-30 15:53:36 -04001076 switch (vkFormat) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001077 case VK_FORMAT_R8_UNORM:
1078 return kAlpha_8_as_Red_GrPixelConfig;
1079 case VK_FORMAT_R8G8B8A8_UNORM:
1080 return kRGBA_8888_GrPixelConfig;
1081 case VK_FORMAT_R8G8B8_UNORM:
1082 return kRGB_888_GrPixelConfig;
1083 case VK_FORMAT_R8G8_UNORM:
1084 return kRG_88_GrPixelConfig;
1085 case VK_FORMAT_B8G8R8A8_UNORM:
1086 return kBGRA_8888_GrPixelConfig;
Robert Phillips2dd1b472019-03-21 09:00:20 -04001087 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1088 return kRGBA_1010102_GrPixelConfig;
Robert Phillipsfe18de52019-06-06 17:21:50 -04001089 case VK_FORMAT_R16_UNORM:
1090 return kR_16_GrPixelConfig;
1091 case VK_FORMAT_R16G16_UNORM:
1092 return kRG_1616_GrPixelConfig;
Robert Phillips66a46032019-06-18 08:00:42 -04001093 // Experimental (for Y416 and mutant P016/P010)
1094 case VK_FORMAT_R16G16B16A16_UNORM:
1095 return kRGBA_16161616_GrPixelConfig;
1096 case VK_FORMAT_R16G16_SFLOAT:
1097 return kRG_half_GrPixelConfig;
Brian Salomonf391d0f2018-12-14 09:18:50 -05001098 default:
1099 return kUnknown_GrPixelConfig;
Jim Van Verthb7f0b9c2018-10-22 14:12:03 -04001100 }
Jim Van Verthb7f0b9c2018-10-22 14:12:03 -04001101}
1102
Brian Salomonf391d0f2018-12-14 09:18:50 -05001103GrPixelConfig GrVkCaps::getYUVAConfigFromBackendFormat(const GrBackendFormat& format) const {
Jim Van Verth9bf81202018-10-30 15:53:36 -04001104 const VkFormat* vkFormat = format.getVkFormat();
1105 if (!vkFormat) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001106 return kUnknown_GrPixelConfig;
Jim Van Verth9bf81202018-10-30 15:53:36 -04001107 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001108 return get_yuva_config(*vkFormat);
Timothy Liang036fdfe2018-06-28 15:50:36 -04001109}
Greg Daniel4065d452018-11-16 15:43:41 -05001110
Greg Daniele877dce2019-07-11 10:52:43 -04001111GrBackendFormat GrVkCaps::getBackendFormatFromColorType(GrColorType ct) const {
1112 GrPixelConfig config = GrColorTypeToPixelConfig(ct);
Greg Daniel4065d452018-11-16 15:43:41 -05001113 if (config == kUnknown_GrPixelConfig) {
1114 return GrBackendFormat();
1115 }
1116 VkFormat format;
1117 if (!GrPixelConfigToVkFormat(config, &format)) {
1118 return GrBackendFormat();
1119 }
1120 return GrBackendFormat::MakeVk(format);
1121}
Timothy Liang036fdfe2018-06-28 15:50:36 -04001122
Brian Salomonbb8dde82019-06-27 10:52:13 -04001123GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
1124 SkImage::CompressionType compressionType) const {
1125 switch (compressionType) {
1126 case SkImage::kETC1_CompressionType:
1127 return GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
1128 }
1129 SK_ABORT("Invalid compression type");
1130 return {};
1131}
1132
Brian Salomona3e29962019-07-16 11:52:08 -04001133bool GrVkCaps::canClearTextureOnCreation() const { return true; }
1134
Greg Danieleb4a8272019-05-16 16:52:55 -04001135#ifdef SK_DEBUG
1136static bool format_color_type_valid_pair(VkFormat vkFormat, GrColorType colorType) {
1137 switch (colorType) {
1138 case GrColorType::kUnknown:
1139 return false;
1140 case GrColorType::kAlpha_8:
1141 return VK_FORMAT_R8_UNORM == vkFormat;
Greg Daniel48fec762019-06-18 17:06:43 -04001142 case GrColorType::kBGR_565:
Greg Danieleb4a8272019-05-16 16:52:55 -04001143 return VK_FORMAT_R5G6B5_UNORM_PACK16 == vkFormat;
1144 case GrColorType::kABGR_4444:
1145 return VK_FORMAT_B4G4R4A4_UNORM_PACK16 == vkFormat ||
1146 VK_FORMAT_R4G4B4A4_UNORM_PACK16 == vkFormat;
1147 case GrColorType::kRGBA_8888:
Greg Daniele877dce2019-07-11 10:52:43 -04001148 return VK_FORMAT_R8G8B8A8_UNORM == vkFormat;
1149 case GrColorType::kRGBA_8888_SRGB:
1150 return VK_FORMAT_R8G8B8A8_SRGB == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001151 case GrColorType::kRGB_888x:
Brian Salomonbb8dde82019-06-27 10:52:13 -04001152 GR_STATIC_ASSERT(GrCompressionTypeClosestColorType(SkImage::kETC1_CompressionType) ==
1153 GrColorType::kRGB_888x);
1154 return VK_FORMAT_R8G8B8_UNORM == vkFormat || VK_FORMAT_R8G8B8A8_UNORM == vkFormat ||
1155 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001156 case GrColorType::kRG_88:
1157 return VK_FORMAT_R8G8_UNORM == vkFormat;
1158 case GrColorType::kBGRA_8888:
Greg Daniel00fb7242019-07-18 14:28:01 -04001159 return VK_FORMAT_B8G8R8A8_UNORM == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001160 case GrColorType::kRGBA_1010102:
1161 return VK_FORMAT_A2B10G10R10_UNORM_PACK32 == vkFormat;
1162 case GrColorType::kGray_8:
1163 return VK_FORMAT_R8_UNORM == vkFormat;
1164 case GrColorType::kAlpha_F16:
1165 return VK_FORMAT_R16_SFLOAT == vkFormat;
1166 case GrColorType::kRGBA_F16:
1167 return VK_FORMAT_R16G16B16A16_SFLOAT == vkFormat;
1168 case GrColorType::kRGBA_F16_Clamped:
1169 return VK_FORMAT_R16G16B16A16_SFLOAT == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001170 case GrColorType::kRGBA_F32:
1171 return VK_FORMAT_R32G32B32A32_SFLOAT == vkFormat;
Robert Phillipsfe18de52019-06-06 17:21:50 -04001172 case GrColorType::kR_16:
1173 return VK_FORMAT_R16_UNORM == vkFormat;
1174 case GrColorType::kRG_1616:
1175 return VK_FORMAT_R16G16_UNORM == vkFormat;
Robert Phillips66a46032019-06-18 08:00:42 -04001176 // Experimental (for Y416 and mutant P016/P010)
1177 case GrColorType::kRGBA_16161616:
1178 return VK_FORMAT_R16G16B16A16_UNORM == vkFormat;
Brian Salomone14cfbe2019-06-24 15:00:58 -04001179 case GrColorType::kRG_F16:
Robert Phillips66a46032019-06-18 08:00:42 -04001180 return VK_FORMAT_R16G16_SFLOAT == vkFormat;
Greg Danieleb4a8272019-05-16 16:52:55 -04001181 }
Greg Daniel4f71ccc2019-05-17 10:56:46 -04001182 SK_ABORT("Unknown color type");
1183 return false;
Greg Danieleb4a8272019-05-16 16:52:55 -04001184}
1185#endif
1186
1187static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
1188 bool forOutput) {
1189 SkASSERT(format.getVkFormat());
1190 VkFormat vkFormat = *format.getVkFormat();
1191
1192 SkASSERT(format_color_type_valid_pair(vkFormat, colorType));
1193
1194 switch (colorType) {
1195 case GrColorType::kAlpha_8: // fall through
1196 case GrColorType::kAlpha_F16:
1197 if (forOutput) {
1198 return GrSwizzle::AAAA();
1199 } else {
1200 return GrSwizzle::RRRR();
1201 }
1202 case GrColorType::kGray_8:
1203 if (!forOutput) {
1204 return GrSwizzle::RRRA();
1205 }
1206 break;
1207 case GrColorType::kABGR_4444:
1208 if (VK_FORMAT_B4G4R4A4_UNORM_PACK16 == vkFormat) {
1209 return GrSwizzle::BGRA();
1210 }
1211 break;
1212 case GrColorType::kRGB_888x:
1213 if (!forOutput) {
1214 return GrSwizzle::RGB1();
1215 }
1216 default:
1217 return GrSwizzle::RGBA();
1218 }
1219 return GrSwizzle::RGBA();
1220}
1221
1222GrSwizzle GrVkCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1223 return get_swizzle(format, colorType, false);
1224}
1225GrSwizzle GrVkCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1226 return get_swizzle(format, colorType, true);
1227}
1228
Brian Salomon26de56e2019-04-10 12:14:26 -04001229size_t GrVkCaps::onTransferFromOffsetAlignment(GrColorType bufferColorType) const {
Brian Salomona585fe92019-04-09 14:57:00 -04001230 // This GrColorType has 32 bpp but the Vulkan pixel format we use for with may have 24bpp
1231 // (VK_FORMAT_R8G8B8_...) or may be 32 bpp. We don't support post transforming the pixel data
1232 // for transfer-from currently and don't want to have to pass info about the src surface here.
1233 if (bufferColorType == GrColorType::kRGB_888x) {
1234 return false;
1235 }
1236 size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
1237 // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1238 switch (bpp & 0b11) {
Brian Salomon26de56e2019-04-10 12:14:26 -04001239 // bpp is already a multiple of 4.
1240 case 0: return bpp;
1241 // bpp is a multiple of 2 but not 4.
1242 case 2: return 2 * bpp;
1243 // bpp is not a multiple of 2.
1244 default: return 4 * bpp;
Brian Salomona585fe92019-04-09 14:57:00 -04001245 }
Brian Salomona585fe92019-04-09 14:57:00 -04001246}
Greg Daniel00fb7242019-07-18 14:28:01 -04001247
1248GrCaps::SupportedRead GrVkCaps::supportedReadPixelsColorType(
1249 GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1250 GrColorType dstColorType) const {
1251 const VkFormat* vkFormat = srcBackendFormat.getVkFormat();
1252 if (!vkFormat) {
1253 return {GrSwizzle(), GrColorType::kUnknown};
1254 }
1255
1256 switch (*vkFormat) {
1257 case VK_FORMAT_R8G8B8A8_UNORM:
1258 return {GrSwizzle::RGBA(), GrColorType::kRGBA_8888};
1259 case VK_FORMAT_R8_UNORM:
1260 if (srcColorType == GrColorType::kAlpha_8) {
1261 return {GrSwizzle::RGBA(), GrColorType::kAlpha_8};
1262 } else if (srcColorType == GrColorType::kGray_8) {
1263 return {GrSwizzle::RGBA(), GrColorType::kGray_8};
1264 }
1265 case VK_FORMAT_B8G8R8A8_UNORM:
1266 return {GrSwizzle::RGBA(), GrColorType::kBGRA_8888};
1267 case VK_FORMAT_R5G6B5_UNORM_PACK16:
1268 return {GrSwizzle::RGBA(), GrColorType::kBGR_565};
1269 case VK_FORMAT_R16G16B16A16_SFLOAT:
1270 if (srcColorType == GrColorType::kRGBA_F16) {
1271 return {GrSwizzle::RGBA(), GrColorType::kRGBA_F16};
1272 } else if (srcColorType == GrColorType::kRGBA_F16_Clamped){
1273 return {GrSwizzle::RGBA(), GrColorType::kRGBA_F16_Clamped};
1274 }
1275 case VK_FORMAT_R16_SFLOAT:
1276 return {GrSwizzle::RGBA(), GrColorType::kAlpha_F16};
1277 case VK_FORMAT_R8G8B8_UNORM:
1278 return {GrSwizzle::RGBA(), GrColorType::kRGB_888x};
1279 case VK_FORMAT_R8G8_UNORM:
1280 return {GrSwizzle::RGBA(), GrColorType::kRG_88};
1281 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1282 return {GrSwizzle::RGBA(), GrColorType::kRGBA_1010102};
1283 case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
1284 return {GrSwizzle::RGBA(), GrColorType::kABGR_4444};
1285 case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
1286 return {GrSwizzle::RGBA(), GrColorType::kABGR_4444};
1287 case VK_FORMAT_R32G32B32A32_SFLOAT:
1288 return {GrSwizzle::RGBA(), GrColorType::kRGBA_F32};
1289 case VK_FORMAT_R8G8B8A8_SRGB:
1290 return {GrSwizzle::RGBA(), GrColorType::kRGBA_8888_SRGB};
1291 case VK_FORMAT_R16_UNORM:
1292 return {GrSwizzle::RGBA(), GrColorType::kR_16};
1293 case VK_FORMAT_R16G16_UNORM:
1294 return {GrSwizzle::RGBA(), GrColorType::kRG_1616};
1295 // Experimental (for Y416 and mutant P016/P010)
1296 case VK_FORMAT_R16G16B16A16_UNORM:
1297 return {GrSwizzle::RGBA(), GrColorType::kRGBA_16161616};
1298 case VK_FORMAT_R16G16_SFLOAT:
1299 return {GrSwizzle::RGBA(), GrColorType::kRG_F16};
1300 default:
1301 return {GrSwizzle(), GrColorType::kUnknown};
1302 }
1303}