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