• 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 "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()68     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()74     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()80     const GrVkImageInfo& vkImageInfo() const { return fInfo; }
imageFormat()81     VkFormat imageFormat() const { return fInfo.fFormat; }
backendFormat()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()92     uint32_t mipLevels() const { return fInfo.fLevelCount; }
ycbcrConversionInfo()93     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()100     bool supportsInputAttachmentUsage() const {
101         return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
102     }
103 
framebufferView()104     const GrVkImageView* framebufferView() const { return fFramebufferView.get(); }
textureView()105     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()117     const Resource* resource() const {
118         SkASSERT(fResource);
119         return fResource;
120     }
isLinearTiled()121     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()127     bool isBorrowed() const { return fIsBorrowed; }
128 
getMutableState()129     sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; }
130 
currentLayout()131     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()149     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 
ImageDescImageDesc184         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 private:
217     static sk_sp<GrVkImage> Make(GrVkGpu* gpu,
218                                  SkISize dimensions,
219                                  UsageFlags attachmentUsages,
220                                  int sampleCnt,
221                                  VkFormat format,
222                                  uint32_t mipLevels,
223                                  VkImageUsageFlags vkUsageFlags,
224                                  GrProtected isProtected,
225                                  GrMemoryless,
226                                  SkBudgeted);
227 
228     GrVkImage(GrVkGpu* gpu,
229               SkISize dimensions,
230               UsageFlags supportedUsages,
231               const GrVkImageInfo&,
232               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
233               sk_sp<const GrVkImageView> framebufferView,
234               sk_sp<const GrVkImageView> textureView,
235               SkBudgeted);
236 
237     GrVkImage(GrVkGpu* gpu,
238               SkISize dimensions,
239               UsageFlags supportedUsages,
240               const GrVkImageInfo&,
241               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
242               sk_sp<const GrVkImageView> framebufferView,
243               sk_sp<const GrVkImageView> textureView,
244               GrBackendObjectOwnership,
245               GrWrapCacheable,
246               bool forSecondaryCB);
247 
248     void init(GrVkGpu*, bool forSecondaryCB);
249 
250     void onRelease() override;
251     void onAbandon() override;
252 
253     void releaseImage();
hasResource()254     bool hasResource() const { return fResource; }
255 
256     GrVkGpu* getVkGpu() const;
257 
258     GrVkImageInfo                           fInfo;
259     uint32_t                                fInitialQueueFamily;
260     sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
261 
262     sk_sp<const GrVkImageView>              fFramebufferView;
263     sk_sp<const GrVkImageView>              fTextureView;
264 
265     bool fIsBorrowed;
266 
267     // Descriptor set used when this is used as an input attachment for reading the dst in blending.
268     gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet;
269     // Descriptor set used when this is used as an input attachment for loading an msaa attachment.
270     gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet;
271 
272     class Resource : public GrTextureResource {
273     public:
Resource(const GrVkGpu * gpu)274         explicit Resource(const GrVkGpu* gpu)
275                 : fGpu(gpu)
276                 , fImage(VK_NULL_HANDLE) {
277             fAlloc.fMemory = VK_NULL_HANDLE;
278             fAlloc.fOffset = 0;
279         }
280 
Resource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)281         Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
282             : fGpu(gpu)
283             , fImage(image)
284             , fAlloc(alloc) {}
285 
~Resource()286         ~Resource() override {}
287 
288 #ifdef SK_TRACE_MANAGED_RESOURCES
dumpInfo()289         void dumpInfo() const override {
290             SkDebugf("GrVkImage: %" PRIdPTR " (%d refs)\n", (intptr_t)fImage, this->getRefCnt());
291         }
292 #endif
293 
294 #ifdef SK_DEBUG
asVkImageResource()295         const GrManagedResource* asVkImageResource() const override { return this; }
296 #endif
297 
298     private:
299         void freeGPUData() const override;
300 
301         const GrVkGpu* fGpu;
302         VkImage        fImage;
303         GrVkAlloc      fAlloc;
304 
305         using INHERITED = GrTextureResource;
306     };
307 
308     // for wrapped textures
309     class BorrowedResource : public Resource {
310     public:
BorrowedResource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)311         BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc,
312                          VkImageTiling tiling)
313             : Resource(gpu, image, alloc, tiling) {
314         }
315     private:
316         void freeGPUData() const override;
317     };
318 
319     Resource* fResource;
320 
321     friend class GrVkRenderTarget;
322 };
323 
324 #endif
325