• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrBackendSurface.h"
12 #include "GrTexture.h"
13 #include "GrTypesPriv.h"
14 #include "GrVkImageLayout.h"
15 #include "GrVkResource.h"
16 #include "SkTypes.h"
17 #include "vk/GrVkTypes.h"
18 
19 class GrVkGpu;
20 class GrVkTexture;
21 
22 class GrVkImage : SkNoncopyable {
23 private:
24     class Resource;
25 
26 public:
27     GrVkImage(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(info.fImage, info.fAlloc, info.fImageTiling);
38         } else {
39             fResource = new Resource(info.fImage, info.fAlloc, info.fImageTiling);
40         }
41     }
42     virtual ~GrVkImage();
43 
image()44     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     }
alloc()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     }
imageFormat()56     VkFormat imageFormat() const { return fInfo.fFormat; }
getBackendFormat()57     GrBackendFormat getBackendFormat() const {
58         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);
63         return GrBackendFormat::MakeVk(this->imageFormat());
64     }
mipLevels()65     uint32_t mipLevels() const { return fInfo.fLevelCount; }
ycbcrConversionInfo()66     const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
67         // 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);
70         return fInfo.fYcbcrConversionInfo;
71     }
resource()72     const Resource* resource() const {
73         SkASSERT(fResource);
74         return fResource;
75     }
isLinearTiled()76     bool isLinearTiled() const {
77         // 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);
80         return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
81     }
isBorrowed()82     bool isBorrowed() const { return fIsBorrowed; }
83 
grVkImageLayout()84     sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
85 
currentLayout()86     VkImageLayout currentLayout() const {
87         return fLayout->getImageLayout();
88     }
89 
90     void setImageLayout(const GrVkGpu* gpu,
91                         VkImageLayout newLayout,
92                         VkAccessFlags dstAccessMask,
93                         VkPipelineStageFlags dstStageMask,
94                         bool byRegion,
95                         bool releaseFamilyQueue = false);
96 
97     // Returns the image to its original queue family and changes the layout to present if the queue
98     // family is not external or foreign.
99     void prepareForPresent(GrVkGpu* gpu);
100 
101     // This simply updates our tracking of the image layout and does not actually do any gpu work.
102     // This is only used for mip map generation where we are manually changing the layouts as we
103     // blit each layer, and then at the end need to update our tracking.
updateImageLayout(VkImageLayout newLayout)104     void updateImageLayout(VkImageLayout newLayout) {
105         // Should only be called when we have a real fResource object, i.e. never when being used as
106         // a RT in an external secondary command buffer.
107         SkASSERT(fResource);
108         fLayout->setImageLayout(newLayout);
109     }
110 
111     struct ImageDesc {
112         VkImageType         fImageType;
113         VkFormat            fFormat;
114         uint32_t            fWidth;
115         uint32_t            fHeight;
116         uint32_t            fLevels;
117         uint32_t            fSamples;
118         VkImageTiling       fImageTiling;
119         VkImageUsageFlags   fUsageFlags;
120         VkFlags             fMemProps;
121 
ImageDescImageDesc122         ImageDesc()
123             : fImageType(VK_IMAGE_TYPE_2D)
124             , fFormat(VK_FORMAT_UNDEFINED)
125             , fWidth(0)
126             , fHeight(0)
127             , fLevels(1)
128             , fSamples(1)
129             , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
130             , fUsageFlags(0)
131             , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {}
132     };
133 
134     static bool InitImageInfo(const GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
135     // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
136     static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
137 
138     // These match the definitions in SkImage, for whence they came
139     typedef void* ReleaseCtx;
140     typedef void (*ReleaseProc)(ReleaseCtx);
141 
142     void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
143 
144     // Helpers to use for setting the layout of the VkImage
145     static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
146     static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
147 
148 #if GR_TEST_UTILS
149     void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
150 #endif
151 
152 protected:
153     void releaseImage(GrVkGpu* gpu);
154     void abandonImage();
hasResource()155     bool hasResource() const { return fResource; }
156 
157     GrVkImageInfo          fInfo;
158     uint32_t               fInitialQueueFamily;
159     sk_sp<GrVkImageLayout> fLayout;
160     bool                   fIsBorrowed;
161 
162 private:
163     class Resource : public GrVkResource {
164     public:
Resource()165         Resource()
166                 : fImage(VK_NULL_HANDLE) {
167             fAlloc.fMemory = VK_NULL_HANDLE;
168             fAlloc.fOffset = 0;
169         }
170 
Resource(VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)171         Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
172             : fImage(image)
173             , fAlloc(alloc)
174             , fImageTiling(tiling) {}
175 
~Resource()176         ~Resource() override {
177             SkASSERT(!fReleaseHelper);
178         }
179 
180 #ifdef SK_TRACE_VK_RESOURCES
dumpInfo()181         void dumpInfo() const override {
182             SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
183         }
184 #endif
setRelease(sk_sp<GrRefCntedCallback> releaseHelper)185         void setRelease(sk_sp<GrRefCntedCallback> releaseHelper) {
186             fReleaseHelper = std::move(releaseHelper);
187         }
188 
189         /**
190          * These are used to coordinate calling the idle proc between the GrVkTexture and the
191          * Resource. If the GrVkTexture becomes purgeable and if there are no command buffers
192          * referring to the Resource then it calls the proc. Otherwise, the Resource calls it
193          * when the last command buffer reference goes away and the GrVkTexture is purgeable.
194          */
195         void replaceIdleProc(GrVkTexture* owner, sk_sp<GrRefCntedCallback>) const;
196         void removeOwningTexture() const;
197 
198         /**
199          * We track how many outstanding references this Resource has in command buffers and
200          * when the count reaches zero we call the idle proc.
201          */
202         void notifyAddedToCommandBuffer() const override;
203         void notifyRemovedFromCommandBuffer() const override;
isOwnedByCommandBuffer()204         bool isOwnedByCommandBuffer() const { return fNumCommandBufferOwners > 0; }
205 
206     protected:
207         mutable sk_sp<GrRefCntedCallback> fReleaseHelper;
208 
invokeReleaseProc()209         void invokeReleaseProc() const {
210             if (fReleaseHelper) {
211                 // Depending on the ref count of fReleaseHelper this may or may not actually trigger
212                 // the ReleaseProc to be called.
213                 fReleaseHelper.reset();
214             }
215         }
216 
217     private:
218         void freeGPUData(GrVkGpu* gpu) const override;
abandonGPUData()219         void abandonGPUData() const override {
220             this->invokeReleaseProc();
221             SkASSERT(!fReleaseHelper);
222         }
223 
224         VkImage        fImage;
225         GrVkAlloc      fAlloc;
226         VkImageTiling  fImageTiling;
227         mutable int fNumCommandBufferOwners = 0;
228         mutable sk_sp<GrRefCntedCallback> fIdleCallback;
229         mutable GrVkTexture* fOwningTexture = nullptr;
230 
231         typedef GrVkResource INHERITED;
232     };
233 
234     // for wrapped textures
235     class BorrowedResource : public Resource {
236     public:
BorrowedResource(VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)237         BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
238             : Resource(image, alloc, tiling) {
239         }
240     private:
241         void freeGPUData(GrVkGpu* gpu) const override;
242         void abandonGPUData() const override;
243     };
244 
245     Resource* fResource;
246 
247     friend class GrVkRenderTarget;
248 };
249 
250 #endif
251