1 /* 2 * Copyright 2015 Google Inc. 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 GrVkImage_DEFINED 9 #define GrVkImage_DEFINED 10 11 #include "include/core/SkTypes.h" 12 #include "include/gpu/GrBackendSurface.h" 13 #include "include/gpu/vk/GrVkTypes.h" 14 #include "include/private/gpu/ganesh/GrTypesPriv.h" 15 #include "include/private/gpu/ganesh/GrVkTypesPriv.h" 16 #include "src/gpu/MutableTextureStateRef.h" 17 #include "src/gpu/ganesh/GrAttachment.h" 18 #include "src/gpu/ganesh/GrManagedResource.h" 19 #include "src/gpu/ganesh/GrRefCnt.h" 20 #include "src/gpu/ganesh/GrTexture.h" 21 #include "src/gpu/ganesh/vk/GrVkDescriptorSet.h" 22 23 #include <cinttypes> 24 25 class GrVkGpu; 26 class GrVkImageView; 27 28 class GrVkImage : public GrAttachment { 29 private: 30 class Resource; 31 32 public: 33 static sk_sp<GrVkImage> MakeStencil(GrVkGpu* gpu, 34 SkISize dimensions, 35 int sampleCnt, 36 VkFormat format); 37 38 static sk_sp<GrVkImage> MakeMSAA(GrVkGpu* gpu, 39 SkISize dimensions, 40 int numSamples, 41 VkFormat format, 42 GrProtected isProtected, 43 GrMemoryless memoryless); 44 45 static sk_sp<GrVkImage> MakeTexture(GrVkGpu* gpu, 46 SkISize dimensions, 47 VkFormat format, 48 uint32_t mipLevels, 49 GrRenderable renderable, 50 int numSamples, 51 skgpu::Budgeted budgeted, 52 GrProtected isProtected); 53 54 static sk_sp<GrVkImage> MakeWrapped(GrVkGpu* gpu, 55 SkISize dimensions, 56 const GrVkImageInfo&, 57 sk_sp<skgpu::MutableTextureStateRef>, 58 UsageFlags attachmentUsages, 59 GrWrapOwnership, 60 GrWrapCacheable, 61 std::string_view label, 62 bool forSecondaryCB = false); 63 64 ~GrVkImage() override; 65 image()66 VkImage image() const { 67 // Should only be called when we have a real fResource object, i.e. never when being used as 68 // a RT in an external secondary command buffer. 69 SkASSERT(fResource); 70 return fInfo.fImage; 71 } alloc()72 const skgpu::VulkanAlloc& alloc() const { 73 // Should only be called when we have a real fResource object, i.e. never when being used as 74 // a RT in an external secondary command buffer. 75 SkASSERT(fResource); 76 return fInfo.fAlloc; 77 } vkImageInfo()78 const GrVkImageInfo& vkImageInfo() const { return fInfo; } imageFormat()79 VkFormat imageFormat() const { return fInfo.fFormat; } backendFormat()80 GrBackendFormat backendFormat() const override { 81 bool usesDRMModifier = 82 this->vkImageInfo().fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; 83 if (fResource && this->ycbcrConversionInfo().isValid()) { 84 SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat); 85 return GrBackendFormat::MakeVk(this->ycbcrConversionInfo(), usesDRMModifier); 86 } 87 SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED); 88 return GrBackendFormat::MakeVk(this->imageFormat(), usesDRMModifier); 89 } mipLevels()90 uint32_t mipLevels() const { return fInfo.fLevelCount; } ycbcrConversionInfo()91 const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const { 92 // Should only be called when we have a real fResource object, i.e. never when being used as 93 // a RT in an external secondary command buffer. 94 SkASSERT(fResource); 95 return fInfo.fYcbcrConversionInfo; 96 } vkUsageFlags()97 VkImageUsageFlags vkUsageFlags() { return fInfo.fImageUsageFlags; } supportsInputAttachmentUsage()98 bool supportsInputAttachmentUsage() const { 99 return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 100 } 101 framebufferView()102 const GrVkImageView* framebufferView() const { return fFramebufferView.get(); } textureView()103 const GrVkImageView* textureView() const { return fTextureView.get(); } 104 105 // So that we don't need to rewrite descriptor sets each time, we keep cached input descriptor 106 // sets on the attachment and simply reuse those descriptor sets for this attachment only. These 107 // calls will fail if the attachment does not support being used as an input attachment. These 108 // calls do not ref the GrVkDescriptorSet so they called will need to manually ref them if they 109 // need to be kept alive. 110 gr_rp<const GrVkDescriptorSet> inputDescSetForBlending(GrVkGpu* gpu); 111 // Input descripotr set used when needing to read a resolve attachment to load data into a 112 // discardable msaa attachment. 113 gr_rp<const GrVkDescriptorSet> inputDescSetForMSAALoad(GrVkGpu* gpu); 114 resource()115 const Resource* resource() const { 116 SkASSERT(fResource); 117 return fResource; 118 } isLinearTiled()119 bool isLinearTiled() const { 120 // Should only be called when we have a real fResource object, i.e. never when being used as 121 // a RT in an external secondary command buffer. 122 SkASSERT(fResource); 123 return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling); 124 } isBorrowed()125 bool isBorrowed() const { return fIsBorrowed; } 126 getMutableState()127 sk_sp<skgpu::MutableTextureStateRef> getMutableState() const { return fMutableState; } 128 currentLayout()129 VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); } 130 131 void setImageLayoutAndQueueIndex(const GrVkGpu* gpu, 132 VkImageLayout newLayout, 133 VkAccessFlags dstAccessMask, 134 VkPipelineStageFlags dstStageMask, 135 bool byRegion, 136 uint32_t newQueueFamilyIndex); 137 setImageLayout(const GrVkGpu * gpu,VkImageLayout newLayout,VkAccessFlags dstAccessMask,VkPipelineStageFlags dstStageMask,bool byRegion)138 void setImageLayout(const GrVkGpu* gpu, 139 VkImageLayout newLayout, 140 VkAccessFlags dstAccessMask, 141 VkPipelineStageFlags dstStageMask, 142 bool byRegion) { 143 this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion, 144 VK_QUEUE_FAMILY_IGNORED); 145 } 146 currentQueueFamilyIndex()147 uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); } 148 setQueueFamilyIndex(uint32_t queueFamilyIndex)149 void setQueueFamilyIndex(uint32_t queueFamilyIndex) { 150 fMutableState->setQueueFamilyIndex(queueFamilyIndex); 151 } 152 153 // Returns the image to its original queue family and changes the layout to present if the queue 154 // family is not external or foreign. 155 void prepareForPresent(GrVkGpu* gpu); 156 157 // Returns the image to its original queue family 158 void prepareForExternal(GrVkGpu* gpu); 159 160 // This simply updates our tracking of the image layout and does not actually do any gpu work. 161 // This is only used for mip map generation where we are manually changing the layouts as we 162 // blit each layer, and then at the end need to update our tracking. updateImageLayout(VkImageLayout newLayout)163 void updateImageLayout(VkImageLayout newLayout) { 164 // Should only be called when we have a real fResource object, i.e. never when being used as 165 // a RT in an external secondary command buffer. 166 SkASSERT(fResource); 167 fMutableState->setImageLayout(newLayout); 168 } 169 170 struct ImageDesc { 171 VkImageType fImageType; 172 VkFormat fFormat; 173 uint32_t fWidth; 174 uint32_t fHeight; 175 uint32_t fLevels; 176 uint32_t fSamples; 177 VkImageTiling fImageTiling; 178 VkImageUsageFlags fUsageFlags; 179 VkFlags fMemProps; 180 GrProtected fIsProtected; 181 ImageDescImageDesc182 ImageDesc() 183 : fImageType(VK_IMAGE_TYPE_2D) 184 , fFormat(VK_FORMAT_UNDEFINED) 185 , fWidth(0) 186 , fHeight(0) 187 , fLevels(1) 188 , fSamples(1) 189 , fImageTiling(VK_IMAGE_TILING_OPTIMAL) 190 , fUsageFlags(0) 191 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) 192 , fIsProtected(GrProtected::kNo) {} 193 }; 194 195 static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*); 196 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo 197 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*); 198 199 // These match the definitions in SkImage, for whence they came 200 typedef void* ReleaseCtx; 201 typedef void (*ReleaseProc)(ReleaseCtx); 202 203 void setResourceRelease(sk_sp<RefCntedReleaseProc> releaseHelper); 204 205 // Helpers to use for setting the layout of the VkImage 206 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout); 207 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); 208 209 #if GR_TEST_UTILS 210 void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu); 211 #endif 212 213 private: 214 static sk_sp<GrVkImage> Make(GrVkGpu* gpu, 215 SkISize dimensions, 216 UsageFlags attachmentUsages, 217 int sampleCnt, 218 VkFormat format, 219 uint32_t mipLevels, 220 VkImageUsageFlags vkUsageFlags, 221 GrProtected isProtected, 222 GrMemoryless, 223 skgpu::Budgeted); 224 225 GrVkImage(GrVkGpu* gpu, 226 SkISize dimensions, 227 UsageFlags supportedUsages, 228 const GrVkImageInfo&, 229 sk_sp<skgpu::MutableTextureStateRef> mutableState, 230 sk_sp<const GrVkImageView> framebufferView, 231 sk_sp<const GrVkImageView> textureView, 232 skgpu::Budgeted, 233 std::string_view label); 234 235 GrVkImage(GrVkGpu* gpu, 236 SkISize dimensions, 237 UsageFlags supportedUsages, 238 const GrVkImageInfo&, 239 sk_sp<skgpu::MutableTextureStateRef> mutableState, 240 sk_sp<const GrVkImageView> framebufferView, 241 sk_sp<const GrVkImageView> textureView, 242 GrBackendObjectOwnership, 243 GrWrapCacheable, 244 bool forSecondaryCB, 245 std::string_view label); 246 247 void init(GrVkGpu*, bool forSecondaryCB); 248 249 void onRelease() override; 250 void onAbandon() override; 251 252 void releaseImage(); hasResource()253 bool hasResource() const { return fResource; } 254 255 GrVkGpu* getVkGpu() const; 256 257 GrVkImageInfo fInfo; 258 uint32_t fInitialQueueFamily; 259 sk_sp<skgpu::MutableTextureStateRef> fMutableState; 260 261 sk_sp<const GrVkImageView> fFramebufferView; 262 sk_sp<const GrVkImageView> fTextureView; 263 264 bool fIsBorrowed; 265 266 // Descriptor set used when this is used as an input attachment for reading the dst in blending. 267 gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet; 268 // Descriptor set used when this is used as an input attachment for loading an msaa attachment. 269 gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet; 270 271 class Resource : public GrTextureResource { 272 public: Resource(const GrVkGpu * gpu)273 explicit Resource(const GrVkGpu* gpu) 274 : fGpu(gpu) 275 , fImage(VK_NULL_HANDLE) { 276 fAlloc.fMemory = VK_NULL_HANDLE; 277 fAlloc.fOffset = 0; 278 } 279 Resource(const GrVkGpu * gpu,VkImage image,const skgpu::VulkanAlloc & alloc,VkImageTiling tiling)280 Resource(const GrVkGpu* gpu, 281 VkImage image, 282 const skgpu::VulkanAlloc& alloc, 283 VkImageTiling tiling) 284 : fGpu(gpu) 285 , fImage(image) 286 , fAlloc(alloc) {} 287 ~Resource()288 ~Resource() override {} 289 290 #ifdef SK_TRACE_MANAGED_RESOURCES dumpInfo()291 void dumpInfo() const override { 292 SkDebugf("GrVkImage: %" PRIdPTR " (%d refs)\n", (intptr_t)fImage, this->getRefCnt()); 293 } 294 #endif 295 296 #ifdef SK_DEBUG asVkImageResource()297 const GrManagedResource* asVkImageResource() const override { return this; } 298 #endif 299 300 private: 301 void freeGPUData() const override; 302 303 const GrVkGpu* fGpu; 304 VkImage fImage; 305 skgpu::VulkanAlloc fAlloc; 306 307 using INHERITED = GrTextureResource; 308 }; 309 310 // for wrapped textures 311 class BorrowedResource : public Resource { 312 public: BorrowedResource(const GrVkGpu * gpu,VkImage image,const skgpu::VulkanAlloc & alloc,VkImageTiling tiling)313 BorrowedResource(const GrVkGpu* gpu, VkImage image, const skgpu::VulkanAlloc& alloc, 314 VkImageTiling tiling) 315 : Resource(gpu, image, alloc, tiling) { 316 } 317 private: 318 void freeGPUData() const override; 319 }; 320 321 Resource* fResource; 322 323 friend class GrVkRenderTarget; 324 }; 325 326 #endif 327