1 /* 2 * Copyright 2022 Google LLC 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 skgpu_graphite_VulkanCaps_DEFINED 9 #define skgpu_graphite_VulkanCaps_DEFINED 10 11 #include "include/private/base/SkTDArray.h" 12 #include "src/gpu/graphite/Caps.h" 13 #include "src/gpu/vk/VulkanInterface.h" 14 #include "src/gpu/vk/VulkanUtilsPriv.h" 15 16 namespace skgpu::graphite { 17 struct ContextOptions; 18 class VulkanTextureInfo; 19 20 class VulkanCaps final : public Caps { 21 public: 22 VulkanCaps(const ContextOptions&, 23 const skgpu::VulkanInterface*, 24 VkPhysicalDevice, 25 uint32_t physicalDeviceVersion, 26 const VkPhysicalDeviceFeatures2*, 27 const skgpu::VulkanExtensions*, 28 Protected); 29 ~VulkanCaps() override; 30 31 TextureInfo getDefaultSampledTextureInfo(SkColorType, 32 Mipmapped mipmapped, 33 Protected, 34 Renderable) const override; 35 36 TextureInfo getTextureInfoForSampledCopy(const TextureInfo& textureInfo, 37 Mipmapped mipmapped) const override; 38 39 TextureInfo getDefaultCompressedTextureInfo(SkTextureCompressionType, 40 Mipmapped mipmapped, 41 Protected) const override; 42 43 TextureInfo getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo, 44 Discardable discardable) const override; 45 46 TextureInfo getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags>, 47 uint32_t sampleCount, 48 Protected, 49 Discardable discardable) const override; 50 51 TextureInfo getDefaultStorageTextureInfo(SkColorType) const override; 52 53 // Override Caps's implementation in order to consult Vulkan-specific texture properties. 54 DstReadStrategy getDstReadStrategy(const TextureInfo& info) const override; 55 56 ImmutableSamplerInfo getImmutableSamplerInfo(const TextureInfo&) const override; 57 58 UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc&, 59 const RenderPassDesc&) const override; makeComputePipelineKey(const ComputePipelineDesc &)60 UniqueKey makeComputePipelineKey(const ComputePipelineDesc&) const override { return {}; } 61 62 bool serializeTextureInfo(const TextureInfo&, SkWStream*) const override; 63 bool deserializeTextureInfo(SkStream*, TextureInfo* out) const override; 64 65 bool isTexturable(const VulkanTextureInfo&) const; 66 67 bool isRenderable(const TextureInfo&) const override; 68 bool isRenderable(const VulkanTextureInfo&) const; 69 bool isStorage(const TextureInfo&) const override; 70 71 void buildKeyForTexture(SkISize dimensions, 72 const TextureInfo&, 73 ResourceType, 74 GraphiteResourceKey*) const override; 75 shouldAlwaysUseDedicatedImageMemory()76 bool shouldAlwaysUseDedicatedImageMemory() const { 77 return fShouldAlwaysUseDedicatedImageMemory; 78 } 79 80 // Returns whether a pure GPU accessible buffer is more performant to read than a buffer that is 81 // also host visible. If so then in some cases we may prefer the cost of doing a copy to the 82 // buffer. This typically would only be the case for buffers that are written once and read 83 // many times on the gpu. gpuOnlyBuffersMorePerformant()84 bool gpuOnlyBuffersMorePerformant() const { return fGpuOnlyBuffersMorePerformant; } 85 86 // For our CPU write and GPU read buffers (vertex, uniform, etc.), we should keep these buffers 87 // persistently mapped. In general, the answer will be yes. The main case where we don't do this 88 // is when using special memory that is DEVICE_LOCAL and HOST_VISIBLE on discrete GPUs. shouldPersistentlyMapCpuToGpuBuffers()89 bool shouldPersistentlyMapCpuToGpuBuffers() const { 90 return fShouldPersistentlyMapCpuToGpuBuffers; 91 } 92 supportsYcbcrConversion()93 bool supportsYcbcrConversion() const { return fSupportsYcbcrConversion; } supportsDeviceFaultInfo()94 bool supportsDeviceFaultInfo() const { return fSupportsDeviceFaultInfo; } 95 maxVertexAttributes()96 uint32_t maxVertexAttributes() const { return fMaxVertexAttributes; } maxUniformBufferRange()97 uint64_t maxUniformBufferRange() const { return fMaxUniformBufferRange; } maxStorageBufferRange()98 uint64_t maxStorageBufferRange() const { return fMaxStorageBufferRange; } 99 physicalDeviceMemoryProperties2()100 const VkPhysicalDeviceMemoryProperties2& physicalDeviceMemoryProperties2() const { 101 return fPhysicalDeviceMemoryProperties2; 102 } 103 104 bool isTransferSrc(const VulkanTextureInfo&) const; 105 bool isTransferDst(const VulkanTextureInfo&) const; 106 mustLoadFullImageForMSAA()107 bool mustLoadFullImageForMSAA() const { return fMustLoadFullImageForMSAA; } 108 109 private: 110 enum VkVendor { 111 kAMD_VkVendor = 4098, 112 kARM_VkVendor = 5045, 113 kImagination_VkVendor = 4112, 114 kIntel_VkVendor = 32902, 115 kNvidia_VkVendor = 4318, 116 kQualcomm_VkVendor = 20803, 117 }; 118 119 void init(const ContextOptions&, 120 const skgpu::VulkanInterface*, 121 VkPhysicalDevice, 122 uint32_t physicalDeviceVersion, 123 const VkPhysicalDeviceFeatures2*, 124 const skgpu::VulkanExtensions*, 125 Protected); 126 127 void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&); 128 129 void initFormatTable(const skgpu::VulkanInterface*, 130 VkPhysicalDevice, 131 const VkPhysicalDeviceProperties&); 132 133 void initDepthStencilFormatTable(const skgpu::VulkanInterface*, 134 VkPhysicalDevice, 135 const VkPhysicalDeviceProperties&); 136 137 const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const override; 138 139 bool onIsTexturable(const TextureInfo&) const override; 140 141 bool supportsWritePixels(const TextureInfo&) const override; 142 bool supportsReadPixels(const TextureInfo&) const override; 143 144 std::pair<SkColorType, bool /*isRGBFormat*/> supportedWritePixelsColorType( 145 SkColorType dstColorType, 146 const TextureInfo& dstTextureInfo, 147 SkColorType srcColorType) const override; 148 std::pair<SkColorType, bool /*isRGBFormat*/> supportedReadPixelsColorType( 149 SkColorType srcColorType, 150 const TextureInfo& srcTextureInfo, 151 SkColorType dstColorType) const override; 152 153 // Struct that determines and stores which sample count quantities a VkFormat supports. 154 struct SupportedSampleCounts { 155 void initSampleCounts(const skgpu::VulkanInterface*, 156 VkPhysicalDevice, 157 const VkPhysicalDeviceProperties&, 158 VkFormat, 159 VkImageUsageFlags); 160 161 bool isSampleCountSupported(int requestedCount) const; 162 163 SkTDArray<int> fSampleCounts; 164 }; 165 166 // Struct that determines and stores useful information about VkFormats. 167 struct FormatInfo { colorTypeFlagsFormatInfo168 uint32_t colorTypeFlags(SkColorType colorType) const { 169 for (int i = 0; i < fColorTypeInfoCount; ++i) { 170 if (fColorTypeInfos[i].fColorType == colorType) { 171 return fColorTypeInfos[i].fFlags; 172 } 173 } 174 return 0; 175 } 176 177 void init(const skgpu::VulkanInterface*, 178 VkPhysicalDevice, 179 const VkPhysicalDeviceProperties&, 180 VkFormat); 181 182 bool isTexturable(VkImageTiling) const; 183 bool isRenderable(VkImageTiling, uint32_t sampleCount) const; 184 bool isStorage(VkImageTiling) const; 185 bool isTransferSrc(VkImageTiling) const; 186 bool isTransferDst(VkImageTiling) const; 187 188 std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos; 189 int fColorTypeInfoCount = 0; 190 191 VkFormatProperties fFormatProperties; 192 SupportedSampleCounts fSupportedSampleCounts; 193 194 // Indicates that a format is only supported if we are wrapping a texture with it. 195 SkDEBUGCODE(bool fIsWrappedOnly = false;) 196 }; 197 198 // Map SkColorType to VkFormat. 199 VkFormat fColorTypeToFormatTable[kSkColorTypeCnt]; 200 void setColorType(SkColorType, std::initializer_list<VkFormat> formats); 201 VkFormat getFormatFromColorType(SkColorType) const; 202 203 // Map VkFormat to FormatInfo. 204 static const size_t kNumVkFormats = 23; 205 FormatInfo fFormatTable[kNumVkFormats]; 206 207 FormatInfo& getFormatInfo(VkFormat); 208 const FormatInfo& getFormatInfo(VkFormat) const; 209 210 // A more lightweight equivalent to FormatInfo for depth/stencil VkFormats. 211 struct DepthStencilFormatInfo { 212 void init(const skgpu::VulkanInterface*, 213 VkPhysicalDevice, 214 const VkPhysicalDeviceProperties&, 215 VkFormat); 216 bool isDepthStencilSupported(VkFormatFeatureFlags) const; 217 218 VkFormatProperties fFormatProperties; 219 SupportedSampleCounts fSupportedSampleCounts; 220 }; 221 222 // Map DepthStencilFlags to VkFormat. 223 static const size_t kNumDepthStencilFlags = 4; 224 VkFormat fDepthStencilFlagsToFormatTable[kNumDepthStencilFlags]; 225 VkFormat getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags>& flags) const; 226 227 // Map depth/stencil VkFormats to DepthStencilFormatInfo. 228 static const size_t kNumDepthStencilVkFormats = 5; 229 DepthStencilFormatInfo fDepthStencilFormatTable[kNumDepthStencilVkFormats]; 230 231 DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat); 232 const DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat) const; 233 234 uint32_t fMaxVertexAttributes; 235 uint64_t fMaxUniformBufferRange; 236 uint64_t fMaxStorageBufferRange; 237 VkPhysicalDeviceMemoryProperties2 fPhysicalDeviceMemoryProperties2; 238 239 // ColorTypeInfo struct for use w/ external formats. 240 const ColorTypeInfo fExternalFormatColorTypeInfo = {SkColorType::kRGBA_8888_SkColorType, 241 SkColorType::kRGBA_8888_SkColorType, 242 /*flags=*/0, 243 skgpu::Swizzle::RGBA(), 244 skgpu::Swizzle::RGBA()}; 245 246 // Various bools to define whether certain Vulkan features are supported. 247 bool fSupportsMemorylessAttachments = false; 248 bool fSupportsYcbcrConversion = false; 249 bool fShouldAlwaysUseDedicatedImageMemory = false; 250 bool fGpuOnlyBuffersMorePerformant = false; 251 bool fShouldPersistentlyMapCpuToGpuBuffers = true; 252 bool fSupportsDeviceFaultInfo = false; 253 254 // Flags to enable workarounds for driver bugs 255 bool fMustLoadFullImageForMSAA = false; 256 }; 257 258 } // namespace skgpu::graphite 259 260 #endif // skgpu_graphite_VulkanCaps_DEFINED 261