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 "include/core/SkTypes.h"
12 #include "include/gpu/GrBackendSurface.h"
13 #include "include/gpu/vk/GrVkTypes.h"
14 #include "include/private/GrTypesPriv.h"
15 #include "include/private/GrVkTypesPriv.h"
16 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
17 #include "src/gpu/GrManagedResource.h"
18 #include "src/gpu/GrTexture.h"
19 
20 class GrVkGpu;
21 class GrVkTexture;
22 
23 class GrVkImage : SkNoncopyable {
24 private:
25     class Resource;
26 
27 public:
28     GrVkImage(const GrVkGpu* gpu,
29               const GrVkImageInfo& info,
30               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
31               GrBackendObjectOwnership ownership,
32               bool forSecondaryCB = false);
33 
34     virtual ~GrVkImage();
35 
image()36     VkImage image() const {
37         // Should only be called when we have a real fResource object, i.e. never when being used as
38         // a RT in an external secondary command buffer.
39         SkASSERT(fResource);
40         return fInfo.fImage;
41     }
alloc()42     const GrVkAlloc& alloc() const {
43         // Should only be called when we have a real fResource object, i.e. never when being used as
44         // a RT in an external secondary command buffer.
45         SkASSERT(fResource);
46         return fInfo.fAlloc;
47     }
vkImageInfo()48     const GrVkImageInfo& vkImageInfo() const { return fInfo; }
imageFormat()49     VkFormat imageFormat() const { return fInfo.fFormat; }
getBackendFormat()50     GrBackendFormat getBackendFormat() const {
51         if (fResource && this->ycbcrConversionInfo().isValid()) {
52             SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
53             return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
54         }
55         SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
56         return GrBackendFormat::MakeVk(this->imageFormat());
57     }
mipLevels()58     uint32_t mipLevels() const { return fInfo.fLevelCount; }
ycbcrConversionInfo()59     const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
60         // Should only be called when we have a real fResource object, i.e. never when being used as
61         // a RT in an external secondary command buffer.
62         SkASSERT(fResource);
63         return fInfo.fYcbcrConversionInfo;
64     }
vkUsageFlags()65     VkImageUsageFlags vkUsageFlags() { return fInfo.fImageUsageFlags; }
supportsInputAttachmentUsage()66     bool supportsInputAttachmentUsage() const {
67         return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
68     }
resource()69     const Resource* resource() const {
70         SkASSERT(fResource);
71         return fResource;
72     }
isLinearTiled()73     bool isLinearTiled() const {
74         // Should only be called when we have a real fResource object, i.e. never when being used as
75         // a RT in an external secondary command buffer.
76         SkASSERT(fResource);
77         return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
78     }
isBorrowed()79     bool isBorrowed() const { return fIsBorrowed; }
80 
getMutableState()81     sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; }
82 
currentLayout()83     VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); }
84 
85     void setImageLayoutAndQueueIndex(const GrVkGpu* gpu,
86                                      VkImageLayout newLayout,
87                                      VkAccessFlags dstAccessMask,
88                                      VkPipelineStageFlags dstStageMask,
89                                      bool byRegion,
90                                      uint32_t newQueueFamilyIndex);
91 
setImageLayout(const GrVkGpu * gpu,VkImageLayout newLayout,VkAccessFlags dstAccessMask,VkPipelineStageFlags dstStageMask,bool byRegion)92     void setImageLayout(const GrVkGpu* gpu,
93                         VkImageLayout newLayout,
94                         VkAccessFlags dstAccessMask,
95                         VkPipelineStageFlags dstStageMask,
96                         bool byRegion) {
97         this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion,
98                                           VK_QUEUE_FAMILY_IGNORED);
99     }
100 
currentQueueFamilyIndex()101     uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); }
102 
setQueueFamilyIndex(uint32_t queueFamilyIndex)103     void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
104         fMutableState->setQueueFamilyIndex(queueFamilyIndex);
105     }
106 
107     // Returns the image to its original queue family and changes the layout to present if the queue
108     // family is not external or foreign.
109     void prepareForPresent(GrVkGpu* gpu);
110 
111     // Returns the image to its original queue family
112     void prepareForExternal(GrVkGpu* gpu);
113 
114     // This simply updates our tracking of the image layout and does not actually do any gpu work.
115     // This is only used for mip map generation where we are manually changing the layouts as we
116     // blit each layer, and then at the end need to update our tracking.
updateImageLayout(VkImageLayout newLayout)117     void updateImageLayout(VkImageLayout newLayout) {
118         // Should only be called when we have a real fResource object, i.e. never when being used as
119         // a RT in an external secondary command buffer.
120         SkASSERT(fResource);
121         fMutableState->setImageLayout(newLayout);
122     }
123 
124     struct ImageDesc {
125         VkImageType         fImageType;
126         VkFormat            fFormat;
127         uint32_t            fWidth;
128         uint32_t            fHeight;
129         uint32_t            fLevels;
130         uint32_t            fSamples;
131         VkImageTiling       fImageTiling;
132         VkImageUsageFlags   fUsageFlags;
133         VkFlags             fMemProps;
134         GrProtected         fIsProtected;
135 
ImageDescImageDesc136         ImageDesc()
137                 : fImageType(VK_IMAGE_TYPE_2D)
138                 , fFormat(VK_FORMAT_UNDEFINED)
139                 , fWidth(0)
140                 , fHeight(0)
141                 , fLevels(1)
142                 , fSamples(1)
143                 , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
144                 , fUsageFlags(0)
145                 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
146                 , fIsProtected(GrProtected::kNo) {}
147     };
148 
149     static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
150     // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
151     static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
152 
153     // These match the definitions in SkImage, for whence they came
154     typedef void* ReleaseCtx;
155     typedef void (*ReleaseProc)(ReleaseCtx);
156 
157     void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
158 
159     // Helpers to use for setting the layout of the VkImage
160     static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
161     static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
162 
163 #if GR_TEST_UTILS
164     void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
165 #endif
166 
167 protected:
168     void releaseImage();
hasResource()169     bool hasResource() const { return fResource; }
170 
171     GrVkImageInfo                    fInfo;
172     uint32_t                         fInitialQueueFamily;
173     sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
174     bool                             fIsBorrowed;
175 
176 private:
177     class Resource : public GrTextureResource {
178     public:
Resource(const GrVkGpu * gpu)179         explicit Resource(const GrVkGpu* gpu)
180                 : fGpu(gpu)
181                 , fImage(VK_NULL_HANDLE) {
182             fAlloc.fMemory = VK_NULL_HANDLE;
183             fAlloc.fOffset = 0;
184         }
185 
Resource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)186         Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
187             : fGpu(gpu)
188             , fImage(image)
189             , fAlloc(alloc)
190             , fImageTiling(tiling) {}
191 
~Resource()192         ~Resource() override {}
193 
194 #ifdef SK_TRACE_MANAGED_RESOURCES
dumpInfo()195         void dumpInfo() const override {
196             SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
197         }
198 #endif
199 
200 #ifdef SK_DEBUG
asVkImageResource()201         const GrManagedResource* asVkImageResource() const override { return this; }
202 #endif
203 
204     private:
205         void freeGPUData() const override;
206 
207         const GrVkGpu* fGpu;
208         VkImage        fImage;
209         GrVkAlloc      fAlloc;
210         VkImageTiling  fImageTiling;
211 
212         using INHERITED = GrTextureResource;
213     };
214 
215     // for wrapped textures
216     class BorrowedResource : public Resource {
217     public:
BorrowedResource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)218         BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc,
219                          VkImageTiling tiling)
220             : Resource(gpu, image, alloc, tiling) {
221         }
222     private:
223         void freeGPUData() const override;
224     };
225 
226     Resource* fResource;
227 
228     friend class GrVkRenderTarget;
229 };
230 
231 #endif
232