blob: 8f448639c62c7a3660e4c135ffdabdb2b87739ce [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkTypes.h"
12#include "include/gpu/GrBackendSurface.h"
13#include "include/gpu/GrTexture.h"
14#include "include/gpu/vk/GrVkTypes.h"
15#include "include/private/GrTypesPriv.h"
16#include "src/gpu/vk/GrVkImageLayout.h"
17#include "src/gpu/vk/GrVkResource.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 {
Jim Van Verth658d4992019-07-11 14:07:53 -040039 SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
jvanverth6b6ffc42016-06-13 14:28:07 -070040 fResource = new Resource(info.fImage, info.fAlloc, info.fImageTiling);
Greg Daniel164a9f02016-02-22 09:56:40 -050041 }
Greg Daniel164a9f02016-02-22 09:56:40 -050042 }
Greg Daniel164a9f02016-02-22 09:56:40 -050043 virtual ~GrVkImage();
44
Greg Danielb46add82019-01-02 14:51:29 -050045 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 }
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 }
egdanielb2df0c22016-05-13 11:30:37 -070057 VkFormat imageFormat() const { return fInfo.fFormat; }
Greg Daniel4065d452018-11-16 15:43:41 -050058 GrBackendFormat getBackendFormat() const {
Greg Daniel89df7842019-02-21 12:40:21 -050059 if (fResource && this->ycbcrConversionInfo().isValid()) {
Sergey Ulanov2739fd22019-08-11 22:46:33 -070060 SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
Greg Daniel89df7842019-02-21 12:40:21 -050061 return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
62 }
63 SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
Greg Daniel4065d452018-11-16 15:43:41 -050064 return GrBackendFormat::MakeVk(this->imageFormat());
65 }
egdaniel7ac5da82016-07-15 13:41:42 -070066 uint32_t mipLevels() const { return fInfo.fLevelCount; }
Greg Daniel9a51a862018-11-30 10:18:14 -050067 const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
Greg Danielb46add82019-01-02 14:51:29 -050068 // 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);
Greg Daniel9a51a862018-11-30 10:18:14 -050071 return fInfo.fYcbcrConversionInfo;
72 }
Greg Danielb46add82019-01-02 14:51:29 -050073 const Resource* resource() const {
74 SkASSERT(fResource);
75 return fResource;
76 }
Greg Daniel164a9f02016-02-22 09:56:40 -050077 bool isLinearTiled() const {
Greg Danielb46add82019-01-02 14:51:29 -050078 // 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);
egdanielb2df0c22016-05-13 11:30:37 -070081 return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
Greg Daniel164a9f02016-02-22 09:56:40 -050082 }
Brian Osman13dddce2017-05-09 13:19:50 -040083 bool isBorrowed() const { return fIsBorrowed; }
Greg Daniel164a9f02016-02-22 09:56:40 -050084
Greg Daniel52e16d92018-04-10 09:34:07 -040085 sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
86
87 VkImageLayout currentLayout() const {
Greg Daniel52e16d92018-04-10 09:34:07 -040088 return fLayout->getImageLayout();
89 }
Greg Daniel164a9f02016-02-22 09:56:40 -050090
egdaniel58a8d922016-04-21 08:03:10 -070091 void setImageLayout(const GrVkGpu* gpu,
92 VkImageLayout newLayout,
Greg Daniel164a9f02016-02-22 09:56:40 -050093 VkAccessFlags dstAccessMask,
Greg Daniel164a9f02016-02-22 09:56:40 -050094 VkPipelineStageFlags dstStageMask,
Greg Danielecddbc02018-08-30 16:39:34 -040095 bool byRegion,
96 bool releaseFamilyQueue = false);
Greg Daniel164a9f02016-02-22 09:56:40 -050097
Greg Danielbae71212019-03-01 15:24:35 -050098 // 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
Greg Daniel797efca2019-05-09 14:04:20 -0400102 // Returns the image to its original queue family
103 void prepareForExternal(GrVkGpu* gpu);
104
Greg Daniel31cc7312018-03-05 11:41:06 -0500105 // 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.
Greg Daniel52e16d92018-04-10 09:34:07 -0400108 void updateImageLayout(VkImageLayout newLayout) {
Greg Danielb46add82019-01-02 14:51:29 -0500109 // 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);
Greg Daniel52e16d92018-04-10 09:34:07 -0400112 fLayout->setImageLayout(newLayout);
Greg Daniel52e16d92018-04-10 09:34:07 -0400113 }
Greg Daniel31cc7312018-03-05 11:41:06 -0500114
Greg Daniel164a9f02016-02-22 09:56:40 -0500115 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;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400125 GrProtected fIsProtected;
Greg Daniel164a9f02016-02-22 09:56:40 -0500126
127 ImageDesc()
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400128 : 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) {}
Greg Daniel164a9f02016-02-22 09:56:40 -0500138 };
139
egdanielb2df0c22016-05-13 11:30:37 -0700140 static bool InitImageInfo(const GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
141 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
142 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
Greg Daniel164a9f02016-02-22 09:56:40 -0500143
Greg Danielcef213c2017-04-21 11:52:27 -0400144 // These match the definitions in SkImage, for whence they came
145 typedef void* ReleaseCtx;
146 typedef void (*ReleaseProc)(ReleaseCtx);
147
Brian Salomonb2c5dae2019-03-04 10:25:17 -0500148 void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400149
Greg Daniel6ddbafc2018-05-24 12:34:29 -0400150 // Helpers to use for setting the layout of the VkImage
Greg Danielf7828d02018-10-09 12:01:32 -0400151 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
Greg Daniel6ddbafc2018-05-24 12:34:29 -0400152 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
153
Greg Daniel59dc1482019-02-22 10:46:38 -0500154#if GR_TEST_UTILS
155 void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
156#endif
157
Greg Daniel164a9f02016-02-22 09:56:40 -0500158protected:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500159 void releaseImage(GrVkGpu* gpu);
Greg Daniel164a9f02016-02-22 09:56:40 -0500160 void abandonImage();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500161 bool hasResource() const { return fResource; }
Greg Daniel164a9f02016-02-22 09:56:40 -0500162
Greg Daniel52e16d92018-04-10 09:34:07 -0400163 GrVkImageInfo fInfo;
Greg Danielecddbc02018-08-30 16:39:34 -0400164 uint32_t fInitialQueueFamily;
Greg Daniel52e16d92018-04-10 09:34:07 -0400165 sk_sp<GrVkImageLayout> fLayout;
Greg Daniel52e16d92018-04-10 09:34:07 -0400166 bool fIsBorrowed;
egdanielb2df0c22016-05-13 11:30:37 -0700167
168private:
egdanielb2df0c22016-05-13 11:30:37 -0700169 class Resource : public GrVkResource {
170 public:
171 Resource()
Greg Daniel6a0176b2018-01-30 09:28:44 -0500172 : fImage(VK_NULL_HANDLE) {
jvanverth1e305ba2016-06-01 09:39:15 -0700173 fAlloc.fMemory = VK_NULL_HANDLE;
174 fAlloc.fOffset = 0;
egdanielb2df0c22016-05-13 11:30:37 -0700175 }
176
jvanverth6b6ffc42016-06-13 14:28:07 -0700177 Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
Greg Daniel6a0176b2018-01-30 09:28:44 -0500178 : fImage(image)
Greg Danielcef213c2017-04-21 11:52:27 -0400179 , fAlloc(alloc)
180 , fImageTiling(tiling) {}
egdanielb2df0c22016-05-13 11:30:37 -0700181
Greg Danielcef213c2017-04-21 11:52:27 -0400182 ~Resource() override {
Greg Daniel6a0176b2018-01-30 09:28:44 -0500183 SkASSERT(!fReleaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400184 }
egdanielb2df0c22016-05-13 11:30:37 -0700185
jvanverth7ec92412016-07-06 09:24:57 -0700186#ifdef SK_TRACE_VK_RESOURCES
187 void dumpInfo() const override {
egdaniela95220d2016-07-21 11:50:37 -0700188 SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
jvanverth7ec92412016-07-06 09:24:57 -0700189 }
190#endif
Brian Salomonb2c5dae2019-03-04 10:25:17 -0500191 void setRelease(sk_sp<GrRefCntedCallback> releaseHelper) {
Greg Daniel6a0176b2018-01-30 09:28:44 -0500192 fReleaseHelper = std::move(releaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400193 }
Brian Salomon614c1a82018-12-19 15:42:06 -0500194
195 /**
Brian Salomone80b8092019-03-08 13:25:19 -0500196 * These are used to coordinate calling the "finished" idle procs between the GrVkTexture
197 * and the Resource. If the GrVkTexture becomes purgeable and if there are no command
198 * buffers referring to the Resource then it calls the procs. Otherwise, the Resource calls
199 * them when the last command buffer reference goes away and the GrVkTexture is purgeable.
Brian Salomon614c1a82018-12-19 15:42:06 -0500200 */
Brian Salomone80b8092019-03-08 13:25:19 -0500201 void addIdleProc(GrVkTexture*, sk_sp<GrRefCntedCallback>) const;
202 int idleProcCnt() const;
203 sk_sp<GrRefCntedCallback> idleProc(int) const;
204 void resetIdleProcs() const;
Brian Salomon614c1a82018-12-19 15:42:06 -0500205 void removeOwningTexture() const;
206
207 /**
208 * We track how many outstanding references this Resource has in command buffers and
209 * when the count reaches zero we call the idle proc.
210 */
211 void notifyAddedToCommandBuffer() const override;
212 void notifyRemovedFromCommandBuffer() const override;
213 bool isOwnedByCommandBuffer() const { return fNumCommandBufferOwners > 0; }
214
Greg Danielcef213c2017-04-21 11:52:27 -0400215 protected:
Brian Salomonb2c5dae2019-03-04 10:25:17 -0500216 mutable sk_sp<GrRefCntedCallback> fReleaseHelper;
Greg Danielcef213c2017-04-21 11:52:27 -0400217
Brian Salomon8cabb322019-02-22 10:44:19 -0500218 void invokeReleaseProc() const {
219 if (fReleaseHelper) {
220 // Depending on the ref count of fReleaseHelper this may or may not actually trigger
221 // the ReleaseProc to be called.
222 fReleaseHelper.reset();
223 }
224 }
225
egdanielb2df0c22016-05-13 11:30:37 -0700226 private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500227 void freeGPUData(GrVkGpu* gpu) const override;
Greg Danielcef213c2017-04-21 11:52:27 -0400228 void abandonGPUData() const override {
Brian Salomon8cabb322019-02-22 10:44:19 -0500229 this->invokeReleaseProc();
Greg Daniel6a0176b2018-01-30 09:28:44 -0500230 SkASSERT(!fReleaseHelper);
Greg Danielcef213c2017-04-21 11:52:27 -0400231 }
egdanielb2df0c22016-05-13 11:30:37 -0700232
jvanverth1e305ba2016-06-01 09:39:15 -0700233 VkImage fImage;
234 GrVkAlloc fAlloc;
jvanverth6b6ffc42016-06-13 14:28:07 -0700235 VkImageTiling fImageTiling;
Brian Salomon614c1a82018-12-19 15:42:06 -0500236 mutable int fNumCommandBufferOwners = 0;
Brian Salomone80b8092019-03-08 13:25:19 -0500237 mutable SkTArray<sk_sp<GrRefCntedCallback>> fIdleProcs;
Brian Salomon614c1a82018-12-19 15:42:06 -0500238 mutable GrVkTexture* fOwningTexture = nullptr;
egdanielb2df0c22016-05-13 11:30:37 -0700239
240 typedef GrVkResource INHERITED;
241 };
242
243 // for wrapped textures
244 class BorrowedResource : public Resource {
245 public:
jvanverth6b6ffc42016-06-13 14:28:07 -0700246 BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
247 : Resource(image, alloc, tiling) {
egdanielb2df0c22016-05-13 11:30:37 -0700248 }
249 private:
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500250 void freeGPUData(GrVkGpu* gpu) const override;
Greg Danielcef213c2017-04-21 11:52:27 -0400251 void abandonGPUData() const override;
egdanielb2df0c22016-05-13 11:30:37 -0700252 };
253
Greg Daniel6a0176b2018-01-30 09:28:44 -0500254 Resource* fResource;
Greg Daniel164a9f02016-02-22 09:56:40 -0500255
egdanielb2df0c22016-05-13 11:30:37 -0700256 friend class GrVkRenderTarget;
Greg Daniel164a9f02016-02-22 09:56:40 -0500257};
258
259#endif