blob: a43c59620baacdfb5bab37dca9350bf2efaab6ad [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
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
Greg Daniel4065d452018-11-16 15:43:41 -050011#include "GrBackendSurface.h"
Brian Salomon614c1a82018-12-19 15:42:06 -050012#include "GrTexture.h"
jvanverth900bd4a2016-04-29 13:53:12 -070013#include "GrTypesPriv.h"
Greg Daniel52e16d92018-04-10 09:34:07 -040014#include "GrVkImageLayout.h"
Brian Salomon614c1a82018-12-19 15:42:06 -050015#include "GrVkResource.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050016#include "SkTypes.h"
egdanielb2df0c22016-05-13 11:30:37 -070017#include "vk/GrVkTypes.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050018
19class GrVkGpu;
Brian Salomon614c1a82018-12-19 15:42:06 -050020class GrVkTexture;
Greg Daniel164a9f02016-02-22 09:56:40 -050021
22class GrVkImage : SkNoncopyable {
egdanielb2df0c22016-05-13 11:30:37 -070023private:
24 class Resource;
25
Greg Daniel164a9f02016-02-22 09:56:40 -050026public:
Greg Daniel52e16d92018-04-10 09:34:07 -040027 GrVkImage(const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout,
Greg Danielb46add82019-01-02 14:51:29 -050028 GrBackendObjectOwnership ownership, bool forSecondaryCB = false)
Greg Daniel52e16d92018-04-10 09:34:07 -040029 : fInfo(info)
Greg Danielecddbc02018-08-30 16:39:34 -040030 , fInitialQueueFamily(info.fCurrentQueueFamily)
Greg Daniel52e16d92018-04-10 09:34:07 -040031 , fLayout(std::move(layout))
32 , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
33 SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout);
Greg Danielb46add82019-01-02 14:51:29 -050034 if (forSecondaryCB) {
35 fResource = nullptr;
36 } else if (fIsBorrowed) {
jvanverth6b6ffc42016-06-13 14:28:07 -070037 fResource = new BorrowedResource(info.fImage, info.fAlloc, info.fImageTiling);
Greg Daniel164a9f02016-02-22 09:56:40 -050038 } else {
jvanverth6b6ffc42016-06-13 14:28:07 -070039 fResource = new Resource(info.fImage, info.fAlloc, info.fImageTiling);
Greg Daniel164a9f02016-02-22 09:56:40 -050040 }
Greg Daniel164a9f02016-02-22 09:56:40 -050041 }
Greg Daniel164a9f02016-02-22 09:56:40 -050042 virtual ~GrVkImage();
43
Greg Danielb46add82019-01-02 14:51:29 -050044 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 }
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 }
egdanielb2df0c22016-05-13 11:30:37 -070056 VkFormat imageFormat() const { return fInfo.fFormat; }
Greg Daniel4065d452018-11-16 15:43:41 -050057 GrBackendFormat getBackendFormat() const {
Greg Daniel89df7842019-02-21 12:40:21 -050058 if (fResource && this->ycbcrConversionInfo().isValid()) {
59 SkASSERT(this->imageFormat() == VK_FORMAT_UNDEFINED);
60 return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
61 }
62 SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
Greg Daniel4065d452018-11-16 15:43:41 -050063 return GrBackendFormat::MakeVk(this->imageFormat());
64 }
egdaniel7ac5da82016-07-15 13:41:42 -070065 uint32_t mipLevels() const { return fInfo.fLevelCount; }
Greg Daniel9a51a862018-11-30 10:18:14 -050066 const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
Greg Danielb46add82019-01-02 14:51:29 -050067 // Should only be called when we have a real fResource object, i.e. never when being used as
68 // a RT in an external secondary command buffer.
69 SkASSERT(fResource);
Greg Daniel9a51a862018-11-30 10:18:14 -050070 return fInfo.fYcbcrConversionInfo;
71 }
Greg Danielb46add82019-01-02 14:51:29 -050072 const Resource* resource() const {
73 SkASSERT(fResource);
74 return fResource;
75 }
Greg Daniel164a9f02016-02-22 09:56:40 -050076 bool isLinearTiled() const {
Greg Danielb46add82019-01-02 14:51:29 -050077 // Should only be called when we have a real fResource object, i.e. never when being used as
78 // a RT in an external secondary command buffer.
79 SkASSERT(fResource);
egdanielb2df0c22016-05-13 11:30:37 -070080 return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
Greg Daniel164a9f02016-02-22 09:56:40 -050081 }
Brian Osman13dddce2017-05-09 13:19:50 -040082 bool isBorrowed() const { return fIsBorrowed; }
Greg Daniel164a9f02016-02-22 09:56:40 -050083
Greg Daniel52e16d92018-04-10 09:34:07 -040084 sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
85
86 VkImageLayout currentLayout() const {
Greg Daniel52e16d92018-04-10 09:34:07 -040087 return fLayout->getImageLayout();
88 }
Greg Daniel164a9f02016-02-22 09:56:40 -050089
egdaniel58a8d922016-04-21 08:03:10 -070090 void setImageLayout(const GrVkGpu* gpu,
91 VkImageLayout newLayout,
Greg Daniel164a9f02016-02-22 09:56:40 -050092 VkAccessFlags dstAccessMask,
Greg Daniel164a9f02016-02-22 09:56:40 -050093 VkPipelineStageFlags dstStageMask,
Greg Danielecddbc02018-08-30 16:39:34 -040094 bool byRegion,
95 bool releaseFamilyQueue = false);
Greg Daniel164a9f02016-02-22 09:56:40 -050096
Greg Daniel31cc7312018-03-05 11:41:06 -050097 // This simply updates our tracking of the image layout and does not actually do any gpu work.
98 // This is only used for mip map generation where we are manually changing the layouts as we
99 // blit each layer, and then at the end need to update our tracking.
Greg Daniel52e16d92018-04-10 09:34:07 -0400100 void updateImageLayout(VkImageLayout newLayout) {
Greg Danielb46add82019-01-02 14:51:29 -0500101 // Should only be called when we have a real fResource object, i.e. never when being used as
102 // a RT in an external secondary command buffer.
103 SkASSERT(fResource);
Greg Daniel52e16d92018-04-10 09:34:07 -0400104 fLayout->setImageLayout(newLayout);
Greg Daniel52e16d92018-04-10 09:34:07 -0400105 }
Greg Daniel31cc7312018-03-05 11:41:06 -0500106
Greg Daniel164a9f02016-02-22 09:56:40 -0500107 struct ImageDesc {
108 VkImageType fImageType;
109 VkFormat fFormat;
110 uint32_t fWidth;
111 uint32_t fHeight;
112 uint32_t fLevels;
113 uint32_t fSamples;
114 VkImageTiling fImageTiling;
115 VkImageUsageFlags fUsageFlags;
116 VkFlags fMemProps;
117
118 ImageDesc()
119 : fImageType(VK_IMAGE_TYPE_2D)
120 , fFormat(VK_FORMAT_UNDEFINED)
121 , fWidth(0)
122 , fHeight(0)
123 , fLevels(1)
124 , fSamples(1)
125 , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
126 , fUsageFlags(0)
127 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {}
128 };
129
egdanielb2df0c22016-05-13 11:30:37 -0700130 static bool InitImageInfo(const GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
131 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
132 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
Greg Daniel164a9f02016-02-22 09:56:40 -0500133
Greg Danielcef213c2017-04-21 11:52:27 -0400134 // These match the definitions in SkImage, for whence they came
135 typedef void* ReleaseCtx;
136 typedef void (*ReleaseProc)(ReleaseCtx);
137
Greg Daniel6a0176b2018-01-30 09:28:44 -0500138 void setResourceRelease(sk_sp<GrReleaseProcHelper> releaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400139
Greg Daniel6ddbafc2018-05-24 12:34:29 -0400140 // Helpers to use for setting the layout of the VkImage
Greg Danielf7828d02018-10-09 12:01:32 -0400141 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
Greg Daniel6ddbafc2018-05-24 12:34:29 -0400142 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
143
Greg Daniel59dc1482019-02-22 10:46:38 -0500144#if GR_TEST_UTILS
145 void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
146#endif
147
Greg Daniel164a9f02016-02-22 09:56:40 -0500148protected:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500149 void releaseImage(GrVkGpu* gpu);
Greg Daniel164a9f02016-02-22 09:56:40 -0500150 void abandonImage();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500151 bool hasResource() const { return fResource; }
Greg Daniel164a9f02016-02-22 09:56:40 -0500152
Greg Daniel52e16d92018-04-10 09:34:07 -0400153 GrVkImageInfo fInfo;
Greg Danielecddbc02018-08-30 16:39:34 -0400154 uint32_t fInitialQueueFamily;
Greg Daniel52e16d92018-04-10 09:34:07 -0400155 sk_sp<GrVkImageLayout> fLayout;
Greg Daniel52e16d92018-04-10 09:34:07 -0400156 bool fIsBorrowed;
egdanielb2df0c22016-05-13 11:30:37 -0700157
158private:
egdanielb2df0c22016-05-13 11:30:37 -0700159 class Resource : public GrVkResource {
160 public:
161 Resource()
Greg Daniel6a0176b2018-01-30 09:28:44 -0500162 : fImage(VK_NULL_HANDLE) {
jvanverth1e305ba2016-06-01 09:39:15 -0700163 fAlloc.fMemory = VK_NULL_HANDLE;
164 fAlloc.fOffset = 0;
egdanielb2df0c22016-05-13 11:30:37 -0700165 }
166
jvanverth6b6ffc42016-06-13 14:28:07 -0700167 Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
Greg Daniel6a0176b2018-01-30 09:28:44 -0500168 : fImage(image)
Greg Danielcef213c2017-04-21 11:52:27 -0400169 , fAlloc(alloc)
170 , fImageTiling(tiling) {}
egdanielb2df0c22016-05-13 11:30:37 -0700171
Greg Danielcef213c2017-04-21 11:52:27 -0400172 ~Resource() override {
Greg Daniel6a0176b2018-01-30 09:28:44 -0500173 SkASSERT(!fReleaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400174 }
egdanielb2df0c22016-05-13 11:30:37 -0700175
jvanverth7ec92412016-07-06 09:24:57 -0700176#ifdef SK_TRACE_VK_RESOURCES
177 void dumpInfo() const override {
egdaniela95220d2016-07-21 11:50:37 -0700178 SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
jvanverth7ec92412016-07-06 09:24:57 -0700179 }
180#endif
Greg Daniel6a0176b2018-01-30 09:28:44 -0500181 void setRelease(sk_sp<GrReleaseProcHelper> releaseHelper) {
182 fReleaseHelper = std::move(releaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400183 }
Brian Salomon614c1a82018-12-19 15:42:06 -0500184
185 /**
186 * These are used to coordinate calling the idle proc between the GrVkTexture and the
187 * Resource. If the GrVkTexture becomes purgeable and if there are no command buffers
188 * referring to the Resource then it calls the proc. Otherwise, the Resource calls it
189 * when the last command buffer reference goes away and the GrVkTexture is purgeable.
190 */
191 void setIdleProc(GrVkTexture* owner, GrTexture::IdleProc, void* context) const;
192 void removeOwningTexture() const;
193
194 /**
195 * We track how many outstanding references this Resource has in command buffers and
196 * when the count reaches zero we call the idle proc.
197 */
198 void notifyAddedToCommandBuffer() const override;
199 void notifyRemovedFromCommandBuffer() const override;
200 bool isOwnedByCommandBuffer() const { return fNumCommandBufferOwners > 0; }
201
Greg Danielcef213c2017-04-21 11:52:27 -0400202 protected:
Greg Daniel6a0176b2018-01-30 09:28:44 -0500203 mutable sk_sp<GrReleaseProcHelper> fReleaseHelper;
Greg Danielcef213c2017-04-21 11:52:27 -0400204
Brian Salomon8cabb322019-02-22 10:44:19 -0500205 void invokeReleaseProc() const {
206 if (fReleaseHelper) {
207 // Depending on the ref count of fReleaseHelper this may or may not actually trigger
208 // the ReleaseProc to be called.
209 fReleaseHelper.reset();
210 }
211 }
212
egdanielb2df0c22016-05-13 11:30:37 -0700213 private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500214 void freeGPUData(GrVkGpu* gpu) const override;
Greg Danielcef213c2017-04-21 11:52:27 -0400215 void abandonGPUData() const override {
Brian Salomon8cabb322019-02-22 10:44:19 -0500216 this->invokeReleaseProc();
Greg Daniel6a0176b2018-01-30 09:28:44 -0500217 SkASSERT(!fReleaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400218 }
egdanielb2df0c22016-05-13 11:30:37 -0700219
jvanverth1e305ba2016-06-01 09:39:15 -0700220 VkImage fImage;
221 GrVkAlloc fAlloc;
jvanverth6b6ffc42016-06-13 14:28:07 -0700222 VkImageTiling fImageTiling;
Brian Salomon614c1a82018-12-19 15:42:06 -0500223 mutable int fNumCommandBufferOwners = 0;
224 mutable GrTexture::IdleProc* fIdleProc = nullptr;
225 mutable void* fIdleProcContext = nullptr;
226 mutable GrVkTexture* fOwningTexture = nullptr;
egdanielb2df0c22016-05-13 11:30:37 -0700227
228 typedef GrVkResource INHERITED;
229 };
230
231 // for wrapped textures
232 class BorrowedResource : public Resource {
233 public:
jvanverth6b6ffc42016-06-13 14:28:07 -0700234 BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
235 : Resource(image, alloc, tiling) {
egdanielb2df0c22016-05-13 11:30:37 -0700236 }
237 private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500238 void freeGPUData(GrVkGpu* gpu) const override;
Greg Danielcef213c2017-04-21 11:52:27 -0400239 void abandonGPUData() const override;
egdanielb2df0c22016-05-13 11:30:37 -0700240 };
241
Greg Daniel6a0176b2018-01-30 09:28:44 -0500242 Resource* fResource;
Greg Daniel164a9f02016-02-22 09:56:40 -0500243
egdanielb2df0c22016-05-13 11:30:37 -0700244 friend class GrVkRenderTarget;
Greg Daniel164a9f02016-02-22 09:56:40 -0500245};
246
247#endif