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 "src/gpu/GrManagedResource.h" 16 #include "src/gpu/GrTexture.h" 17 #include "src/gpu/vk/GrVkImageLayout.h" 18 19 class GrVkGpu; 20 class GrVkTexture; 21 22 class GrVkImage : SkNoncopyable { 23 private: 24 class Resource; 25 26 public: 27 GrVkImage(const GrVkGpu* gpu, 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(gpu, info.fImage, info.fAlloc, info.fImageTiling); 38 } else { 39 SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory); 40 fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling); 41 } 42 } 43 virtual ~GrVkImage(); 44 image()45 VkImage image() const { 46 // Should only be called when we have a real fResource object, i.e. never when being used as 47 // a RT in an external secondary command buffer. 48 SkASSERT(fResource); 49 return fInfo.fImage; 50 } alloc()51 const GrVkAlloc& alloc() const { 52 // Should only be called when we have a real fResource object, i.e. never when being used as 53 // a RT in an external secondary command buffer. 54 SkASSERT(fResource); 55 return fInfo.fAlloc; 56 } imageFormat()57 VkFormat imageFormat() const { return fInfo.fFormat; } getBackendFormat()58 GrBackendFormat getBackendFormat() const { 59 if (fResource && this->ycbcrConversionInfo().isValid()) { 60 SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat); 61 return GrBackendFormat::MakeVk(this->ycbcrConversionInfo()); 62 } 63 SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED); 64 return GrBackendFormat::MakeVk(this->imageFormat()); 65 } mipLevels()66 uint32_t mipLevels() const { return fInfo.fLevelCount; } ycbcrConversionInfo()67 const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const { 68 // Should only be called when we have a real fResource object, i.e. never when being used as 69 // a RT in an external secondary command buffer. 70 SkASSERT(fResource); 71 return fInfo.fYcbcrConversionInfo; 72 } resource()73 const Resource* resource() const { 74 SkASSERT(fResource); 75 return fResource; 76 } isLinearTiled()77 bool isLinearTiled() 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 SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling); 82 } isBorrowed()83 bool isBorrowed() const { return fIsBorrowed; } 84 grVkImageLayout()85 sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; } 86 currentLayout()87 VkImageLayout currentLayout() const { 88 return fLayout->getImageLayout(); 89 } 90 91 void setImageLayout(const GrVkGpu* gpu, 92 VkImageLayout newLayout, 93 VkAccessFlags dstAccessMask, 94 VkPipelineStageFlags dstStageMask, 95 bool byRegion, 96 bool releaseFamilyQueue = false); 97 98 // Returns the image to its original queue family and changes the layout to present if the queue 99 // family is not external or foreign. 100 void prepareForPresent(GrVkGpu* gpu); 101 102 // Returns the image to its original queue family 103 void prepareForExternal(GrVkGpu* gpu); 104 105 // This simply updates our tracking of the image layout and does not actually do any gpu work. 106 // This is only used for mip map generation where we are manually changing the layouts as we 107 // blit each layer, and then at the end need to update our tracking. updateImageLayout(VkImageLayout newLayout)108 void updateImageLayout(VkImageLayout newLayout) { 109 // Should only be called when we have a real fResource object, i.e. never when being used as 110 // a RT in an external secondary command buffer. 111 SkASSERT(fResource); 112 fLayout->setImageLayout(newLayout); 113 } 114 115 struct ImageDesc { 116 VkImageType fImageType; 117 VkFormat fFormat; 118 uint32_t fWidth; 119 uint32_t fHeight; 120 uint32_t fLevels; 121 uint32_t fSamples; 122 VkImageTiling fImageTiling; 123 VkImageUsageFlags fUsageFlags; 124 VkFlags fMemProps; 125 GrProtected fIsProtected; 126 ImageDescImageDesc127 ImageDesc() 128 : fImageType(VK_IMAGE_TYPE_2D) 129 , fFormat(VK_FORMAT_UNDEFINED) 130 , fWidth(0) 131 , fHeight(0) 132 , fLevels(1) 133 , fSamples(1) 134 , fImageTiling(VK_IMAGE_TILING_OPTIMAL) 135 , fUsageFlags(0) 136 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) 137 , fIsProtected(GrProtected::kNo) {} 138 }; 139 140 static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*); 141 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo 142 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*); 143 144 // These match the definitions in SkImage, for whence they came 145 typedef void* ReleaseCtx; 146 typedef void (*ReleaseProc)(ReleaseCtx); 147 148 void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper); 149 150 // Helpers to use for setting the layout of the VkImage 151 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout); 152 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); 153 154 #if GR_TEST_UTILS 155 void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu); 156 #endif 157 158 protected: 159 void releaseImage(GrVkGpu* gpu); hasResource()160 bool hasResource() const { return fResource; } 161 162 GrVkImageInfo fInfo; 163 uint32_t fInitialQueueFamily; 164 sk_sp<GrVkImageLayout> fLayout; 165 bool fIsBorrowed; 166 167 private: 168 class Resource : public GrTextureResource { 169 public: Resource(const GrVkGpu * gpu)170 explicit Resource(const GrVkGpu* gpu) 171 : fGpu(gpu) 172 , fImage(VK_NULL_HANDLE) { 173 fAlloc.fMemory = VK_NULL_HANDLE; 174 fAlloc.fOffset = 0; 175 } 176 Resource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)177 Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling) 178 : fGpu(gpu) 179 , fImage(image) 180 , fAlloc(alloc) 181 , fImageTiling(tiling) {} 182 ~Resource()183 ~Resource() override {} 184 185 #ifdef SK_TRACE_MANAGED_RESOURCES dumpInfo()186 void dumpInfo() const override { 187 SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt()); 188 } 189 #endif 190 191 private: 192 void freeGPUData() const override; 193 194 const GrVkGpu* fGpu; 195 VkImage fImage; 196 GrVkAlloc fAlloc; 197 VkImageTiling fImageTiling; 198 199 typedef GrTextureResource INHERITED; 200 }; 201 202 // for wrapped textures 203 class BorrowedResource : public Resource { 204 public: BorrowedResource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)205 BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, 206 VkImageTiling tiling) 207 : Resource(gpu, image, alloc, tiling) { 208 } 209 private: 210 void freeGPUData() const override; 211 }; 212 213 Resource* fResource; 214 215 friend class GrVkRenderTarget; 216 }; 217 218 #endif 219