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