xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrAttachment.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2011 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 #include "src/gpu/ganesh/GrAttachment.h"
9 
10 #include "include/gpu/GpuTypes.h"
11 #include "include/private/base/SkAssert.h"
12 #include "include/private/base/SkTo.h"
13 #include "src/gpu/DataUtils.h"
14 #include "src/gpu/ResourceKey.h"
15 #include "src/gpu/ganesh/GrBackendUtils.h"
16 #include "src/gpu/ganesh/GrCaps.h"
17 #include "src/gpu/ganesh/GrGpu.h"
18 
19 enum class SkTextureCompressionType;
20 
onGpuMemorySize() const21 size_t GrAttachment::onGpuMemorySize() const {
22     // The GrTexture[RenderTarget] is built up by a bunch of attachments each of which are their
23     // own GrGpuResource. Ideally the GrRenderTarget would not be a GrGpuResource and the GrTexture
24     // would just merge with the new GrSurface/Attachment world. Then we could just depend on each
25     // attachment to give its own size since we don't have GrGpuResources owning other
26     // GrGpuResources. Until we get to that point we need to live in some hybrid world. We will let
27     // the msaa and stencil attachments track their own size because they do get cached separately.
28     // For all GrTexture* based things we will continue to to use the GrTexture* to report size and
29     // the owned attachments will have no size and be uncached.
30     if (!(fSupportedUsages & UsageFlags::kTexture) && fMemoryless == GrMemoryless::kNo) {
31         GrBackendFormat format = this->backendFormat();
32         SkTextureCompressionType compression = GrBackendFormatToCompressionType(format);
33 
34         uint64_t size = skgpu::NumCompressedBlocks(compression, this->dimensions());
35         size *= GrBackendFormatBytesPerBlock(this->backendFormat());
36         size *= this->numSamples();
37         return size;
38     }
39     return 0;
40 }
41 
build_key(skgpu::ResourceKey::Builder * builder,const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,GrAttachment::UsageFlags requiredUsage,int sampleCnt,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrMemoryless memoryless)42 static void build_key(skgpu::ResourceKey::Builder* builder,
43                       const GrCaps& caps,
44                       const GrBackendFormat& format,
45                       SkISize dimensions,
46                       GrAttachment::UsageFlags requiredUsage,
47                       int sampleCnt,
48                       skgpu::Mipmapped mipmapped,
49                       GrProtected isProtected,
50                       GrMemoryless memoryless) {
51     SkASSERT(!dimensions.isEmpty());
52 
53     SkASSERT(static_cast<uint32_t>(isProtected) <= 1);
54     SkASSERT(static_cast<uint32_t>(memoryless) <= 1);
55     SkASSERT(static_cast<uint32_t>(requiredUsage) < (1u << 8));
56     SkASSERT(static_cast<uint32_t>(sampleCnt) < (1u << (32 - 10)));
57 
58     uint64_t formatKey = caps.computeFormatKey(format);
59     (*builder)[0] = dimensions.width();
60     (*builder)[1] = dimensions.height();
61     (*builder)[2] = formatKey & 0xFFFFFFFF;
62     (*builder)[3] = (formatKey >> 32) & 0xFFFFFFFF;
63     (*builder)[4] = (static_cast<uint32_t>(isProtected) << 0) |
64                     (static_cast<uint32_t>(memoryless) << 1) |
65                     (static_cast<uint32_t>(requiredUsage) << 2) |
66                     (static_cast<uint32_t>(sampleCnt) << 10);
67 }
68 
ComputeSharedAttachmentUniqueKey(const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,UsageFlags requiredUsage,int sampleCnt,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrMemoryless memoryless,skgpu::UniqueKey * key)69 void GrAttachment::ComputeSharedAttachmentUniqueKey(const GrCaps& caps,
70                                                     const GrBackendFormat& format,
71                                                     SkISize dimensions,
72                                                     UsageFlags requiredUsage,
73                                                     int sampleCnt,
74                                                     skgpu::Mipmapped mipmapped,
75                                                     GrProtected isProtected,
76                                                     GrMemoryless memoryless,
77                                                     skgpu::UniqueKey* key) {
78     static const skgpu::UniqueKey::Domain kDomain = skgpu::UniqueKey::GenerateDomain();
79 
80     skgpu::UniqueKey::Builder builder(key, kDomain, 5);
81     build_key(&builder, caps, format, dimensions, requiredUsage, sampleCnt, mipmapped, isProtected,
82               memoryless);
83 }
84 
ComputeScratchKey(const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,UsageFlags requiredUsage,int sampleCnt,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrMemoryless memoryless,skgpu::ScratchKey * key)85 void GrAttachment::ComputeScratchKey(const GrCaps& caps,
86                                      const GrBackendFormat& format,
87                                      SkISize dimensions,
88                                      UsageFlags requiredUsage,
89                                      int sampleCnt,
90                                      skgpu::Mipmapped mipmapped,
91                                      GrProtected isProtected,
92                                      GrMemoryless memoryless,
93                                      skgpu::ScratchKey* key) {
94     static const skgpu::ScratchKey::ResourceType kType = skgpu::ScratchKey::GenerateResourceType();
95 
96     skgpu::ScratchKey::Builder builder(key, kType, 5);
97     build_key(&builder, caps, format, dimensions, requiredUsage, sampleCnt, mipmapped, isProtected,
98               memoryless);
99 }
100 
computeScratchKey(skgpu::ScratchKey * key) const101 void GrAttachment::computeScratchKey(skgpu::ScratchKey* key) const {
102     // We do don't cache GrAttachments as scratch resources when used for stencils or textures. For
103     // stencils we share/cache them with unique keys so that they can be shared. Textures are in a
104     // weird place on the Vulkan backend. Currently, GrVkTexture contains a GrAttachment (GrVkImage)
105     // that actually holds the VkImage. The GrVkTexture is cached as a scratch resource and is
106     // responsible for tracking the gpuMemorySize. Thus we set the size of the texture GrVkImage,
107     // above in onGpuMemorySize, to be zero. Therefore, we can't have the GrVkImage getting cached
108     // separately on its own in the GrResourceCache or we may grow forever adding them thinking they
109     // contatin a memory that's size 0 and never freeing the actual VkImages.
110     if (!SkToBool(fSupportedUsages & UsageFlags::kStencilAttachment) &&
111         !SkToBool(fSupportedUsages & UsageFlags::kTexture)) {
112         auto isProtected = this->isProtected() ? GrProtected::kYes : GrProtected::kNo;
113         ComputeScratchKey(*this->getGpu()->caps(),
114                           this->backendFormat(),
115                           this->dimensions(),
116                           fSupportedUsages,
117                           this->numSamples(),
118                           this->mipmapped(),
119                           isProtected,
120                           fMemoryless,
121                           key);
122     }
123 }
124