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; } 92 supportsDeviceFaultInfo()93 bool supportsDeviceFaultInfo() const { return fSupportsDeviceFaultInfo; } 94 maxVertexAttributes()95 uint32_t maxVertexAttributes() const { 96 return fMaxVertexAttributes; 97 } maxUniformBufferRange()98 uint64_t maxUniformBufferRange() const { return fMaxUniformBufferRange; } 99 maxStorageBufferRange()100 uint64_t maxStorageBufferRange() const { return fMaxStorageBufferRange; } 101 physicalDeviceMemoryProperties2()102 const VkPhysicalDeviceMemoryProperties2& physicalDeviceMemoryProperties2() const { 103 return fPhysicalDeviceMemoryProperties2; 104 } 105 106 bool isTransferSrc(const VulkanTextureInfo&) const; 107 bool isTransferDst(const VulkanTextureInfo&) const; 108 mustLoadFullImageForMSAA()109 bool mustLoadFullImageForMSAA() const { return fMustLoadFullImageForMSAA; } 110 111 private: 112 enum VkVendor { 113 kAMD_VkVendor = 4098, 114 kARM_VkVendor = 5045, 115 kImagination_VkVendor = 4112, 116 kIntel_VkVendor = 32902, 117 kNvidia_VkVendor = 4318, 118 kQualcomm_VkVendor = 20803, 119 }; 120 121 void init(const ContextOptions&, 122 const skgpu::VulkanInterface*, 123 VkPhysicalDevice, 124 uint32_t physicalDeviceVersion, 125 const VkPhysicalDeviceFeatures2*, 126 const skgpu::VulkanExtensions*, 127 Protected); 128 129 void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&); 130 131 void initFormatTable(const skgpu::VulkanInterface*, 132 VkPhysicalDevice, 133 const VkPhysicalDeviceProperties&); 134 135 void initDepthStencilFormatTable(const skgpu::VulkanInterface*, 136 VkPhysicalDevice, 137 const VkPhysicalDeviceProperties&); 138 139 const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const override; 140 141 bool onIsTexturable(const TextureInfo&) const override; 142 143 bool supportsWritePixels(const TextureInfo&) const override; 144 bool supportsReadPixels(const TextureInfo&) const override; 145 146 std::pair<SkColorType, bool /*isRGBFormat*/> supportedWritePixelsColorType( 147 SkColorType dstColorType, 148 const TextureInfo& dstTextureInfo, 149 SkColorType srcColorType) const override; 150 std::pair<SkColorType, bool /*isRGBFormat*/> supportedReadPixelsColorType( 151 SkColorType srcColorType, 152 const TextureInfo& srcTextureInfo, 153 SkColorType dstColorType) const override; 154 155 // Struct that determines and stores which sample count quantities a VkFormat supports. 156 struct SupportedSampleCounts { 157 void initSampleCounts(const skgpu::VulkanInterface*, 158 VkPhysicalDevice, 159 const VkPhysicalDeviceProperties&, 160 VkFormat, 161 VkImageUsageFlags); 162 163 bool isSampleCountSupported(int requestedCount) const; 164 165 SkTDArray<int> fSampleCounts; 166 }; 167 168 // Struct that determines and stores useful information about VkFormats. 169 struct FormatInfo { colorTypeFlagsFormatInfo170 uint32_t colorTypeFlags(SkColorType colorType) const { 171 for (int i = 0; i < fColorTypeInfoCount; ++i) { 172 if (fColorTypeInfos[i].fColorType == colorType) { 173 return fColorTypeInfos[i].fFlags; 174 } 175 } 176 return 0; 177 } 178 179 void init(const skgpu::VulkanInterface*, 180 VkPhysicalDevice, 181 const VkPhysicalDeviceProperties&, 182 VkFormat); 183 184 bool isTexturable(VkImageTiling) const; 185 bool isRenderable(VkImageTiling, uint32_t sampleCount) const; 186 bool isStorage(VkImageTiling) const; 187 bool isTransferSrc(VkImageTiling) const; 188 bool isTransferDst(VkImageTiling) const; 189 190 std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos; 191 int fColorTypeInfoCount = 0; 192 193 VkFormatProperties fFormatProperties; 194 SupportedSampleCounts fSupportedSampleCounts; 195 196 // Indicates that a format is only supported if we are wrapping a texture with it. 197 SkDEBUGCODE(bool fIsWrappedOnly = false;) 198 }; 199 200 // Map SkColorType to VkFormat. 201 VkFormat fColorTypeToFormatTable[kSkColorTypeCnt]; 202 void setColorType(SkColorType, std::initializer_list<VkFormat> formats); 203 VkFormat getFormatFromColorType(SkColorType) const; 204 205 // Map VkFormat to FormatInfo. 206 static const size_t kNumVkFormats = 22; 207 FormatInfo fFormatTable[kNumVkFormats]; 208 209 FormatInfo& getFormatInfo(VkFormat); 210 const FormatInfo& getFormatInfo(VkFormat) const; 211 212 // A more lightweight equivalent to FormatInfo for depth/stencil VkFormats. 213 struct DepthStencilFormatInfo { 214 void init(const skgpu::VulkanInterface*, 215 VkPhysicalDevice, 216 const VkPhysicalDeviceProperties&, 217 VkFormat); 218 bool isDepthStencilSupported(VkFormatFeatureFlags) const; 219 220 VkFormatProperties fFormatProperties; 221 SupportedSampleCounts fSupportedSampleCounts; 222 }; 223 224 // Map DepthStencilFlags to VkFormat. 225 static const size_t kNumDepthStencilFlags = 4; 226 VkFormat fDepthStencilFlagsToFormatTable[kNumDepthStencilFlags]; 227 VkFormat getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags>& flags) const; 228 229 // Map depth/stencil VkFormats to DepthStencilFormatInfo. 230 static const size_t kNumDepthStencilVkFormats = 5; 231 DepthStencilFormatInfo fDepthStencilFormatTable[kNumDepthStencilVkFormats]; 232 233 DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat); 234 const DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat) const; 235 236 uint32_t fMaxVertexAttributes; 237 uint64_t fMaxUniformBufferRange; 238 uint64_t fMaxStorageBufferRange; 239 VkPhysicalDeviceMemoryProperties2 fPhysicalDeviceMemoryProperties2; 240 241 // ColorTypeInfo struct for use w/ external formats. 242 const ColorTypeInfo fExternalFormatColorTypeInfo = {SkColorType::kRGBA_8888_SkColorType, 243 SkColorType::kRGBA_8888_SkColorType, 244 /*flags=*/0, 245 skgpu::Swizzle::RGBA(), 246 skgpu::Swizzle::RGBA()}; 247 248 // Various bools to define whether certain Vulkan features are supported. 249 bool fSupportsMemorylessAttachments = false; 250 bool fSupportsYcbcrConversion = false; 251 bool fShouldAlwaysUseDedicatedImageMemory = false; 252 bool fGpuOnlyBuffersMorePerformant = false; 253 bool fShouldPersistentlyMapCpuToGpuBuffers = true; 254 bool fSupportsDeviceFaultInfo = false; 255 256 // Flags to enable workarounds for driver bugs 257 bool fMustLoadFullImageForMSAA = false; 258 }; 259 260 } // namespace skgpu::graphite 261 262 #endif // skgpu_graphite_VulkanCaps_DEFINED 263