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 #include "src/gpu/ganesh/vk/GrVkTextureRenderTarget.h"
9
10 #include "include/core/SkSize.h"
11 #include "include/core/SkTypes.h"
12 #include "include/gpu/GpuTypes.h"
13 #include "include/gpu/MutableTextureState.h"
14 #include "include/gpu/ganesh/GrDirectContext.h"
15 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
16 #include "include/gpu/ganesh/vk/GrVkTypes.h"
17 #include "include/gpu/vk/VulkanTypes.h"
18 #include "src/gpu/ganesh/GrAttachment.h"
19 #include "src/gpu/ganesh/GrDirectContextPriv.h"
20 #include "src/gpu/ganesh/GrResourceProvider.h"
21 #include "src/gpu/ganesh/GrSurface.h"
22 #include "src/gpu/ganesh/vk/GrVkGpu.h"
23 #include "src/gpu/ganesh/vk/GrVkImage.h"
24 #include "src/gpu/ganesh/vk/GrVkUtil.h"
25
26 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
27
GrVkTextureRenderTarget(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,sk_sp<GrVkImage> texture,sk_sp<GrVkImage> colorAttachment,sk_sp<GrVkImage> resolveAttachment,GrMipmapStatus mipmapStatus,std::string_view label)28 GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
29 skgpu::Budgeted budgeted,
30 SkISize dimensions,
31 sk_sp<GrVkImage> texture,
32 sk_sp<GrVkImage> colorAttachment,
33 sk_sp<GrVkImage> resolveAttachment,
34 GrMipmapStatus mipmapStatus,
35 std::string_view label)
36 : GrSurface(gpu,
37 dimensions,
38 texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
39 label)
40 , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus, label)
41 , GrVkRenderTarget(gpu,
42 dimensions,
43 std::move(colorAttachment),
44 std::move(resolveAttachment),
45 CreateType::kFromTextureRT,
46 label) {
47 #ifdef SKIA_OHOS
48 GrVkImage* image = textureImage();
49 if (image && image->GetBudgeted() == skgpu::Budgeted::kYes) {
50 this->registerWithCache(skgpu::Budgeted::kNo);
51 } else {
52 this->registerWithCache(budgeted);
53 }
54 #else
55 this->registerWithCache(budgeted);
56 #endif
57 }
58
GrVkTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,sk_sp<GrVkImage> colorAttachment,sk_sp<GrVkImage> resolveAttachment,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,std::string_view label)59 GrVkTextureRenderTarget::GrVkTextureRenderTarget(
60 GrVkGpu* gpu,
61 SkISize dimensions,
62 sk_sp<GrVkImage> texture,
63 sk_sp<GrVkImage> colorAttachment,
64 sk_sp<GrVkImage> resolveAttachment,
65 GrMipmapStatus mipmapStatus,
66 GrWrapCacheable cacheable,
67 std::string_view label)
68 : GrSurface(gpu,
69 dimensions,
70 texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
71 label)
72 , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus, label)
73 , GrVkRenderTarget(gpu, dimensions, std::move(colorAttachment),
74 std::move(resolveAttachment), CreateType::kFromTextureRT, label) {
75 this->registerWithCacheWrapped(cacheable);
76 }
77
create_rt_attachments(GrVkGpu * gpu,SkISize dimensions,VkFormat format,int sampleCnt,GrProtected isProtected,sk_sp<GrVkImage> texture,sk_sp<GrVkImage> * colorAttachment,sk_sp<GrVkImage> * resolveAttachment)78 bool create_rt_attachments(GrVkGpu* gpu, SkISize dimensions, VkFormat format, int sampleCnt,
79 GrProtected isProtected,
80 sk_sp<GrVkImage> texture,
81 sk_sp<GrVkImage>* colorAttachment,
82 sk_sp<GrVkImage>* resolveAttachment) {
83 if (sampleCnt > 1) {
84 auto rp = gpu->getContext()->priv().resourceProvider();
85 sk_sp<GrAttachment> msaaAttachment = rp->makeMSAAAttachment(
86 dimensions, GrBackendFormats::MakeVk(format), sampleCnt, isProtected,
87 GrMemoryless::kNo);
88 if (!msaaAttachment) {
89 return false;
90 }
91 *colorAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
92 *resolveAttachment = std::move(texture);
93 } else {
94 *colorAttachment = std::move(texture);
95 }
96 return true;
97 }
98
MakeNewTextureRenderTarget(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,VkFormat format,uint32_t mipLevels,int sampleCnt,GrMipmapStatus mipmapStatus,GrProtected isProtected,std::string_view label)99 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarget(
100 GrVkGpu* gpu,
101 skgpu::Budgeted budgeted,
102 SkISize dimensions,
103 VkFormat format,
104 uint32_t mipLevels,
105 int sampleCnt,
106 GrMipmapStatus mipmapStatus,
107 GrProtected isProtected,
108 std::string_view label) {
109 sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(gpu,
110 dimensions,
111 format,
112 mipLevels,
113 GrRenderable::kYes,
114 /*numSamples=*/1,
115 budgeted,
116 isProtected);
117 if (!texture) {
118 return nullptr;
119 }
120
121 sk_sp<GrVkImage> colorAttachment;
122 sk_sp<GrVkImage> resolveAttachment;
123 if (!create_rt_attachments(gpu, dimensions, format, sampleCnt, isProtected, texture,
124 &colorAttachment, &resolveAttachment)) {
125 return nullptr;
126 }
127 SkASSERT(colorAttachment);
128 SkASSERT(sampleCnt == 1 || resolveAttachment);
129 return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(gpu,
130 budgeted,
131 dimensions,
132 std::move(texture),
133 std::move(colorAttachment),
134 std::move(resolveAttachment),
135 mipmapStatus,
136 label));
137 }
138
MakeWrappedTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState)139 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(
140 GrVkGpu* gpu,
141 SkISize dimensions,
142 int sampleCnt,
143 GrWrapOwnership wrapOwnership,
144 GrWrapCacheable cacheable,
145 const GrVkImageInfo& info,
146 sk_sp<skgpu::MutableTextureState> mutableState) {
147 // Adopted textures require both image and allocation because we're responsible for freeing
148 SkASSERT(VK_NULL_HANDLE != info.fImage &&
149 (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
150
151 GrAttachment::UsageFlags textureUsageFlags = GrAttachment::UsageFlags::kTexture;
152 if (info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
153 textureUsageFlags |= GrAttachment::UsageFlags::kColorAttachment;
154 }
155
156 sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
157 dimensions,
158 info,
159 std::move(mutableState),
160 textureUsageFlags,
161 wrapOwnership,
162 cacheable,
163 "VkImage_MakeWrappedTextureRenderTarget");
164 if (!texture) {
165 return nullptr;
166 }
167
168 sk_sp<GrVkImage> colorAttachment;
169 sk_sp<GrVkImage> resolveAttachment;
170 if (!create_rt_attachments(gpu, dimensions, info.fFormat, sampleCnt, info.fProtected, texture,
171 &colorAttachment, &resolveAttachment)) {
172 return nullptr;
173 }
174 SkASSERT(colorAttachment);
175 SkASSERT(sampleCnt == 1 || resolveAttachment);
176
177 GrMipmapStatus mipmapStatus =
178 info.fLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated;
179
180 return sk_sp<GrVkTextureRenderTarget>(
181 new GrVkTextureRenderTarget(gpu,
182 dimensions,
183 std::move(texture),
184 std::move(colorAttachment),
185 std::move(resolveAttachment),
186 mipmapStatus,
187 cacheable,
188 /*label=*/"Vk_MakeWrappedTextureRenderTarget"));
189 }
190
onGpuMemorySize() const191 size_t GrVkTextureRenderTarget::onGpuMemorySize() const {
192 // The GrTexture[RenderTarget] is built up by a bunch of attachments each of which are their
193 // own GrGpuResource. Ideally the GrRenderTarget would not be a GrGpuResource and the GrTexture
194 // would just merge with the new GrSurface/Attachment world. Then we could just depend on each
195 // attachment to give its own size since we don't have GrGpuResources owning other
196 // GrGpuResources. Until we get to that point we need to live in some hybrid world. We will let
197 // the msaa and stencil attachments track their own size because they do get cached separately.
198 // For all GrTexture* based things we will continue to to use the GrTexture* to report size and
199 // the owned attachments will have no size and be uncached.
200 #ifdef SK_DEBUG
201 // The nonMSAA attachment (either color or resolve depending on numSamples should have size of
202 // zero since it is a texture attachment.
203 SkASSERT(this->nonMSAAAttachment()->gpuMemorySize() == 0);
204 if (this->numSamples() > 1) {
205 // Msaa attachment should have a valid size
206 SkASSERT(this->colorAttachment()->gpuMemorySize() ==
207 GrSurface::ComputeSize(this->backendFormat(),
208 this->dimensions(),
209 this->numSamples(),
210 skgpu::Mipmapped::kNo));
211 }
212 #endif
213 return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
214 1 /*colorSamplesPerPixel*/, this->mipmapped());
215 }
216
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const217 void GrVkTextureRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
218 SkString resourceName = this->getResourceName();
219 resourceName.append("/texture_renderbuffer");
220 if (textureImage()->isBorrowed() && !textureImage()->isRealAlloc()) {
221 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "External RenderTarget",
222 this->gpuMemorySize());
223 } else {
224 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget",
225 this->gpuMemorySize());
226 }
227 }
228