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 "GrBackendSurface.h" 12 #include "GrTexture.h" 13 #include "GrTypesPriv.h" 14 #include "GrVkImageLayout.h" 15 #include "GrVkResource.h" 16 #include "SkTypes.h" 17 #include "vk/GrVkTypes.h" 18 19 class GrVkGpu; 20 class GrVkTexture; 21 22 class GrVkImage : SkNoncopyable { 23 private: 24 class Resource; 25 26 public: 27 GrVkImage(const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout, 28 GrBackendObjectOwnership ownership, bool forSecondaryCB = false) fInfo(info)29 : fInfo(info) 30 , fInitialQueueFamily(info.fCurrentQueueFamily) 31 , fLayout(std::move(layout)) 32 , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) { 33 SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout); 34 if (forSecondaryCB) { 35 fResource = nullptr; 36 } else if (fIsBorrowed) { 37 fResource = new BorrowedResource(info.fImage, info.fAlloc, info.fImageTiling); 38 } else { 39 fResource = new Resource(info.fImage, info.fAlloc, info.fImageTiling); 40 } 41 } 42 virtual ~GrVkImage(); 43 image()44 VkImage image() const { 45 // Should only be called when we have a real fResource object, i.e. never when being used as 46 // a RT in an external secondary command buffer. 47 SkASSERT(fResource); 48 return fInfo.fImage; 49 } alloc()50 const GrVkAlloc& alloc() const { 51 // Should only be called when we have a real fResource object, i.e. never when being used as 52 // a RT in an external secondary command buffer. 53 SkASSERT(fResource); 54 return fInfo.fAlloc; 55 } imageFormat()56 VkFormat imageFormat() const { return fInfo.fFormat; } getBackendFormat()57 GrBackendFormat getBackendFormat() const { 58 return GrBackendFormat::MakeVk(this->imageFormat()); 59 } mipLevels()60 uint32_t mipLevels() const { return fInfo.fLevelCount; } ycbcrConversionInfo()61 const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const { 62 // Should only be called when we have a real fResource object, i.e. never when being used as 63 // a RT in an external secondary command buffer. 64 SkASSERT(fResource); 65 return fInfo.fYcbcrConversionInfo; 66 } resource()67 const Resource* resource() const { 68 SkASSERT(fResource); 69 return fResource; 70 } isLinearTiled()71 bool isLinearTiled() 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 SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling); 76 } isBorrowed()77 bool isBorrowed() const { return fIsBorrowed; } 78 grVkImageLayout()79 sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; } 80 currentLayout()81 VkImageLayout currentLayout() const { 82 return fLayout->getImageLayout(); 83 } 84 85 void setImageLayout(const GrVkGpu* gpu, 86 VkImageLayout newLayout, 87 VkAccessFlags dstAccessMask, 88 VkPipelineStageFlags dstStageMask, 89 bool byRegion, 90 bool releaseFamilyQueue = false); 91 92 // This simply updates our tracking of the image layout and does not actually do any gpu work. 93 // This is only used for mip map generation where we are manually changing the layouts as we 94 // blit each layer, and then at the end need to update our tracking. updateImageLayout(VkImageLayout newLayout)95 void updateImageLayout(VkImageLayout newLayout) { 96 // Should only be called when we have a real fResource object, i.e. never when being used as 97 // a RT in an external secondary command buffer. 98 SkASSERT(fResource); 99 fLayout->setImageLayout(newLayout); 100 } 101 102 struct ImageDesc { 103 VkImageType fImageType; 104 VkFormat fFormat; 105 uint32_t fWidth; 106 uint32_t fHeight; 107 uint32_t fLevels; 108 uint32_t fSamples; 109 VkImageTiling fImageTiling; 110 VkImageUsageFlags fUsageFlags; 111 VkFlags fMemProps; 112 ImageDescImageDesc113 ImageDesc() 114 : fImageType(VK_IMAGE_TYPE_2D) 115 , fFormat(VK_FORMAT_UNDEFINED) 116 , fWidth(0) 117 , fHeight(0) 118 , fLevels(1) 119 , fSamples(1) 120 , fImageTiling(VK_IMAGE_TILING_OPTIMAL) 121 , fUsageFlags(0) 122 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {} 123 }; 124 125 static bool InitImageInfo(const GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*); 126 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo 127 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*); 128 129 // These match the definitions in SkImage, for whence they came 130 typedef void* ReleaseCtx; 131 typedef void (*ReleaseProc)(ReleaseCtx); 132 133 void setResourceRelease(sk_sp<GrReleaseProcHelper> releaseHelper); 134 135 // Helpers to use for setting the layout of the VkImage 136 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout); 137 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); 138 139 protected: 140 void releaseImage(GrVkGpu* gpu); 141 void abandonImage(); hasResource()142 bool hasResource() const { return fResource; } 143 144 GrVkImageInfo fInfo; 145 uint32_t fInitialQueueFamily; 146 sk_sp<GrVkImageLayout> fLayout; 147 bool fIsBorrowed; 148 149 private: 150 class Resource : public GrVkResource { 151 public: Resource()152 Resource() 153 : fImage(VK_NULL_HANDLE) { 154 fAlloc.fMemory = VK_NULL_HANDLE; 155 fAlloc.fOffset = 0; 156 } 157 Resource(VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)158 Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling) 159 : fImage(image) 160 , fAlloc(alloc) 161 , fImageTiling(tiling) {} 162 ~Resource()163 ~Resource() override { 164 SkASSERT(!fReleaseHelper); 165 } 166 167 #ifdef SK_TRACE_VK_RESOURCES dumpInfo()168 void dumpInfo() const override { 169 SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt()); 170 } 171 #endif setRelease(sk_sp<GrReleaseProcHelper> releaseHelper)172 void setRelease(sk_sp<GrReleaseProcHelper> releaseHelper) { 173 fReleaseHelper = std::move(releaseHelper); 174 } 175 176 /** 177 * These are used to coordinate calling the idle proc between the GrVkTexture and the 178 * Resource. If the GrVkTexture becomes purgeable and if there are no command buffers 179 * referring to the Resource then it calls the proc. Otherwise, the Resource calls it 180 * when the last command buffer reference goes away and the GrVkTexture is purgeable. 181 */ 182 void setIdleProc(GrVkTexture* owner, GrTexture::IdleProc, void* context) const; 183 void removeOwningTexture() const; 184 185 /** 186 * We track how many outstanding references this Resource has in command buffers and 187 * when the count reaches zero we call the idle proc. 188 */ 189 void notifyAddedToCommandBuffer() const override; 190 void notifyRemovedFromCommandBuffer() const override; isOwnedByCommandBuffer()191 bool isOwnedByCommandBuffer() const { return fNumCommandBufferOwners > 0; } 192 193 protected: 194 mutable sk_sp<GrReleaseProcHelper> fReleaseHelper; 195 196 private: 197 void freeGPUData(GrVkGpu* gpu) const override; abandonGPUData()198 void abandonGPUData() const override { 199 SkASSERT(!fReleaseHelper); 200 } 201 202 VkImage fImage; 203 GrVkAlloc fAlloc; 204 VkImageTiling fImageTiling; 205 mutable int fNumCommandBufferOwners = 0; 206 mutable GrTexture::IdleProc* fIdleProc = nullptr; 207 mutable void* fIdleProcContext = nullptr; 208 mutable GrVkTexture* fOwningTexture = nullptr; 209 210 typedef GrVkResource INHERITED; 211 }; 212 213 // for wrapped textures 214 class BorrowedResource : public Resource { 215 public: BorrowedResource(VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)216 BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling) 217 : Resource(image, alloc, tiling) { 218 } 219 private: invokeReleaseProc()220 void invokeReleaseProc() const { 221 if (fReleaseHelper) { 222 // Depending on the ref count of fReleaseHelper this may or may not actually trigger 223 // the ReleaseProc to be called. 224 fReleaseHelper.reset(); 225 } 226 } 227 228 void freeGPUData(GrVkGpu* gpu) const override; 229 void abandonGPUData() const override; 230 }; 231 232 Resource* fResource; 233 234 friend class GrVkRenderTarget; 235 }; 236 237 #endif 238