• 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         return GrBackendFormat::MakeVk(this->imageFormat());
59     }
mipLevels()60     uint32_t mipLevels() const { return fInfo.fLevelCount; }
ycbcrConversionInfo()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     }
resource()67     const Resource* resource() const {
68         SkASSERT(fResource);
69         return fResource;
70     }
isLinearTiled()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     }
isBorrowed()77     bool isBorrowed() const { return fIsBorrowed; }
78 
grVkImageLayout()79     sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
80 
currentLayout()81     VkImageLayout currentLayout() const {
82         return fLayout->getImageLayout();
83     }
84 
85     void setImageLayout(const GrVkGpu* gpu,
86                         VkImageLayout newLayout,
87                         VkAccessFlags dstAccessMask,
88                         VkPipelineStageFlags dstStageMask,
89                         bool byRegion,
90                         bool releaseFamilyQueue = false);
91 
92     // This simply updates our tracking of the image layout and does not actually do any gpu work.
93     // This is only used for mip map generation where we are manually changing the layouts as we
94     // blit each layer, and then at the end need to update our tracking.
updateImageLayout(VkImageLayout newLayout)95     void updateImageLayout(VkImageLayout newLayout) {
96         // Should only be called when we have a real fResource object, i.e. never when being used as
97         // a RT in an external secondary command buffer.
98         SkASSERT(fResource);
99         fLayout->setImageLayout(newLayout);
100     }
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 
ImageDescImageDesc113         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     };
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 
129     // These match the definitions in SkImage, for whence they came
130     typedef void* ReleaseCtx;
131     typedef void (*ReleaseProc)(ReleaseCtx);
132 
133     void setResourceRelease(sk_sp<GrReleaseProcHelper> releaseHelper);
134 
135     // Helpers to use for setting the layout of the VkImage
136     static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
137     static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
138 
139 protected:
140     void releaseImage(GrVkGpu* gpu);
141     void abandonImage();
hasResource()142     bool hasResource() const { return fResource; }
143 
144     GrVkImageInfo          fInfo;
145     uint32_t               fInitialQueueFamily;
146     sk_sp<GrVkImageLayout> fLayout;
147     bool                   fIsBorrowed;
148 
149 private:
150     class Resource : public GrVkResource {
151     public:
Resource()152         Resource()
153                 : fImage(VK_NULL_HANDLE) {
154             fAlloc.fMemory = VK_NULL_HANDLE;
155             fAlloc.fOffset = 0;
156         }
157 
Resource(VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)158         Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
159             : fImage(image)
160             , fAlloc(alloc)
161             , fImageTiling(tiling) {}
162 
~Resource()163         ~Resource() override {
164             SkASSERT(!fReleaseHelper);
165         }
166 
167 #ifdef SK_TRACE_VK_RESOURCES
dumpInfo()168         void dumpInfo() const override {
169             SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
170         }
171 #endif
setRelease(sk_sp<GrReleaseProcHelper> releaseHelper)172         void setRelease(sk_sp<GrReleaseProcHelper> releaseHelper) {
173             fReleaseHelper = std::move(releaseHelper);
174         }
175 
176         /**
177          * These are used to coordinate calling the idle proc between the GrVkTexture and the
178          * Resource. If the GrVkTexture becomes purgeable and if there are no command buffers
179          * referring to the Resource then it calls the proc. Otherwise, the Resource calls it
180          * when the last command buffer reference goes away and the GrVkTexture is purgeable.
181          */
182         void setIdleProc(GrVkTexture* owner, GrTexture::IdleProc, void* context) const;
183         void removeOwningTexture() const;
184 
185         /**
186          * We track how many outstanding references this Resource has in command buffers and
187          * when the count reaches zero we call the idle proc.
188          */
189         void notifyAddedToCommandBuffer() const override;
190         void notifyRemovedFromCommandBuffer() const override;
isOwnedByCommandBuffer()191         bool isOwnedByCommandBuffer() const { return fNumCommandBufferOwners > 0; }
192 
193     protected:
194         mutable sk_sp<GrReleaseProcHelper> fReleaseHelper;
195 
196     private:
197         void freeGPUData(GrVkGpu* gpu) const override;
abandonGPUData()198         void abandonGPUData() const override {
199             SkASSERT(!fReleaseHelper);
200         }
201 
202         VkImage        fImage;
203         GrVkAlloc      fAlloc;
204         VkImageTiling  fImageTiling;
205         mutable int fNumCommandBufferOwners = 0;
206         mutable GrTexture::IdleProc* fIdleProc = nullptr;
207         mutable void* fIdleProcContext = nullptr;
208         mutable GrVkTexture* fOwningTexture = nullptr;
209 
210         typedef GrVkResource INHERITED;
211     };
212 
213     // for wrapped textures
214     class BorrowedResource : public Resource {
215     public:
BorrowedResource(VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)216         BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
217             : Resource(image, alloc, tiling) {
218         }
219     private:
invokeReleaseProc()220         void invokeReleaseProc() const {
221             if (fReleaseHelper) {
222                 // Depending on the ref count of fReleaseHelper this may or may not actually trigger
223                 // the ReleaseProc to be called.
224                 fReleaseHelper.reset();
225             }
226         }
227 
228         void freeGPUData(GrVkGpu* gpu) const override;
229         void abandonGPUData() const override;
230     };
231 
232     Resource* fResource;
233 
234     friend class GrVkRenderTarget;
235 };
236 
237 #endif
238