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