| OLD | NEW |
| (Empty) |
| 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, colorI
mage, pixelFormat, | |
| 162 GrVkImageVi
ew::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, msaaRe
source, | |
| 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, im
ageDesc); | |
| 192 if (!imageResource) { | |
| 193 return nullptr; | |
| 194 } | |
| 195 | |
| 196 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageR
esource); | |
| 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* imageReso
urce) { | |
| 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 wit
h 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().findOrCreateCompatibleRend
erPass(*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, fColorAttach
mentView, | |
| 236 fResolveAttachmentView, stencilView); | |
| 237 SkASSERT(fFramebuffer); | |
| 238 } | |
| 239 | |
| 240 void GrVkRenderTarget::getAttachmentsDescriptor( | |
| 241 GrVkRenderPass::AttachmentsDescriptor
* desc, | |
| 242 GrVkRenderPass::AttachmentFlags* atta
chmentFlags) 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().getStencilAtta
chment(); | |
| 258 if (stencil) { | |
| 259 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAt
tachment*>(stencil); | |
| 260 desc->fStencil.fFormat = vkStencil->vkFormat(); | |
| 261 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSample
s() : 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 ob
ject. | |
| 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 th
e handle | |
| 363 return (GrBackendObject)&fResource; | |
| 364 } | |
| 365 | |
| 366 const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const { | |
| 367 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAtta
chment(); | |
| 368 if (stencil) { | |
| 369 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAt
tachment*>(stencil); | |
| 370 return vkStencil->imageResource(); | |
| 371 } | |
| 372 | |
| 373 return nullptr; | |
| 374 } | |
| 375 | |
| 376 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const { | |
| 377 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAtta
chment(); | |
| 378 if (stencil) { | |
| 379 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAt
tachment*>(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 | |
| OLD | NEW |