GrVkImage.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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. #ifndef GrVkImage_DEFINED
  8. #define GrVkImage_DEFINED
  9. #include "include/core/SkTypes.h"
  10. #include "include/gpu/GrBackendSurface.h"
  11. #include "include/gpu/GrTexture.h"
  12. #include "include/gpu/vk/GrVkTypes.h"
  13. #include "include/private/GrTypesPriv.h"
  14. #include "src/gpu/vk/GrVkImageLayout.h"
  15. #include "src/gpu/vk/GrVkResource.h"
  16. class GrVkGpu;
  17. class GrVkTexture;
  18. class GrVkImage : SkNoncopyable {
  19. private:
  20. class Resource;
  21. public:
  22. GrVkImage(const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout,
  23. GrBackendObjectOwnership ownership, bool forSecondaryCB = false)
  24. : fInfo(info)
  25. , fInitialQueueFamily(info.fCurrentQueueFamily)
  26. , fLayout(std::move(layout))
  27. , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
  28. SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout);
  29. if (forSecondaryCB) {
  30. fResource = nullptr;
  31. } else if (fIsBorrowed) {
  32. fResource = new BorrowedResource(info.fImage, info.fAlloc, info.fImageTiling);
  33. } else {
  34. SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
  35. fResource = new Resource(info.fImage, info.fAlloc, info.fImageTiling);
  36. }
  37. }
  38. virtual ~GrVkImage();
  39. VkImage image() const {
  40. // Should only be called when we have a real fResource object, i.e. never when being used as
  41. // a RT in an external secondary command buffer.
  42. SkASSERT(fResource);
  43. return fInfo.fImage;
  44. }
  45. const GrVkAlloc& alloc() 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.fAlloc;
  50. }
  51. VkFormat imageFormat() const { return fInfo.fFormat; }
  52. GrBackendFormat getBackendFormat() const {
  53. if (fResource && this->ycbcrConversionInfo().isValid()) {
  54. SkASSERT(this->imageFormat() == VK_FORMAT_UNDEFINED);
  55. return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
  56. }
  57. SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
  58. return GrBackendFormat::MakeVk(this->imageFormat());
  59. }
  60. uint32_t mipLevels() const { return fInfo.fLevelCount; }
  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. }
  67. const Resource* resource() const {
  68. SkASSERT(fResource);
  69. return fResource;
  70. }
  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. }
  77. bool isBorrowed() const { return fIsBorrowed; }
  78. sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
  79. VkImageLayout currentLayout() const {
  80. return fLayout->getImageLayout();
  81. }
  82. void setImageLayout(const GrVkGpu* gpu,
  83. VkImageLayout newLayout,
  84. VkAccessFlags dstAccessMask,
  85. VkPipelineStageFlags dstStageMask,
  86. bool byRegion,
  87. bool releaseFamilyQueue = false);
  88. // Returns the image to its original queue family and changes the layout to present if the queue
  89. // family is not external or foreign.
  90. void prepareForPresent(GrVkGpu* gpu);
  91. // Returns the image to its original queue family
  92. void prepareForExternal(GrVkGpu* gpu);
  93. // This simply updates our tracking of the image layout and does not actually do any gpu work.
  94. // This is only used for mip map generation where we are manually changing the layouts as we
  95. // blit each layer, and then at the end need to update our tracking.
  96. void updateImageLayout(VkImageLayout newLayout) {
  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. fLayout->setImageLayout(newLayout);
  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. GrProtected fIsProtected;
  113. 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. , fIsProtected(GrProtected::kNo) {}
  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. // These match the definitions in SkImage, for whence they came
  129. typedef void* ReleaseCtx;
  130. typedef void (*ReleaseProc)(ReleaseCtx);
  131. void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
  132. // Helpers to use for setting the layout of the VkImage
  133. static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
  134. static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
  135. #if GR_TEST_UTILS
  136. void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
  137. #endif
  138. protected:
  139. void releaseImage(GrVkGpu* gpu);
  140. void abandonImage();
  141. bool hasResource() const { return fResource; }
  142. GrVkImageInfo fInfo;
  143. uint32_t fInitialQueueFamily;
  144. sk_sp<GrVkImageLayout> fLayout;
  145. bool fIsBorrowed;
  146. private:
  147. class Resource : public GrVkResource {
  148. public:
  149. Resource()
  150. : fImage(VK_NULL_HANDLE) {
  151. fAlloc.fMemory = VK_NULL_HANDLE;
  152. fAlloc.fOffset = 0;
  153. }
  154. Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
  155. : fImage(image)
  156. , fAlloc(alloc)
  157. , fImageTiling(tiling) {}
  158. ~Resource() override {
  159. SkASSERT(!fReleaseHelper);
  160. }
  161. #ifdef SK_TRACE_VK_RESOURCES
  162. void dumpInfo() const override {
  163. SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
  164. }
  165. #endif
  166. void setRelease(sk_sp<GrRefCntedCallback> releaseHelper) {
  167. fReleaseHelper = std::move(releaseHelper);
  168. }
  169. /**
  170. * These are used to coordinate calling the "finished" idle procs between the GrVkTexture
  171. * and the Resource. If the GrVkTexture becomes purgeable and if there are no command
  172. * buffers referring to the Resource then it calls the procs. Otherwise, the Resource calls
  173. * them when the last command buffer reference goes away and the GrVkTexture is purgeable.
  174. */
  175. void addIdleProc(GrVkTexture*, sk_sp<GrRefCntedCallback>) const;
  176. int idleProcCnt() const;
  177. sk_sp<GrRefCntedCallback> idleProc(int) const;
  178. void resetIdleProcs() const;
  179. void removeOwningTexture() const;
  180. /**
  181. * We track how many outstanding references this Resource has in command buffers and
  182. * when the count reaches zero we call the idle proc.
  183. */
  184. void notifyAddedToCommandBuffer() const override;
  185. void notifyRemovedFromCommandBuffer() const override;
  186. bool isOwnedByCommandBuffer() const { return fNumCommandBufferOwners > 0; }
  187. protected:
  188. mutable sk_sp<GrRefCntedCallback> fReleaseHelper;
  189. void invokeReleaseProc() const {
  190. if (fReleaseHelper) {
  191. // Depending on the ref count of fReleaseHelper this may or may not actually trigger
  192. // the ReleaseProc to be called.
  193. fReleaseHelper.reset();
  194. }
  195. }
  196. private:
  197. void freeGPUData(GrVkGpu* gpu) const override;
  198. void abandonGPUData() const override {
  199. this->invokeReleaseProc();
  200. SkASSERT(!fReleaseHelper);
  201. }
  202. VkImage fImage;
  203. GrVkAlloc fAlloc;
  204. VkImageTiling fImageTiling;
  205. mutable int fNumCommandBufferOwners = 0;
  206. mutable SkTArray<sk_sp<GrRefCntedCallback>> fIdleProcs;
  207. mutable GrVkTexture* fOwningTexture = nullptr;
  208. typedef GrVkResource INHERITED;
  209. };
  210. // for wrapped textures
  211. class BorrowedResource : public Resource {
  212. public:
  213. BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
  214. : Resource(image, alloc, tiling) {
  215. }
  216. private:
  217. void freeGPUData(GrVkGpu* gpu) const override;
  218. void abandonGPUData() const override;
  219. };
  220. Resource* fResource;
  221. friend class GrVkRenderTarget;
  222. };
  223. #endif