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