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