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