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