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 "src/gpu/GrManagedResource.h"
16 #include "src/gpu/GrTexture.h"
17 #include "src/gpu/vk/GrVkImageLayout.h"
18 
19 class GrVkGpu;
20 class GrVkTexture;
21 
22 class GrVkImage : SkNoncopyable {
23 private:
24     class Resource;
25 
26 public:
27     GrVkImage(const GrVkGpu* gpu, 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(gpu, info.fImage, info.fAlloc, info.fImageTiling);
38         } else {
39             SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
40             fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
41         }
42     }
43     virtual ~GrVkImage();
44 
image()45     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     }
alloc()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     }
imageFormat()57     VkFormat imageFormat() const { return fInfo.fFormat; }
getBackendFormat()58     GrBackendFormat getBackendFormat() const {
59         if (fResource && this->ycbcrConversionInfo().isValid()) {
60             SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
61             return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
62         }
63         SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
64         return GrBackendFormat::MakeVk(this->imageFormat());
65     }
mipLevels()66     uint32_t mipLevels() const { return fInfo.fLevelCount; }
ycbcrConversionInfo()67     const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
68         // 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);
71         return fInfo.fYcbcrConversionInfo;
72     }
resource()73     const Resource* resource() const {
74         SkASSERT(fResource);
75         return fResource;
76     }
isLinearTiled()77     bool isLinearTiled() const {
78         // 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);
81         return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
82     }
isBorrowed()83     bool isBorrowed() const { return fIsBorrowed; }
84 
grVkImageLayout()85     sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
86 
currentLayout()87     VkImageLayout currentLayout() const {
88         return fLayout->getImageLayout();
89     }
90 
91     void setImageLayout(const GrVkGpu* gpu,
92                         VkImageLayout newLayout,
93                         VkAccessFlags dstAccessMask,
94                         VkPipelineStageFlags dstStageMask,
95                         bool byRegion,
96                         bool releaseFamilyQueue = false);
97 
98     // 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 
102     // Returns the image to its original queue family
103     void prepareForExternal(GrVkGpu* gpu);
104 
105     // 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.
updateImageLayout(VkImageLayout newLayout)108     void updateImageLayout(VkImageLayout newLayout) {
109         // 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);
112         fLayout->setImageLayout(newLayout);
113     }
114 
115     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;
125         GrProtected         fIsProtected;
126 
ImageDescImageDesc127         ImageDesc()
128                 : 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) {}
138     };
139 
140     static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
141     // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
142     static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
143 
144     // These match the definitions in SkImage, for whence they came
145     typedef void* ReleaseCtx;
146     typedef void (*ReleaseProc)(ReleaseCtx);
147 
148     void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
149 
150     // Helpers to use for setting the layout of the VkImage
151     static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
152     static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
153 
154 #if GR_TEST_UTILS
155     void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
156 #endif
157 
158 protected:
159     void releaseImage(GrVkGpu* gpu);
hasResource()160     bool hasResource() const { return fResource; }
161 
162     GrVkImageInfo          fInfo;
163     uint32_t               fInitialQueueFamily;
164     sk_sp<GrVkImageLayout> fLayout;
165     bool                   fIsBorrowed;
166 
167 private:
168     class Resource : public GrTextureResource {
169     public:
Resource(const GrVkGpu * gpu)170         explicit Resource(const GrVkGpu* gpu)
171                 : fGpu(gpu)
172                 , fImage(VK_NULL_HANDLE) {
173             fAlloc.fMemory = VK_NULL_HANDLE;
174             fAlloc.fOffset = 0;
175         }
176 
Resource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)177         Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
178             : fGpu(gpu)
179             , fImage(image)
180             , fAlloc(alloc)
181             , fImageTiling(tiling) {}
182 
~Resource()183         ~Resource() override {}
184 
185 #ifdef SK_TRACE_MANAGED_RESOURCES
dumpInfo()186         void dumpInfo() const override {
187             SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
188         }
189 #endif
190 
191     private:
192         void freeGPUData() const override;
193 
194         const GrVkGpu* fGpu;
195         VkImage        fImage;
196         GrVkAlloc      fAlloc;
197         VkImageTiling  fImageTiling;
198 
199         typedef GrTextureResource INHERITED;
200     };
201 
202     // for wrapped textures
203     class BorrowedResource : public Resource {
204     public:
BorrowedResource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)205         BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc,
206                          VkImageTiling tiling)
207             : Resource(gpu, image, alloc, tiling) {
208         }
209     private:
210         void freeGPUData() const override;
211     };
212 
213     Resource* fResource;
214 
215     friend class GrVkRenderTarget;
216 };
217 
218 #endif
219