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/GrAttachment.h"
17 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
18 #include "src/gpu/GrManagedResource.h"
19 #include "src/gpu/GrRefCnt.h"
20 #include "src/gpu/GrTexture.h"
21 #include "src/gpu/vk/GrVkDescriptorSet.h"
22 
23 #include <cinttypes>
24 
25 class GrVkGpu;
26 class GrVkImageView;
27 
28 class SK_API GrVkImage : public GrAttachment {
29 private:
30     class Resource;
31 
32 public:
33     static sk_sp<GrVkImage> MakeStencil(GrVkGpu* gpu,
34                                         SkISize dimensions,
35                                         int sampleCnt,
36                                         VkFormat format);
37 
38     static sk_sp<GrVkImage> MakeMSAA(GrVkGpu* gpu,
39                                      SkISize dimensions,
40                                      int numSamples,
41                                      VkFormat format,
42                                      GrProtected isProtected,
43                                      GrMemoryless memoryless);
44 
45     static sk_sp<GrVkImage> MakeTexture(GrVkGpu* gpu,
46                                         SkISize dimensions,
47                                         VkFormat format,
48                                         uint32_t mipLevels,
49                                         GrRenderable renderable,
50                                         int numSamples,
51                                         SkBudgeted budgeted,
52                                         GrProtected isProtected);
53 
54     static sk_sp<GrVkImage> MakeWrapped(GrVkGpu* gpu,
55                                         SkISize dimensions,
56                                         const GrVkImageInfo&,
57                                         sk_sp<GrBackendSurfaceMutableStateImpl>,
58                                         UsageFlags attachmentUsages,
59                                         GrWrapOwnership,
60                                         GrWrapCacheable,
61                                         bool forSecondaryCB = false);
62 
63     // OH ISSUE: Integrate Destroy and Free
64     static void DestroyAndFreeImageMemory(const GrVkGpu* gpu, const GrVkAlloc& alloc, const VkImage& image);
65 
66     ~GrVkImage() override;
67 
image() const68     VkImage image() const {
69         // Should only be called when we have a real fResource object, i.e. never when being used as
70         // a RT in an external secondary command buffer.
71         SkASSERT(fResource);
72         return fInfo.fImage;
73     }
alloc() const74     const GrVkAlloc& alloc() const {
75         // Should only be called when we have a real fResource object, i.e. never when being used as
76         // a RT in an external secondary command buffer.
77         SkASSERT(fResource);
78         return fInfo.fAlloc;
79     }
vkImageInfo() const80     const GrVkImageInfo& vkImageInfo() const { return fInfo; }
imageFormat() const81     VkFormat imageFormat() const { return fInfo.fFormat; }
82     GrBackendFormat backendFormat() const override {
83         bool usesDRMModifier =
84                 this->vkImageInfo().fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
85         if (fResource && this->ycbcrConversionInfo().isValid()) {
86             SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
87             return GrBackendFormat::MakeVk(this->ycbcrConversionInfo(), usesDRMModifier);
88         }
89         SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
90         return GrBackendFormat::MakeVk(this->imageFormat(), usesDRMModifier);
91     }
mipLevels() const92     uint32_t mipLevels() const { return fInfo.fLevelCount; }
ycbcrConversionInfo() const93     const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
94         // Should only be called when we have a real fResource object, i.e. never when being used as
95         // a RT in an external secondary command buffer.
96         SkASSERT(fResource);
97         return fInfo.fYcbcrConversionInfo;
98     }
vkUsageFlags()99     VkImageUsageFlags vkUsageFlags() { return fInfo.fImageUsageFlags; }
supportsInputAttachmentUsage() const100     bool supportsInputAttachmentUsage() const {
101         return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
102     }
103 
framebufferView() const104     const GrVkImageView* framebufferView() const { return fFramebufferView.get(); }
textureView() const105     const GrVkImageView* textureView() const { return fTextureView.get(); }
106 
107     // So that we don't need to rewrite descriptor sets each time, we keep cached input descriptor
108     // sets on the attachment and simply reuse those descriptor sets for this attachment only. These
109     // calls will fail if the attachment does not support being used as an input attachment. These
110     // calls do not ref the GrVkDescriptorSet so they called will need to manually ref them if they
111     // need to be kept alive.
112     gr_rp<const GrVkDescriptorSet> inputDescSetForBlending(GrVkGpu* gpu);
113     // Input descripotr set used when needing to read a resolve attachment to load data into a
114     // discardable msaa attachment.
115     gr_rp<const GrVkDescriptorSet> inputDescSetForMSAALoad(GrVkGpu* gpu);
116 
resource() const117     const Resource* resource() const {
118         SkASSERT(fResource);
119         return fResource;
120     }
isLinearTiled() const121     bool isLinearTiled() const {
122         // Should only be called when we have a real fResource object, i.e. never when being used as
123         // a RT in an external secondary command buffer.
124         SkASSERT(fResource);
125         return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
126     }
isBorrowed() const127     bool isBorrowed() const { return fIsBorrowed; }
128 
getMutableState() const129     sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; }
130 
currentLayout() const131     VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); }
132 
133     void setImageLayoutAndQueueIndex(const GrVkGpu* gpu,
134                                      VkImageLayout newLayout,
135                                      VkAccessFlags dstAccessMask,
136                                      VkPipelineStageFlags dstStageMask,
137                                      bool byRegion,
138                                      uint32_t newQueueFamilyIndex);
139 
setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, VkAccessFlags dstAccessMask, VkPipelineStageFlags dstStageMask, bool byRegion)140     void setImageLayout(const GrVkGpu* gpu,
141                         VkImageLayout newLayout,
142                         VkAccessFlags dstAccessMask,
143                         VkPipelineStageFlags dstStageMask,
144                         bool byRegion) {
145         this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion,
146                                           VK_QUEUE_FAMILY_IGNORED);
147     }
148 
currentQueueFamilyIndex() const149     uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); }
150 
setQueueFamilyIndex(uint32_t queueFamilyIndex)151     void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
152         fMutableState->setQueueFamilyIndex(queueFamilyIndex);
153     }
154 
155     // Returns the image to its original queue family and changes the layout to present if the queue
156     // family is not external or foreign.
157     void prepareForPresent(GrVkGpu* gpu);
158 
159     // Returns the image to its original queue family
160     void prepareForExternal(GrVkGpu* gpu);
161 
162     // This simply updates our tracking of the image layout and does not actually do any gpu work.
163     // This is only used for mip map generation where we are manually changing the layouts as we
164     // blit each layer, and then at the end need to update our tracking.
updateImageLayout(VkImageLayout newLayout)165     void updateImageLayout(VkImageLayout newLayout) {
166         // Should only be called when we have a real fResource object, i.e. never when being used as
167         // a RT in an external secondary command buffer.
168         SkASSERT(fResource);
169         fMutableState->setImageLayout(newLayout);
170     }
171 
172     struct ImageDesc {
173         VkImageType         fImageType;
174         VkFormat            fFormat;
175         uint32_t            fWidth;
176         uint32_t            fHeight;
177         uint32_t            fLevels;
178         uint32_t            fSamples;
179         VkImageTiling       fImageTiling;
180         VkImageUsageFlags   fUsageFlags;
181         VkFlags             fMemProps;
182         GrProtected         fIsProtected;
183 
ImageDescGrVkImage::ImageDesc184         ImageDesc()
185                 : fImageType(VK_IMAGE_TYPE_2D)
186                 , fFormat(VK_FORMAT_UNDEFINED)
187                 , fWidth(0)
188                 , fHeight(0)
189                 , fLevels(1)
190                 , fSamples(1)
191                 , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
192                 , fUsageFlags(0)
193                 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
194                 , fIsProtected(GrProtected::kNo) {}
195     };
196 
197     static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
198     // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
199     static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
200 
201     // These match the definitions in SkImage, for whence they came
202     typedef void* ReleaseCtx;
203     typedef void (*ReleaseProc)(ReleaseCtx);
204 
205     void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
206 
207     // Helpers to use for setting the layout of the VkImage
208     static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
209     static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
210 
211     size_t onGpuMemorySize() const override;
212 #if GR_TEST_UTILS
213     void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
214 #endif
215 
216 #ifdef SKIA_OHOS
GetBudgeted() const217     SkBudgeted GetBudgeted() const { return fBudgeted; }
218 #endif
219 
220 private:
221     static sk_sp<GrVkImage> Make(GrVkGpu* gpu,
222                                  SkISize dimensions,
223                                  UsageFlags attachmentUsages,
224                                  int sampleCnt,
225                                  VkFormat format,
226                                  uint32_t mipLevels,
227                                  VkImageUsageFlags vkUsageFlags,
228                                  GrProtected isProtected,
229                                  GrMemoryless,
230                                  SkBudgeted);
231 
232     GrVkImage(GrVkGpu* gpu,
233               SkISize dimensions,
234               UsageFlags supportedUsages,
235               const GrVkImageInfo&,
236               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
237               sk_sp<const GrVkImageView> framebufferView,
238               sk_sp<const GrVkImageView> textureView,
239               SkBudgeted);
240 
241     GrVkImage(GrVkGpu* gpu,
242               SkISize dimensions,
243               UsageFlags supportedUsages,
244               const GrVkImageInfo&,
245               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
246               sk_sp<const GrVkImageView> framebufferView,
247               sk_sp<const GrVkImageView> textureView,
248               GrBackendObjectOwnership,
249               GrWrapCacheable,
250               bool forSecondaryCB);
251 
252     void init(GrVkGpu*, bool forSecondaryCB);
253 
254     void onRelease() override;
255     void onAbandon() override;
256 
257     void releaseImage();
hasResource() const258     bool hasResource() const { return fResource; }
259 
260     GrVkGpu* getVkGpu() const;
261 
262     GrVkImageInfo                           fInfo;
263     uint32_t                                fInitialQueueFamily;
264     sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
265 
266     sk_sp<const GrVkImageView>              fFramebufferView;
267     sk_sp<const GrVkImageView>              fTextureView;
268 
269 #ifdef SKIA_OHOS
270     SkBudgeted fBudgeted = SkBudgeted::kNo;
271 #endif
272     bool fIsBorrowed;
273 
274     // Descriptor set used when this is used as an input attachment for reading the dst in blending.
275     gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet;
276     // Descriptor set used when this is used as an input attachment for loading an msaa attachment.
277     gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet;
278 
279     class Resource : public GrTextureResource {
280     public:
Resource(const GrVkGpu* gpu)281         explicit Resource(const GrVkGpu* gpu)
282                 : fGpu(gpu)
283                 , fImage(VK_NULL_HANDLE) {
284             fAlloc.fMemory = VK_NULL_HANDLE;
285             fAlloc.fOffset = 0;
286         }
287 
Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)288         Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
289             : fGpu(gpu)
290             , fImage(image)
291             , fAlloc(alloc) {}
292 
293         ~Resource() override {}
294 
295 #ifdef SK_TRACE_MANAGED_RESOURCES
296         void dumpInfo() const override {
297             SkDebugf("GrVkImage: %" PRIdPTR " (%d refs)\n", (intptr_t)fImage, this->getRefCnt());
298         }
299 #endif
300 
301 #ifdef SK_DEBUG
302         const GrManagedResource* asVkImageResource() const override { return this; }
303 #endif
304 
305     private:
306         void freeGPUData() const override;
307 
308         const GrVkGpu* fGpu;
309         VkImage        fImage;
310         GrVkAlloc      fAlloc;
311 
312         using INHERITED = GrTextureResource;
313     };
314 
315     // for wrapped textures
316     class BorrowedResource : public Resource {
317     public:
BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)318         BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc,
319                          VkImageTiling tiling)
320             : Resource(gpu, image, alloc, tiling) {
321         }
322     private:
323         void freeGPUData() const override;
324     };
325 
326     Resource* fResource;
327 
328     friend class GrVkRenderTarget;
329 };
330 
331 #endif
332