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