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 19 class VulkanCaps final : public Caps { 20 public: 21 VulkanCaps(const skgpu::VulkanInterface*, 22 VkPhysicalDevice device, 23 uint32_t physicalDeviceVersion, 24 const skgpu::VulkanExtensions*, 25 const ContextOptions&); 26 ~VulkanCaps() override; 27 28 TextureInfo getDefaultSampledTextureInfo(SkColorType, 29 Mipmapped mipmapped, 30 Protected, 31 Renderable) const override; 32 33 TextureInfo getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo, 34 Discardable discardable) const override; 35 36 TextureInfo getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags>, 37 uint32_t sampleCount, 38 Protected) const override; 39 makeGraphicsPipelineKey(const GraphicsPipelineDesc &,const RenderPassDesc &)40 UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc&, 41 const RenderPassDesc&) const override { return {}; } makeComputePipelineKey(const ComputePipelineDesc &)42 UniqueKey makeComputePipelineKey(const ComputePipelineDesc&) const override { return {}; } 43 isRenderable(const TextureInfo &)44 bool isRenderable(const TextureInfo&) const override { return false; } 45 buildKeyForTexture(SkISize dimensions,const TextureInfo &,ResourceType,Shareable,GraphiteResourceKey *)46 void buildKeyForTexture(SkISize dimensions, 47 const TextureInfo&, 48 ResourceType, 49 Shareable, 50 GraphiteResourceKey*) const override {} 51 shouldAlwaysUseDedicatedImageMemory()52 bool shouldAlwaysUseDedicatedImageMemory() const { 53 return fShouldAlwaysUseDedicatedImageMemory; 54 } 55 56 // Returns whether a pure GPU accessible buffer is more performant to read than a buffer that is 57 // also host visible. If so then in some cases we may prefer the cost of doing a copy to the 58 // buffer. This typically would only be the case for buffers that are written once and read 59 // many times on the gpu. gpuOnlyBuffersMorePerformant()60 bool gpuOnlyBuffersMorePerformant() const { return fGpuOnlyBuffersMorePerformant; } 61 62 // For our CPU write and GPU read buffers (vertex, uniform, etc.), we should keep these buffers 63 // persistently mapped. In general, the answer will be yes. The main case where we don't do this 64 // is when using special memory that is DEVICE_LOCAL and HOST_VISIBLE on discrete GPUs. shouldPersistentlyMapCpuToGpuBuffers()65 bool shouldPersistentlyMapCpuToGpuBuffers() const { 66 return fShouldPersistentlyMapCpuToGpuBuffers; 67 } 68 69 private: 70 enum VkVendor { 71 kAMD_VkVendor = 4098, 72 kARM_VkVendor = 5045, 73 kImagination_VkVendor = 4112, 74 kIntel_VkVendor = 32902, 75 kNvidia_VkVendor = 4318, 76 kQualcomm_VkVendor = 20803, 77 }; 78 79 void init(const skgpu::VulkanInterface*, 80 VkPhysicalDevice, 81 uint32_t physicalDeviceVersion, 82 const skgpu::VulkanExtensions*, 83 const ContextOptions&); 84 85 void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&); 86 87 void initFormatTable(const skgpu::VulkanInterface*, 88 VkPhysicalDevice, 89 const VkPhysicalDeviceProperties&); 90 91 void initDepthStencilFormatTable(const skgpu::VulkanInterface*, 92 VkPhysicalDevice, 93 const VkPhysicalDeviceProperties&); 94 getColorTypeInfo(SkColorType,const TextureInfo &)95 const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const override { 96 return nullptr; 97 } 98 onIsTexturable(const TextureInfo &)99 bool onIsTexturable(const TextureInfo&) const override { return false; } 100 supportsWritePixels(const TextureInfo &)101 bool supportsWritePixels(const TextureInfo&) const override { return false; } supportsReadPixels(const TextureInfo &)102 bool supportsReadPixels(const TextureInfo&) const override { return false; } 103 supportedWritePixelsColorType(SkColorType dstColorType,const TextureInfo & dstTextureInfo,SkColorType srcColorType)104 SkColorType supportedWritePixelsColorType(SkColorType dstColorType, 105 const TextureInfo& dstTextureInfo, 106 SkColorType srcColorType) const override { 107 return kUnknown_SkColorType; 108 } supportedReadPixelsColorType(SkColorType srcColorType,const TextureInfo & srcTextureInfo,SkColorType dstColorType)109 SkColorType supportedReadPixelsColorType(SkColorType srcColorType, 110 const TextureInfo& srcTextureInfo, 111 SkColorType dstColorType) const override { 112 return kUnknown_SkColorType; 113 } 114 // Struct that determines and stores which sample count quantities a VkFormat supports. 115 struct SupportedSampleCounts { 116 void initSampleCounts(const skgpu::VulkanInterface*, 117 VkPhysicalDevice, 118 const VkPhysicalDeviceProperties&, 119 VkFormat, 120 VkImageUsageFlags); 121 122 bool isSampleCountSupported(int requestedCount) const; 123 124 SkTDArray<int> fSampleCounts; 125 }; 126 127 // Struct that determines and stores useful information about VkFormats. 128 struct FormatInfo { colorTypeFlagsFormatInfo129 uint32_t colorTypeFlags(SkColorType colorType) const { 130 for (int i = 0; i < fColorTypeInfoCount; ++i) { 131 if (fColorTypeInfos[i].fColorType == colorType) { 132 return fColorTypeInfos[i].fFlags; 133 } 134 } 135 return 0; 136 } 137 138 void init(const skgpu::VulkanInterface*, 139 VkPhysicalDevice, 140 const VkPhysicalDeviceProperties&, 141 VkFormat); 142 143 144 bool isTexturable(VkImageTiling) const; 145 bool isRenderable(VkImageTiling, uint32_t sampleCount) const; 146 147 std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos; 148 int fColorTypeInfoCount = 0; 149 150 VkFormatProperties fFormatProperties; 151 SupportedSampleCounts fSupportedSampleCounts; 152 153 // Indicates that a format is only supported if we are wrapping a texture with it. 154 SkDEBUGCODE(bool fIsWrappedOnly;) 155 156 private: 157 bool isTexturable(VkFormatFeatureFlags) const; 158 bool isRenderable(VkFormatFeatureFlags) const; 159 }; 160 161 // Map SkColorType to VkFormat. 162 VkFormat fColorTypeToFormatTable[kSkColorTypeCnt]; 163 void setColorType(SkColorType, std::initializer_list<VkFormat> formats); 164 VkFormat getFormatFromColorType(SkColorType) const; 165 166 // Map VkFormat to FormatInfo. 167 static const size_t kNumVkFormats = 22; 168 FormatInfo fFormatTable[kNumVkFormats]; 169 170 FormatInfo& getFormatInfo(VkFormat); 171 const FormatInfo& getFormatInfo(VkFormat) const; 172 173 // A more lightweight equivalent to FormatInfo for depth/stencil VkFormats. 174 struct DepthStencilFormatInfo { 175 void init(const skgpu::VulkanInterface*, 176 VkPhysicalDevice, 177 const VkPhysicalDeviceProperties&, 178 VkFormat); 179 bool isDepthStencilSupported(VkFormatFeatureFlags) const; 180 181 VkFormatProperties fFormatProperties; 182 SupportedSampleCounts fSupportedSampleCounts; 183 }; 184 185 // Map DepthStencilFlags to VkFormat. 186 static const size_t kNumDepthStencilFlags = 4; 187 VkFormat fDepthStencilFlagsToFormatTable[kNumDepthStencilFlags]; 188 VkFormat getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags>& flags) const; 189 190 // Map depth/stencil VkFormats to DepthStencilFormatInfo. 191 static const size_t kNumDepthStencilVkFormats = 3; 192 DepthStencilFormatInfo fDepthStencilFormatTable[kNumDepthStencilVkFormats]; 193 194 DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat); 195 const DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat) const; 196 197 // Various bools to define whether certain Vulkan features are supported. 198 bool fSupportsMemorylessAttachments = false; 199 bool fSupportsYcbcrConversion = false; // TODO: Determine & assign real value. 200 bool fShouldAlwaysUseDedicatedImageMemory = false; 201 bool fGpuOnlyBuffersMorePerformant = false; 202 bool fShouldPersistentlyMapCpuToGpuBuffers = true; 203 }; 204 205 } // namespace skgpu::graphite 206 207 #endif // skgpu_graphite_VulkanCaps_DEFINED 208