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 struct ImageDesc { 176 VkImageType fImageType; 177 VkFormat fFormat; 178 uint32_t fWidth; 179 uint32_t fHeight; 180 uint32_t fLevels; 181 uint32_t fSamples; 182 VkImageTiling fImageTiling; 183 VkImageUsageFlags fUsageFlags; 184 VkFlags fMemProps; 185 GrProtected fIsProtected; 186 ImageDescImageDesc187 ImageDesc() 188 : fImageType(VK_IMAGE_TYPE_2D) 189 , fFormat(VK_FORMAT_UNDEFINED) 190 , fWidth(0) 191 , fHeight(0) 192 , fLevels(1) 193 , fSamples(1) 194 , fImageTiling(VK_IMAGE_TILING_OPTIMAL) 195 , fUsageFlags(0) 196 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) 197 , fIsProtected(GrProtected::kNo) {} 198 }; 199 200 static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*); 201 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo 202 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*); 203 204 // These match the definitions in SkImage, for whence they came 205 typedef void* ReleaseCtx; 206 typedef void (*ReleaseProc)(ReleaseCtx); 207 208 void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper); 209 210 // Helpers to use for setting the layout of the VkImage 211 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout); 212 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); 213 214 size_t onGpuMemorySize() const override; 215 #ifdef SKIA_DFX_FOR_RECORD_VKIMAGE 216 void dumpVkImageInfo(std::stringstream& dump) const override; getResourceType()217 const char* getResourceType() const override { return "VkImage"; } 218 #endif 219 #if GR_TEST_UTILS 220 void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu); 221 #endif 222 223 #ifdef SKIA_OHOS GetBudgeted()224 SkBudgeted GetBudgeted() const { return fBudgeted; } 225 #endif 226 227 private: 228 static sk_sp<GrVkImage> Make(GrVkGpu* gpu, 229 SkISize dimensions, 230 UsageFlags attachmentUsages, 231 int sampleCnt, 232 VkFormat format, 233 uint32_t mipLevels, 234 VkImageUsageFlags vkUsageFlags, 235 GrProtected isProtected, 236 GrMemoryless, 237 SkBudgeted); 238 239 GrVkImage(GrVkGpu* gpu, 240 SkISize dimensions, 241 UsageFlags supportedUsages, 242 const GrVkImageInfo&, 243 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, 244 sk_sp<const GrVkImageView> framebufferView, 245 sk_sp<const GrVkImageView> textureView, 246 SkBudgeted); 247 248 GrVkImage(GrVkGpu* gpu, 249 SkISize dimensions, 250 UsageFlags supportedUsages, 251 const GrVkImageInfo&, 252 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, 253 sk_sp<const GrVkImageView> framebufferView, 254 sk_sp<const GrVkImageView> textureView, 255 GrBackendObjectOwnership, 256 GrWrapCacheable, 257 bool forSecondaryCB); 258 259 void init(GrVkGpu*, bool forSecondaryCB); 260 261 void onRelease() override; 262 void onAbandon() override; 263 264 void releaseImage(); hasResource()265 bool hasResource() const { return fResource; } 266 267 GrVkGpu* getVkGpu() const; 268 269 GrVkImageInfo fInfo; 270 uint32_t fInitialQueueFamily; 271 sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState; 272 273 sk_sp<const GrVkImageView> fFramebufferView; 274 sk_sp<const GrVkImageView> fTextureView; 275 276 #ifdef SKIA_OHOS 277 SkBudgeted fBudgeted = SkBudgeted::kNo; 278 #endif 279 bool fIsBorrowed; 280 281 // Descriptor set used when this is used as an input attachment for reading the dst in blending. 282 gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet; 283 // Descriptor set used when this is used as an input attachment for loading an msaa attachment. 284 gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet; 285 286 class Resource : public GrTextureResource { 287 public: Resource(const GrVkGpu * gpu)288 explicit Resource(const GrVkGpu* gpu) 289 : fGpu(gpu) 290 , fImage(VK_NULL_HANDLE) { 291 fAlloc.fMemory = VK_NULL_HANDLE; 292 fAlloc.fOffset = 0; 293 } 294 Resource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)295 Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling) 296 : fGpu(gpu) 297 , fImage(image) 298 , fAlloc(alloc) {} 299 300 ~Resource() override; 301 302 #ifdef SK_TRACE_MANAGED_RESOURCES dumpInfo()303 void dumpInfo() const override { 304 SkDebugf("GrVkImage: %" PRIdPTR " (%d refs)\n", (intptr_t)fImage, this->getRefCnt()); 305 } 306 #endif 307 308 #ifdef SKIA_DFX_FOR_RECORD_VKIMAGE 309 ParallelDebug::VkImageInvokeRecord* fCaller = ParallelDebug::GenerateVkImageInvokeRecord(); 310 void dumpVkImageResource(std::stringstream& dump); 311 void RecordFreeVkImage(bool isBorrowed) const; 312 #endif 313 #ifdef SK_DEBUG asVkImageResource()314 const GrManagedResource* asVkImageResource() const override { return this; } 315 #endif 316 317 private: 318 void freeGPUData() const override; 319 320 const GrVkGpu* fGpu; 321 VkImage fImage; 322 GrVkAlloc fAlloc; 323 324 using INHERITED = GrTextureResource; 325 }; 326 327 // for wrapped textures 328 class BorrowedResource : public Resource { 329 public: BorrowedResource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)330 BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, 331 VkImageTiling tiling) 332 : Resource(gpu, image, alloc, tiling) { 333 } 334 private: 335 void freeGPUData() const override; 336 }; 337 338 Resource* fResource; 339 340 friend class GrVkRenderTarget; 341 }; 342 343 #endif 344