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