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