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