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