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 #ifndef GrVkCaps_DEFINED 9 #define GrVkCaps_DEFINED 10 11 #include "include/gpu/ganesh/GrBackendSurface.h" 12 #include "include/gpu/ganesh/GrTypes.h" 13 #include "include/gpu/vk/VulkanTypes.h" 14 #include "include/private/base/SkAssert.h" 15 #include "include/private/base/SkTArray.h" 16 #include "include/private/base/SkTDArray.h" 17 #include "include/private/base/SkTo.h" 18 #include "include/private/gpu/ganesh/GrTypesPriv.h" 19 #include "include/private/gpu/vk/SkiaVulkan.h" 20 #include "src/gpu/Swizzle.h" 21 #include "src/gpu/ganesh/GrCaps.h" 22 #include "src/gpu/ganesh/GrProgramDesc.h" 23 #include "src/gpu/ganesh/GrSamplerState.h" 24 25 #include <cstddef> 26 #include <cstdint> 27 #include <initializer_list> 28 #include <memory> 29 #include <vector> 30 31 class GrProgramInfo; 32 class GrRenderTarget; 33 class GrRenderTargetProxy; 34 class GrSurface; 35 class GrSurfaceProxy; 36 class GrVkRenderTarget; 37 enum class SkTextureCompressionType; 38 struct GrContextOptions; 39 struct SkIRect; 40 41 namespace GrTest { 42 struct TestFormatColorTypeCombination; 43 } 44 45 namespace skgpu { 46 class KeyBuilder; 47 class VulkanExtensions; 48 enum class Protected : bool; 49 struct VulkanInterface; 50 } // namespace skgpu 51 52 /** 53 * Stores some capabilities of a Vk backend. 54 */ 55 class GrVkCaps : public GrCaps { 56 public: 57 /** 58 * Creates a GrVkCaps that is set such that nothing is supported. The init function should 59 * be called to fill out the caps. 60 */ 61 GrVkCaps(const GrContextOptions&, 62 const skgpu::VulkanInterface*, 63 VkPhysicalDevice, 64 const VkPhysicalDeviceFeatures2&, 65 uint32_t instanceVersion, 66 uint32_t physicalDeviceVersion, 67 const skgpu::VulkanExtensions&, 68 skgpu::Protected); 69 70 bool isFormatSRGB(const GrBackendFormat&) const override; 71 72 bool isFormatTexturable(const GrBackendFormat&, GrTextureType) const override; 73 bool isVkFormatTexturable(VkFormat) const; 74 isFormatCopyable(const GrBackendFormat &)75 bool isFormatCopyable(const GrBackendFormat&) const override { return true; } 76 77 bool isFormatAsColorTypeRenderable(GrColorType ct, 78 const GrBackendFormat& format, 79 int sampleCount = 1) const override; 80 bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override; 81 bool isFormatRenderable(VkFormat, int sampleCount) const; 82 83 int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override; 84 int getRenderTargetSampleCount(int requestedCount, VkFormat) const; 85 86 int maxRenderTargetSampleCount(const GrBackendFormat&) const override; 87 int maxRenderTargetSampleCount(VkFormat format) const; 88 89 SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType, 90 const GrBackendFormat& surfaceFormat, 91 GrColorType srcColorType) const override; 92 93 SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override; 94 isVkFormatTexturableLinearly(VkFormat format)95 bool isVkFormatTexturableLinearly(VkFormat format) const { 96 return SkToBool(FormatInfo::kTexturable_Flag & this->getFormatInfo(format).fLinearFlags); 97 } 98 formatCanBeDstofBlit(VkFormat format,bool linearTiled)99 bool formatCanBeDstofBlit(VkFormat format, bool linearTiled) const { 100 const FormatInfo& info = this->getFormatInfo(format); 101 const uint16_t& flags = linearTiled ? info.fLinearFlags : info.fOptimalFlags; 102 return SkToBool(FormatInfo::kBlitDst_Flag & flags); 103 } 104 formatCanBeSrcofBlit(VkFormat format,bool linearTiled)105 bool formatCanBeSrcofBlit(VkFormat format, bool linearTiled) const { 106 const FormatInfo& info = this->getFormatInfo(format); 107 const uint16_t& flags = linearTiled ? info.fLinearFlags : info.fOptimalFlags; 108 return SkToBool(FormatInfo::kBlitSrc_Flag & flags); 109 } 110 111 // Gets the GrColorType that should be used to transfer data in/out of a transfer buffer to 112 // write/read data when using a VkFormat with a specified color type. 113 GrColorType transferColorType(VkFormat, GrColorType surfaceColorType) const; 114 115 // On some GPUs (Windows Nvidia and Imagination) calls to QueueWaitIdle return before actually 116 // signalling the fences on the command buffers even though they have completed. This causes 117 // issues when then deleting the command buffers. Therefore we additionally will call 118 // vkWaitForFences on each outstanding command buffer to make sure the driver signals the fence. mustSyncCommandBuffersWithQueue()119 bool mustSyncCommandBuffersWithQueue() const { return fMustSyncCommandBuffersWithQueue; } 120 121 // Returns true if we should always make dedicated allocations for VkImages. shouldAlwaysUseDedicatedImageMemory()122 bool shouldAlwaysUseDedicatedImageMemory() const { 123 return fShouldAlwaysUseDedicatedImageMemory; 124 } 125 126 // Always use a transfer buffer instead of vkCmdUpdateBuffer to upload data to a VkBuffer. avoidUpdateBuffers()127 bool avoidUpdateBuffers() const { return fAvoidUpdateBuffers; } 128 129 /** 130 * Returns both a supported and most preferred stencil format to use in draws. 131 */ preferredStencilFormat()132 VkFormat preferredStencilFormat() const { return fPreferredStencilFormat; } 133 134 // Returns total number of bits used by stencil + depth + padding GetStencilFormatTotalBitCount(VkFormat format)135 static int GetStencilFormatTotalBitCount(VkFormat format) { 136 switch (format) { 137 case VK_FORMAT_S8_UINT: 138 return 8; 139 case VK_FORMAT_D24_UNORM_S8_UINT: 140 return 32; 141 case VK_FORMAT_D32_SFLOAT_S8_UINT: 142 // can optionally have 24 unused bits at the end so we assume the total bits is 64. 143 return 64; 144 default: 145 SkASSERT(false); 146 return 0; 147 } 148 } 149 150 // Returns whether the device supports VK_KHR_Swapchain. Internally Skia never uses any of the 151 // swapchain functions, but we may need to transition to and from the 152 // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR image layout, so we must know whether that layout is 153 // supported. supportsSwapchain()154 bool supportsSwapchain() const { return fSupportsSwapchain; } 155 156 // Returns whether the device supports the ability to extend VkPhysicalDeviceProperties struct. supportsPhysicalDeviceProperties2()157 bool supportsPhysicalDeviceProperties2() const { return fSupportsPhysicalDeviceProperties2; } 158 // Returns whether the device supports the ability to extend VkMemoryRequirements struct. supportsMemoryRequirements2()159 bool supportsMemoryRequirements2() const { return fSupportsMemoryRequirements2; } 160 161 // Returns whether the device supports the ability to extend the vkBindMemory call. supportsBindMemory2()162 bool supportsBindMemory2() const { return fSupportsBindMemory2; } 163 164 // Returns whether or not the device suports the various API maintenance fixes to Vulkan 1.0. In 165 // Vulkan 1.1 all these maintenance are part of the core spec. supportsMaintenance1()166 bool supportsMaintenance1() const { return fSupportsMaintenance1; } supportsMaintenance2()167 bool supportsMaintenance2() const { return fSupportsMaintenance2; } supportsMaintenance3()168 bool supportsMaintenance3() const { return fSupportsMaintenance3; } 169 170 // Returns true if the device supports passing in a flag to say we are using dedicated GPU when 171 // allocating memory. For some devices this allows them to return more optimized memory knowning 172 // they will never need to suballocate amonst multiple objects. supportsDedicatedAllocation()173 bool supportsDedicatedAllocation() const { return fSupportsDedicatedAllocation; } 174 175 // Returns true if the device supports importing of external memory into Vulkan memory. supportsExternalMemory()176 bool supportsExternalMemory() const { return fSupportsExternalMemory; } 177 // Returns true if the device supports importing Android hardware buffers into Vulkan memory. supportsAndroidHWBExternalMemory()178 bool supportsAndroidHWBExternalMemory() const { return fSupportsAndroidHWBExternalMemory; } 179 180 // Returns true if it supports ycbcr conversion for samplers supportsYcbcrConversion()181 bool supportsYcbcrConversion() const { return fSupportsYcbcrConversion; } 182 183 // Returns the number of descriptor slots used by immutable ycbcr VkImages. 184 // 185 // TODO: We should update this to return a count for a specific format or external format. We 186 // can use vkGetPhysicalDeviceImageFormatProperties2 with a 187 // VkSamplerYcbcrConversionImageFormatProperties to query this. However, right now that call 188 // does not support external android formats which is where the majority of ycbcr images are 189 // coming from. So for now we stay safe and always return 3 here which is the max value that the 190 // count could be for any format. ycbcrCombinedImageSamplerDescriptorCount()191 uint32_t ycbcrCombinedImageSamplerDescriptorCount() const { 192 return 3; 193 } 194 195 // Returns true if the VK_EXT_image_drm_format_modifier is enabled. supportsDRMFormatModifiers()196 bool supportsDRMFormatModifiers() const { return fSupportsDRMFormatModifiers; } 197 supportsDeviceFaultInfo()198 bool supportsDeviceFaultInfo() const { return fSupportsDeviceFaultInfo; } 199 supportsFrameBoundary()200 bool supportsFrameBoundary() const { return fSupportsFrameBoundary; } 201 202 // Returns whether we prefer to record draws directly into a primary command buffer. preferPrimaryOverSecondaryCommandBuffers()203 bool preferPrimaryOverSecondaryCommandBuffers() const { 204 return fPreferPrimaryOverSecondaryCommandBuffers; 205 } 206 maxPerPoolCachedSecondaryCommandBuffers()207 int maxPerPoolCachedSecondaryCommandBuffers() const { 208 return fMaxPerPoolCachedSecondaryCommandBuffers; 209 } 210 maxInputAttachmentDescriptors()211 uint32_t maxInputAttachmentDescriptors() const { return fMaxInputAttachmentDescriptors; } 212 maxSamplerAnisotropy()213 float maxSamplerAnisotropy() const { return fMaxSamplerAnisotropy; } 214 mustInvalidatePrimaryCmdBufferStateAfterClearAttachments()215 bool mustInvalidatePrimaryCmdBufferStateAfterClearAttachments() const { 216 return fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments; 217 } 218 219 // Returns whether a pure GPU accessible buffer is more performant to read than a buffer that is 220 // also host visible. If so then in some cases we may prefer the cost of doing a copy to the 221 // buffer. This typically would only be the case for buffers that are written once and read 222 // many times on the gpu. gpuOnlyBuffersMorePerformant()223 bool gpuOnlyBuffersMorePerformant() const { return fGpuOnlyBuffersMorePerformant; } 224 225 // For our CPU write and GPU read buffers (vertex, uniform, etc.), should we keep these buffers 226 // persistently mapped. In general the answer will be yes. The main case we don't do this is 227 // when using special memory that is DEVICE_LOCAL and HOST_VISIBLE on discrete GPUs. shouldPersistentlyMapCpuToGpuBuffers()228 bool shouldPersistentlyMapCpuToGpuBuffers() const { 229 return fShouldPersistentlyMapCpuToGpuBuffers; 230 } 231 232 // The max draw count that can be passed into indirect draw calls. maxDrawIndirectDrawCount()233 uint32_t maxDrawIndirectDrawCount() const { return fMaxDrawIndirectDrawCount; } 234 235 /** 236 * Helpers used by canCopySurface. In all cases if the SampleCnt parameter is zero that means 237 * the surface is not a render target, otherwise it is the number of samples in the render 238 * target. 239 */ 240 bool canCopyImage(VkFormat dstFormat, 241 int dstSampleCnt, 242 bool dstHasYcbcr, 243 VkFormat srcFormat, 244 int srcSamplecnt, 245 bool srcHasYcbcr) const; 246 247 bool canCopyAsBlit(VkFormat dstConfig, 248 int dstSampleCnt, 249 bool dstIsLinear, 250 bool dstHasYcbcr, 251 VkFormat srcConfig, 252 int srcSampleCnt, 253 bool srcIsLinear, 254 bool srcHasYcbcr) const; 255 256 bool canCopyAsResolve(VkFormat dstConfig, 257 int dstSampleCnt, 258 bool dstHasYcbcr, 259 VkFormat srcConfig, 260 int srcSamplecnt, 261 bool srcHasYcbcr) const; 262 getBackendFormatFromCompressionType(SkTextureCompressionType)263 GrBackendFormat getBackendFormatFromCompressionType(SkTextureCompressionType) const override; 264 265 VkFormat getFormatFromColorType(GrColorType colorType) const { 266 int idx = static_cast<int>(colorType); 267 return fColorTypeToFormatTable[idx]; 268 } 269 270 skgpu::Swizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; 271 272 uint64_t computeFormatKey(const GrBackendFormat&) const override; 273 274 int getFragmentUniformBinding() const; 275 int getFragmentUniformSet() const; 276 277 void addExtraSamplerKey(skgpu::KeyBuilder*, 278 GrSamplerState, 279 const GrBackendFormat&) const override; 280 281 GrProgramDesc makeDesc(GrRenderTarget*, 282 const GrProgramInfo&, 283 ProgramDescOverrideFlags) const override; 284 285 GrInternalSurfaceFlags getExtraSurfaceFlagsForDeferredRT() const override; 286 287 VkShaderStageFlags getPushConstantStageFlags() const; 288 mustLoadFullImageWithDiscardableMSAA()289 bool mustLoadFullImageWithDiscardableMSAA() const { 290 return fMustLoadFullImageWithDiscardableMSAA; 291 } supportsDiscardableMSAAForDMSAA()292 bool supportsDiscardableMSAAForDMSAA() const { return fSupportsDiscardableMSAAForDMSAA; } 293 bool renderTargetSupportsDiscardableMSAA(const GrVkRenderTarget*) const; 294 bool programInfoWillUseDiscardableMSAA(const GrProgramInfo&) const; 295 dmsaaResolveCanBeUsedAsTextureInSameRenderPass()296 bool dmsaaResolveCanBeUsedAsTextureInSameRenderPass() const override { return false; } 297 supportsMemorylessAttachments()298 bool supportsMemorylessAttachments() const { return fSupportsMemorylessAttachments; } 299 300 #if defined(GPU_TEST_UTILS) 301 std::vector<GrTest::TestFormatColorTypeCombination> getTestingCombinations() const override; 302 #endif 303 304 private: 305 enum VkVendor { 306 kAMD_VkVendor = 4098, 307 kARM_VkVendor = 5045, 308 kGoogle_VkVendor = 0x1AE0, 309 kImagination_VkVendor = 4112, 310 kIntel_VkVendor = 32902, 311 kNvidia_VkVendor = 4318, 312 kQualcomm_VkVendor = 20803, 313 }; 314 315 enum class IntelGPUType { 316 // 9th gen 317 kSkyLake, 318 319 // 11th gen 320 kIceLake, 321 kJasperLake, 322 323 // 12th gen or above 324 kRocketLake, 325 kTigerLake, 326 kAlderLake, 327 kRaptorLake, 328 kAlchemist, 329 kLunarLake, 330 kMeteorLake, 331 kArrowLake, 332 kBattlemage, 333 kPantherLake, 334 335 kOther 336 }; 337 338 enum DeviceID { 339 kSwiftshader_DeviceID = 0xC0DE, // As listed in Swiftshader code this may be a placeholder 340 // value but works for now. 341 }; 342 343 static IntelGPUType GetIntelGPUType(uint32_t deviceID); GetIntelGen(IntelGPUType type)344 static int GetIntelGen(IntelGPUType type) { 345 switch (type) { 346 case IntelGPUType::kSkyLake: 347 return 9; 348 case IntelGPUType::kIceLake: // fall through 349 case IntelGPUType::kJasperLake: 350 return 11; 351 case IntelGPUType::kRocketLake: // fall through 352 case IntelGPUType::kTigerLake: // fall through 353 case IntelGPUType::kAlderLake: // fall through 354 case IntelGPUType::kRaptorLake: // fall through 355 case IntelGPUType::kAlchemist: // fall through 356 case IntelGPUType::kLunarLake: // fall through 357 case IntelGPUType::kMeteorLake: // fall through 358 case IntelGPUType::kArrowLake: // fall through 359 case IntelGPUType::kBattlemage: // fall through 360 case IntelGPUType::kPantherLake: 361 return 12; 362 case IntelGPUType::kOther: 363 // For now all our workaround checks are in the form of "if gen > some_value". So 364 // we can return 0 for kOther which means we won't put in the new workaround for 365 // older gens which is fine. If we stay on top of adding support for new gen 366 // intel devices we shouldn't hit cases where we'd need to change this pattern. 367 return 0; 368 } 369 SkUNREACHABLE; 370 } 371 372 void init(const GrContextOptions&, 373 const skgpu::VulkanInterface*, 374 VkPhysicalDevice, 375 const VkPhysicalDeviceFeatures2&, 376 uint32_t physicalDeviceVersion, 377 const skgpu::VulkanExtensions&, 378 GrProtected); 379 void initGrCaps(const skgpu::VulkanInterface* vkInterface, 380 VkPhysicalDevice physDev, 381 const VkPhysicalDeviceProperties&, 382 const VkPhysicalDeviceMemoryProperties&, 383 const VkPhysicalDeviceFeatures2&, 384 const skgpu::VulkanExtensions&); 385 void initShaderCaps(const VkPhysicalDeviceProperties&, const VkPhysicalDeviceFeatures2&); 386 387 void initFormatTable(const GrContextOptions&, 388 const skgpu::VulkanInterface*, 389 VkPhysicalDevice, 390 const VkPhysicalDeviceProperties&, 391 const VkPhysicalDeviceFeatures2&, 392 const skgpu::VulkanExtensions&); 393 void initStencilFormat(const skgpu::VulkanInterface* iface, VkPhysicalDevice physDev); 394 395 void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&); 396 397 bool onSurfaceSupportsWritePixels(const GrSurface*) const override; 398 bool onCanCopySurface(const GrSurfaceProxy* dst, const SkIRect& dstRect, 399 const GrSurfaceProxy* src, const SkIRect& srcRect) const override; 400 GrBackendFormat onGetDefaultBackendFormat(GrColorType) const override; 401 402 bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override; 403 404 SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&, 405 GrColorType) const override; 406 407 skgpu::Swizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override; 408 409 GrDstSampleFlags onGetDstSampleFlagsForProxy(const GrRenderTargetProxy*) const override; 410 411 bool onSupportsDynamicMSAA(const GrRenderTargetProxy*) const override; 412 413 // ColorTypeInfo for a specific format 414 struct ColorTypeInfo { 415 GrColorType fColorType = GrColorType::kUnknown; 416 GrColorType fTransferColorType = GrColorType::kUnknown; 417 enum { 418 kUploadData_Flag = 0x1, 419 // Does Ganesh itself support rendering to this colorType & format pair. Renderability 420 // still additionally depends on if the format itself is renderable. 421 kRenderable_Flag = 0x2, 422 // Indicates that this colorType is supported only if we are wrapping a texture with 423 // the given format and colorType. We do not allow creation with this pair. 424 kWrappedOnly_Flag = 0x4, 425 }; 426 uint32_t fFlags = 0; 427 428 skgpu::Swizzle fReadSwizzle; 429 skgpu::Swizzle fWriteSwizzle; 430 }; 431 432 struct FormatInfo { colorTypeFlagsFormatInfo433 uint32_t colorTypeFlags(GrColorType colorType) const { 434 for (int i = 0; i < fColorTypeInfoCount; ++i) { 435 if (fColorTypeInfos[i].fColorType == colorType) { 436 return fColorTypeInfos[i].fFlags; 437 } 438 } 439 return 0; 440 } 441 442 void init(const GrContextOptions&, 443 const skgpu::VulkanInterface*, 444 VkPhysicalDevice, 445 const VkPhysicalDeviceProperties&, 446 VkFormat); 447 static void InitFormatFlags(VkFormatFeatureFlags, uint16_t* flags); 448 void initSampleCounts(const GrContextOptions&, 449 const skgpu::VulkanInterface*, 450 VkPhysicalDevice, 451 const VkPhysicalDeviceProperties&, 452 VkFormat); 453 454 enum { 455 kTexturable_Flag = 0x1, 456 kRenderable_Flag = 0x2, 457 kBlitSrc_Flag = 0x4, 458 kBlitDst_Flag = 0x8, 459 }; 460 461 uint16_t fOptimalFlags = 0; 462 uint16_t fLinearFlags = 0; 463 464 SkTDArray<int> fColorSampleCounts; 465 466 std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos; 467 int fColorTypeInfoCount = 0; 468 }; 469 static const size_t kNumVkFormats = 25; 470 FormatInfo fFormatTable[kNumVkFormats]; 471 472 FormatInfo& getFormatInfo(VkFormat); 473 const FormatInfo& getFormatInfo(VkFormat) const; 474 475 VkFormat fColorTypeToFormatTable[kGrColorTypeCnt]; 476 void setColorType(GrColorType, std::initializer_list<VkFormat> formats); 477 478 VkFormat fPreferredStencilFormat; 479 480 skia_private::STArray<1, skgpu::VulkanYcbcrConversionInfo> fYcbcrInfos; 481 482 bool fMustSyncCommandBuffersWithQueue = false; 483 bool fShouldAlwaysUseDedicatedImageMemory = false; 484 485 bool fAvoidUpdateBuffers = false; 486 487 bool fSupportsSwapchain = false; 488 489 bool fSupportsPhysicalDeviceProperties2 = false; 490 bool fSupportsMemoryRequirements2 = false; 491 bool fSupportsBindMemory2 = false; 492 bool fSupportsMaintenance1 = false; 493 bool fSupportsMaintenance2 = false; 494 bool fSupportsMaintenance3 = false; 495 496 bool fSupportsDedicatedAllocation = false; 497 bool fSupportsExternalMemory = false; 498 bool fSupportsAndroidHWBExternalMemory = false; 499 500 bool fSupportsYcbcrConversion = false; 501 502 bool fSupportsDRMFormatModifiers = false; 503 504 bool fSupportsDeviceFaultInfo = false; 505 506 bool fSupportsFrameBoundary = false; 507 508 bool fPreferPrimaryOverSecondaryCommandBuffers = true; 509 bool fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments = false; 510 511 bool fGpuOnlyBuffersMorePerformant = false; 512 bool fShouldPersistentlyMapCpuToGpuBuffers = true; 513 514 // We default this to 100 since we already cap the max render tasks at 100 before doing a 515 // submission in the GrDrawingManager, so we shouldn't be going over 100 secondary command 516 // buffers per primary anyways. 517 int fMaxPerPoolCachedSecondaryCommandBuffers = 100; 518 519 uint32_t fMaxInputAttachmentDescriptors = 0; 520 521 float fMaxSamplerAnisotropy = 1.f; 522 523 bool fMustLoadFullImageWithDiscardableMSAA = false; 524 bool fSupportsDiscardableMSAAForDMSAA = true; 525 bool fSupportsMemorylessAttachments = false; 526 527 uint32_t fMaxDrawIndirectDrawCount = 0; 528 529 using INHERITED = GrCaps; 530 }; 531 532 #endif 533