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