Home | History | Annotate | Download | only in vk
      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