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 "GrVkRenderTarget.h" 9 10 #include "GrRenderTargetPriv.h" 11 #include "GrVkCommandBuffer.h" 12 #include "GrVkFramebuffer.h" 13 #include "GrVkGpu.h" 14 #include "GrVkImageView.h" 15 #include "GrVkResourceProvider.h" 16 #include "GrVkUtil.h" 17 18 #include "vk/GrVkTypes.h" 19 20 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) 21 22 // We're virtually derived from GrSurface (via GrRenderTarget) so its 23 // constructor must be explicitly called. GrVkRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageInfo & msaaInfo,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrVkImage::Wrapped wrapped)24 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, 25 SkBudgeted budgeted, 26 const GrSurfaceDesc& desc, 27 const GrVkImageInfo& info, 28 const GrVkImageInfo& msaaInfo, 29 const GrVkImageView* colorAttachmentView, 30 const GrVkImageView* resolveAttachmentView, 31 GrVkImage::Wrapped wrapped) 32 : GrSurface(gpu, desc) 33 , GrVkImage(info, wrapped) 34 // for the moment we only support 1:1 color to stencil 35 , GrRenderTarget(gpu, desc) 36 , fColorAttachmentView(colorAttachmentView) 37 , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped)) 38 , fResolveAttachmentView(resolveAttachmentView) 39 , fFramebuffer(nullptr) 40 , fCachedSimpleRenderPass(nullptr) { 41 SkASSERT(desc.fSampleCnt); 42 this->createFramebuffer(gpu); 43 this->registerWithCache(budgeted); 44 } 45 46 // We're virtually derived from GrSurface (via GrRenderTarget) so its 47 // constructor must be explicitly called. GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageInfo & msaaInfo,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrVkImage::Wrapped wrapped)48 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, 49 const GrSurfaceDesc& desc, 50 const GrVkImageInfo& info, 51 const GrVkImageInfo& msaaInfo, 52 const GrVkImageView* colorAttachmentView, 53 const GrVkImageView* resolveAttachmentView, 54 GrVkImage::Wrapped wrapped) 55 : GrSurface(gpu, desc) 56 , GrVkImage(info, wrapped) 57 // for the moment we only support 1:1 color to stencil 58 , GrRenderTarget(gpu, desc) 59 , fColorAttachmentView(colorAttachmentView) 60 , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped)) 61 , fResolveAttachmentView(resolveAttachmentView) 62 , fFramebuffer(nullptr) 63 , fCachedSimpleRenderPass(nullptr) { 64 SkASSERT(desc.fSampleCnt); 65 this->createFramebuffer(gpu); 66 } 67 68 // We're virtually derived from GrSurface (via GrRenderTarget) so its 69 // constructor must be explicitly called. GrVkRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * colorAttachmentView,GrVkImage::Wrapped wrapped)70 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, 71 SkBudgeted budgeted, 72 const GrSurfaceDesc& desc, 73 const GrVkImageInfo& info, 74 const GrVkImageView* colorAttachmentView, 75 GrVkImage::Wrapped wrapped) 76 : GrSurface(gpu, desc) 77 , GrVkImage(info, wrapped) 78 , GrRenderTarget(gpu, desc) 79 , fColorAttachmentView(colorAttachmentView) 80 , fMSAAImage(nullptr) 81 , fResolveAttachmentView(nullptr) 82 , fFramebuffer(nullptr) 83 , fCachedSimpleRenderPass(nullptr) { 84 SkASSERT(!desc.fSampleCnt); 85 this->createFramebuffer(gpu); 86 this->registerWithCache(budgeted); 87 } 88 89 // We're virtually derived from GrSurface (via GrRenderTarget) so its 90 // constructor must be explicitly called. GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * colorAttachmentView,GrVkImage::Wrapped wrapped)91 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, 92 const GrSurfaceDesc& desc, 93 const GrVkImageInfo& info, 94 const GrVkImageView* colorAttachmentView, 95 GrVkImage::Wrapped wrapped) 96 : GrSurface(gpu, desc) 97 , GrVkImage(info, wrapped) 98 , GrRenderTarget(gpu, desc) 99 , fColorAttachmentView(colorAttachmentView) 100 , fMSAAImage(nullptr) 101 , fResolveAttachmentView(nullptr) 102 , fFramebuffer(nullptr) 103 , fCachedSimpleRenderPass(nullptr) { 104 SkASSERT(!desc.fSampleCnt); 105 this->createFramebuffer(gpu); 106 } 107 108 GrVkRenderTarget* Create(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,GrVkImage::Wrapped wrapped)109 GrVkRenderTarget::Create(GrVkGpu* gpu, 110 SkBudgeted budgeted, 111 const GrSurfaceDesc& desc, 112 const GrVkImageInfo& info, 113 GrVkImage::Wrapped wrapped) { 114 SkASSERT(1 == info.fLevelCount); 115 VkFormat pixelFormat; 116 GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat); 117 118 VkImage colorImage; 119 120 // create msaa surface if necessary 121 GrVkImageInfo msInfo; 122 const GrVkImageView* resolveAttachmentView = nullptr; 123 if (desc.fSampleCnt) { 124 GrVkImage::ImageDesc msImageDesc; 125 msImageDesc.fImageType = VK_IMAGE_TYPE_2D; 126 msImageDesc.fFormat = pixelFormat; 127 msImageDesc.fWidth = desc.fWidth; 128 msImageDesc.fHeight = desc.fHeight; 129 msImageDesc.fLevels = 1; 130 msImageDesc.fSamples = desc.fSampleCnt; 131 msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL; 132 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 133 VK_IMAGE_USAGE_TRANSFER_DST_BIT | 134 VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 135 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 136 137 if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) { 138 return nullptr; 139 } 140 141 // Set color attachment image 142 colorImage = msInfo.fImage; 143 144 // Create Resolve attachment view 145 resolveAttachmentView = GrVkImageView::Create(gpu, info.fImage, pixelFormat, 146 GrVkImageView::kColor_Type, 1); 147 if (!resolveAttachmentView) { 148 GrVkImage::DestroyImageInfo(gpu, &msInfo); 149 return nullptr; 150 } 151 } else { 152 // Set color attachment image 153 colorImage = info.fImage; 154 } 155 156 // Get color attachment view 157 const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat, 158 GrVkImageView::kColor_Type, 1); 159 if (!colorAttachmentView) { 160 if (desc.fSampleCnt) { 161 resolveAttachmentView->unref(gpu); 162 GrVkImage::DestroyImageInfo(gpu, &msInfo); 163 } 164 return nullptr; 165 } 166 167 GrVkRenderTarget* texRT; 168 if (desc.fSampleCnt) { 169 texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, msInfo, 170 colorAttachmentView, resolveAttachmentView, wrapped); 171 } else { 172 texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, colorAttachmentView, wrapped); 173 } 174 175 return texRT; 176 } 177 178 GrVkRenderTarget* CreateNewRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImage::ImageDesc & imageDesc)179 GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu, 180 SkBudgeted budgeted, 181 const GrSurfaceDesc& desc, 182 const GrVkImage::ImageDesc& imageDesc) { 183 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); 184 185 GrVkImageInfo info; 186 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) { 187 return nullptr; 188 } 189 190 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, budgeted, desc, info, 191 GrVkImage::kNot_Wrapped); 192 if (!rt) { 193 GrVkImage::DestroyImageInfo(gpu, &info); 194 } 195 return rt; 196 } 197 198 sk_sp<GrVkRenderTarget> MakeWrappedRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo * info)199 GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu, 200 const GrSurfaceDesc& desc, 201 const GrVkImageInfo* info) { 202 SkASSERT(info); 203 SkASSERT(VK_NULL_HANDLE != info->fImage); 204 205 return sk_sp<GrVkRenderTarget>( 206 GrVkRenderTarget::Create(gpu, SkBudgeted::kNo, desc, *info, GrVkImage::kBorrowed_Wrapped)); 207 } 208 completeStencilAttachment()209 bool GrVkRenderTarget::completeStencilAttachment() { 210 this->createFramebuffer(this->getVkGpu()); 211 return true; 212 } 213 createFramebuffer(GrVkGpu * gpu)214 void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) { 215 if (fFramebuffer) { 216 fFramebuffer->unref(gpu); 217 } 218 if (fCachedSimpleRenderPass) { 219 fCachedSimpleRenderPass->unref(gpu); 220 } 221 222 // Vulkan requires us to create a compatible renderpass before we can create our framebuffer, 223 // so we use this to get a (cached) basic renderpass, only for creation. 224 fCachedSimpleRenderPass = 225 gpu->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle); 226 227 // Stencil attachment view is stored in the base RT stencil attachment 228 const GrVkImageView* stencilView = this->stencilAttachmentView(); 229 fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), 230 fCachedSimpleRenderPass, fColorAttachmentView, 231 stencilView); 232 SkASSERT(fFramebuffer); 233 } 234 getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags) const235 void GrVkRenderTarget::getAttachmentsDescriptor( 236 GrVkRenderPass::AttachmentsDescriptor* desc, 237 GrVkRenderPass::AttachmentFlags* attachmentFlags) const { 238 int colorSamples = this->numColorSamples(); 239 VkFormat colorFormat; 240 GrPixelConfigToVkFormat(this->config(), &colorFormat); 241 desc->fColor.fFormat = colorFormat; 242 desc->fColor.fSamples = colorSamples ? colorSamples : 1; 243 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag; 244 uint32_t attachmentCount = 1; 245 246 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); 247 if (stencil) { 248 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); 249 desc->fStencil.fFormat = vkStencil->vkFormat(); 250 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1; 251 // Currently in vulkan stencil and color attachments must all have same number of samples 252 SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples); 253 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag; 254 ++attachmentCount; 255 } 256 desc->fAttachmentCount = attachmentCount; 257 } 258 ~GrVkRenderTarget()259 GrVkRenderTarget::~GrVkRenderTarget() { 260 // either release or abandon should have been called by the owner of this object. 261 SkASSERT(!fMSAAImage); 262 SkASSERT(!fResolveAttachmentView); 263 SkASSERT(!fColorAttachmentView); 264 SkASSERT(!fFramebuffer); 265 SkASSERT(!fCachedSimpleRenderPass); 266 } 267 addResources(GrVkCommandBuffer & commandBuffer) const268 void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const { 269 commandBuffer.addResource(this->framebuffer()); 270 commandBuffer.addResource(this->colorAttachmentView()); 271 commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource() 272 : this->resource()); 273 if (this->stencilImageResource()) { 274 commandBuffer.addResource(this->stencilImageResource()); 275 commandBuffer.addResource(this->stencilAttachmentView()); 276 } 277 } 278 releaseInternalObjects()279 void GrVkRenderTarget::releaseInternalObjects() { 280 GrVkGpu* gpu = this->getVkGpu(); 281 282 if (fMSAAImage) { 283 fMSAAImage->releaseImage(gpu); 284 fMSAAImage = nullptr; 285 } 286 287 if (fResolveAttachmentView) { 288 fResolveAttachmentView->unref(gpu); 289 fResolveAttachmentView = nullptr; 290 } 291 if (fColorAttachmentView) { 292 fColorAttachmentView->unref(gpu); 293 fColorAttachmentView = nullptr; 294 } 295 if (fFramebuffer) { 296 fFramebuffer->unref(gpu); 297 fFramebuffer = nullptr; 298 } 299 if (fCachedSimpleRenderPass) { 300 fCachedSimpleRenderPass->unref(gpu); 301 fCachedSimpleRenderPass = nullptr; 302 } 303 } 304 abandonInternalObjects()305 void GrVkRenderTarget::abandonInternalObjects() { 306 if (fMSAAImage) { 307 fMSAAImage->abandonImage(); 308 fMSAAImage = nullptr; 309 } 310 311 if (fResolveAttachmentView) { 312 fResolveAttachmentView->unrefAndAbandon(); 313 fResolveAttachmentView = nullptr; 314 } 315 if (fColorAttachmentView) { 316 fColorAttachmentView->unrefAndAbandon(); 317 fColorAttachmentView = nullptr; 318 } 319 if (fFramebuffer) { 320 fFramebuffer->unrefAndAbandon(); 321 fFramebuffer = nullptr; 322 } 323 if (fCachedSimpleRenderPass) { 324 fCachedSimpleRenderPass->unrefAndAbandon(); 325 fCachedSimpleRenderPass = nullptr; 326 } 327 } 328 onRelease()329 void GrVkRenderTarget::onRelease() { 330 this->releaseInternalObjects(); 331 this->releaseImage(this->getVkGpu()); 332 GrRenderTarget::onRelease(); 333 } 334 onAbandon()335 void GrVkRenderTarget::onAbandon() { 336 this->abandonInternalObjects(); 337 this->abandonImage(); 338 GrRenderTarget::onAbandon(); 339 } 340 341 getRenderTargetHandle() const342 GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const { 343 // If the render target is multisampled, we currently return the ImageInfo for the resolved 344 // image. If we only wrap the msaa target (currently not implemented) we should return a handle 345 // to that instead. 346 return (GrBackendObject)&fInfo; 347 } 348 stencilImageResource() const349 const GrVkResource* GrVkRenderTarget::stencilImageResource() const { 350 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); 351 if (stencil) { 352 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); 353 return vkStencil->imageResource(); 354 } 355 356 return nullptr; 357 } 358 stencilAttachmentView() const359 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const { 360 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); 361 if (stencil) { 362 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); 363 return vkStencil->stencilView(); 364 } 365 366 return nullptr; 367 } 368 369 getVkGpu() const370 GrVkGpu* GrVkRenderTarget::getVkGpu() const { 371 SkASSERT(!this->wasDestroyed()); 372 return static_cast<GrVkGpu*>(this->getGpu()); 373 } 374