blob: 2d940f380722dba7afb333ad7d98aa45d4fb2a28 [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:
Robert Phillipsebab03f2019-07-22 08:48:18 -040096 case kAlpha_half_as_Lum_GrPixelConfig:
Greg Daniel5c7b5412019-05-10 11:39:55 -040097 SK_ABORT("Unsupported Vulkan pixel config");
98 return 0;
Robert Phillips66a46032019-06-18 08:00:42 -040099
100 // Experimental (for Y416 and mutant P016/P010)
101 case kRGBA_16161616_GrPixelConfig:
102 return 8;
103 case kRG_half_GrPixelConfig:
Robert Phillipsfe18de52019-06-06 17:21:50 -0400104 return 4;
Greg Daniel5c7b5412019-05-10 11:39:55 -0400105 }
106 SK_ABORT("Invalid pixel config");
107 return 0;
108}
109
Greg Daniel46cfbc62019-06-07 11:43:30 -0400110bool GrVkCaps::canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
111 GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
Greg Daniel25af6712018-04-25 10:44:38 -0400112 if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
113 return false;
114 }
115
Greg Daniela51e93c2019-03-25 12:30:45 -0400116 if (dstHasYcbcr || srcHasYcbcr) {
117 return false;
118 }
119
Greg Daniel25af6712018-04-25 10:44:38 -0400120 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
121 // as image usage flags.
Greg Daniel46cfbc62019-06-07 11:43:30 -0400122 if (get_compatible_format_class(srcConfig) != get_compatible_format_class(dstConfig)) {
Greg Daniel25af6712018-04-25 10:44:38 -0400123 return false;
124 }
125
Greg Daniel25af6712018-04-25 10:44:38 -0400126 return true;
127}
128
129bool GrVkCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dstIsLinear,
Greg Daniela51e93c2019-03-25 12:30:45 -0400130 bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt,
131 bool srcIsLinear, bool srcHasYcbcr) const {
Greg Danielcaa795f2019-05-14 11:54:25 -0400132
133 VkFormat dstFormat;
134 SkAssertResult(GrPixelConfigToVkFormat(dstConfig, &dstFormat));
135 VkFormat srcFormat;
136 SkAssertResult(GrPixelConfigToVkFormat(srcConfig, &srcFormat));
Greg Daniel25af6712018-04-25 10:44:38 -0400137 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
138 // as image usage flags.
Greg Danielcaa795f2019-05-14 11:54:25 -0400139 if (!this->formatCanBeDstofBlit(dstFormat, dstIsLinear) ||
140 !this->formatCanBeSrcofBlit(srcFormat, srcIsLinear)) {
Greg Daniel25af6712018-04-25 10:44:38 -0400141 return false;
142 }
143
Greg Daniel25af6712018-04-25 10:44:38 -0400144 // We cannot blit images that are multisampled. Will need to figure out if we can blit the
145 // resolved msaa though.
146 if (dstSampleCnt > 1 || srcSampleCnt > 1) {
147 return false;
148 }
149
Greg Daniela51e93c2019-03-25 12:30:45 -0400150 if (dstHasYcbcr || srcHasYcbcr) {
151 return false;
152 }
153
Greg Daniel25af6712018-04-25 10:44:38 -0400154 return true;
155}
156
Greg Daniel46cfbc62019-06-07 11:43:30 -0400157bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
158 GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
Greg Daniel25af6712018-04-25 10:44:38 -0400159 // The src surface must be multisampled.
160 if (srcSampleCnt <= 1) {
161 return false;
162 }
163
164 // The dst must not be multisampled.
165 if (dstSampleCnt > 1) {
166 return false;
167 }
168
169 // Surfaces must have the same format.
170 if (dstConfig != srcConfig) {
171 return false;
172 }
173
Greg Daniela51e93c2019-03-25 12:30:45 -0400174 if (dstHasYcbcr || srcHasYcbcr) {
175 return false;
176 }
177
Greg Daniel25af6712018-04-25 10:44:38 -0400178 return true;
179}
180
Brian Salomonc67c31c2018-12-06 10:00:03 -0500181bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
182 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400183 if (src->isProtected() && !dst->isProtected()) {
184 return false;
185 }
186
Greg Daniel25af6712018-04-25 10:44:38 -0400187 GrPixelConfig dstConfig = dst->config();
188 GrPixelConfig srcConfig = src->config();
189
190 // TODO: Figure out a way to track if we've wrapped a linear texture in a proxy (e.g.
191 // PromiseImage which won't get instantiated right away. Does this need a similar thing like the
192 // tracking of external or rectangle textures in GL? For now we don't create linear textures
193 // internally, and I don't believe anyone is wrapping them.
194 bool srcIsLinear = false;
195 bool dstIsLinear = false;
196
197 int dstSampleCnt = 0;
198 int srcSampleCnt = 0;
199 if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
Greg Danielbe7fc462019-01-03 16:40:42 -0500200 // Copying to or from render targets that wrap a secondary command buffer is not allowed
201 // since they would require us to know the VkImage, which we don't have, as well as need us
202 // to stop and start the VkRenderPass which we don't have access to.
203 if (rtProxy->wrapsVkSecondaryCB()) {
204 return false;
205 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600206 dstSampleCnt = rtProxy->numSamples();
Greg Daniel25af6712018-04-25 10:44:38 -0400207 }
208 if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
Greg Danielbe7fc462019-01-03 16:40:42 -0500209 // Copying to or from render targets that wrap a secondary command buffer is not allowed
210 // since they would require us to know the VkImage, which we don't have, as well as need us
211 // to stop and start the VkRenderPass which we don't have access to.
212 if (rtProxy->wrapsVkSecondaryCB()) {
213 return false;
214 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600215 srcSampleCnt = rtProxy->numSamples();
Greg Daniel25af6712018-04-25 10:44:38 -0400216 }
217 SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
218 SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
219
Greg Daniela51e93c2019-03-25 12:30:45 -0400220 bool dstHasYcbcr = false;
221 if (auto ycbcr = dst->backendFormat().getVkYcbcrConversionInfo()) {
222 if (ycbcr->isValid()) {
223 dstHasYcbcr = true;
224 }
225 }
226
227 bool srcHasYcbcr = false;
228 if (auto ycbcr = src->backendFormat().getVkYcbcrConversionInfo()) {
229 if (ycbcr->isValid()) {
230 srcHasYcbcr = true;
231 }
232 }
233
Greg Daniel46cfbc62019-06-07 11:43:30 -0400234 return this->canCopyImage(dstConfig, dstSampleCnt, dstHasYcbcr,
235 srcConfig, srcSampleCnt, srcHasYcbcr) ||
Greg Daniela51e93c2019-03-25 12:30:45 -0400236 this->canCopyAsBlit(dstConfig, dstSampleCnt, dstIsLinear, dstHasYcbcr,
237 srcConfig, srcSampleCnt, srcIsLinear, srcHasYcbcr) ||
Greg Daniel46cfbc62019-06-07 11:43:30 -0400238 this->canCopyAsResolve(dstConfig, dstSampleCnt, dstHasYcbcr,
239 srcConfig, srcSampleCnt, srcHasYcbcr);
Greg Daniel25af6712018-04-25 10:44:38 -0400240}
241
Greg Daniel7e000222018-12-03 10:08:21 -0500242template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features,
243 VkStructureType type) {
244 // All Vulkan structs that could be part of the features chain will start with the
245 // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
246 // so we can get access to the pNext for the next struct.
247 struct CommonVulkanHeader {
248 VkStructureType sType;
249 void* pNext;
250 };
251
252 void* pNext = features.pNext;
253 while (pNext) {
254 CommonVulkanHeader* header = static_cast<CommonVulkanHeader*>(pNext);
255 if (header->sType == type) {
256 return static_cast<T*>(pNext);
257 }
258 pNext = header->pNext;
259 }
260 return nullptr;
261}
262
Greg Daniel164a9f02016-02-22 09:56:40 -0500263void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
Greg Daniela0651ac2018-08-08 09:23:18 -0400264 VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400265 uint32_t physicalDeviceVersion, const GrVkExtensions& extensions,
266 GrProtected isProtected) {
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000267 VkPhysicalDeviceProperties properties;
268 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
egdanield5e3b9e2016-03-08 12:19:54 -0800269
egdanield5e3b9e2016-03-08 12:19:54 -0800270 VkPhysicalDeviceMemoryProperties memoryProperties;
271 GR_VK_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &memoryProperties));
272
Greg Daniel41f0e282019-01-28 13:15:05 -0500273 SkASSERT(physicalDeviceVersion <= properties.apiVersion);
Greg Danielc0b03d82018-08-03 14:41:15 -0400274
Greg Danielcb324152019-02-25 11:36:53 -0500275 if (extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 1)) {
276 fSupportsSwapchain = true;
277 }
278
Greg Danielc0b03d82018-08-03 14:41:15 -0400279 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
280 extensions.hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
281 fSupportsPhysicalDeviceProperties2 = true;
282 }
283
284 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
285 extensions.hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1)) {
286 fSupportsMemoryRequirements2 = true;
287 }
288
289 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Daniel637c06a2018-09-12 09:44:25 -0400290 extensions.hasExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, 1)) {
291 fSupportsBindMemory2 = true;
292 }
293
294 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Danielc0b03d82018-08-03 14:41:15 -0400295 extensions.hasExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME, 1)) {
296 fSupportsMaintenance1 = true;
297 }
298
299 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
300 extensions.hasExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME, 1)) {
301 fSupportsMaintenance2 = true;
302 }
303
304 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
305 extensions.hasExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME, 1)) {
306 fSupportsMaintenance3 = true;
307 }
308
Greg Daniela9979d12018-08-27 15:56:46 -0400309 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
Greg Daniel637c06a2018-09-12 09:44:25 -0400310 (extensions.hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
Greg Daniela9979d12018-08-27 15:56:46 -0400311 this->supportsMemoryRequirements2())) {
312 fSupportsDedicatedAllocation = true;
313 }
314
315 if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
316 (extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 1) &&
317 this->supportsPhysicalDeviceProperties2() &&
318 extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, 1) &&
319 this->supportsDedicatedAllocation())) {
320 fSupportsExternalMemory = true;
321 }
322
323#ifdef SK_BUILD_FOR_ANDROID
Greg Daniel637c06a2018-09-12 09:44:25 -0400324 // Currently Adreno devices are not supporting the QUEUE_FAMILY_FOREIGN_EXTENSION, so until they
325 // do we don't explicitly require it here even the spec says it is required.
Greg Daniela9979d12018-08-27 15:56:46 -0400326 if (extensions.hasExtension(
Greg Daniel637c06a2018-09-12 09:44:25 -0400327 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2) &&
328 /* extensions.hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1) &&*/
329 this->supportsExternalMemory() &&
330 this->supportsBindMemory2()) {
Greg Daniela9979d12018-08-27 15:56:46 -0400331 fSupportsAndroidHWBExternalMemory = true;
Greg Daniel637c06a2018-09-12 09:44:25 -0400332 fSupportsAHardwareBufferImages = true;
Greg Daniela9979d12018-08-27 15:56:46 -0400333 }
334#endif
335
Greg Daniel7e000222018-12-03 10:08:21 -0500336 auto ycbcrFeatures =
337 get_extension_feature_struct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
338 features,
339 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
340 if (ycbcrFeatures && ycbcrFeatures->samplerYcbcrConversion &&
341 fSupportsAndroidHWBExternalMemory &&
342 (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
343 (extensions.hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1) &&
344 this->supportsMaintenance1() &&
345 this->supportsBindMemory2() &&
346 this->supportsMemoryRequirements2() &&
347 this->supportsPhysicalDeviceProperties2()))) {
348 fSupportsYcbcrConversion = true;
349 }
350 // We always push back the default GrVkYcbcrConversionInfo so that the case of no conversion
351 // will return a key of 0.
352 fYcbcrInfos.push_back(GrVkYcbcrConversionInfo());
353
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400354 if ((isProtected == GrProtected::kYes) &&
355 (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0))) {
356 fSupportsProtectedMemory = true;
357 fAvoidUpdateBuffers = true;
358 fShouldAlwaysUseDedicatedImageMemory = true;
359 }
360
Greg Daniel313c6952018-08-08 09:24:08 -0400361 this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
Greg Daniel36443602018-08-02 12:51:52 -0400362 this->initShaderCaps(properties, features);
Greg Danielf3b11622018-03-01 15:01:27 -0500363
364 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
365#if defined(SK_CPU_X86)
366 // We need to do this before initing the config table since it uses fSRGBSupport
367 if (kImagination_VkVendor == properties.vendorID) {
368 fSRGBSupport = false;
369 }
370#endif
371 }
372
Chris Dalton8e738a22018-10-05 16:41:44 -0600373 if (kQualcomm_VkVendor == properties.vendorID) {
374 // A "clear" load for the CCPR atlas runs faster on QC than a "discard" load followed by a
375 // scissored clear.
376 // On NVIDIA and Intel, the discard load followed by clear is faster.
377 // TODO: Evaluate on ARM, Imagination, and ATI.
378 fPreferFullscreenClears = true;
379 }
380
Greg Daniel44e69f92019-03-20 11:18:25 -0400381 if (kQualcomm_VkVendor == properties.vendorID || kARM_VkVendor == properties.vendorID) {
382 // On Qualcomm and ARM mapping a gpu buffer and doing both reads and writes to it is slow.
383 // Thus for index and vertex buffers we will force to use a cpu side buffer and then copy
384 // the whole buffer up to the gpu.
Greg Daniel78e6a4c2019-03-19 14:13:36 -0400385 fBufferMapThreshold = SK_MaxS32;
386 }
387
388 if (kQualcomm_VkVendor == properties.vendorID) {
389 // On Qualcomm it looks like using vkCmdUpdateBuffer is slower than using a transfer buffer
390 // even for small sizes.
391 fAvoidUpdateBuffers = true;
392 }
393
Chris Dalton0dffbab2019-03-27 13:08:50 -0600394 if (kARM_VkVendor == properties.vendorID) {
395 // ARM seems to do better with more fine triangles as opposed to using the sample mask.
396 // (At least in our current round rect op.)
397 fPreferTrianglesOverSampleMask = true;
398 }
Greg Daniel78e6a4c2019-03-19 14:13:36 -0400399
Greg Danielcaa795f2019-05-14 11:54:25 -0400400 this->initFormatTable(vkInterface, physDev, properties);
egdaniel8f1dcaa2016-04-01 10:10:45 -0700401 this->initStencilFormat(vkInterface, physDev);
Greg Daniel164a9f02016-02-22 09:56:40 -0500402
Greg Daniel691f5e72018-02-28 14:21:34 -0500403 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
404 this->applyDriverCorrectnessWorkarounds(properties);
egdanielc5ec1402016-03-28 12:14:42 -0700405 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500406
Greg Daniel691f5e72018-02-28 14:21:34 -0500407 this->applyOptionsOverrides(contextOptions);
408 fShaderCaps->applyOptionsOverrides(contextOptions);
409}
410
411void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) {
egdaniel6fa0a912016-09-12 11:51:29 -0700412 if (kQualcomm_VkVendor == properties.vendorID) {
413 fMustDoCopiesFromOrigin = true;
Brian Salomona585fe92019-04-09 14:57:00 -0400414 // Transfer doesn't support this workaround.
415 fTransferBufferSupport = false;
egdaniel6fa0a912016-09-12 11:51:29 -0700416 }
417
Greg Daniel80a08dd2017-01-20 10:45:49 -0500418#if defined(SK_BUILD_FOR_WIN)
Greg Daniel900e5c82018-08-28 10:59:24 -0400419 if (kNvidia_VkVendor == properties.vendorID || kIntel_VkVendor == properties.vendorID) {
Greg Daniel80a08dd2017-01-20 10:45:49 -0500420 fMustSleepOnTearDown = true;
421 }
422#elif defined(SK_BUILD_FOR_ANDROID)
423 if (kImagination_VkVendor == properties.vendorID) {
424 fMustSleepOnTearDown = true;
425 }
426#endif
Greg Danielbce5eb92018-03-01 13:13:44 -0500427
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400428#if defined(SK_BUILD_FOR_ANDROID)
429 // Protected memory features have problems in Android P and earlier.
430 if (fSupportsProtectedMemory && (kQualcomm_VkVendor == properties.vendorID)) {
431 char androidAPIVersion[PROP_VALUE_MAX];
432 int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersion);
433 if (strLength == 0 || atoi(androidAPIVersion) <= 28) {
434 fSupportsProtectedMemory = false;
435 }
436 }
437#endif
438
Greg Danielbce5eb92018-03-01 13:13:44 -0500439 // AMD seems to have issues binding new VkPipelines inside a secondary command buffer.
440 // Current workaround is to use a different secondary command buffer for each new VkPipeline.
441 if (kAMD_VkVendor == properties.vendorID) {
442 fNewCBOnPipelineChange = true;
443 }
444
Greg Danielddc0c602018-06-18 11:26:30 -0400445 // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
446 if (kARM_VkVendor == properties.vendorID) {
447 fShouldAlwaysUseDedicatedImageMemory = true;
448 }
449
Greg Danielbce5eb92018-03-01 13:13:44 -0500450 ////////////////////////////////////////////////////////////////////////////
451 // GrCaps workarounds
452 ////////////////////////////////////////////////////////////////////////////
453
454 if (kARM_VkVendor == properties.vendorID) {
455 fInstanceAttribSupport = false;
Greg Daniel4374e962018-09-28 15:09:47 -0400456 fAvoidWritePixelsFastPath = true; // bugs.skia.org/8064
Greg Danielbce5eb92018-03-01 13:13:44 -0500457 }
458
459 // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32.
460 if (kAMD_VkVendor == properties.vendorID) {
461 fMaxVertexAttributes = SkTMin(fMaxVertexAttributes, 32);
462 }
463
Greg Danielbce5eb92018-03-01 13:13:44 -0500464 ////////////////////////////////////////////////////////////////////////////
465 // GrShaderCaps workarounds
466 ////////////////////////////////////////////////////////////////////////////
467
Greg Danielbce5eb92018-03-01 13:13:44 -0500468 if (kImagination_VkVendor == properties.vendorID) {
469 fShaderCaps->fAtan2ImplementedAsAtanYOverX = true;
470 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500471}
472
473int get_max_sample_count(VkSampleCountFlags flags) {
474 SkASSERT(flags & VK_SAMPLE_COUNT_1_BIT);
475 if (!(flags & VK_SAMPLE_COUNT_2_BIT)) {
476 return 0;
477 }
478 if (!(flags & VK_SAMPLE_COUNT_4_BIT)) {
479 return 2;
480 }
481 if (!(flags & VK_SAMPLE_COUNT_8_BIT)) {
482 return 4;
483 }
484 if (!(flags & VK_SAMPLE_COUNT_16_BIT)) {
485 return 8;
486 }
487 if (!(flags & VK_SAMPLE_COUNT_32_BIT)) {
488 return 16;
489 }
490 if (!(flags & VK_SAMPLE_COUNT_64_BIT)) {
491 return 32;
492 }
493 return 64;
494}
495
Greg Daniel313c6952018-08-08 09:24:08 -0400496void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
497 VkPhysicalDevice physDev,
498 const VkPhysicalDeviceProperties& properties,
jvanverthfd7bd452016-03-25 06:29:52 -0700499 const VkPhysicalDeviceMemoryProperties& memoryProperties,
Greg Daniel313c6952018-08-08 09:24:08 -0400500 const VkPhysicalDeviceFeatures2& features,
501 const GrVkExtensions& extensions) {
Greg Danielc5cc2de2017-03-20 11:40:58 -0400502 // So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no
503 // need for us ever to support that amount, and it makes tests which tests all the vertex
504 // attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if
505 // we ever find that need.
506 static const uint32_t kMaxVertexAttributes = 64;
507 fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
Greg Danielc5cc2de2017-03-20 11:40:58 -0400508
egdanield5e3b9e2016-03-08 12:19:54 -0800509 // We could actually query and get a max size for each config, however maxImageDimension2D will
510 // give the minimum max size across all configs. So for simplicity we will use that for now.
jvanverthe78d4872016-09-27 03:33:05 -0700511 fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
512 fMaxTextureSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
Adrienne Walker724afe82018-05-15 11:36:26 -0700513 if (fDriverBugWorkarounds.max_texture_size_limit_4096) {
514 fMaxTextureSize = SkTMin(fMaxTextureSize, 4096);
515 }
516 // Our render targets are always created with textures as the color
517 // attachment, hence this min:
518 fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
egdanield5e3b9e2016-03-08 12:19:54 -0800519
Chris Dalton2612bae2018-02-22 13:41:37 -0700520 // TODO: check if RT's larger than 4k incur a performance cost on ARM.
521 fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
522
egdanield5e3b9e2016-03-08 12:19:54 -0800523 // Assuming since we will always map in the end to upload the data we might as well just map
524 // from the get go. There is no hard data to suggest this is faster or slower.
cdalton397536c2016-03-25 12:15:03 -0700525 fBufferMapThreshold = 0;
egdanield5e3b9e2016-03-08 12:19:54 -0800526
Brian Salomon105d7c22019-04-16 13:46:14 -0400527 fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;
egdanield5e3b9e2016-03-08 12:19:54 -0800528
egdanield5e3b9e2016-03-08 12:19:54 -0800529 fOversizedStencilSupport = true;
Greg Daniel313c6952018-08-08 09:24:08 -0400530
531 if (extensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2) &&
532 this->supportsPhysicalDeviceProperties2()) {
533
534 VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProps;
535 blendProps.sType =
536 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
537 blendProps.pNext = nullptr;
538
539 VkPhysicalDeviceProperties2 props;
540 props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
541 props.pNext = &blendProps;
542
543 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props));
544
545 if (blendProps.advancedBlendAllOperations == VK_TRUE) {
546 fShaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kAutomatic_AdvBlendEqInteraction;
547
548 auto blendFeatures =
549 get_extension_feature_struct<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(
550 features,
551 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT);
552 if (blendFeatures && blendFeatures->advancedBlendCoherentOperations == VK_TRUE) {
553 fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
554 } else {
555 // TODO: Currently non coherent blends are not supported in our vulkan backend. They
556 // require us to support self dependencies in our render passes.
557 // fBlendEquationSupport = kAdvanced_BlendEquationSupport;
558 }
559 }
560 }
egdanield5e3b9e2016-03-08 12:19:54 -0800561}
562
Greg Daniel36443602018-08-02 12:51:52 -0400563void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
Greg Daniela0651ac2018-08-08 09:23:18 -0400564 const VkPhysicalDeviceFeatures2& features) {
Brian Salomon1edc5b92016-11-29 13:43:46 -0500565 GrShaderCaps* shaderCaps = fShaderCaps.get();
566 shaderCaps->fVersionDeclString = "#version 330\n";
egdaniel3a15fd42016-04-05 11:00:29 -0700567
egdanield5e3b9e2016-03-08 12:19:54 -0800568 // Vulkan is based off ES 3.0 so the following should all be supported
Brian Salomon1edc5b92016-11-29 13:43:46 -0500569 shaderCaps->fUsesPrecisionModifiers = true;
570 shaderCaps->fFlatInterpolationSupport = true;
Brian Salomon41274562017-09-15 09:40:03 -0700571 // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed
572 // to be true with Vulkan as well.
573 shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID;
egdanield5e3b9e2016-03-08 12:19:54 -0800574
575 // GrShaderCaps
576
Brian Salomon1edc5b92016-11-29 13:43:46 -0500577 shaderCaps->fShaderDerivativeSupport = true;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600578
Ethan Nicholas6ac8d362019-01-22 21:43:55 +0000579 // FIXME: http://skbug.com/7733: Disable geometry shaders until Intel/Radeon GMs draw correctly.
580 // shaderCaps->fGeometryShaderSupport =
581 // shaderCaps->fGSInvocationsSupport = features.features.geometryShader;
egdanield632bb42016-03-30 12:06:48 -0700582
Greg Daniela0651ac2018-08-08 09:23:18 -0400583 shaderCaps->fDualSourceBlendingSupport = features.features.dualSrcBlend;
egdanield632bb42016-03-30 12:06:48 -0700584
Brian Salomon1edc5b92016-11-29 13:43:46 -0500585 shaderCaps->fIntegerSupport = true;
Chris Dalton1d616352017-05-31 12:51:23 -0600586 shaderCaps->fVertexIDSupport = true;
Chris Dalton7c7ff032018-03-28 20:09:58 -0600587 shaderCaps->fFPManipulationSupport = true;
cdalton9c3f1432016-03-11 10:07:37 -0800588
cdaltona6b92ad2016-04-11 12:03:08 -0700589 // Assume the minimum precisions mandated by the SPIR-V spec.
Chris Dalton47c8ed32017-11-15 18:27:09 -0700590 shaderCaps->fFloatIs32Bits = true;
591 shaderCaps->fHalfIs32Bits = false;
cdaltona6b92ad2016-04-11 12:03:08 -0700592
Brian Salomon1edc5b92016-11-29 13:43:46 -0500593 shaderCaps->fMaxFragmentSamplers = SkTMin(
594 SkTMin(properties.limits.maxPerStageDescriptorSampledImages,
595 properties.limits.maxPerStageDescriptorSamplers),
596 (uint32_t)INT_MAX);
Greg Daniel164a9f02016-02-22 09:56:40 -0500597}
598
egdaniel8f1dcaa2016-04-01 10:10:45 -0700599bool stencil_format_supported(const GrVkInterface* interface,
600 VkPhysicalDevice physDev,
601 VkFormat format) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500602 VkFormatProperties props;
603 memset(&props, 0, sizeof(VkFormatProperties));
604 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
egdaniel8f1dcaa2016-04-01 10:10:45 -0700605 return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures);
Greg Daniel164a9f02016-02-22 09:56:40 -0500606}
607
egdaniel8f1dcaa2016-04-01 10:10:45 -0700608void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevice physDev) {
609 // List of legal stencil formats (though perhaps not supported on
610 // the particular gpu/driver) from most preferred to least. We are guaranteed to have either
jvanvertha4b0fed2016-04-27 11:42:21 -0700611 // 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 -0700612 // can optionally have 24 unused bits at the end so we assume the total bits is 64.
Greg Daniel164a9f02016-02-22 09:56:40 -0500613 static const StencilFormat
614 // internal Format stencil bits total bits packed?
615 gS8 = { VK_FORMAT_S8_UINT, 8, 8, false },
egdaniel8f1dcaa2016-04-01 10:10:45 -0700616 gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT, 8, 32, true },
617 gD32S8 = { VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 64, true };
Greg Daniel164a9f02016-02-22 09:56:40 -0500618
egdaniel8f1dcaa2016-04-01 10:10:45 -0700619 if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) {
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400620 fPreferredStencilFormat = gS8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700621 } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) {
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400622 fPreferredStencilFormat = gD24S8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700623 } else {
624 SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT));
Ethan Nicholasf610bae2018-09-20 16:55:21 -0400625 fPreferredStencilFormat = gD32S8;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700626 }
627}
628
Greg Danielcaa795f2019-05-14 11:54:25 -0400629static bool format_is_srgb(VkFormat format) {
Robert Phillipsf209e882019-06-25 15:59:50 -0400630 SkASSERT(GrVkFormatIsSupported(format));
631
Greg Danielcaa795f2019-05-14 11:54:25 -0400632 switch (format) {
633 case VK_FORMAT_R8G8B8A8_SRGB:
Greg Danielcaa795f2019-05-14 11:54:25 -0400634 return true;
Greg Danielcaa795f2019-05-14 11:54:25 -0400635 default:
Greg Danielcaa795f2019-05-14 11:54:25 -0400636 return false;
637 }
638}
639
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400640// These are all the valid VkFormats that we support in Skia. They are roughly ordered from most
Greg Danielcaa795f2019-05-14 11:54:25 -0400641// frequently used to least to improve look up times in arrays.
642static constexpr VkFormat kVkFormats[] = {
643 VK_FORMAT_R8G8B8A8_UNORM,
644 VK_FORMAT_R8_UNORM,
645 VK_FORMAT_B8G8R8A8_UNORM,
646 VK_FORMAT_R5G6B5_UNORM_PACK16,
647 VK_FORMAT_R16G16B16A16_SFLOAT,
648 VK_FORMAT_R16_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400649 VK_FORMAT_R8G8B8_UNORM,
650 VK_FORMAT_R8G8_UNORM,
651 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
652 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
Greg Danieleb4a8272019-05-16 16:52:55 -0400653 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
Greg Danielcaa795f2019-05-14 11:54:25 -0400654 VK_FORMAT_R32G32B32A32_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400655 VK_FORMAT_R8G8B8A8_SRGB,
Robert Phillipsfe18de52019-06-06 17:21:50 -0400656 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
Robert Phillipsfe18de52019-06-06 17:21:50 -0400657 VK_FORMAT_R16_UNORM,
658 VK_FORMAT_R16G16_UNORM,
Robert Phillips66a46032019-06-18 08:00:42 -0400659 // Experimental (for Y416 and mutant P016/P010)
660 VK_FORMAT_R16G16B16A16_UNORM,
661 VK_FORMAT_R16G16_SFLOAT,
Greg Danielcaa795f2019-05-14 11:54:25 -0400662};
663
664const GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) const {
Greg Daniel1ff50212019-08-02 15:54:08 -0400665 GrVkCaps* nonConstThis = const_cast<GrVkCaps*>(this);
666 return nonConstThis->getFormatInfo(format);
667}
668
669GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400670 static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
671 "Size of VkFormats array must match static value in header");
672 for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
673 if (kVkFormats[i] == format) {
674 return fFormatTable[i];
675 }
676 }
Greg Daniel1ff50212019-08-02 15:54:08 -0400677 static FormatInfo kInvalidFormat;
Greg Daniel52ee5f62019-06-20 13:38:18 -0400678 return kInvalidFormat;
Greg Danielcaa795f2019-05-14 11:54:25 -0400679}
680
681void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +0000682 const VkPhysicalDeviceProperties& properties) {
Greg Danielcaa795f2019-05-14 11:54:25 -0400683 static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
684 "Size of VkFormats array must match static value in header");
685 for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
686 VkFormat format = kVkFormats[i];
687 if (!format_is_srgb(format) || fSRGBSupport) {
688 fFormatTable[i].init(interface, physDev, properties, format);
egdaniel8f1dcaa2016-04-01 10:10:45 -0700689 }
690 }
Greg Daniel1ff50212019-08-02 15:54:08 -0400691
692 // Go through all the formats and init their support surface and data GrColorTypes.
693
694 // Format: VK_FORMAT_R8G8B8A8_UNORM
695 {
696 auto& info = this->getFormatInfo(VK_FORMAT_R8G8B8A8_UNORM);
697 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
698 info.fColorTypeInfoCount = 2;
699 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
700 int ctIdx = 0;
701 // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
702 {
703 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
704 ctInfo.fColorType = GrColorType::kRGBA_8888;
705 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
706 }
707 // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
708 {
709 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
710 ctInfo.fColorType = GrColorType::kRGB_888x;
711 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
712 ctInfo.fTextureSwizzle = GrSwizzle::RGB1();
713 }
714 }
715 }
716
717 // Format: VK_FORMAT_R8_UNORM
718 {
719 auto& info = this->getFormatInfo(VK_FORMAT_R8_UNORM);
720 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
721 info.fColorTypeInfoCount = 2;
722 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
723 int ctIdx = 0;
724 // Format: VK_FORMAT_R8_UNORM, Surface: kAlpha_8
725 {
726 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
727 ctInfo.fColorType = GrColorType::kAlpha_8;
728 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
729 ctInfo.fTextureSwizzle = GrSwizzle::RRRR();
730 ctInfo.fOutputSwizzle = GrSwizzle::AAAA();
731 }
732 // Format: VK_FORMAT_R8_UNORM, Surface: kGray_8
733 {
734 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
735 ctInfo.fColorType = GrColorType::kGray_8;
736 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
737 ctInfo.fTextureSwizzle = GrSwizzle("rrr1");
738 }
739 }
740 }
741 // Format: VK_FORMAT_B8G8R8A8_UNORM
742 {
743 auto& info = this->getFormatInfo(VK_FORMAT_B8G8R8A8_UNORM);
744 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
745 info.fColorTypeInfoCount = 1;
746 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
747 int ctIdx = 0;
748 // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
749 {
750 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
751 ctInfo.fColorType = GrColorType::kBGRA_8888;
752 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
753 }
754 }
755 }
756 // Format: VK_FORMAT_R5G6B5_UNORM_PACK16
757 {
758 auto& info = this->getFormatInfo(VK_FORMAT_R5G6B5_UNORM_PACK16);
759 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
760 info.fColorTypeInfoCount = 1;
761 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
762 int ctIdx = 0;
763 // Format: VK_FORMAT_R5G6B5_UNORM_PACK16, Surface: kBGR_565
764 {
765 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
766 ctInfo.fColorType = GrColorType::kBGR_565;
767 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
768 }
769 }
770 }
771 // Format: VK_FORMAT_R16G16B16A16_SFLOAT
772 {
773 auto& info = this->getFormatInfo(VK_FORMAT_R16G16B16A16_SFLOAT);
774 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
775 info.fColorTypeInfoCount = 2;
776 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
777 int ctIdx = 0;
778 // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16
779 {
780 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
781 ctInfo.fColorType = GrColorType::kRGBA_F16;
782 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
783 }
784 // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16_Clamped
785 {
786 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
787 ctInfo.fColorType = GrColorType::kRGBA_F16_Clamped;
788 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
789 }
790 }
791 }
792 // Format: VK_FORMAT_R16_SFLOAT
793 {
794 auto& info = this->getFormatInfo(VK_FORMAT_R16_SFLOAT);
795 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
796 info.fColorTypeInfoCount = 1;
797 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
798 int ctIdx = 0;
799 // Format: VK_FORMAT_R16_SFLOAT, Surface: kAlpha_F16
800 {
801 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
802 ctInfo.fColorType = GrColorType::kAlpha_F16;
803 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
804 ctInfo.fTextureSwizzle = GrSwizzle::RRRR();
805 ctInfo.fOutputSwizzle = GrSwizzle::AAAA();
806 }
807 }
808 }
809 // Format: VK_FORMAT_R8G8B8_UNORM
810 {
811 auto& info = this->getFormatInfo(VK_FORMAT_R8G8B8_UNORM);
812 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
813 info.fColorTypeInfoCount = 1;
814 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
815 int ctIdx = 0;
816 // Format: VK_FORMAT_R8G8B8_UNORM, Surface: kRGB_888x
817 {
818 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
819 ctInfo.fColorType = GrColorType::kRGB_888x;
820 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
821 }
822 }
823 }
824 // Format: VK_FORMAT_R8G8_UNORM
825 {
826 auto& info = this->getFormatInfo(VK_FORMAT_R8G8_UNORM);
827 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
828 info.fColorTypeInfoCount = 1;
829 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
830 int ctIdx = 0;
831 // Format: VK_FORMAT_R8G8_UNORM, Surface: kRG_88
832 {
833 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
834 ctInfo.fColorType = GrColorType::kRG_88;
835 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
836 }
837 }
838 }
839 // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32
840 {
841 auto& info = this->getFormatInfo(VK_FORMAT_A2B10G10R10_UNORM_PACK32);
842 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
843 info.fColorTypeInfoCount = 1;
844 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
845 int ctIdx = 0;
846 // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGBA_1010102
847 {
848 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
849 ctInfo.fColorType = GrColorType::kRGBA_1010102;
850 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
851 }
852 }
853 }
854 // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16
855 {
856 auto& info = this->getFormatInfo(VK_FORMAT_B4G4R4A4_UNORM_PACK16);
857 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
858 info.fColorTypeInfoCount = 1;
859 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
860 int ctIdx = 0;
861 // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16, Surface: kABGR_4444
862 {
863 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
864 ctInfo.fColorType = GrColorType::kABGR_4444;
865 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
866 ctInfo.fTextureSwizzle = GrSwizzle::BGRA();
867 ctInfo.fOutputSwizzle = GrSwizzle::BGRA();
868 }
869 }
870 }
871 // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16
872 {
873 auto& info = this->getFormatInfo(VK_FORMAT_R4G4B4A4_UNORM_PACK16);
874 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
875 info.fColorTypeInfoCount = 1;
876 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
877 int ctIdx = 0;
878 // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16, Surface: kABGR_4444
879 {
880 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
881 ctInfo.fColorType = GrColorType::kABGR_4444;
882 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
883 }
884 }
885 }
886 // Format: VK_FORMAT_R32G32B32A32_SFLOAT
887 {
888 auto& info = this->getFormatInfo(VK_FORMAT_R32G32B32A32_SFLOAT);
889 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
890 info.fColorTypeInfoCount = 1;
891 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
892 int ctIdx = 0;
893 // Format: VK_FORMAT_R32G32B32A32_SFLOAT, Surface: kRGBA_F32
894 {
895 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
896 ctInfo.fColorType = GrColorType::kRGBA_F32;
897 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
898 }
899 }
900 }
901 // Format: VK_FORMAT_R8G8B8A8_SRGB
902 {
903 auto& info = this->getFormatInfo(VK_FORMAT_R8G8B8A8_SRGB);
904 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
905 info.fColorTypeInfoCount = 1;
906 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
907 int ctIdx = 0;
908 // Format: VK_FORMAT_R8G8B8A8_SRGB, Surface: kRGBA_8888_SRGB
909 {
910 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
911 ctInfo.fColorType = GrColorType::kRGBA_8888_SRGB;
912 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
913 }
914 }
915 }
916 // Format: VK_FORMAT_R16_UNORM
917 {
918 auto& info = this->getFormatInfo(VK_FORMAT_R16_UNORM);
919 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
920 info.fColorTypeInfoCount = 1;
921 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
922 int ctIdx = 0;
923 // Format: VK_FORMAT_R16_UNORM, Surface: kR_16
924 {
925 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
926 ctInfo.fColorType = GrColorType::kR_16;
927 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
928 }
929 }
930 }
931 // Format: VK_FORMAT_R16G16_UNORM
932 {
933 auto& info = this->getFormatInfo(VK_FORMAT_R16G16_UNORM);
934 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
935 info.fColorTypeInfoCount = 1;
936 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
937 int ctIdx = 0;
938 // Format: VK_FORMAT_R16G16_UNORM, Surface: kRG_1616
939 {
940 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
941 ctInfo.fColorType = GrColorType::kRG_1616;
942 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
943 }
944 }
945 }
946 // Format: VK_FORMAT_R16G16B16A16_UNORM
947 {
948 auto& info = this->getFormatInfo(VK_FORMAT_R16G16B16A16_UNORM);
949 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
950 info.fColorTypeInfoCount = 1;
951 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
952 int ctIdx = 0;
953 // Format: VK_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
954 {
955 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
956 ctInfo.fColorType = GrColorType::kRGBA_16161616;
957 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
958 }
959 }
960 }
961 // Format: VK_FORMAT_R16G16_SFLOAT
962 {
963 auto& info = this->getFormatInfo(VK_FORMAT_R16G16_SFLOAT);
964 if (SkToBool(info.fOptimalFlags & FormatInfo::kTextureable_Flag)) {
965 info.fColorTypeInfoCount = 1;
966 info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
967 int ctIdx = 0;
968 // Format: VK_FORMAT_R16G16_SFLOAT, Surface: kRG_F16
969 {
970 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
971 ctInfo.fColorType = GrColorType::kRG_F16;
972 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
973 }
974 }
975 }
976 // Format: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
977 {
978 // No supported GrColorTypes.
979 }
egdaniel8f1dcaa2016-04-01 10:10:45 -0700980}
981
Greg Daniel1ff50212019-08-02 15:54:08 -0400982void GrVkCaps::FormatInfo::InitFormatFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
egdaniel8f1dcaa2016-04-01 10:10:45 -0700983 if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
984 SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
985 *flags = *flags | kTextureable_Flag;
egdaniel8f1dcaa2016-04-01 10:10:45 -0700986
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400987 // Ganesh assumes that all renderable surfaces are also texturable
Greg Danielcaa795f2019-05-14 11:54:25 -0400988 if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400989 *flags = *flags | kRenderable_Flag;
990 }
egdaniel8f1dcaa2016-04-01 10:10:45 -0700991 }
992
993 if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) {
994 *flags = *flags | kBlitSrc_Flag;
995 }
996
997 if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) {
998 *flags = *flags | kBlitDst_Flag;
999 }
1000}
1001
Greg Danielcaa795f2019-05-14 11:54:25 -04001002void GrVkCaps::FormatInfo::initSampleCounts(const GrVkInterface* interface,
Greg Daniel81e7bf82017-07-19 14:47:42 -04001003 VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +00001004 const VkPhysicalDeviceProperties& physProps,
Greg Daniel81e7bf82017-07-19 14:47:42 -04001005 VkFormat format) {
1006 VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1007 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1008 VK_IMAGE_USAGE_SAMPLED_BIT |
1009 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Greg Daniel81e7bf82017-07-19 14:47:42 -04001010 VkImageFormatProperties properties;
1011 GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev,
1012 format,
1013 VK_IMAGE_TYPE_2D,
1014 VK_IMAGE_TILING_OPTIMAL,
1015 usage,
Brian Osman2b23c4b2018-06-01 12:25:08 -04001016 0, // createFlags
Greg Daniel81e7bf82017-07-19 14:47:42 -04001017 &properties));
1018 VkSampleCountFlags flags = properties.sampleCounts;
1019 if (flags & VK_SAMPLE_COUNT_1_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001020 fColorSampleCounts.push_back(1);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001021 }
Greg Daniel2bb6ecc2017-07-20 13:11:14 +00001022 if (kImagination_VkVendor == physProps.vendorID) {
1023 // MSAA does not work on imagination
1024 return;
1025 }
Brian Osman7fbb3632019-07-19 11:38:57 -04001026 if (kIntel_VkVendor == physProps.vendorID) {
1027 // MSAA on Intel before Gen 9 is slow and/or buggy
1028 if (GrGetIntelGpuFamily(physProps.deviceID) < kFirstGen9_IntelGpuFamily) {
1029 return;
1030 }
1031 }
Greg Daniel81e7bf82017-07-19 14:47:42 -04001032 if (flags & VK_SAMPLE_COUNT_2_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001033 fColorSampleCounts.push_back(2);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001034 }
1035 if (flags & VK_SAMPLE_COUNT_4_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001036 fColorSampleCounts.push_back(4);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001037 }
1038 if (flags & VK_SAMPLE_COUNT_8_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001039 fColorSampleCounts.push_back(8);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001040 }
1041 if (flags & VK_SAMPLE_COUNT_16_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001042 fColorSampleCounts.push_back(16);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001043 }
1044 if (flags & VK_SAMPLE_COUNT_32_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001045 fColorSampleCounts.push_back(32);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001046 }
1047 if (flags & VK_SAMPLE_COUNT_64_BIT) {
Mike Reedb5475792018-08-08 16:17:42 -04001048 fColorSampleCounts.push_back(64);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001049 }
1050}
1051
Greg Danielcaa795f2019-05-14 11:54:25 -04001052void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,
egdaniel8f1dcaa2016-04-01 10:10:45 -07001053 VkPhysicalDevice physDev,
Greg Daniel2bb6ecc2017-07-20 13:11:14 +00001054 const VkPhysicalDeviceProperties& properties,
Greg Danielcaa795f2019-05-14 11:54:25 -04001055 VkFormat format) {
egdaniel8f1dcaa2016-04-01 10:10:45 -07001056 VkFormatProperties props;
1057 memset(&props, 0, sizeof(VkFormatProperties));
1058 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
Greg Daniel1ff50212019-08-02 15:54:08 -04001059 InitFormatFlags(props.linearTilingFeatures, &fLinearFlags);
1060 InitFormatFlags(props.optimalTilingFeatures, &fOptimalFlags);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001061 if (fOptimalFlags & kRenderable_Flag) {
Greg Daniel2bb6ecc2017-07-20 13:11:14 +00001062 this->initSampleCounts(interface, physDev, properties, format);
Greg Daniel81e7bf82017-07-19 14:47:42 -04001063 }
Greg Daniel164a9f02016-02-22 09:56:40 -05001064}
Greg Daniel81e7bf82017-07-19 14:47:42 -04001065
Robert Phillipsf209e882019-06-25 15:59:50 -04001066bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
1067 if (!format.getVkFormat()) {
1068 return false;
1069 }
1070
1071 return format_is_srgb(*format.getVkFormat());
1072}
1073
Robert Phillips8ff8bcc2019-07-29 17:03:35 -04001074bool GrVkCaps::isFormatCompressed(const GrBackendFormat& format) const {
1075 if (!format.getVkFormat()) {
1076 return false;
1077 }
1078
1079 VkFormat vkFormat = *format.getVkFormat();
1080 SkASSERT(GrVkFormatIsSupported(vkFormat));
1081
1082 return vkFormat == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
1083}
1084
Greg Daniel1ff50212019-08-02 15:54:08 -04001085bool GrVkCaps::isFormatTexturable(GrColorType ct, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001086 if (!format.getVkFormat()) {
1087 return false;
1088 }
1089
Greg Daniel1ff50212019-08-02 15:54:08 -04001090 VkFormat vkFormat = *format.getVkFormat();
1091 uint32_t ctFlags = this->getFormatInfo(vkFormat).colorTypeFlags(ct);
1092 return this->isVkFormatTexturable(vkFormat) &&
1093 SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag);
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001094}
1095
Greg Daniel2f2caea2019-07-08 14:24:47 -04001096bool GrVkCaps::isVkFormatTexturable(VkFormat format) const {
Greg Danielcaa795f2019-05-14 11:54:25 -04001097 const FormatInfo& info = this->getFormatInfo(format);
1098 return SkToBool(FormatInfo::kTextureable_Flag & info.fOptimalFlags);
1099}
1100
1101bool GrVkCaps::isConfigTexturable(GrPixelConfig config) const {
1102 VkFormat format;
1103 if (!GrPixelConfigToVkFormat(config, &format)) {
1104 return false;
1105 }
Greg Daniel1ff50212019-08-02 15:54:08 -04001106 GrColorType ct = GrPixelConfigToColorType(config);
1107 uint32_t ctFlags = this->getFormatInfo(format).colorTypeFlags(ct);
1108 return this->isVkFormatTexturable(format) &&
1109 SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag);
Robert Phillips39ef2ef2019-05-15 08:45:53 -04001110}
1111
Greg Danieleadfac92019-08-02 09:03:53 -04001112bool GrVkCaps::isFormatRenderable(GrColorType ct, const GrBackendFormat& format,
1113 int sampleCount) const {
1114 if (!format.getVkFormat()) {
1115 return false;
1116 }
Greg Danieleadfac92019-08-02 09:03:53 -04001117 VkFormat vkFormat = *format.getVkFormat();
Greg Daniel1ff50212019-08-02 15:54:08 -04001118 const auto& info = this->getFormatInfo(vkFormat);
1119 if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
Greg Danieleadfac92019-08-02 09:03:53 -04001120 return false;
1121 }
1122
1123 return sampleCount <= this->maxRenderTargetSampleCount(vkFormat);
1124}
1125
Robert Phillips39ef2ef2019-05-15 08:45:53 -04001126bool GrVkCaps::isFormatRenderable(VkFormat format) const {
1127 return this->maxRenderTargetSampleCount(format) > 0;
Greg Danielcaa795f2019-05-14 11:54:25 -04001128}
1129
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001130int GrVkCaps::getRenderTargetSampleCount(int requestedCount,
Greg Daniel5c96db82019-07-09 14:06:58 -04001131 GrColorType, const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001132 if (!format.getVkFormat()) {
1133 return 0;
1134 }
1135
1136 return this->getRenderTargetSampleCount(requestedCount, *format.getVkFormat());
1137}
1138
Brian Salomonbdecacf2018-02-02 20:32:49 -05001139int GrVkCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
Greg Danielcaa795f2019-05-14 11:54:25 -04001140 // Currently we don't allow RGB_888X to be renderable because we don't have a way to handle
1141 // blends that reference dst alpha when the values in the dst alpha channel are uninitialized.
Greg Daniel1ff50212019-08-02 15:54:08 -04001142 // We also do not support rendering to Gray_8.
1143 if (config == kRGB_888X_GrPixelConfig ||
1144 config == kGray_8_GrPixelConfig ||
1145 config == kGray_8_as_Red_GrPixelConfig) {
Greg Danielcaa795f2019-05-14 11:54:25 -04001146 return 0;
1147 }
1148
1149 VkFormat format;
1150 if (!GrPixelConfigToVkFormat(config, &format)) {
1151 return 0;
1152 }
1153
1154 return this->getRenderTargetSampleCount(requestedCount, format);
1155}
1156
1157int GrVkCaps::getRenderTargetSampleCount(int requestedCount, VkFormat format) const {
Brian Salomonbdecacf2018-02-02 20:32:49 -05001158 requestedCount = SkTMax(1, requestedCount);
Greg Danielcaa795f2019-05-14 11:54:25 -04001159
1160 const FormatInfo& info = this->getFormatInfo(format);
1161
1162 int count = info.fColorSampleCounts.count();
Brian Salomonbdecacf2018-02-02 20:32:49 -05001163
1164 if (!count) {
Greg Daniel81e7bf82017-07-19 14:47:42 -04001165 return 0;
1166 }
1167
Brian Salomonbdecacf2018-02-02 20:32:49 -05001168 if (1 == requestedCount) {
Greg Danielcaa795f2019-05-14 11:54:25 -04001169 SkASSERT(info.fColorSampleCounts.count() && info.fColorSampleCounts[0] == 1);
Brian Salomonbdecacf2018-02-02 20:32:49 -05001170 return 1;
1171 }
1172
Greg Daniel81e7bf82017-07-19 14:47:42 -04001173 for (int i = 0; i < count; ++i) {
Greg Danielcaa795f2019-05-14 11:54:25 -04001174 if (info.fColorSampleCounts[i] >= requestedCount) {
1175 return info.fColorSampleCounts[i];
Greg Daniel81e7bf82017-07-19 14:47:42 -04001176 }
1177 }
Brian Salomonbdecacf2018-02-02 20:32:49 -05001178 return 0;
1179}
1180
Greg Danieleadfac92019-08-02 09:03:53 -04001181int GrVkCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001182 if (!format.getVkFormat()) {
1183 return 0;
1184 }
1185
Greg Danieleadfac92019-08-02 09:03:53 -04001186 return this->maxRenderTargetSampleCount(*format.getVkFormat());
Greg Danielcaa795f2019-05-14 11:54:25 -04001187}
1188
1189int GrVkCaps::maxRenderTargetSampleCount(VkFormat format) const {
1190 const FormatInfo& info = this->getFormatInfo(format);
1191
1192 const auto& table = info.fColorSampleCounts;
Brian Salomonbdecacf2018-02-02 20:32:49 -05001193 if (!table.count()) {
1194 return 0;
1195 }
1196 return table[table.count() - 1];
Brian Salomond653cac2018-02-01 13:58:00 -05001197}
1198
Brian Salomon42be09d2019-07-26 12:12:26 -04001199static inline size_t align_to_4(size_t v) {
1200 switch (v & 0b11) {
1201 // v is already a multiple of 4.
1202 case 0: return v;
1203 // v is a multiple of 2 but not 4.
1204 case 2: return 2 * v;
1205 // v is not a multiple of 2.
1206 default: return 4 * v;
1207 }
1208}
1209
Brian Salomon01915c02019-08-02 09:57:21 -04001210GrCaps::SupportedWrite GrVkCaps::supportedWritePixelsColorType(GrColorType surfaceColorType,
1211 const GrBackendFormat& surfaceFormat,
Brian Salomon42be09d2019-07-26 12:12:26 -04001212 GrColorType srcColorType) const {
Greg Daniel1ff50212019-08-02 15:54:08 -04001213 const VkFormat* vkFormat = surfaceFormat.getVkFormat();
1214 if (!vkFormat) {
1215 return {GrColorType::kUnknown, 0};
1216 }
1217
1218 // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1219 size_t offsetAlignment = align_to_4(GrVkBytesPerFormat(*vkFormat));
1220
1221 const auto& info = this->getFormatInfo(*vkFormat);
1222 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1223 const auto& ctInfo = info.fColorTypeInfos[i];
1224 if (ctInfo.fColorType == surfaceColorType) {
1225 return {surfaceColorType, offsetAlignment};
1226 }
1227 }
1228 return {GrColorType::kUnknown, 0};
Brian Salomon42be09d2019-07-26 12:12:26 -04001229}
1230
Brian Salomondc0710f2019-07-01 14:59:32 -04001231GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
1232 const GrSurface* surface) const {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -04001233 if (surface->isProtected()) {
Brian Salomondc0710f2019-07-01 14:59:32 -04001234 return SurfaceReadPixelsSupport::kUnsupported;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -04001235 }
Greg Daniela51e93c2019-03-25 12:30:45 -04001236 if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
1237 // We can't directly read from a VkImage that has a ycbcr sampler.
1238 if (tex->ycbcrConversionInfo().isValid()) {
Brian Salomondc0710f2019-07-01 14:59:32 -04001239 return SurfaceReadPixelsSupport::kCopyToTexture2D;
Greg Daniela51e93c2019-03-25 12:30:45 -04001240 }
Greg Daniel00fb7242019-07-18 14:28:01 -04001241 // We can't directly read from a compressed format
1242 SkImage::CompressionType compressionType;
1243 if (GrVkFormatToCompressionType(tex->imageFormat(), &compressionType)) {
1244 return SurfaceReadPixelsSupport::kCopyToTexture2D;
1245 }
Greg Daniela51e93c2019-03-25 12:30:45 -04001246 }
Brian Salomondc0710f2019-07-01 14:59:32 -04001247 return SurfaceReadPixelsSupport::kSupported;
Greg Daniela51e93c2019-03-25 12:30:45 -04001248}
1249
Brian Salomonc67c31c2018-12-06 10:00:03 -05001250bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
Brian Salomon3d86a192018-02-27 16:46:11 -05001251 if (auto rt = surface->asRenderTarget()) {
Chris Dalton6ce447a2019-06-23 18:07:38 -06001252 return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
Brian Salomon3d86a192018-02-27 16:46:11 -05001253 }
Greg Daniela51e93c2019-03-25 12:30:45 -04001254 // We can't write to a texture that has a ycbcr sampler.
1255 if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
1256 // We can't directly read from a VkImage that has a ycbcr sampler.
1257 if (tex->ycbcrConversionInfo().isValid()) {
1258 return false;
1259 }
1260 }
Brian Salomon3d86a192018-02-27 16:46:11 -05001261 return true;
1262}
1263
Robert Phillips1e2cb442019-07-02 15:51:28 -04001264static GrPixelConfig validate_image_info(VkFormat format, GrColorType ct, bool hasYcbcrConversion) {
Greg Daniel14c55c22018-12-04 11:25:03 -05001265 if (format == VK_FORMAT_UNDEFINED) {
1266 // If the format is undefined then it is only valid as an external image which requires that
1267 // we have a valid VkYcbcrConversion.
1268 if (hasYcbcrConversion) {
1269 // 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 -04001270 // values for external textures. However, for read pixels we will draw to a non ycbcr
1271 // texture of this config so we set RGBA here for that.
Brian Salomonf391d0f2018-12-14 09:18:50 -05001272 return kRGBA_8888_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -05001273 } else {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001274 return kUnknown_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -05001275 }
1276 }
1277
1278 if (hasYcbcrConversion) {
1279 // We only support having a ycbcr conversion for external images.
Brian Salomonf391d0f2018-12-14 09:18:50 -05001280 return kUnknown_GrPixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -05001281 }
1282
Greg Danielf5d87582017-12-18 14:48:15 -05001283 switch (ct) {
Robert Phillips1e2cb442019-07-02 15:51:28 -04001284 case GrColorType::kUnknown:
Brian Salomonf391d0f2018-12-14 09:18:50 -05001285 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001286 case GrColorType::kAlpha_8:
Greg Danielf5d87582017-12-18 14:48:15 -05001287 if (VK_FORMAT_R8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001288 return kAlpha_8_as_Red_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001289 }
1290 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001291 case GrColorType::kBGR_565:
Greg Danielf5d87582017-12-18 14:48:15 -05001292 if (VK_FORMAT_R5G6B5_UNORM_PACK16 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001293 return kRGB_565_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001294 }
1295 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001296 case GrColorType::kABGR_4444:
Greg Danieleb4a8272019-05-16 16:52:55 -04001297 if (VK_FORMAT_B4G4R4A4_UNORM_PACK16 == format ||
1298 VK_FORMAT_R4G4B4A4_UNORM_PACK16 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001299 return kRGBA_4444_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001300 }
1301 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001302 case GrColorType::kRGBA_8888:
Greg Danielf5d87582017-12-18 14:48:15 -05001303 if (VK_FORMAT_R8G8B8A8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001304 return kRGBA_8888_GrPixelConfig;
Greg Daniele877dce2019-07-11 10:52:43 -04001305 }
1306 break;
1307 case GrColorType::kRGBA_8888_SRGB:
1308 if (VK_FORMAT_R8G8B8A8_SRGB == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001309 return kSRGBA_8888_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001310 }
1311 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001312 case GrColorType::kRGB_888x:
Greg Daniel475eb702018-09-28 14:16:50 -04001313 if (VK_FORMAT_R8G8B8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001314 return kRGB_888_GrPixelConfig;
Robert Phillipsffe27292019-08-01 10:08:07 -04001315 } else if (VK_FORMAT_R8G8B8A8_UNORM == format) {
Greg Danielf259b8b2019-02-14 09:03:43 -05001316 return kRGB_888X_GrPixelConfig;
Robert Phillipsffe27292019-08-01 10:08:07 -04001317 } else if (VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK == format) {
1318 return kRGB_ETC1_GrPixelConfig;
Greg Danielf259b8b2019-02-14 09:03:43 -05001319 }
Greg Daniel475eb702018-09-28 14:16:50 -04001320 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001321 case GrColorType::kRG_88:
1322 if (VK_FORMAT_R8G8_UNORM == format) {
1323 return kRG_88_GrPixelConfig;
1324 }
1325 break;
1326 case GrColorType::kBGRA_8888:
Greg Danielf5d87582017-12-18 14:48:15 -05001327 if (VK_FORMAT_B8G8R8A8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001328 return kBGRA_8888_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001329 }
1330 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001331 case GrColorType::kRGBA_1010102:
Brian Osman10fc6fd2018-03-02 11:01:10 -05001332 if (VK_FORMAT_A2B10G10R10_UNORM_PACK32 == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001333 return kRGBA_1010102_GrPixelConfig;
Brian Osman10fc6fd2018-03-02 11:01:10 -05001334 }
1335 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001336 case GrColorType::kGray_8:
Greg Danielf5d87582017-12-18 14:48:15 -05001337 if (VK_FORMAT_R8_UNORM == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001338 return kGray_8_as_Red_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001339 }
1340 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001341 case GrColorType::kAlpha_F16:
1342 if (VK_FORMAT_R16_SFLOAT == format) {
Robert Phillips0902c982019-07-16 07:47:56 -04001343 return kAlpha_half_as_Red_GrPixelConfig;
Mike Kleinb70990e2019-02-28 10:03:27 -06001344 }
1345 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001346 case GrColorType::kRGBA_F16:
Greg Danielf5d87582017-12-18 14:48:15 -05001347 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001348 return kRGBA_half_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001349 }
1350 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001351 case GrColorType::kRGBA_F16_Clamped:
1352 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
1353 return kRGBA_half_Clamped_GrPixelConfig;
1354 }
1355 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001356 case GrColorType::kRGBA_F32:
Mike Klein37854712018-06-26 11:43:06 -04001357 if (VK_FORMAT_R32G32B32A32_SFLOAT == format) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001358 return kRGBA_float_GrPixelConfig;
Mike Klein37854712018-06-26 11:43:06 -04001359 }
1360 break;
Robert Phillips1e2cb442019-07-02 15:51:28 -04001361 case GrColorType::kR_16:
1362 if (VK_FORMAT_R16_UNORM == format) {
1363 return kR_16_GrPixelConfig;
1364 }
1365 break;
1366 case GrColorType::kRG_1616:
1367 if (VK_FORMAT_R16G16_UNORM == format) {
1368 return kRG_1616_GrPixelConfig;
1369 }
1370 break;
1371 case GrColorType::kRGBA_16161616:
1372 if (VK_FORMAT_R16G16B16A16_UNORM == format) {
1373 return kRGBA_16161616_GrPixelConfig;
1374 }
1375 break;
1376 case GrColorType::kRG_F16:
1377 if (VK_FORMAT_R16G16_SFLOAT == format) {
1378 return kRG_half_GrPixelConfig;
1379 }
1380 break;
Brian Salomon8f8354a2019-07-31 20:12:02 -04001381 // These have no equivalent:
1382 case GrColorType::kAlpha_8xxx:
1383 case GrColorType::kAlpha_F32xxx:
1384 case GrColorType::kGray_8xxx:
1385 break;
Greg Danielf5d87582017-12-18 14:48:15 -05001386 }
1387
Brian Salomonf391d0f2018-12-14 09:18:50 -05001388 return kUnknown_GrPixelConfig;
Greg Danielf5d87582017-12-18 14:48:15 -05001389}
1390
Greg Daniel627d0532019-07-08 16:48:14 -04001391bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
1392 const GrBackendFormat& format) const {
Robert Phillipsc046ff02019-07-01 10:34:03 -04001393 const VkFormat* vkFormat = format.getVkFormat();
1394 const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1395 if (!vkFormat || !ycbcrInfo) {
1396 return false;
1397 }
1398
1399 return kUnknown_GrPixelConfig != validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
1400}
1401
1402
Greg Daniel627d0532019-07-08 16:48:14 -04001403GrPixelConfig GrVkCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
1404 GrColorType ct) const {
Robert Phillipsfc711a22018-02-13 17:03:00 -05001405 const VkFormat* vkFormat = format.getVkFormat();
Greg Daniel14c55c22018-12-04 11:25:03 -05001406 const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1407 if (!vkFormat || !ycbcrInfo) {
Brian Salomonf391d0f2018-12-14 09:18:50 -05001408 return kUnknown_GrPixelConfig;
Robert Phillipsfc711a22018-02-13 17:03:00 -05001409 }
Brian Salomonf391d0f2018-12-14 09:18:50 -05001410 return validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
Greg Danielfaa095e2017-12-19 13:15:02 -05001411}
Greg Danielf5d87582017-12-18 14:48:15 -05001412
Robert Phillips00c9f0d2019-08-02 17:17:35 -04001413GrColorType GrVkCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
1414 bool isAlphaChannel) const {
Robert Phillipsc80b0e92019-07-23 10:27:09 -04001415 const VkFormat* vkFormat = format.getVkFormat();
1416 if (!vkFormat) {
1417 return GrColorType::kUnknown;
1418 }
1419
1420 switch (*vkFormat) {
Robert Phillips00c9f0d2019-08-02 17:17:35 -04001421 case VK_FORMAT_R8_UNORM: return isAlphaChannel ? GrColorType::kAlpha_8
1422 : GrColorType::kGray_8;
Robert Phillipsc80b0e92019-07-23 10:27:09 -04001423 case VK_FORMAT_R8G8B8A8_UNORM: return GrColorType::kRGBA_8888;
1424 case VK_FORMAT_R8G8B8_UNORM: return GrColorType::kRGB_888x;
1425 case VK_FORMAT_R8G8_UNORM: return GrColorType::kRG_88;
1426 case VK_FORMAT_B8G8R8A8_UNORM: return GrColorType::kBGRA_8888;
1427 case VK_FORMAT_A2B10G10R10_UNORM_PACK32: return GrColorType::kRGBA_1010102;
1428 case VK_FORMAT_R16_UNORM: return GrColorType::kR_16;
1429 case VK_FORMAT_R16G16_UNORM: return GrColorType::kRG_1616;
1430 // Experimental (for Y416 and mutant P016/P010)
1431 case VK_FORMAT_R16G16B16A16_UNORM: return GrColorType::kRGBA_16161616;
1432 case VK_FORMAT_R16G16_SFLOAT: return GrColorType::kRG_F16;
1433 default: return GrColorType::kUnknown;
1434 }
1435
1436 SkUNREACHABLE;
1437}
1438
Robert Phillips0a15cc62019-07-30 12:49:10 -04001439GrBackendFormat GrVkCaps::onGetDefaultBackendFormat(GrColorType ct,
1440 GrRenderable renderable) const {
Greg Daniele877dce2019-07-11 10:52:43 -04001441 GrPixelConfig config = GrColorTypeToPixelConfig(ct);
Greg Daniel4065d452018-11-16 15:43:41 -05001442 if (config == kUnknown_GrPixelConfig) {
1443 return GrBackendFormat();
1444 }
1445 VkFormat format;
1446 if (!GrPixelConfigToVkFormat(config, &format)) {
1447 return GrBackendFormat();
1448 }
1449 return GrBackendFormat::MakeVk(format);
1450}
Timothy Liang036fdfe2018-06-28 15:50:36 -04001451
Brian Salomonbb8dde82019-06-27 10:52:13 -04001452GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
1453 SkImage::CompressionType compressionType) const {
1454 switch (compressionType) {
1455 case SkImage::kETC1_CompressionType:
1456 return GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
1457 }
1458 SK_ABORT("Invalid compression type");
1459 return {};
1460}
1461
Brian Salomona3e29962019-07-16 11:52:08 -04001462bool GrVkCaps::canClearTextureOnCreation() const { return true; }
1463
Greg Daniel1ff50212019-08-02 15:54:08 -04001464GrSwizzle GrVkCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
Greg Danieleb4a8272019-05-16 16:52:55 -04001465 SkASSERT(format.getVkFormat());
1466 VkFormat vkFormat = *format.getVkFormat();
Greg Daniel1ff50212019-08-02 15:54:08 -04001467 const auto& info = this->getFormatInfo(vkFormat);
1468 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1469 const auto& ctInfo = info.fColorTypeInfos[i];
1470 if (ctInfo.fColorType == colorType) {
1471 return ctInfo.fTextureSwizzle;
1472 }
Greg Danieleb4a8272019-05-16 16:52:55 -04001473 }
1474 return GrSwizzle::RGBA();
1475}
1476
Greg Danieleb4a8272019-05-16 16:52:55 -04001477GrSwizzle GrVkCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
Greg Daniel1ff50212019-08-02 15:54:08 -04001478 SkASSERT(format.getVkFormat());
1479 VkFormat vkFormat = *format.getVkFormat();
1480 const auto& info = this->getFormatInfo(vkFormat);
1481 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1482 const auto& ctInfo = info.fColorTypeInfos[i];
1483 if (ctInfo.fColorType == colorType) {
1484 return ctInfo.fOutputSwizzle;
1485 }
1486 }
1487 return GrSwizzle::RGBA();
Greg Danieleb4a8272019-05-16 16:52:55 -04001488}
1489
Greg Danielba88ab62019-07-26 09:14:01 -04001490GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType(
Greg Daniel00fb7242019-07-18 14:28:01 -04001491 GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1492 GrColorType dstColorType) const {
1493 const VkFormat* vkFormat = srcBackendFormat.getVkFormat();
1494 if (!vkFormat) {
Brian Salomon8f8354a2019-07-31 20:12:02 -04001495 return {GrColorType::kUnknown, 0};
Greg Danielba88ab62019-07-26 09:14:01 -04001496 }
1497
1498 // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
Brian Salomon42be09d2019-07-26 12:12:26 -04001499 size_t offsetAlignment = align_to_4(GrVkBytesPerFormat(*vkFormat));
Greg Daniel00fb7242019-07-18 14:28:01 -04001500
Greg Daniel1ff50212019-08-02 15:54:08 -04001501 const auto& info = this->getFormatInfo(*vkFormat);
1502 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1503 const auto& ctInfo = info.fColorTypeInfos[i];
1504 if (ctInfo.fColorType == srcColorType) {
1505 return {srcColorType, offsetAlignment};
1506 }
Greg Daniel00fb7242019-07-18 14:28:01 -04001507 }
Greg Daniel1ff50212019-08-02 15:54:08 -04001508 return {GrColorType::kUnknown, 0};
Greg Daniel00fb7242019-07-18 14:28:01 -04001509}
Robert Phillipsffe27292019-08-01 10:08:07 -04001510
1511#if GR_TEST_UTILS
1512std::vector<GrCaps::TestFormatColorTypeCombination> GrVkCaps::getTestingCombinations() const {
1513 std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
1514 { GrColorType::kAlpha_8, GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM) },
1515 { GrColorType::kBGR_565, GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16) },
1516 { GrColorType::kABGR_4444, GrBackendFormat::MakeVk(VK_FORMAT_R4G4B4A4_UNORM_PACK16)},
1517 { GrColorType::kABGR_4444, GrBackendFormat::MakeVk(VK_FORMAT_B4G4R4A4_UNORM_PACK16)},
1518 { GrColorType::kRGBA_8888, GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM) },
1519 { GrColorType::kRGBA_8888_SRGB, GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_SRGB) },
1520 { GrColorType::kRGB_888x, GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM) },
1521 { GrColorType::kRGB_888x, GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM) },
1522 { GrColorType::kRGB_888x, GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK)},
1523 { GrColorType::kRG_88, GrBackendFormat::MakeVk(VK_FORMAT_R8G8_UNORM) },
1524 { GrColorType::kBGRA_8888, GrBackendFormat::MakeVk(VK_FORMAT_B8G8R8A8_UNORM) },
1525 { GrColorType::kRGBA_1010102, GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32)},
1526 { GrColorType::kGray_8, GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM) },
1527 { GrColorType::kAlpha_F16, GrBackendFormat::MakeVk(VK_FORMAT_R16_SFLOAT) },
1528 { GrColorType::kRGBA_F16, GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT) },
1529 { GrColorType::kRGBA_F16_Clamped, GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT) },
1530 { GrColorType::kRGBA_F32, GrBackendFormat::MakeVk(VK_FORMAT_R32G32B32A32_SFLOAT) },
1531 { GrColorType::kR_16, GrBackendFormat::MakeVk(VK_FORMAT_R16_UNORM) },
1532 { GrColorType::kRG_1616, GrBackendFormat::MakeVk(VK_FORMAT_R16G16_UNORM) },
1533 { GrColorType::kRGBA_16161616, GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_UNORM) },
1534 { GrColorType::kRG_F16, GrBackendFormat::MakeVk(VK_FORMAT_R16G16_SFLOAT) },
1535 };
1536
1537#ifdef SK_DEBUG
1538 for (auto combo : combos) {
1539 SkASSERT(this->onAreColorTypeAndFormatCompatible(combo.fColorType, combo.fFormat));
1540 }
1541#endif
1542
1543 return combos;
1544}
1545#endif