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