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/vk/GrVkRenderTarget.h"
9
10 #include "include/gpu/GrBackendSurface.h"
11 #include "include/gpu/GrDirectContext.h"
12 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
13 #include "src/gpu/GrDirectContextPriv.h"
14 #include "src/gpu/GrResourceProvider.h"
15 #include "src/gpu/vk/GrVkAttachment.h"
16 #include "src/gpu/vk/GrVkCommandBuffer.h"
17 #include "src/gpu/vk/GrVkDescriptorSet.h"
18 #include "src/gpu/vk/GrVkFramebuffer.h"
19 #include "src/gpu/vk/GrVkGpu.h"
20 #include "src/gpu/vk/GrVkImageView.h"
21 #include "src/gpu/vk/GrVkResourceProvider.h"
22 #include "src/gpu/vk/GrVkUtil.h"
23
24 #include "include/gpu/vk/GrVkTypes.h"
25
26 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
27
renderpass_features_to_index(bool hasResolve,bool hasStencil,GrVkRenderPass::SelfDependencyFlags selfDepFlags,GrVkRenderPass::LoadFromResolve loadFromReslove)28 static int renderpass_features_to_index(bool hasResolve, bool hasStencil,
29 GrVkRenderPass::SelfDependencyFlags selfDepFlags,
30 GrVkRenderPass::LoadFromResolve loadFromReslove) {
31 int index = 0;
32 if (hasResolve) {
33 index += 1;
34 }
35 if (hasStencil) {
36 index += 2;
37 }
38 if (selfDepFlags & GrVkRenderPass::SelfDependencyFlags::kForInputAttachment) {
39 index += 4;
40 }
41 if (selfDepFlags & GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend) {
42 index += 8;
43 }
44 if (loadFromReslove == GrVkRenderPass::LoadFromResolve::kLoad) {
45 index += 16;
46 }
47 return index;
48 }
49
50 // We're virtually derived from GrSurface (via GrRenderTarget) so its
51 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkAttachment> colorAttachment,sk_sp<GrVkAttachment> resolveAttachment,CreateType createType)52 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
53 SkISize dimensions,
54 sk_sp<GrVkAttachment> colorAttachment,
55 sk_sp<GrVkAttachment> resolveAttachment,
56 CreateType createType)
57 : GrSurface(gpu, dimensions,
58 colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo)
59 // for the moment we only support 1:1 color to stencil
60 , GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(),
61 colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo)
62 , fColorAttachment(std::move(colorAttachment))
63 , fResolveAttachment(std::move(resolveAttachment))
64 , fCachedFramebuffers() {
65 SkASSERT(fColorAttachment);
66 SkASSERT(!resolveAttachment ||
67 (fResolveAttachment->isProtected() == fColorAttachment->isProtected()));
68 SkASSERT(SkToBool(fColorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
69 this->setFlags();
70 if (createType == CreateType::kDirectlyWrapped) {
71 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
72 }
73 }
74
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkFramebuffer> externalFramebuffer)75 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
76 SkISize dimensions,
77 sk_sp<GrVkFramebuffer> externalFramebuffer)
78 : GrSurface(gpu, dimensions,
79 externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
80 : GrProtected::kNo)
81 , GrRenderTarget(gpu, dimensions, 1,
82 externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
83 : GrProtected::kNo)
84 , fCachedFramebuffers()
85 , fExternalFramebuffer(externalFramebuffer) {
86 SkASSERT(fExternalFramebuffer);
87 SkASSERT(!fColorAttachment);
88 SkDEBUGCODE(auto colorAttachment = fExternalFramebuffer->colorAttachment());
89 SkASSERT(colorAttachment);
90 SkASSERT(colorAttachment->numSamples() == 1);
91 SkASSERT(SkToBool(colorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
92 SkASSERT(!SkToBool(colorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT));
93 this->setFlags();
94 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
95 }
96
setFlags()97 void GrVkRenderTarget::setFlags() {
98 if (this->wrapsSecondaryCommandBuffer()) {
99 return;
100 }
101 GrVkAttachment* nonMSAAAttachment = this->nonMSAAAttachment();
102 if (nonMSAAAttachment && nonMSAAAttachment->supportsInputAttachmentUsage()) {
103 this->setVkRTSupportsInputAttachment();
104 }
105 }
106
MakeWrappedRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)107 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
108 GrVkGpu* gpu,
109 SkISize dimensions,
110 int sampleCnt,
111 const GrVkImageInfo& info,
112 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
113 SkASSERT(VK_NULL_HANDLE != info.fImage);
114 SkASSERT(1 == info.fLevelCount);
115 SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
116
117 int wrappedImageSampleCnt = static_cast<int>(info.fSampleCount);
118 if (sampleCnt != wrappedImageSampleCnt && wrappedImageSampleCnt != 1) {
119 return nullptr;
120 }
121
122 sk_sp<GrVkAttachment> wrappedAttachment =
123 GrVkAttachment::MakeWrapped(gpu, dimensions, info, std::move(mutableState),
124 GrAttachment::UsageFlags::kColorAttachment,
125 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo);
126 if (!wrappedAttachment) {
127 return nullptr;
128 }
129
130 sk_sp<GrVkAttachment> colorAttachment;
131 colorAttachment = std::move(wrappedAttachment);
132
133 if (!colorAttachment) {
134 return nullptr;
135 }
136
137 GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, std::move(colorAttachment),
138 nullptr, CreateType::kDirectlyWrapped);
139 return sk_sp<GrVkRenderTarget>(vkRT);
140 }
141
MakeSecondaryCBRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkDrawableInfo & vkInfo)142 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
143 GrVkGpu* gpu, SkISize dimensions, const GrVkDrawableInfo& vkInfo) {
144 const GrVkRenderPass* rp = gpu->resourceProvider().findCompatibleExternalRenderPass(
145 vkInfo.fCompatibleRenderPass, vkInfo.fColorAttachmentIndex);
146 if (!rp) {
147 return nullptr;
148 }
149
150 if (vkInfo.fSecondaryCommandBuffer == VK_NULL_HANDLE) {
151 return nullptr;
152 }
153
154 // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
155 // others we keep at the default "null" values.
156 GrVkImageInfo info;
157 info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
158 info.fFormat = vkInfo.fFormat;
159 info.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
160 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
161
162 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(new GrBackendSurfaceMutableStateImpl(
163 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED));
164
165 sk_sp<GrVkAttachment> colorAttachment =
166 GrVkAttachment::MakeWrapped(gpu, dimensions, info, std::move(mutableState),
167 GrAttachment::UsageFlags::kColorAttachment,
168 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, true);
169
170 std::unique_ptr<GrVkSecondaryCommandBuffer> scb(
171 GrVkSecondaryCommandBuffer::Create(vkInfo.fSecondaryCommandBuffer, rp));
172 if (!scb) {
173 return nullptr;
174 }
175
176 sk_sp<GrVkFramebuffer> framebuffer(new GrVkFramebuffer(
177 gpu, std::move(colorAttachment), sk_sp<const GrVkRenderPass>(rp),
178 std::move(scb)));
179
180 GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, std::move(framebuffer));
181
182 return sk_sp<GrVkRenderTarget>(vkRT);
183 }
184
backendFormat() const185 GrBackendFormat GrVkRenderTarget::backendFormat() const {
186 if (this->wrapsSecondaryCommandBuffer()) {
187 return fExternalFramebuffer->colorAttachment()->getBackendFormat();
188 }
189 return fColorAttachment->getBackendFormat();
190 }
191
nonMSAAAttachment() const192 GrVkAttachment* GrVkRenderTarget::nonMSAAAttachment() const {
193 if (fColorAttachment->numSamples() == 1) {
194 return fColorAttachment.get();
195 } else {
196 return fResolveAttachment.get();
197 }
198 }
199
dynamicMSAAAttachment()200 GrVkAttachment* GrVkRenderTarget::dynamicMSAAAttachment() {
201 if (fDynamicMSAAAttachment) {
202 return fDynamicMSAAAttachment.get();
203 }
204 const GrVkAttachment* nonMSAAColorAttachment = this->colorAttachment();
205 SkASSERT(nonMSAAColorAttachment->numSamples() == 1);
206
207 GrVkGpu* gpu = this->getVkGpu();
208 auto rp = gpu->getContext()->priv().resourceProvider();
209
210 const GrBackendFormat& format = nonMSAAColorAttachment->backendFormat();
211
212 sk_sp<GrAttachment> msaaAttachment =
213 rp->makeMSAAAttachment(nonMSAAColorAttachment->dimensions(),
214 format,
215 gpu->caps()->internalMultisampleCount(format),
216 GrProtected(nonMSAAColorAttachment->isProtected()));
217 if (!msaaAttachment) {
218 return nullptr;
219 }
220 fDynamicMSAAAttachment =
221 sk_sp<GrVkAttachment>(static_cast<GrVkAttachment*>(msaaAttachment.release()));
222 return fDynamicMSAAAttachment.get();
223 }
224
msaaAttachment()225 GrVkAttachment* GrVkRenderTarget::msaaAttachment() {
226 return this->colorAttachment()->numSamples() == 1 ? this->dynamicMSAAAttachment()
227 : this->colorAttachment();
228 }
229
completeStencilAttachment(GrAttachment * stencil,bool useMSAASurface)230 bool GrVkRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
231 SkASSERT(!this->wrapsSecondaryCommandBuffer());
232 SkASSERT(useMSAASurface == (this->numSamples() > 1));
233 return true;
234 }
235
externalFramebuffer() const236 sk_sp<GrVkFramebuffer> GrVkRenderTarget::externalFramebuffer() const {
237 return fExternalFramebuffer;
238 }
239
compatibleRenderPassHandle(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)240 GrVkResourceProvider::CompatibleRPHandle GrVkRenderTarget::compatibleRenderPassHandle(
241 bool withResolve,
242 bool withStencil,
243 SelfDependencyFlags selfDepFlags,
244 LoadFromResolve loadFromResolve) {
245 SkASSERT(!this->wrapsSecondaryCommandBuffer());
246
247 const GrVkFramebuffer* fb =
248 this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
249 if (!fb) {
250 return {};
251 }
252
253 return fb->compatibleRenderPassHandle();
254 }
255
getSimpleRenderPass(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)256 const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withResolve,
257 bool withStencil,
258 SelfDependencyFlags selfDepFlags,
259 LoadFromResolve loadFromResolve) {
260 if (this->wrapsSecondaryCommandBuffer()) {
261 return fExternalFramebuffer->externalRenderPass();
262 }
263
264 const GrVkFramebuffer* fb =
265 this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
266 if (!fb) {
267 return nullptr;
268 }
269
270 return fb->compatibleRenderPass();
271 }
272
273 std::pair<const GrVkRenderPass*, GrVkResourceProvider::CompatibleRPHandle>
createSimpleRenderPass(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)274 GrVkRenderTarget::createSimpleRenderPass(bool withResolve,
275 bool withStencil,
276 SelfDependencyFlags selfDepFlags,
277 LoadFromResolve loadFromResolve) {
278 SkASSERT(!this->wrapsSecondaryCommandBuffer());
279
280 GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();
281
282 GrVkResourceProvider::CompatibleRPHandle handle;
283 const GrVkRenderPass* renderPass = rp.findCompatibleRenderPass(
284 this, &handle, withResolve, withStencil, selfDepFlags,
285 loadFromResolve);
286 SkASSERT(!renderPass || handle.isValid());
287 return {renderPass, handle};
288 }
289
getFramebuffer(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)290 const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withResolve,
291 bool withStencil,
292 SelfDependencyFlags selfDepFlags,
293 LoadFromResolve loadFromResolve) {
294 int cacheIndex =
295 renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
296 SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
297 if (auto fb = fCachedFramebuffers[cacheIndex]) {
298 return fb.get();
299 }
300
301 this->createFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
302 return fCachedFramebuffers[cacheIndex].get();
303 }
304
createFramebuffer(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)305 void GrVkRenderTarget::createFramebuffer(bool withResolve,
306 bool withStencil,
307 SelfDependencyFlags selfDepFlags,
308 LoadFromResolve loadFromResolve) {
309 SkASSERT(!this->wrapsSecondaryCommandBuffer());
310 GrVkGpu* gpu = this->getVkGpu();
311
312 auto[renderPass, compatibleHandle] =
313 this->createSimpleRenderPass(withResolve, withStencil, selfDepFlags, loadFromResolve);
314 if (!renderPass) {
315 return;
316 }
317 SkASSERT(compatibleHandle.isValid());
318
319 int cacheIndex =
320 renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
321 SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
322
323 GrVkAttachment* resolve = withResolve ? this->resolveAttachment() : nullptr;
324 GrVkAttachment* colorAttachment =
325 withResolve ? this->msaaAttachment() : this->colorAttachment();
326
327 // Stencil attachment view is stored in the base RT stencil attachment
328 GrVkAttachment* stencil =
329 withStencil ? static_cast<GrVkAttachment*>(this->getStencilAttachment())
330 : nullptr;
331 fCachedFramebuffers[cacheIndex] =
332 GrVkFramebuffer::Make(gpu, this->dimensions(),
333 sk_sp<const GrVkRenderPass>(renderPass),
334 colorAttachment, resolve, stencil, compatibleHandle);
335 }
336
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags,bool withResolve,bool withStencil)337 void GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
338 GrVkRenderPass::AttachmentFlags* attachmentFlags,
339 bool withResolve,
340 bool withStencil) {
341 SkASSERT(!this->wrapsSecondaryCommandBuffer());
342 const GrVkAttachment* colorAttachment =
343 withResolve ? this->msaaAttachment() : this->colorAttachment();
344
345 desc->fColor.fFormat = colorAttachment->imageFormat();
346 desc->fColor.fSamples = colorAttachment->numSamples();
347 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
348 uint32_t attachmentCount = 1;
349
350 if (withResolve) {
351 desc->fResolve.fFormat = desc->fColor.fFormat;
352 desc->fResolve.fSamples = 1;
353 *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
354 ++attachmentCount;
355 }
356
357 if (withStencil) {
358 const GrAttachment* stencil = this->getStencilAttachment();
359 SkASSERT(stencil);
360 const GrVkAttachment* vkStencil = static_cast<const GrVkAttachment*>(stencil);
361 desc->fStencil.fFormat = vkStencil->imageFormat();
362 desc->fStencil.fSamples = vkStencil->numSamples();
363 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
364 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
365 ++attachmentCount;
366 }
367 desc->fAttachmentCount = attachmentCount;
368 }
369
ReconstructAttachmentsDescriptor(const GrVkCaps & vkCaps,const GrProgramInfo & programInfo,GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * flags)370 void GrVkRenderTarget::ReconstructAttachmentsDescriptor(const GrVkCaps& vkCaps,
371 const GrProgramInfo& programInfo,
372 GrVkRenderPass::AttachmentsDescriptor* desc,
373 GrVkRenderPass::AttachmentFlags* flags) {
374 VkFormat format;
375 SkAssertResult(programInfo.backendFormat().asVkFormat(&format));
376
377 desc->fColor.fFormat = format;
378 desc->fColor.fSamples = programInfo.numSamples();
379 *flags = GrVkRenderPass::kColor_AttachmentFlag;
380 uint32_t attachmentCount = 1;
381
382 if (programInfo.targetSupportsVkResolveLoad() && vkCaps.preferDiscardableMSAAAttachment()) {
383 desc->fResolve.fFormat = desc->fColor.fFormat;
384 desc->fResolve.fSamples = 1;
385 *flags |= GrVkRenderPass::kResolve_AttachmentFlag;
386 ++attachmentCount;
387 }
388
389 SkASSERT(!programInfo.isStencilEnabled() || programInfo.needsStencil());
390 if (programInfo.needsStencil()) {
391 VkFormat stencilFormat = vkCaps.preferredStencilFormat();
392 desc->fStencil.fFormat = stencilFormat;
393 desc->fStencil.fSamples = programInfo.numSamples();
394 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
395 *flags |= GrVkRenderPass::kStencil_AttachmentFlag;
396 ++attachmentCount;
397 }
398 desc->fAttachmentCount = attachmentCount;
399 }
400
~GrVkRenderTarget()401 GrVkRenderTarget::~GrVkRenderTarget() {
402 // either release or abandon should have been called by the owner of this object.
403 SkASSERT(!fColorAttachment);
404 SkASSERT(!fResolveAttachment);
405 SkASSERT(!fDynamicMSAAAttachment);
406
407 for (int i = 0; i < kNumCachedFramebuffers; ++i) {
408 SkASSERT(!fCachedFramebuffers[i]);
409 }
410
411 SkASSERT(!fCachedInputDescriptorSet);
412 }
413
releaseInternalObjects()414 void GrVkRenderTarget::releaseInternalObjects() {
415 fColorAttachment.reset();
416 fResolveAttachment.reset();
417 fDynamicMSAAAttachment.reset();
418
419 for (int i = 0; i < kNumCachedFramebuffers; ++i) {
420 if (fCachedFramebuffers[i]) {
421 fCachedFramebuffers[i].reset();
422 }
423 }
424
425 if (fCachedInputDescriptorSet) {
426 fCachedInputDescriptorSet->recycle();
427 fCachedInputDescriptorSet = nullptr;
428 }
429
430 fExternalFramebuffer.reset();
431 }
432
onRelease()433 void GrVkRenderTarget::onRelease() {
434 this->releaseInternalObjects();
435 GrRenderTarget::onRelease();
436 }
437
onAbandon()438 void GrVkRenderTarget::onAbandon() {
439 this->releaseInternalObjects();
440 GrRenderTarget::onAbandon();
441 }
442
getBackendRenderTarget() const443 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
444 SkASSERT(!this->wrapsSecondaryCommandBuffer());
445 // This should only get called with a non-released GrVkRenderTargets.
446 SkASSERT(!this->wasDestroyed());
447 // If we have a resolve attachment that is what we return for the backend render target
448 const GrVkAttachment* beAttachment = this->externalAttachment();
449 return GrBackendRenderTarget(beAttachment->width(), beAttachment->height(),
450 beAttachment->vkImageInfo(), beAttachment->getMutableState());
451 }
452
stencilImageResource() const453 const GrManagedResource* GrVkRenderTarget::stencilImageResource() const {
454 SkASSERT(!this->wrapsSecondaryCommandBuffer());
455 const GrAttachment* stencil = this->getStencilAttachment();
456 if (stencil) {
457 const GrVkAttachment* vkStencil = static_cast<const GrVkAttachment*>(stencil);
458 return vkStencil->imageResource();
459 }
460
461 return nullptr;
462 }
463
stencilAttachmentView() const464 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
465 SkASSERT(!this->wrapsSecondaryCommandBuffer());
466 const GrAttachment* stencil = this->getStencilAttachment();
467 if (stencil) {
468 const GrVkAttachment* vkStencil = static_cast<const GrVkAttachment*>(stencil);
469 return vkStencil->framebufferView();
470 }
471
472 return nullptr;
473 }
474
getVkGpu() const475 GrVkGpu* GrVkRenderTarget::getVkGpu() const {
476 SkASSERT(!this->wasDestroyed());
477 return static_cast<GrVkGpu*>(this->getGpu());
478 }
479