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