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