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/GrDirectContextPriv.h"
11 #include "src/gpu/GrResourceProvider.h"
12 #include "src/gpu/GrTexture.h"
13 #include "src/gpu/vk/GrVkGpu.h"
14 #include "src/gpu/vk/GrVkImage.h"
15 #include "src/gpu/vk/GrVkImageView.h"
16 #include "src/gpu/vk/GrVkUtil.h"
17 
18 #include "src/core/SkMipmap.h"
19 
20 #include "include/gpu/vk/GrVkTypes.h"
21 
22 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
23 
GrVkTextureRenderTarget( GrVkGpu* gpu, SkBudgeted budgeted, SkISize dimensions, sk_sp<GrVkImage> texture, sk_sp<GrVkImage> colorAttachment, sk_sp<GrVkImage> resolveAttachment, GrMipmapStatus mipmapStatus)24 GrVkTextureRenderTarget::GrVkTextureRenderTarget(
25         GrVkGpu* gpu,
26         SkBudgeted budgeted,
27         SkISize dimensions,
28         sk_sp<GrVkImage> texture,
29         sk_sp<GrVkImage> colorAttachment,
30         sk_sp<GrVkImage> resolveAttachment,
31         GrMipmapStatus mipmapStatus)
32         : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
33         , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus)
34         , GrVkRenderTarget(gpu, dimensions, std::move(colorAttachment),
35                            std::move(resolveAttachment), CreateType::kFromTextureRT) {
36 #ifdef SKIA_OHOS
37     GrVkImage* image = textureImage();
38     if (image && image->GetBudgeted() == SkBudgeted::kYes) {
39         this->registerWithCache(SkBudgeted::kNo);
40     } else {
41         this->registerWithCache(budgeted);
42     }
43 #else
44     this->registerWithCache(budgeted);
45 #endif
46 }
47 
GrVkTextureRenderTarget( GrVkGpu* gpu, SkISize dimensions, sk_sp<GrVkImage> texture, sk_sp<GrVkImage> colorAttachment, sk_sp<GrVkImage> resolveAttachment, GrMipmapStatus mipmapStatus, GrWrapCacheable cacheable)48 GrVkTextureRenderTarget::GrVkTextureRenderTarget(
49         GrVkGpu* gpu,
50         SkISize dimensions,
51         sk_sp<GrVkImage> texture,
52         sk_sp<GrVkImage> colorAttachment,
53         sk_sp<GrVkImage> resolveAttachment,
54         GrMipmapStatus mipmapStatus,
55         GrWrapCacheable cacheable)
56         : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
57         , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus)
58         , GrVkRenderTarget(gpu, dimensions, std::move(colorAttachment),
59                            std::move(resolveAttachment), CreateType::kFromTextureRT) {
60     this->registerWithCacheWrapped(cacheable);
61 }
62 
create_rt_attachments(GrVkGpu* gpu, SkISize dimensions, VkFormat format, int sampleCnt, GrProtected isProtected, sk_sp<GrVkImage> texture, sk_sp<GrVkImage>* colorAttachment, sk_sp<GrVkImage>* resolveAttachment)63 bool create_rt_attachments(GrVkGpu* gpu, SkISize dimensions, VkFormat format, int sampleCnt,
64                            GrProtected isProtected,
65                            sk_sp<GrVkImage> texture,
66                            sk_sp<GrVkImage>* colorAttachment,
67                            sk_sp<GrVkImage>* resolveAttachment) {
68     if (sampleCnt > 1) {
69         auto rp = gpu->getContext()->priv().resourceProvider();
70         sk_sp<GrAttachment> msaaAttachment = rp->makeMSAAAttachment(
71                 dimensions, GrBackendFormat::MakeVk(format), sampleCnt, isProtected,
72                 GrMemoryless::kNo);
73         if (!msaaAttachment) {
74             return false;
75         }
76         *colorAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
77         *resolveAttachment = std::move(texture);
78     } else {
79         *colorAttachment = std::move(texture);
80     }
81     return true;
82 }
83 
MakeNewTextureRenderTarget( GrVkGpu* gpu, SkBudgeted budgeted, SkISize dimensions, VkFormat format, uint32_t mipLevels, int sampleCnt, GrMipmapStatus mipmapStatus, GrProtected isProtected)84 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarget(
85         GrVkGpu* gpu,
86         SkBudgeted budgeted,
87         SkISize dimensions,
88         VkFormat format,
89         uint32_t mipLevels,
90         int sampleCnt,
91         GrMipmapStatus mipmapStatus,
92         GrProtected isProtected) {
93     sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(gpu,
94                                                       dimensions,
95                                                       format,
96                                                       mipLevels,
97                                                       GrRenderable::kYes,
98                                                       /*numSamples=*/1,
99                                                       budgeted,
100                                                       isProtected);
101     if (!texture) {
102         return nullptr;
103     }
104 
105     sk_sp<GrVkImage> colorAttachment;
106     sk_sp<GrVkImage> resolveAttachment;
107     if (!create_rt_attachments(gpu, dimensions, format, sampleCnt, isProtected, texture,
108                                &colorAttachment, &resolveAttachment)) {
109         return nullptr;
110     }
111     SkASSERT(colorAttachment);
112     SkASSERT(sampleCnt == 1 || resolveAttachment);
113     return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
114             gpu, budgeted, dimensions, std::move(texture), std::move(colorAttachment),
115             std::move(resolveAttachment), mipmapStatus));
116 }
117 
MakeWrappedTextureRenderTarget( GrVkGpu* gpu, SkISize dimensions, int sampleCnt, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable, const GrVkImageInfo& info, sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)118 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(
119         GrVkGpu* gpu,
120         SkISize dimensions,
121         int sampleCnt,
122         GrWrapOwnership wrapOwnership,
123         GrWrapCacheable cacheable,
124         const GrVkImageInfo& info,
125         sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
126     // Adopted textures require both image and allocation because we're responsible for freeing
127     SkASSERT(VK_NULL_HANDLE != info.fImage &&
128              (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
129 
130     GrAttachment::UsageFlags textureUsageFlags = GrAttachment::UsageFlags::kTexture;
131     if (info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
132         textureUsageFlags |= GrAttachment::UsageFlags::kColorAttachment;
133     }
134 
135     sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
136                                                       dimensions,
137                                                       info,
138                                                       std::move(mutableState),
139                                                       textureUsageFlags,
140                                                       wrapOwnership,
141                                                       cacheable);
142     if (!texture) {
143         return nullptr;
144     }
145 
146     sk_sp<GrVkImage> colorAttachment;
147     sk_sp<GrVkImage> resolveAttachment;
148     if (!create_rt_attachments(gpu, dimensions, info.fFormat, sampleCnt, info.fProtected, texture,
149                                &colorAttachment, &resolveAttachment)) {
150         return nullptr;
151     }
152     SkASSERT(colorAttachment);
153     SkASSERT(sampleCnt == 1 || resolveAttachment);
154 
155     GrMipmapStatus mipmapStatus =
156             info.fLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated;
157 
158     return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
159             gpu, dimensions, std::move(texture), std::move(colorAttachment),
160             std::move(resolveAttachment), mipmapStatus, cacheable));
161 }
162 
onGpuMemorySize() const163 size_t GrVkTextureRenderTarget::onGpuMemorySize() const {
164     // The GrTexture[RenderTarget] is built up by a bunch of attachments each of which are their
165     // own GrGpuResource. Ideally the GrRenderTarget would not be a GrGpuResource and the GrTexture
166     // would just merge with the new GrSurface/Attachment world. Then we could just depend on each
167     // attachment to give its own size since we don't have GrGpuResources owning other
168     // GrGpuResources. Until we get to that point we need to live in some hybrid world. We will let
169     // the msaa and stencil attachments track their own size because they do get cached separately.
170     // For all GrTexture* based things we will continue to to use the GrTexture* to report size and
171     // the owned attachments will have no size and be uncached.
172 #ifdef SK_DEBUG
173     // The nonMSAA attachment (either color or resolve depending on numSamples should have size of
174     // zero since it is a texture attachment.
175     SkASSERT(this->nonMSAAAttachment()->gpuMemorySize() == 0);
176     if (this->numSamples() > 1) {
177         // Msaa attachment should have a valid size
178         SkASSERT(this->colorAttachment()->gpuMemorySize() ==
179                  GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
180                                         this->numSamples(), GrMipMapped::kNo));
181     }
182 #endif
183     return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
184                                   1 /*colorSamplesPerPixel*/, this->mipmapped());
185 }
186 
dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const187 void GrVkTextureRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
188     SkString resourceName = this->getResourceName();
189     resourceName.append("/texture_renderbuffer");
190     this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget",
191         this->gpuMemorySize());
192 }