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