GrVkTexture.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. #include "src/gpu/vk/GrVkTexture.h"
  8. #include "src/gpu/GrTexturePriv.h"
  9. #include "src/gpu/vk/GrVkGpu.h"
  10. #include "src/gpu/vk/GrVkImageView.h"
  11. #include "src/gpu/vk/GrVkTextureRenderTarget.h"
  12. #include "src/gpu/vk/GrVkUtil.h"
  13. #include "include/gpu/vk/GrVkTypes.h"
  14. #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
  15. // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
  16. GrVkTexture::GrVkTexture(GrVkGpu* gpu,
  17. SkBudgeted budgeted,
  18. const GrSurfaceDesc& desc,
  19. const GrVkImageInfo& info,
  20. sk_sp<GrVkImageLayout> layout,
  21. const GrVkImageView* view,
  22. GrMipMapsStatus mipMapsStatus)
  23. : GrSurface(gpu, desc, info.fProtected)
  24. , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kOwned)
  25. , INHERITED(gpu, desc, info.fProtected, GrTextureType::k2D, mipMapsStatus)
  26. , fTextureView(view) {
  27. SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
  28. this->registerWithCache(budgeted);
  29. if (GrPixelConfigIsCompressed(desc.fConfig)) {
  30. this->setReadOnly();
  31. }
  32. }
  33. GrVkTexture::GrVkTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info,
  34. sk_sp<GrVkImageLayout> layout, const GrVkImageView* view,
  35. GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership,
  36. GrWrapCacheable cacheable, GrIOType ioType)
  37. : GrSurface(gpu, desc, info.fProtected)
  38. , GrVkImage(info, std::move(layout), ownership)
  39. , INHERITED(gpu, desc, info.fProtected, GrTextureType::k2D, mipMapsStatus)
  40. , fTextureView(view) {
  41. SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
  42. if (ioType == kRead_GrIOType) {
  43. this->setReadOnly();
  44. }
  45. this->registerWithCacheWrapped(cacheable);
  46. }
  47. // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
  48. GrVkTexture::GrVkTexture(GrVkGpu* gpu,
  49. const GrSurfaceDesc& desc,
  50. const GrVkImageInfo& info,
  51. sk_sp<GrVkImageLayout> layout,
  52. const GrVkImageView* view,
  53. GrMipMapsStatus mipMapsStatus,
  54. GrBackendObjectOwnership ownership)
  55. : GrSurface(gpu, desc, info.fProtected)
  56. , GrVkImage(info, layout, ownership)
  57. , INHERITED(gpu, desc, info.fProtected, GrTextureType::k2D, mipMapsStatus)
  58. , fTextureView(view) {
  59. SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
  60. }
  61. sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
  62. const GrSurfaceDesc& desc,
  63. const GrVkImage::ImageDesc& imageDesc,
  64. GrMipMapsStatus mipMapsStatus) {
  65. SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
  66. GrVkImageInfo info;
  67. if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
  68. return nullptr;
  69. }
  70. const GrVkImageView* imageView = GrVkImageView::Create(
  71. gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount,
  72. info.fYcbcrConversionInfo);
  73. if (!imageView) {
  74. GrVkImage::DestroyImageInfo(gpu, &info);
  75. return nullptr;
  76. }
  77. sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
  78. return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, std::move(layout),
  79. imageView, mipMapsStatus));
  80. }
  81. sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
  82. const GrSurfaceDesc& desc,
  83. GrWrapOwnership wrapOwnership,
  84. GrWrapCacheable cacheable,
  85. GrIOType ioType,
  86. const GrVkImageInfo& info,
  87. sk_sp<GrVkImageLayout> layout) {
  88. // Adopted textures require both image and allocation because we're responsible for freeing
  89. SkASSERT(VK_NULL_HANDLE != info.fImage &&
  90. (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
  91. const GrVkImageView* imageView = GrVkImageView::Create(
  92. gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount,
  93. info.fYcbcrConversionInfo);
  94. if (!imageView) {
  95. return nullptr;
  96. }
  97. GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid
  98. : GrMipMapsStatus::kNotAllocated;
  99. GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
  100. ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
  101. return sk_sp<GrVkTexture>(new GrVkTexture(gpu, desc, info, std::move(layout), imageView,
  102. mipMapsStatus, ownership, cacheable, ioType));
  103. }
  104. GrVkTexture::~GrVkTexture() {
  105. // either release or abandon should have been called by the owner of this object.
  106. SkASSERT(!fTextureView);
  107. }
  108. void GrVkTexture::onRelease() {
  109. // We're about to be severed from our GrVkResource. If there are "finish" idle procs we have to
  110. // decide who will handle them. If the resource is still tied to a command buffer we let it
  111. // handle them. Otherwise, we handle them.
  112. if (this->hasResource() && this->resource()->isOwnedByCommandBuffer()) {
  113. this->removeFinishIdleProcs();
  114. }
  115. // we create this and don't hand it off, so we should always destroy it
  116. if (fTextureView) {
  117. fTextureView->unref(this->getVkGpu());
  118. fTextureView = nullptr;
  119. }
  120. this->releaseImage(this->getVkGpu());
  121. INHERITED::onRelease();
  122. }
  123. void GrVkTexture::onAbandon() {
  124. // We're about to be severed from our GrVkResource. If there are "finish" idle procs we have to
  125. // decide who will handle them. If the resource is still tied to a command buffer we let it
  126. // handle them. Otherwise, we handle them.
  127. if (this->hasResource() && this->resource()->isOwnedByCommandBuffer()) {
  128. this->removeFinishIdleProcs();
  129. }
  130. // we create this and don't hand it off, so we should always destroy it
  131. if (fTextureView) {
  132. fTextureView->unrefAndAbandon();
  133. fTextureView = nullptr;
  134. }
  135. this->abandonImage();
  136. INHERITED::onAbandon();
  137. }
  138. GrBackendTexture GrVkTexture::getBackendTexture() const {
  139. return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout());
  140. }
  141. GrVkGpu* GrVkTexture::getVkGpu() const {
  142. SkASSERT(!this->wasDestroyed());
  143. return static_cast<GrVkGpu*>(this->getGpu());
  144. }
  145. const GrVkImageView* GrVkTexture::textureView() {
  146. return fTextureView;
  147. }
  148. void GrVkTexture::addIdleProc(sk_sp<GrRefCntedCallback> idleProc, IdleState type) {
  149. INHERITED::addIdleProc(idleProc, type);
  150. if (type == IdleState::kFinished) {
  151. if (auto* resource = this->resource()) {
  152. resource->addIdleProc(this, std::move(idleProc));
  153. }
  154. }
  155. }
  156. void GrVkTexture::callIdleProcsOnBehalfOfResource() {
  157. // If we got here then the resource is being removed from its last command buffer and the
  158. // texture is idle in the cache. Any kFlush idle procs should already have been called. So
  159. // the texture and resource should have the same set of procs.
  160. SkASSERT(this->resource());
  161. SkASSERT(this->resource()->idleProcCnt() == fIdleProcs.count());
  162. #ifdef SK_DEBUG
  163. for (int i = 0; i < fIdleProcs.count(); ++i) {
  164. SkASSERT(fIdleProcs[i] == this->resource()->idleProc(i));
  165. }
  166. #endif
  167. fIdleProcs.reset();
  168. this->resource()->resetIdleProcs();
  169. }
  170. void GrVkTexture::willRemoveLastRefOrPendingIO() {
  171. if (!fIdleProcs.count()) {
  172. return;
  173. }
  174. // This is called when the GrTexture is purgeable. However, we need to check whether the
  175. // Resource is still owned by any command buffers. If it is then it will call the proc.
  176. auto* resource = this->hasResource() ? this->resource() : nullptr;
  177. bool callFinishProcs = !resource || !resource->isOwnedByCommandBuffer();
  178. if (callFinishProcs) {
  179. // Everything must go!
  180. fIdleProcs.reset();
  181. resource->resetIdleProcs();
  182. } else {
  183. // The procs that should be called on flush but not finish are those that are owned
  184. // by the GrVkTexture and not the Resource. We do this by copying the resource's array
  185. // and thereby dropping refs to procs we own but the resource does not.
  186. SkASSERT(resource);
  187. fIdleProcs.reset(resource->idleProcCnt());
  188. for (int i = 0; i < fIdleProcs.count(); ++i) {
  189. fIdleProcs[i] = resource->idleProc(i);
  190. }
  191. }
  192. }
  193. void GrVkTexture::removeFinishIdleProcs() {
  194. // This should only be called by onRelease/onAbandon when we have already checked for a
  195. // resource.
  196. const auto* resource = this->resource();
  197. SkASSERT(resource);
  198. SkSTArray<4, sk_sp<GrRefCntedCallback>> procsToKeep;
  199. int resourceIdx = 0;
  200. // The idle procs that are common between the GrVkTexture and its Resource should be found in
  201. // the same order.
  202. for (int i = 0; i < fIdleProcs.count(); ++i) {
  203. if (fIdleProcs[i] == resource->idleProc(resourceIdx)) {
  204. ++resourceIdx;
  205. } else {
  206. procsToKeep.push_back(fIdleProcs[i]);
  207. }
  208. }
  209. SkASSERT(resourceIdx == resource->idleProcCnt());
  210. fIdleProcs = procsToKeep;
  211. }