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