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