• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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