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 #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.
     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.
     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.
     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.
     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*
    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*
    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>
    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 
    209 bool GrVkRenderTarget::completeStencilAttachment() {
    210     this->createFramebuffer(this->getVkGpu());
    211     return true;
    212 }
    213 
    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 
    235 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 
    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 
    268 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 
    279 void GrVkRenderTarget::releaseInternalObjects() {
    280     GrVkGpu* gpu = this->getVkGpu();
    281 
    282     if (fMSAAImage) {
    283         fMSAAImage->releaseImage(gpu);
    284         fMSAAImage.reset();
    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 
    305 void GrVkRenderTarget::abandonInternalObjects() {
    306     if (fMSAAImage) {
    307         fMSAAImage->abandonImage();
    308         fMSAAImage.reset();
    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 
    329 void GrVkRenderTarget::onRelease() {
    330     this->releaseInternalObjects();
    331     this->releaseImage(this->getVkGpu());
    332     GrRenderTarget::onRelease();
    333 }
    334 
    335 void GrVkRenderTarget::onAbandon() {
    336     this->abandonInternalObjects();
    337     this->abandonImage();
    338     GrRenderTarget::onAbandon();
    339 }
    340 
    341 
    342 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 
    349 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 
    359 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 
    370 GrVkGpu* GrVkRenderTarget::getVkGpu() const {
    371     SkASSERT(!this->wasDestroyed());
    372     return static_cast<GrVkGpu*>(this->getGpu());
    373 }
    374