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 "GrVkTextureRenderTarget.h"
9
10#include "GrTexturePriv.h"
11#include "GrVkGpu.h"
12#include "GrVkImageView.h"
13#include "GrVkUtil.h"
14
15#include "SkMipMap.h"
16
17#include "vk/GrVkTypes.h"
18
19#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
20
21GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
22                                                 SkBudgeted budgeted,
23                                                 const GrSurfaceDesc& desc,
24                                                 const GrVkImageInfo& info,
25                                                 const GrVkImageView* texView,
26                                                 const GrVkImageInfo& msaaInfo,
27                                                 const GrVkImageView* colorAttachmentView,
28                                                 const GrVkImageView* resolveAttachmentView,
29                                                 GrMipMapsStatus mipMapsStatus,
30                                                 GrBackendObjectOwnership ownership)
31        : GrSurface(gpu, desc)
32        , GrVkImage(info, ownership)
33        , GrVkTexture(gpu, desc, info, texView, mipMapsStatus, ownership)
34        , GrVkRenderTarget(gpu, desc, info, msaaInfo, colorAttachmentView,
35                           resolveAttachmentView, GrBackendObjectOwnership::kOwned) {
36    this->registerWithCache(budgeted);
37}
38
39GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
40                                                 SkBudgeted budgeted,
41                                                 const GrSurfaceDesc& desc,
42                                                 const GrVkImageInfo& info,
43                                                 const GrVkImageView* texView,
44                                                 const GrVkImageView* colorAttachmentView,
45                                                 GrMipMapsStatus mipMapsStatus,
46                                                 GrBackendObjectOwnership ownership)
47        : GrSurface(gpu, desc)
48        , GrVkImage(info, ownership)
49        , GrVkTexture(gpu, desc, info, texView, mipMapsStatus, ownership)
50        , GrVkRenderTarget(gpu, desc, info, colorAttachmentView, GrBackendObjectOwnership::kOwned) {
51    this->registerWithCache(budgeted);
52}
53
54GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
55                                                 const GrSurfaceDesc& desc,
56                                                 const GrVkImageInfo& info,
57                                                 const GrVkImageView* texView,
58                                                 const GrVkImageInfo& msaaInfo,
59                                                 const GrVkImageView* colorAttachmentView,
60                                                 const GrVkImageView* resolveAttachmentView,
61                                                 GrMipMapsStatus mipMapsStatus,
62                                                 GrBackendObjectOwnership ownership)
63        : GrSurface(gpu, desc)
64        , GrVkImage(info, ownership)
65        , GrVkTexture(gpu, desc, info, texView, mipMapsStatus, ownership)
66        , GrVkRenderTarget(gpu, desc, info, msaaInfo, colorAttachmentView,
67                           resolveAttachmentView, ownership) {
68    this->registerWithCacheWrapped();
69}
70
71GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
72                                                 const GrSurfaceDesc& desc,
73                                                 const GrVkImageInfo& info,
74                                                 const GrVkImageView* texView,
75                                                 const GrVkImageView* colorAttachmentView,
76                                                 GrMipMapsStatus mipMapsStatus,
77                                                 GrBackendObjectOwnership ownership)
78        : GrSurface(gpu, desc)
79        , GrVkImage(info, ownership)
80        , GrVkTexture(gpu, desc, info, texView, mipMapsStatus, ownership)
81        , GrVkRenderTarget(gpu, desc, info, colorAttachmentView, ownership) {
82    this->registerWithCacheWrapped();
83}
84
85sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::Make(GrVkGpu* gpu,
86                                                             const GrSurfaceDesc& desc,
87                                                             const GrVkImageInfo& info,
88                                                             GrMipMapsStatus mipMapsStatus,
89                                                             SkBudgeted budgeted,
90                                                             GrBackendObjectOwnership ownership,
91                                                             bool isWrapped) {
92    VkImage image = info.fImage;
93    // Create the texture ImageView
94    const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, info.fFormat,
95                                                           GrVkImageView::kColor_Type,
96                                                           info.fLevelCount);
97    if (!imageView) {
98        return nullptr;
99    }
100
101    VkFormat pixelFormat;
102    GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
103
104    VkImage colorImage;
105
106    // create msaa surface if necessary
107    GrVkImageInfo msInfo;
108    const GrVkImageView* resolveAttachmentView = nullptr;
109    if (desc.fSampleCnt > 1) {
110        GrVkImage::ImageDesc msImageDesc;
111        msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
112        msImageDesc.fFormat = pixelFormat;
113        msImageDesc.fWidth = desc.fWidth;
114        msImageDesc.fHeight = desc.fHeight;
115        msImageDesc.fLevels = 1;
116        msImageDesc.fSamples = desc.fSampleCnt;
117        msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
118        msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
119                                  VK_IMAGE_USAGE_TRANSFER_DST_BIT |
120                                  VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
121        msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
122
123        if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
124            imageView->unref(gpu);
125            return nullptr;
126        }
127
128        // Set color attachment image
129        colorImage = msInfo.fImage;
130
131        // Create resolve attachment view.
132        resolveAttachmentView = GrVkImageView::Create(gpu, image, pixelFormat,
133                                                      GrVkImageView::kColor_Type,
134                                                      info.fLevelCount);
135        if (!resolveAttachmentView) {
136            GrVkImage::DestroyImageInfo(gpu, &msInfo);
137            imageView->unref(gpu);
138            return nullptr;
139        }
140    } else {
141        // Set color attachment image
142        colorImage = info.fImage;
143    }
144
145    const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
146                                                                     GrVkImageView::kColor_Type, 1);
147    if (!colorAttachmentView) {
148        if (desc.fSampleCnt > 1) {
149            resolveAttachmentView->unref(gpu);
150            GrVkImage::DestroyImageInfo(gpu, &msInfo);
151        }
152        imageView->unref(gpu);
153        return nullptr;
154    }
155
156    sk_sp<GrVkTextureRenderTarget> texRT;
157    if (desc.fSampleCnt > 1) {
158        if (!isWrapped) {
159            texRT = sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
160                                                      gpu, budgeted, desc,
161                                                      info, imageView, msInfo,
162                                                      colorAttachmentView,
163                                                      resolveAttachmentView, mipMapsStatus,
164                                                      ownership));
165        } else {
166            texRT = sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
167                                                        gpu, desc,
168                                                        info, imageView, msInfo,
169                                                        colorAttachmentView,
170                                                        resolveAttachmentView, mipMapsStatus,
171                                                        ownership));
172        }
173    } else {
174        if (!isWrapped) {
175            texRT = sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
176                                                        gpu, budgeted, desc,
177                                                        info, imageView,
178                                                        colorAttachmentView, mipMapsStatus,
179                                                        ownership));
180        } else {
181            texRT = sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
182                                                        gpu, desc,
183                                                        info, imageView,
184                                                        colorAttachmentView, mipMapsStatus,
185                                                        ownership));
186        }
187    }
188    return texRT;
189}
190
191sk_sp<GrVkTextureRenderTarget>
192GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
193                                                      SkBudgeted budgeted,
194                                                      const GrSurfaceDesc& desc,
195                                                      const GrVkImage::ImageDesc& imageDesc,
196                                                      GrMipMapsStatus mipMapsStatus) {
197    SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
198    SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
199
200    GrVkImageInfo info;
201    if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
202        return nullptr;
203    }
204
205    sk_sp<GrVkTextureRenderTarget> trt = Make(gpu, desc, info, mipMapsStatus, budgeted,
206                                              GrBackendObjectOwnership::kOwned, false);
207    if (!trt) {
208        GrVkImage::DestroyImageInfo(gpu, &info);
209    }
210
211    return trt;
212}
213
214sk_sp<GrVkTextureRenderTarget>
215GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(GrVkGpu* gpu,
216                                                        const GrSurfaceDesc& desc,
217                                                        GrWrapOwnership wrapOwnership,
218                                                        const GrVkImageInfo* info) {
219    SkASSERT(info);
220    // Wrapped textures require both image and allocation (because they can be mapped)
221    SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
222
223    GrMipMapsStatus mipMapsStatus = info->fLevelCount > 1 ? GrMipMapsStatus::kDirty
224                                                          : GrMipMapsStatus::kNotAllocated;
225
226    GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
227            ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
228
229    return Make(gpu, desc, *info, mipMapsStatus, SkBudgeted::kNo, ownership, true);
230}
231
232bool GrVkTextureRenderTarget::updateForMipmap(GrVkGpu* gpu, const GrVkImageInfo& newInfo) {
233    VkFormat pixelFormat;
234    GrPixelConfigToVkFormat(this->config(), &pixelFormat);
235    if (this->numStencilSamples() > 1) {
236        const GrVkImageView* resolveAttachmentView =
237                GrVkImageView::Create(gpu,
238                                      newInfo.fImage,
239                                      pixelFormat,
240                                      GrVkImageView::kColor_Type,
241                                      newInfo.fLevelCount);
242        if (!resolveAttachmentView) {
243            return false;
244        }
245        fResolveAttachmentView->unref(gpu);
246        fResolveAttachmentView = resolveAttachmentView;
247    } else {
248        const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu,
249                                                                         newInfo.fImage,
250                                                                         pixelFormat,
251                                                                         GrVkImageView::kColor_Type,
252                                                                         1);
253        if (!colorAttachmentView) {
254            return false;
255        }
256        fColorAttachmentView->unref(gpu);
257        fColorAttachmentView = colorAttachmentView;
258    }
259
260    this->createFramebuffer(gpu);
261    return true;
262}
263
264size_t GrVkTextureRenderTarget::onGpuMemorySize() const {
265    int numColorSamples = this->numColorSamples();
266    if (numColorSamples > 1) {
267        // Add one to account for the resolve VkImage.
268        ++numColorSamples;
269    }
270    return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
271                                  numColorSamples,  // TODO: this still correct?
272                                  this->texturePriv().mipMapped());
273}
274