• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const42 void GrAttachment::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
43     SkString type;
44     if (fSupportedUsages == UsageFlags::kStencilAttachment) {
45         type = "StencilAttachment";
46     }
47 
48     if (fSupportedUsages & UsageFlags::kTexture) {
49         // This return since the memory should all be handled by the textures
50         return;
51     } else if (fSupportedUsages & UsageFlags::kColorAttachment) {
52         type = "ColorAttachment";
53     }
54 
55     SkString resourceName = this->getResourceName();
56     resourceName.append("/attachment");
57     this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, type.c_str(), onGpuMemorySize());
58 }
59 
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)60 static void build_key(skgpu::ResourceKey::Builder* builder,
61                       const GrCaps& caps,
62                       const GrBackendFormat& format,
63                       SkISize dimensions,
64                       GrAttachment::UsageFlags requiredUsage,
65                       int sampleCnt,
66                       skgpu::Mipmapped mipmapped,
67                       GrProtected isProtected,
68                       GrMemoryless memoryless) {
69     SkASSERT(!dimensions.isEmpty());
70 
71     SkASSERT(static_cast<uint32_t>(isProtected) <= 1);
72     SkASSERT(static_cast<uint32_t>(memoryless) <= 1);
73     SkASSERT(static_cast<uint32_t>(requiredUsage) < (1u << 8));
74     SkASSERT(static_cast<uint32_t>(sampleCnt) < (1u << (32 - 10)));
75 
76     uint64_t formatKey = caps.computeFormatKey(format);
77     (*builder)[0] = dimensions.width();
78     (*builder)[1] = dimensions.height();
79     (*builder)[2] = formatKey & 0xFFFFFFFF;
80     (*builder)[3] = (formatKey >> 32) & 0xFFFFFFFF;
81     (*builder)[4] = (static_cast<uint32_t>(isProtected) << 0) |
82                     (static_cast<uint32_t>(memoryless) << 1) |
83                     (static_cast<uint32_t>(requiredUsage) << 2) |
84                     (static_cast<uint32_t>(sampleCnt) << 10);
85 }
86 
ComputeSharedAttachmentUniqueKey(const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,UsageFlags requiredUsage,int sampleCnt,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrMemoryless memoryless,skgpu::UniqueKey * key)87 void GrAttachment::ComputeSharedAttachmentUniqueKey(const GrCaps& caps,
88                                                     const GrBackendFormat& format,
89                                                     SkISize dimensions,
90                                                     UsageFlags requiredUsage,
91                                                     int sampleCnt,
92                                                     skgpu::Mipmapped mipmapped,
93                                                     GrProtected isProtected,
94                                                     GrMemoryless memoryless,
95                                                     skgpu::UniqueKey* key) {
96     static const skgpu::UniqueKey::Domain kDomain = skgpu::UniqueKey::GenerateDomain();
97 
98     skgpu::UniqueKey::Builder builder(key, kDomain, 5);
99     build_key(&builder, caps, format, dimensions, requiredUsage, sampleCnt, mipmapped, isProtected,
100               memoryless);
101 }
102 
ComputeScratchKey(const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,UsageFlags requiredUsage,int sampleCnt,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrMemoryless memoryless,skgpu::ScratchKey * key)103 void GrAttachment::ComputeScratchKey(const GrCaps& caps,
104                                      const GrBackendFormat& format,
105                                      SkISize dimensions,
106                                      UsageFlags requiredUsage,
107                                      int sampleCnt,
108                                      skgpu::Mipmapped mipmapped,
109                                      GrProtected isProtected,
110                                      GrMemoryless memoryless,
111                                      skgpu::ScratchKey* key) {
112     static const skgpu::ScratchKey::ResourceType kType = skgpu::ScratchKey::GenerateResourceType();
113 
114     skgpu::ScratchKey::Builder builder(key, kType, 5);
115     build_key(&builder, caps, format, dimensions, requiredUsage, sampleCnt, mipmapped, isProtected,
116               memoryless);
117 }
118 
computeScratchKey(skgpu::ScratchKey * key) const119 void GrAttachment::computeScratchKey(skgpu::ScratchKey* key) const {
120     // We do don't cache GrAttachments as scratch resources when used for stencils or textures. For
121     // stencils we share/cache them with unique keys so that they can be shared. Textures are in a
122     // weird place on the Vulkan backend. Currently, GrVkTexture contains a GrAttachment (GrVkImage)
123     // that actually holds the VkImage. The GrVkTexture is cached as a scratch resource and is
124     // responsible for tracking the gpuMemorySize. Thus we set the size of the texture GrVkImage,
125     // above in onGpuMemorySize, to be zero. Therefore, we can't have the GrVkImage getting cached
126     // separately on its own in the GrResourceCache or we may grow forever adding them thinking they
127     // contatin a memory that's size 0 and never freeing the actual VkImages.
128     if (!SkToBool(fSupportedUsages & UsageFlags::kStencilAttachment) &&
129         !SkToBool(fSupportedUsages & UsageFlags::kTexture)) {
130         auto isProtected = this->isProtected() ? GrProtected::kYes : GrProtected::kNo;
131         ComputeScratchKey(*this->getGpu()->caps(),
132                           this->backendFormat(),
133                           this->dimensions(),
134                           fSupportedUsages,
135                           this->numSamples(),
136                           this->mipmapped(),
137                           isProtected,
138                           fMemoryless,
139                           key);
140     }
141 }
142