• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "dawn_native/PassResourceUsageTracker.h"
16 
17 #include "dawn_native/BindGroup.h"
18 #include "dawn_native/Buffer.h"
19 #include "dawn_native/EnumMaskIterator.h"
20 #include "dawn_native/ExternalTexture.h"
21 #include "dawn_native/Format.h"
22 #include "dawn_native/QuerySet.h"
23 #include "dawn_native/Texture.h"
24 
25 #include <utility>
26 
27 namespace dawn_native {
28 
BufferUsedAs(BufferBase * buffer,wgpu::BufferUsage usage)29     void SyncScopeUsageTracker::BufferUsedAs(BufferBase* buffer, wgpu::BufferUsage usage) {
30         // std::map's operator[] will create the key and return 0 if the key didn't exist
31         // before.
32         mBufferUsages[buffer] |= usage;
33     }
34 
TextureViewUsedAs(TextureViewBase * view,wgpu::TextureUsage usage)35     void SyncScopeUsageTracker::TextureViewUsedAs(TextureViewBase* view, wgpu::TextureUsage usage) {
36         TextureBase* texture = view->GetTexture();
37         const SubresourceRange& range = view->GetSubresourceRange();
38 
39         // Get or create a new TextureSubresourceUsage for that texture (initially filled with
40         // wgpu::TextureUsage::None)
41         auto it = mTextureUsages.emplace(
42             std::piecewise_construct, std::forward_as_tuple(texture),
43             std::forward_as_tuple(texture->GetFormat().aspects, texture->GetArrayLayers(),
44                                   texture->GetNumMipLevels(), wgpu::TextureUsage::None));
45         TextureSubresourceUsage& textureUsage = it.first->second;
46 
47         textureUsage.Update(range,
48                             [usage](const SubresourceRange&, wgpu::TextureUsage* storedUsage) {
49                                 // TODO(crbug.com/dawn/1001): Consider optimizing to have fewer
50                                 // branches.
51                                 if ((*storedUsage & wgpu::TextureUsage::RenderAttachment) != 0 &&
52                                     (usage & wgpu::TextureUsage::RenderAttachment) != 0) {
53                                     // Using the same subresource as an attachment for two different
54                                     // render attachments is a write-write hazard. Add this internal
55                                     // usage so we will fail the check that a subresource with
56                                     // writable usage is the single usage.
57                                     *storedUsage |= kAgainAsRenderAttachment;
58                                 }
59                                 *storedUsage |= usage;
60                             });
61     }
62 
AddRenderBundleTextureUsage(TextureBase * texture,const TextureSubresourceUsage & textureUsage)63     void SyncScopeUsageTracker::AddRenderBundleTextureUsage(
64         TextureBase* texture,
65         const TextureSubresourceUsage& textureUsage) {
66         // Get or create a new TextureSubresourceUsage for that texture (initially filled with
67         // wgpu::TextureUsage::None)
68         auto it = mTextureUsages.emplace(
69             std::piecewise_construct, std::forward_as_tuple(texture),
70             std::forward_as_tuple(texture->GetFormat().aspects, texture->GetArrayLayers(),
71                                   texture->GetNumMipLevels(), wgpu::TextureUsage::None));
72         TextureSubresourceUsage* passTextureUsage = &it.first->second;
73 
74         passTextureUsage->Merge(
75             textureUsage, [](const SubresourceRange&, wgpu::TextureUsage* storedUsage,
76                              const wgpu::TextureUsage& addedUsage) {
77                 ASSERT((addedUsage & wgpu::TextureUsage::RenderAttachment) == 0);
78                 *storedUsage |= addedUsage;
79             });
80     }
81 
AddBindGroup(BindGroupBase * group)82     void SyncScopeUsageTracker::AddBindGroup(BindGroupBase* group) {
83         for (BindingIndex bindingIndex{0}; bindingIndex < group->GetLayout()->GetBindingCount();
84              ++bindingIndex) {
85             const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
86 
87             switch (bindingInfo.bindingType) {
88                 case BindingInfoType::Buffer: {
89                     BufferBase* buffer = group->GetBindingAsBufferBinding(bindingIndex).buffer;
90                     switch (bindingInfo.buffer.type) {
91                         case wgpu::BufferBindingType::Uniform:
92                             BufferUsedAs(buffer, wgpu::BufferUsage::Uniform);
93                             break;
94                         case wgpu::BufferBindingType::Storage:
95                             BufferUsedAs(buffer, wgpu::BufferUsage::Storage);
96                             break;
97                         case kInternalStorageBufferBinding:
98                             BufferUsedAs(buffer, kInternalStorageBuffer);
99                             break;
100                         case wgpu::BufferBindingType::ReadOnlyStorage:
101                             BufferUsedAs(buffer, kReadOnlyStorageBuffer);
102                             break;
103                         case wgpu::BufferBindingType::Undefined:
104                             UNREACHABLE();
105                     }
106                     break;
107                 }
108 
109                 case BindingInfoType::Texture: {
110                     TextureViewBase* view = group->GetBindingAsTextureView(bindingIndex);
111                     TextureViewUsedAs(view, wgpu::TextureUsage::TextureBinding);
112                     break;
113                 }
114 
115                 case BindingInfoType::StorageTexture: {
116                     TextureViewBase* view = group->GetBindingAsTextureView(bindingIndex);
117                     switch (bindingInfo.storageTexture.access) {
118                         case wgpu::StorageTextureAccess::WriteOnly:
119                             TextureViewUsedAs(view, wgpu::TextureUsage::StorageBinding);
120                             break;
121                         case wgpu::StorageTextureAccess::Undefined:
122                             UNREACHABLE();
123                     }
124                     break;
125                 }
126 
127                 case BindingInfoType::ExternalTexture: {
128                     ExternalTextureBase* externalTexture =
129                         group->GetBindingAsExternalTexture(bindingIndex);
130 
131                     const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>& textureViews =
132                         externalTexture->GetTextureViews();
133 
134                     // Only single-plane formats are supported right now, so assert only one
135                     // view exists.
136                     ASSERT(textureViews[1].Get() == nullptr);
137                     ASSERT(textureViews[2].Get() == nullptr);
138 
139                     mExternalTextureUsages.insert(externalTexture);
140                     TextureViewUsedAs(textureViews[0].Get(), wgpu::TextureUsage::TextureBinding);
141                     break;
142                 }
143 
144                 case BindingInfoType::Sampler:
145                     break;
146             }
147         }
148     }
149 
AcquireSyncScopeUsage()150     SyncScopeResourceUsage SyncScopeUsageTracker::AcquireSyncScopeUsage() {
151         SyncScopeResourceUsage result;
152         result.buffers.reserve(mBufferUsages.size());
153         result.bufferUsages.reserve(mBufferUsages.size());
154         result.textures.reserve(mTextureUsages.size());
155         result.textureUsages.reserve(mTextureUsages.size());
156 
157         for (auto& it : mBufferUsages) {
158             result.buffers.push_back(it.first);
159             result.bufferUsages.push_back(it.second);
160         }
161 
162         for (auto& it : mTextureUsages) {
163             result.textures.push_back(it.first);
164             result.textureUsages.push_back(std::move(it.second));
165         }
166 
167         for (auto& it : mExternalTextureUsages) {
168             result.externalTextures.push_back(it);
169         }
170 
171         mBufferUsages.clear();
172         mTextureUsages.clear();
173         mExternalTextureUsages.clear();
174 
175         return result;
176     }
177 
AddDispatch(SyncScopeResourceUsage scope)178     void ComputePassResourceUsageTracker::AddDispatch(SyncScopeResourceUsage scope) {
179         mUsage.dispatchUsages.push_back(std::move(scope));
180     }
181 
AddReferencedBuffer(BufferBase * buffer)182     void ComputePassResourceUsageTracker::AddReferencedBuffer(BufferBase* buffer) {
183         mUsage.referencedBuffers.insert(buffer);
184     }
185 
AddResourcesReferencedByBindGroup(BindGroupBase * group)186     void ComputePassResourceUsageTracker::AddResourcesReferencedByBindGroup(BindGroupBase* group) {
187         for (BindingIndex index{0}; index < group->GetLayout()->GetBindingCount(); ++index) {
188             const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(index);
189 
190             switch (bindingInfo.bindingType) {
191                 case BindingInfoType::Buffer: {
192                     mUsage.referencedBuffers.insert(group->GetBindingAsBufferBinding(index).buffer);
193                     break;
194                 }
195 
196                 case BindingInfoType::Texture: {
197                     mUsage.referencedTextures.insert(
198                         group->GetBindingAsTextureView(index)->GetTexture());
199                     break;
200                 }
201 
202                 case BindingInfoType::ExternalTexture: {
203                     ExternalTextureBase* externalTexture =
204                         group->GetBindingAsExternalTexture(index);
205                     const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>& textureViews =
206                         externalTexture->GetTextureViews();
207 
208                     // Only single-plane formats are supported right now, so assert only one
209                     // view exists.
210                     ASSERT(textureViews[1].Get() == nullptr);
211                     ASSERT(textureViews[2].Get() == nullptr);
212 
213                     mUsage.referencedExternalTextures.insert(externalTexture);
214                     mUsage.referencedTextures.insert(textureViews[0].Get()->GetTexture());
215                     break;
216                 }
217 
218                 case BindingInfoType::StorageTexture:
219                 case BindingInfoType::Sampler:
220                     break;
221             }
222         }
223     }
224 
AcquireResourceUsage()225     ComputePassResourceUsage ComputePassResourceUsageTracker::AcquireResourceUsage() {
226         return std::move(mUsage);
227     }
228 
AcquireResourceUsage()229     RenderPassResourceUsage RenderPassResourceUsageTracker::AcquireResourceUsage() {
230         RenderPassResourceUsage result;
231         *static_cast<SyncScopeResourceUsage*>(&result) = AcquireSyncScopeUsage();
232 
233         result.querySets.reserve(mQueryAvailabilities.size());
234         result.queryAvailabilities.reserve(mQueryAvailabilities.size());
235 
236         for (auto& it : mQueryAvailabilities) {
237             result.querySets.push_back(it.first);
238             result.queryAvailabilities.push_back(std::move(it.second));
239         }
240 
241         mQueryAvailabilities.clear();
242 
243         return result;
244     }
245 
TrackQueryAvailability(QuerySetBase * querySet,uint32_t queryIndex)246     void RenderPassResourceUsageTracker::TrackQueryAvailability(QuerySetBase* querySet,
247                                                                 uint32_t queryIndex) {
248         // The query availability only needs to be tracked again on render passes for checking
249         // query overwrite on render pass and resetting query sets on the Vulkan backend.
250         DAWN_ASSERT(querySet != nullptr);
251 
252         // Gets the iterator for that querySet or create a new vector of bool set to false
253         // if the querySet wasn't registered.
254         auto it = mQueryAvailabilities.emplace(querySet, querySet->GetQueryCount()).first;
255         it->second[queryIndex] = true;
256     }
257 
GetQueryAvailabilityMap() const258     const QueryAvailabilityMap& RenderPassResourceUsageTracker::GetQueryAvailabilityMap() const {
259         return mQueryAvailabilities;
260     }
261 
262 }  // namespace dawn_native
263