1 /* 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 8 #include "GrVkCaps.h" 9 #include "GrBackendSurface.h" 10 #include "GrRenderTargetProxy.h" 11 #include "GrRenderTarget.h" 12 #include "GrShaderCaps.h" 13 #include "GrVkUtil.h" 14 #include "vk/GrVkBackendContext.h" 15 #include "vk/GrVkInterface.h" 16 17 GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface, 18 VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags) 19 : INHERITED(contextOptions) { 20 fCanUseGLSLForShaderModule = false; 21 fMustDoCopiesFromOrigin = false; 22 fSupportsCopiesAsDraws = true; 23 fMustSubmitCommandsBeforeCopyOp = false; 24 fMustSleepOnTearDown = false; 25 fNewCBOnPipelineChange = false; 26 fCanUseWholeSizeOnFlushMappedMemory = true; 27 28 /************************************************************************** 29 * GrDrawTargetCaps fields 30 **************************************************************************/ 31 fMipMapSupport = true; // always available in Vulkan 32 fSRGBSupport = true; // always available in Vulkan 33 fSRGBDecodeDisableSupport = true; // always available in Vulkan 34 fNPOTTextureTileSupport = true; // always available in Vulkan 35 fDiscardRenderTargetSupport = true; 36 fReuseScratchTextures = true; //TODO: figure this out 37 fGpuTracingSupport = false; //TODO: figure this out 38 fOversizedStencilSupport = false; //TODO: figure this out 39 fInstanceAttribSupport = true; 40 41 fBlacklistCoverageCounting = true; // blacklisting ccpr until we work through a few issues. 42 fFenceSyncSupport = true; // always available in Vulkan 43 fCrossContextTextureSupport = true; 44 45 fMapBufferFlags = kNone_MapFlags; //TODO: figure this out 46 fBufferMapThreshold = SK_MaxS32; //TODO: figure this out 47 48 fMaxRenderTargetSize = 4096; // minimum required by spec 49 fMaxTextureSize = 4096; // minimum required by spec 50 51 fShaderCaps.reset(new GrShaderCaps(contextOptions)); 52 53 this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags); 54 } 55 56 bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, 57 bool* rectsMustMatch, bool* disallowSubrect) const { 58 // Vk doesn't use rectsMustMatch or disallowSubrect. Always return false. 59 *rectsMustMatch = false; 60 *disallowSubrect = false; 61 62 // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa). 63 // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a 64 // render target as well. 65 desc->fOrigin = src->origin(); 66 desc->fConfig = src->config(); 67 if (src->numColorSamples() > 1 || (src->asTextureProxy() && this->supportsCopiesAsDraws())) { 68 desc->fFlags = kRenderTarget_GrSurfaceFlag; 69 } else { 70 // Just going to use CopyImage here 71 desc->fFlags = kNone_GrSurfaceFlags; 72 } 73 74 return true; 75 } 76 77 void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface, 78 VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags) { 79 80 VkPhysicalDeviceProperties properties; 81 GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties)); 82 83 VkPhysicalDeviceMemoryProperties memoryProperties; 84 GR_VK_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &memoryProperties)); 85 86 this->initGrCaps(properties, memoryProperties, featureFlags); 87 this->initShaderCaps(properties, featureFlags); 88 89 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) { 90 #if defined(SK_CPU_X86) 91 // We need to do this before initing the config table since it uses fSRGBSupport 92 if (kImagination_VkVendor == properties.vendorID) { 93 fSRGBSupport = false; 94 } 95 #endif 96 } 97 98 this->initConfigTable(vkInterface, physDev, properties); 99 this->initStencilFormat(vkInterface, physDev); 100 101 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) { 102 this->applyDriverCorrectnessWorkarounds(properties); 103 } 104 105 this->applyOptionsOverrides(contextOptions); 106 fShaderCaps->applyOptionsOverrides(contextOptions); 107 } 108 109 void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) { 110 if (kQualcomm_VkVendor == properties.vendorID) { 111 fMustDoCopiesFromOrigin = true; 112 } 113 114 if (kNvidia_VkVendor == properties.vendorID) { 115 fMustSubmitCommandsBeforeCopyOp = true; 116 } 117 118 if (kQualcomm_VkVendor == properties.vendorID || 119 kARM_VkVendor == properties.vendorID) { 120 fSupportsCopiesAsDraws = false; 121 // We require copies as draws to support cross context textures. 122 fCrossContextTextureSupport = false; 123 } 124 125 #if defined(SK_BUILD_FOR_WIN) 126 if (kNvidia_VkVendor == properties.vendorID) { 127 fMustSleepOnTearDown = true; 128 } 129 #elif defined(SK_BUILD_FOR_ANDROID) 130 if (kImagination_VkVendor == properties.vendorID) { 131 fMustSleepOnTearDown = true; 132 } 133 #endif 134 135 // AMD seems to have issues binding new VkPipelines inside a secondary command buffer. 136 // Current workaround is to use a different secondary command buffer for each new VkPipeline. 137 if (kAMD_VkVendor == properties.vendorID) { 138 fNewCBOnPipelineChange = true; 139 } 140 141 //////////////////////////////////////////////////////////////////////////// 142 // GrCaps workarounds 143 //////////////////////////////////////////////////////////////////////////// 144 145 if (kARM_VkVendor == properties.vendorID) { 146 fInstanceAttribSupport = false; 147 } 148 149 // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32. 150 if (kAMD_VkVendor == properties.vendorID) { 151 fMaxVertexAttributes = SkTMin(fMaxVertexAttributes, 32); 152 } 153 154 if (kIntel_VkVendor == properties.vendorID) { 155 fCanUseWholeSizeOnFlushMappedMemory = false; 156 } 157 158 //////////////////////////////////////////////////////////////////////////// 159 // GrShaderCaps workarounds 160 //////////////////////////////////////////////////////////////////////////// 161 162 if (kImagination_VkVendor == properties.vendorID) { 163 fShaderCaps->fAtan2ImplementedAsAtanYOverX = true; 164 } 165 166 } 167 168 int get_max_sample_count(VkSampleCountFlags flags) { 169 SkASSERT(flags & VK_SAMPLE_COUNT_1_BIT); 170 if (!(flags & VK_SAMPLE_COUNT_2_BIT)) { 171 return 0; 172 } 173 if (!(flags & VK_SAMPLE_COUNT_4_BIT)) { 174 return 2; 175 } 176 if (!(flags & VK_SAMPLE_COUNT_8_BIT)) { 177 return 4; 178 } 179 if (!(flags & VK_SAMPLE_COUNT_16_BIT)) { 180 return 8; 181 } 182 if (!(flags & VK_SAMPLE_COUNT_32_BIT)) { 183 return 16; 184 } 185 if (!(flags & VK_SAMPLE_COUNT_64_BIT)) { 186 return 32; 187 } 188 return 64; 189 } 190 191 void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties, 192 const VkPhysicalDeviceMemoryProperties& memoryProperties, 193 uint32_t featureFlags) { 194 // So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no 195 // need for us ever to support that amount, and it makes tests which tests all the vertex 196 // attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if 197 // we ever find that need. 198 static const uint32_t kMaxVertexAttributes = 64; 199 fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes); 200 201 // We could actually query and get a max size for each config, however maxImageDimension2D will 202 // give the minimum max size across all configs. So for simplicity we will use that for now. 203 fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX); 204 fMaxTextureSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX); 205 206 // TODO: check if RT's larger than 4k incur a performance cost on ARM. 207 fMaxPreferredRenderTargetSize = fMaxRenderTargetSize; 208 209 // Assuming since we will always map in the end to upload the data we might as well just map 210 // from the get go. There is no hard data to suggest this is faster or slower. 211 fBufferMapThreshold = 0; 212 213 fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag; 214 215 fOversizedStencilSupport = true; 216 fSampleShadingSupport = SkToBool(featureFlags & kSampleRateShading_GrVkFeatureFlag); 217 218 219 } 220 221 void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint32_t featureFlags) { 222 GrShaderCaps* shaderCaps = fShaderCaps.get(); 223 shaderCaps->fVersionDeclString = "#version 330\n"; 224 225 226 // fConfigOutputSwizzle will default to RGBA so we only need to set it for alpha only config. 227 for (int i = 0; i < kGrPixelConfigCnt; ++i) { 228 GrPixelConfig config = static_cast<GrPixelConfig>(i); 229 // Vulkan doesn't support a single channel format stored in alpha. 230 if (GrPixelConfigIsAlphaOnly(config) && 231 kAlpha_8_as_Alpha_GrPixelConfig != config) { 232 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRR(); 233 shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::AAAA(); 234 } else { 235 if (kGray_8_GrPixelConfig == config || 236 kGray_8_as_Red_GrPixelConfig == config) { 237 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRA(); 238 } else if (kRGBA_4444_GrPixelConfig == config) { 239 // The vulkan spec does not require R4G4B4A4 to be supported for texturing so we 240 // store the data in a B4G4R4A4 texture and then swizzle it when doing texture reads 241 // or writing to outputs. Since we're not actually changing the data at all, the 242 // only extra work is the swizzle in the shader for all operations. 243 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::BGRA(); 244 shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::BGRA(); 245 } else { 246 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA(); 247 } 248 } 249 } 250 251 // Vulkan is based off ES 3.0 so the following should all be supported 252 shaderCaps->fUsesPrecisionModifiers = true; 253 shaderCaps->fFlatInterpolationSupport = true; 254 // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed 255 // to be true with Vulkan as well. 256 shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID; 257 258 // GrShaderCaps 259 260 shaderCaps->fShaderDerivativeSupport = true; 261 262 shaderCaps->fGeometryShaderSupport = SkToBool(featureFlags & kGeometryShader_GrVkFeatureFlag); 263 shaderCaps->fGSInvocationsSupport = shaderCaps->fGeometryShaderSupport; 264 265 shaderCaps->fDualSourceBlendingSupport = SkToBool(featureFlags & kDualSrcBlend_GrVkFeatureFlag); 266 267 shaderCaps->fIntegerSupport = true; 268 shaderCaps->fTexelBufferSupport = true; 269 shaderCaps->fTexelFetchSupport = true; 270 shaderCaps->fVertexIDSupport = true; 271 272 // Assume the minimum precisions mandated by the SPIR-V spec. 273 shaderCaps->fFloatIs32Bits = true; 274 shaderCaps->fHalfIs32Bits = false; 275 276 shaderCaps->fMaxVertexSamplers = 277 shaderCaps->fMaxGeometrySamplers = 278 shaderCaps->fMaxFragmentSamplers = SkTMin( 279 SkTMin(properties.limits.maxPerStageDescriptorSampledImages, 280 properties.limits.maxPerStageDescriptorSamplers), 281 (uint32_t)INT_MAX); 282 shaderCaps->fMaxCombinedSamplers = SkTMin( 283 SkTMin(properties.limits.maxDescriptorSetSampledImages, 284 properties.limits.maxDescriptorSetSamplers), 285 (uint32_t)INT_MAX); 286 } 287 288 bool stencil_format_supported(const GrVkInterface* interface, 289 VkPhysicalDevice physDev, 290 VkFormat format) { 291 VkFormatProperties props; 292 memset(&props, 0, sizeof(VkFormatProperties)); 293 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props)); 294 return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures); 295 } 296 297 void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevice physDev) { 298 // List of legal stencil formats (though perhaps not supported on 299 // the particular gpu/driver) from most preferred to least. We are guaranteed to have either 300 // VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D32_SFLOAT_S8_UINT. VK_FORMAT_D32_SFLOAT_S8_UINT 301 // can optionally have 24 unused bits at the end so we assume the total bits is 64. 302 static const StencilFormat 303 // internal Format stencil bits total bits packed? 304 gS8 = { VK_FORMAT_S8_UINT, 8, 8, false }, 305 gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT, 8, 32, true }, 306 gD32S8 = { VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 64, true }; 307 308 if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) { 309 fPreferedStencilFormat = gS8; 310 } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) { 311 fPreferedStencilFormat = gD24S8; 312 } else { 313 SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT)); 314 fPreferedStencilFormat = gD32S8; 315 } 316 } 317 318 void GrVkCaps::initConfigTable(const GrVkInterface* interface, VkPhysicalDevice physDev, 319 const VkPhysicalDeviceProperties& properties) { 320 for (int i = 0; i < kGrPixelConfigCnt; ++i) { 321 VkFormat format; 322 if (GrPixelConfigToVkFormat(static_cast<GrPixelConfig>(i), &format)) { 323 if (!GrPixelConfigIsSRGB(static_cast<GrPixelConfig>(i)) || fSRGBSupport) { 324 fConfigTable[i].init(interface, physDev, properties, format); 325 } 326 } 327 } 328 } 329 330 void GrVkCaps::ConfigInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) { 331 if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) && 332 SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) { 333 *flags = *flags | kTextureable_Flag; 334 335 // Ganesh assumes that all renderable surfaces are also texturable 336 if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) { 337 *flags = *flags | kRenderable_Flag; 338 } 339 } 340 341 if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) { 342 *flags = *flags | kBlitSrc_Flag; 343 } 344 345 if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) { 346 *flags = *flags | kBlitDst_Flag; 347 } 348 } 349 350 void GrVkCaps::ConfigInfo::initSampleCounts(const GrVkInterface* interface, 351 VkPhysicalDevice physDev, 352 const VkPhysicalDeviceProperties& physProps, 353 VkFormat format) { 354 VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 355 VK_IMAGE_USAGE_TRANSFER_DST_BIT | 356 VK_IMAGE_USAGE_SAMPLED_BIT | 357 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 358 VkImageCreateFlags createFlags = GrVkFormatIsSRGB(format, nullptr) 359 ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0; 360 VkImageFormatProperties properties; 361 GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev, 362 format, 363 VK_IMAGE_TYPE_2D, 364 VK_IMAGE_TILING_OPTIMAL, 365 usage, 366 createFlags, 367 &properties)); 368 VkSampleCountFlags flags = properties.sampleCounts; 369 if (flags & VK_SAMPLE_COUNT_1_BIT) { 370 fColorSampleCounts.push(1); 371 } 372 if (kImagination_VkVendor == physProps.vendorID) { 373 // MSAA does not work on imagination 374 return; 375 } 376 if (flags & VK_SAMPLE_COUNT_2_BIT) { 377 fColorSampleCounts.push(2); 378 } 379 if (flags & VK_SAMPLE_COUNT_4_BIT) { 380 fColorSampleCounts.push(4); 381 } 382 if (flags & VK_SAMPLE_COUNT_8_BIT) { 383 fColorSampleCounts.push(8); 384 } 385 if (flags & VK_SAMPLE_COUNT_16_BIT) { 386 fColorSampleCounts.push(16); 387 } 388 if (flags & VK_SAMPLE_COUNT_32_BIT) { 389 fColorSampleCounts.push(32); 390 } 391 if (flags & VK_SAMPLE_COUNT_64_BIT) { 392 fColorSampleCounts.push(64); 393 } 394 } 395 396 void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface, 397 VkPhysicalDevice physDev, 398 const VkPhysicalDeviceProperties& properties, 399 VkFormat format) { 400 VkFormatProperties props; 401 memset(&props, 0, sizeof(VkFormatProperties)); 402 GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props)); 403 InitConfigFlags(props.linearTilingFeatures, &fLinearFlags); 404 InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags); 405 if (fOptimalFlags & kRenderable_Flag) { 406 this->initSampleCounts(interface, physDev, properties, format); 407 } 408 } 409 410 int GrVkCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const { 411 requestedCount = SkTMax(1, requestedCount); 412 int count = fConfigTable[config].fColorSampleCounts.count(); 413 414 if (!count) { 415 return 0; 416 } 417 418 if (1 == requestedCount) { 419 SkASSERT(fConfigTable[config].fColorSampleCounts.count() && 420 fConfigTable[config].fColorSampleCounts[0] == 1); 421 return 1; 422 } 423 424 for (int i = 0; i < count; ++i) { 425 if (fConfigTable[config].fColorSampleCounts[i] >= requestedCount) { 426 return fConfigTable[config].fColorSampleCounts[i]; 427 } 428 } 429 return 0; 430 } 431 432 int GrVkCaps::maxRenderTargetSampleCount(GrPixelConfig config) const { 433 const auto& table = fConfigTable[config].fColorSampleCounts; 434 if (!table.count()) { 435 return 0; 436 } 437 return table[table.count() - 1]; 438 } 439 440 bool GrVkCaps::surfaceSupportsWritePixels(const GrSurface* surface) const { 441 if (auto rt = surface->asRenderTarget()) { 442 return rt->numColorSamples() <= 1 && SkToBool(surface->asTexture()); 443 } 444 return true; 445 } 446 447 bool validate_image_info(VkFormat format, SkColorType ct, GrPixelConfig* config) { 448 *config = kUnknown_GrPixelConfig; 449 450 switch (ct) { 451 case kUnknown_SkColorType: 452 return false; 453 case kAlpha_8_SkColorType: 454 if (VK_FORMAT_R8_UNORM == format) { 455 *config = kAlpha_8_as_Red_GrPixelConfig; 456 } 457 break; 458 case kRGB_565_SkColorType: 459 if (VK_FORMAT_R5G6B5_UNORM_PACK16 == format) { 460 *config = kRGB_565_GrPixelConfig; 461 } 462 break; 463 case kARGB_4444_SkColorType: 464 if (VK_FORMAT_B4G4R4A4_UNORM_PACK16 == format) { 465 *config = kRGBA_4444_GrPixelConfig; 466 } 467 break; 468 case kRGBA_8888_SkColorType: 469 if (VK_FORMAT_R8G8B8A8_UNORM == format) { 470 *config = kRGBA_8888_GrPixelConfig; 471 } else if (VK_FORMAT_R8G8B8A8_SRGB == format) { 472 *config = kSRGBA_8888_GrPixelConfig; 473 } 474 break; 475 case kRGB_888x_SkColorType: 476 return false; 477 case kBGRA_8888_SkColorType: 478 if (VK_FORMAT_B8G8R8A8_UNORM == format) { 479 *config = kBGRA_8888_GrPixelConfig; 480 } else if (VK_FORMAT_B8G8R8A8_SRGB == format) { 481 *config = kSBGRA_8888_GrPixelConfig; 482 } 483 break; 484 case kRGBA_1010102_SkColorType: 485 if (VK_FORMAT_A2B10G10R10_UNORM_PACK32 == format) { 486 *config = kRGBA_1010102_GrPixelConfig; 487 } 488 break; 489 case kRGB_101010x_SkColorType: 490 return false; 491 case kGray_8_SkColorType: 492 if (VK_FORMAT_R8_UNORM == format) { 493 *config = kGray_8_as_Red_GrPixelConfig; 494 } 495 break; 496 case kRGBA_F16_SkColorType: 497 if (VK_FORMAT_R16G16B16A16_SFLOAT == format) { 498 *config = kRGBA_half_GrPixelConfig; 499 } 500 break; 501 } 502 503 return kUnknown_GrPixelConfig != *config; 504 } 505 506 bool GrVkCaps::validateBackendTexture(const GrBackendTexture& tex, SkColorType ct, 507 GrPixelConfig* config) const { 508 const GrVkImageInfo* imageInfo = tex.getVkImageInfo(); 509 if (!imageInfo) { 510 return false; 511 } 512 513 return validate_image_info(imageInfo->fFormat, ct, config); 514 } 515 516 bool GrVkCaps::validateBackendRenderTarget(const GrBackendRenderTarget& rt, SkColorType ct, 517 GrPixelConfig* config) const { 518 const GrVkImageInfo* imageInfo = rt.getVkImageInfo(); 519 if (!imageInfo) { 520 return false; 521 } 522 523 return validate_image_info(imageInfo->fFormat, ct, config); 524 } 525 526 bool GrVkCaps::getConfigFromBackendFormat(const GrBackendFormat& format, SkColorType ct, 527 GrPixelConfig* config) const { 528 const VkFormat* vkFormat = format.getVkFormat(); 529 if (!vkFormat) { 530 return false; 531 } 532 return validate_image_info(*vkFormat, ct, config); 533 } 534 535