1 /*
2 * Copyright 2022 Google LLC
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/graphite/dawn/DawnTexture.h"
9
10 #include "include/core/SkTraceMemoryDump.h"
11 #include "include/gpu/MutableTextureState.h"
12 #include "include/gpu/graphite/dawn/DawnTypes.h"
13 #include "include/private/gpu/graphite/DawnTypesPriv.h"
14 #include "src/core/SkMipmap.h"
15 #include "src/gpu/graphite/Log.h"
16 #include "src/gpu/graphite/dawn/DawnCaps.h"
17 #include "src/gpu/graphite/dawn/DawnGraphiteUtilsPriv.h"
18 #include "src/gpu/graphite/dawn/DawnSharedContext.h"
19
20 namespace skgpu::graphite {
21
MakeDawnTexture(const DawnSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info)22 wgpu::Texture DawnTexture::MakeDawnTexture(const DawnSharedContext* sharedContext,
23 SkISize dimensions,
24 const TextureInfo& info) {
25 const Caps* caps = sharedContext->caps();
26 if (dimensions.width() > caps->maxTextureSize() ||
27 dimensions.height() > caps->maxTextureSize()) {
28 SKGPU_LOG_E("Texture creation failure: dimensions %d x %d too large.",
29 dimensions.width(), dimensions.height());
30 return {};
31 }
32
33 const DawnTextureSpec& dawnSpec = info.dawnTextureSpec();
34
35 if (dawnSpec.fUsage & wgpu::TextureUsage::TextureBinding && !caps->isTexturable(info)) {
36 return {};
37 }
38
39 if (dawnSpec.fUsage & wgpu::TextureUsage::RenderAttachment &&
40 !(caps->isRenderable(info) || DawnFormatIsDepthOrStencil(dawnSpec.fFormat))) {
41 return {};
42 }
43
44 if (dawnSpec.fUsage & wgpu::TextureUsage::StorageBinding && !caps->isStorage(info)) {
45 return {};
46 }
47
48 int numMipLevels = 1;
49 if (info.mipmapped() == Mipmapped::kYes) {
50 numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
51 }
52
53 wgpu::TextureDescriptor desc;
54 desc.usage = dawnSpec.fUsage;
55 desc.dimension = wgpu::TextureDimension::e2D;
56 desc.size.width = dimensions.width();
57 desc.size.height = dimensions.height();
58 desc.size.depthOrArrayLayers = 1;
59 desc.format = dawnSpec.fFormat;
60 desc.mipLevelCount = numMipLevels;
61 desc.sampleCount = info.numSamples();
62 desc.viewFormatCount = 0;
63 desc.viewFormats = nullptr;
64
65 auto texture = sharedContext->device().CreateTexture(&desc);
66 if (!texture) {
67 return {};
68 }
69
70 return texture;
71 }
72
DawnTexture(const DawnSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,wgpu::Texture texture,wgpu::TextureView sampleTextureView,wgpu::TextureView renderTextureView,Ownership ownership,skgpu::Budgeted budgeted)73 DawnTexture::DawnTexture(const DawnSharedContext* sharedContext,
74 SkISize dimensions,
75 const TextureInfo& info,
76 wgpu::Texture texture,
77 wgpu::TextureView sampleTextureView,
78 wgpu::TextureView renderTextureView,
79 Ownership ownership,
80 skgpu::Budgeted budgeted)
81 : Texture(sharedContext,
82 dimensions,
83 info,
84 /*mutableState=*/nullptr,
85 ownership,
86 budgeted)
87 , fTexture(std::move(texture))
88 , fSampleTextureView(std::move(sampleTextureView))
89 , fRenderTextureView(std::move(renderTextureView)) {}
90
91 // static
CreateTextureViews(const wgpu::Texture & texture,const TextureInfo & info)92 std::pair<wgpu::TextureView, wgpu::TextureView> DawnTexture::CreateTextureViews(
93 const wgpu::Texture& texture, const TextureInfo& info) {
94 const auto aspect = info.dawnTextureSpec().fAspect;
95 if (aspect == wgpu::TextureAspect::All) {
96 wgpu::TextureViewDescriptor viewDesc = {};
97 viewDesc.dimension = wgpu::TextureViewDimension::e2D;
98 viewDesc.baseArrayLayer = info.dawnTextureSpec().fSlice;
99 viewDesc.arrayLayerCount = 1;
100 wgpu::TextureView sampleTextureView = texture.CreateView(&viewDesc);
101 wgpu::TextureView renderTextureView;
102 if (info.mipmapped() == Mipmapped::kYes) {
103 viewDesc.baseMipLevel = 0;
104 viewDesc.mipLevelCount = 1;
105 renderTextureView = texture.CreateView(&viewDesc);
106 } else {
107 renderTextureView = sampleTextureView;
108 }
109 return {sampleTextureView, renderTextureView};
110 }
111
112 #if defined(__EMSCRIPTEN__)
113 SkASSERT(false);
114 return {};
115 #else
116 SkASSERT(aspect == wgpu::TextureAspect::Plane0Only ||
117 aspect == wgpu::TextureAspect::Plane1Only ||
118 aspect == wgpu::TextureAspect::Plane2Only);
119 wgpu::TextureView planeTextureView;
120 wgpu::TextureViewDescriptor planeViewDesc = {};
121 planeViewDesc.format = info.dawnTextureSpec().fViewFormat;
122 planeViewDesc.dimension = wgpu::TextureViewDimension::e2D;
123 planeViewDesc.aspect = aspect;
124 planeViewDesc.baseArrayLayer = info.dawnTextureSpec().fSlice;
125 planeViewDesc.arrayLayerCount = 1;
126 planeTextureView = texture.CreateView(&planeViewDesc);
127 return {planeTextureView, planeTextureView};
128 #endif
129 }
130
Make(const DawnSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,skgpu::Budgeted budgeted)131 sk_sp<Texture> DawnTexture::Make(const DawnSharedContext* sharedContext,
132 SkISize dimensions,
133 const TextureInfo& info,
134 skgpu::Budgeted budgeted) {
135 auto texture = MakeDawnTexture(sharedContext, dimensions, info);
136 if (!texture) {
137 return {};
138 }
139 auto [sampleTextureView, renderTextureView] = CreateTextureViews(texture, info);
140 return sk_sp<Texture>(new DawnTexture(sharedContext,
141 dimensions,
142 info,
143 std::move(texture),
144 std::move(sampleTextureView),
145 std::move(renderTextureView),
146 Ownership::kOwned,
147 budgeted));
148 }
149
MakeWrapped(const DawnSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,wgpu::Texture texture)150 sk_sp<Texture> DawnTexture::MakeWrapped(const DawnSharedContext* sharedContext,
151 SkISize dimensions,
152 const TextureInfo& info,
153 wgpu::Texture texture) {
154 if (!texture) {
155 SKGPU_LOG_E("No valid texture passed into MakeWrapped\n");
156 return {};
157 }
158
159 auto [sampleTextureView, renderTextureView] = CreateTextureViews(texture, info);
160 return sk_sp<Texture>(new DawnTexture(sharedContext,
161 dimensions,
162 info,
163 std::move(texture),
164 std::move(sampleTextureView),
165 std::move(renderTextureView),
166 Ownership::kWrapped,
167 skgpu::Budgeted::kNo));
168 }
169
MakeWrapped(const DawnSharedContext * sharedContext,SkISize dimensions,const TextureInfo & info,const wgpu::TextureView & textureView)170 sk_sp<Texture> DawnTexture::MakeWrapped(const DawnSharedContext* sharedContext,
171 SkISize dimensions,
172 const TextureInfo& info,
173 const wgpu::TextureView& textureView) {
174 if (!textureView) {
175 SKGPU_LOG_E("No valid texture view passed into MakeWrapped\n");
176 return {};
177 }
178 return sk_sp<Texture>(new DawnTexture(sharedContext,
179 dimensions,
180 info,
181 /*texture=*/nullptr,
182 /*sampleTextureView=*/textureView,
183 /*renderTextureView=*/textureView,
184 Ownership::kWrapped,
185 skgpu::Budgeted::kNo));
186 }
187
freeGpuData()188 void DawnTexture::freeGpuData() {
189 if (this->ownership() != Ownership::kWrapped && fTexture) {
190 // Destroy the texture even if it is still referenced by other BindGroup or views.
191 // Graphite should already guarantee that all command buffers using this texture (indirectly
192 // via BindGroup or views) are already completed.
193 fTexture.Destroy();
194 }
195 fTexture = nullptr;
196 fSampleTextureView = nullptr;
197 fRenderTextureView = nullptr;
198 }
199
setBackendLabel(char const * label)200 void DawnTexture::setBackendLabel(char const* label) {
201 if (!sharedContext()->caps()->setBackendLabels()) {
202 return;
203 }
204 SkASSERT(label);
205 // Wrapped texture views won't have an associated texture here.
206 if (fTexture) {
207 fTexture.SetLabel(label);
208 }
209 // But we always have the texture views available.
210 SkASSERT(fSampleTextureView);
211 SkASSERT(fRenderTextureView);
212 if (fSampleTextureView.Get() == fRenderTextureView.Get()) {
213 fSampleTextureView.SetLabel(SkStringPrintf("%s_%s", label, "_TextureView").c_str());
214 } else {
215 fSampleTextureView.SetLabel(SkStringPrintf("%s_%s", label, "_SampleTextureView").c_str());
216 fRenderTextureView.SetLabel(SkStringPrintf("%s_%s", label, "_RenderTextureView").c_str());
217 }
218 }
219
220 } // namespace skgpu::graphite
221
222