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