Factor PassResourceUsageTracker to its own file
GPURenderBundleEncoder and GPUCommandEncoder will need to share code
for tracking resource usages.
Bug: dawn:154
Change-Id: I0286f71c4c0638f89be2754c8e9691e67e5db335
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9700
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index b07b3b1..aed63b1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -154,6 +154,8 @@
"src/dawn_native/ObjectBase.cpp",
"src/dawn_native/ObjectBase.h",
"src/dawn_native/PassResourceUsage.h",
+ "src/dawn_native/PassResourceUsageTracker.cpp",
+ "src/dawn_native/PassResourceUsageTracker.h",
"src/dawn_native/PerStage.cpp",
"src/dawn_native/PerStage.h",
"src/dawn_native/Pipeline.cpp",
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
index be33223..0fff02f 100644
--- a/src/dawn_native/CommandEncoder.cpp
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -23,6 +23,7 @@
#include "dawn_native/ComputePassEncoder.h"
#include "dawn_native/Device.h"
#include "dawn_native/ErrorData.h"
+#include "dawn_native/PassResourceUsageTracker.h"
#include "dawn_native/RenderPassEncoder.h"
#include "dawn_native/RenderPipeline.h"
@@ -475,117 +476,6 @@
return {};
}
- enum class PassType {
- Render,
- Compute,
- };
-
- // Helper class to encapsulate the logic of tracking per-resource usage during the
- // validation of command buffer passes. It is used both to know if there are validation
- // errors, and to get a list of resources used per pass for backends that need the
- // information.
- class PassResourceUsageTracker {
- public:
- void BufferUsedAs(BufferBase* buffer, dawn::BufferUsageBit usage) {
- // std::map's operator[] will create the key and return 0 if the key didn't exist
- // before.
- dawn::BufferUsageBit& storedUsage = mBufferUsages[buffer];
-
- if (usage == dawn::BufferUsageBit::Storage &&
- storedUsage & dawn::BufferUsageBit::Storage) {
- mStorageUsedMultipleTimes = true;
- }
-
- storedUsage |= usage;
- }
-
- void TextureUsedAs(TextureBase* texture, dawn::TextureUsageBit usage) {
- // std::map's operator[] will create the key and return 0 if the key didn't exist
- // before.
- dawn::TextureUsageBit& storedUsage = mTextureUsages[texture];
-
- if (usage == dawn::TextureUsageBit::Storage &&
- storedUsage & dawn::TextureUsageBit::Storage) {
- mStorageUsedMultipleTimes = true;
- }
-
- storedUsage |= usage;
- }
-
- // Performs the per-pass usage validation checks
- MaybeError ValidateUsages(PassType pass) const {
- // Storage resources cannot be used twice in the same compute pass
- if (pass == PassType::Compute && mStorageUsedMultipleTimes) {
- return DAWN_VALIDATION_ERROR(
- "Storage resource used multiple times in compute pass");
- }
-
- // Buffers can only be used as single-write or multiple read.
- for (auto& it : mBufferUsages) {
- BufferBase* buffer = it.first;
- dawn::BufferUsageBit usage = it.second;
-
- if (usage & ~buffer->GetUsage()) {
- return DAWN_VALIDATION_ERROR("Buffer missing usage for the pass");
- }
-
- bool readOnly = (usage & kReadOnlyBufferUsages) == usage;
- bool singleUse = dawn::HasZeroOrOneBits(usage);
-
- if (!readOnly && !singleUse) {
- return DAWN_VALIDATION_ERROR(
- "Buffer used as writable usage and another usage in pass");
- }
- }
-
- // Textures can only be used as single-write or multiple read.
- // TODO(cwallez@chromium.org): implement per-subresource tracking
- for (auto& it : mTextureUsages) {
- TextureBase* texture = it.first;
- dawn::TextureUsageBit usage = it.second;
-
- if (usage & ~texture->GetUsage()) {
- return DAWN_VALIDATION_ERROR("Texture missing usage for the pass");
- }
-
- // For textures the only read-only usage in a pass is Sampled, so checking the
- // usage constraint simplifies to checking a single usage bit is set.
- if (!dawn::HasZeroOrOneBits(it.second)) {
- return DAWN_VALIDATION_ERROR(
- "Texture used with more than one usage in pass");
- }
- }
-
- return {};
- }
-
- // Returns the per-pass usage for use by backends for APIs with explicit barriers.
- PassResourceUsage AcquireResourceUsage() {
- PassResourceUsage result;
- result.buffers.reserve(mBufferUsages.size());
- result.bufferUsages.reserve(mBufferUsages.size());
- result.textures.reserve(mTextureUsages.size());
- result.textureUsages.reserve(mTextureUsages.size());
-
- for (auto& it : mBufferUsages) {
- result.buffers.push_back(it.first);
- result.bufferUsages.push_back(it.second);
- }
-
- for (auto& it : mTextureUsages) {
- result.textures.push_back(it.first);
- result.textureUsages.push_back(it.second);
- }
-
- return result;
- }
-
- private:
- std::map<BufferBase*, dawn::BufferUsageBit> mBufferUsages;
- std::map<TextureBase*, dawn::TextureUsageBit> mTextureUsages;
- bool mStorageUsedMultipleTimes = false;
- };
-
void TrackBindGroupResourceUsage(BindGroupBase* group, PassResourceUsageTracker* tracker) {
const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
@@ -1003,7 +893,7 @@
DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
- DAWN_TRY(usageTracker.ValidateUsages(PassType::Compute));
+ DAWN_TRY(usageTracker.ValidateComputePassUsages());
mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
return {};
} break;
@@ -1092,7 +982,7 @@
DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
- DAWN_TRY(usageTracker.ValidateUsages(PassType::Render));
+ DAWN_TRY(usageTracker.ValidateRenderPassUsages());
mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
return {};
} break;
diff --git a/src/dawn_native/PassResourceUsageTracker.cpp b/src/dawn_native/PassResourceUsageTracker.cpp
new file mode 100644
index 0000000..4f26112
--- /dev/null
+++ b/src/dawn_native/PassResourceUsageTracker.cpp
@@ -0,0 +1,121 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/PassResourceUsageTracker.h"
+
+#include "dawn_native/Buffer.h"
+#include "dawn_native/Texture.h"
+
+namespace dawn_native {
+
+ void PassResourceUsageTracker::BufferUsedAs(BufferBase* buffer, dawn::BufferUsageBit usage) {
+ // std::map's operator[] will create the key and return 0 if the key didn't exist
+ // before.
+ dawn::BufferUsageBit& storedUsage = mBufferUsages[buffer];
+
+ if (usage == dawn::BufferUsageBit::Storage && storedUsage & dawn::BufferUsageBit::Storage) {
+ mStorageUsedMultipleTimes = true;
+ }
+
+ storedUsage |= usage;
+ }
+
+ void PassResourceUsageTracker::TextureUsedAs(TextureBase* texture,
+ dawn::TextureUsageBit usage) {
+ // std::map's operator[] will create the key and return 0 if the key didn't exist
+ // before.
+ dawn::TextureUsageBit& storedUsage = mTextureUsages[texture];
+
+ if (usage == dawn::TextureUsageBit::Storage &&
+ storedUsage & dawn::TextureUsageBit::Storage) {
+ mStorageUsedMultipleTimes = true;
+ }
+
+ storedUsage |= usage;
+ }
+
+ MaybeError PassResourceUsageTracker::ValidateComputePassUsages() const {
+ // Storage resources cannot be used twice in the same compute pass
+ if (mStorageUsedMultipleTimes) {
+ return DAWN_VALIDATION_ERROR("Storage resource used multiple times in compute pass");
+ }
+ return ValidateUsages();
+ }
+
+ MaybeError PassResourceUsageTracker::ValidateRenderPassUsages() const {
+ return ValidateUsages();
+ }
+
+ // Performs the per-pass usage validation checks
+ MaybeError PassResourceUsageTracker::ValidateUsages() const {
+ // Buffers can only be used as single-write or multiple read.
+ for (auto& it : mBufferUsages) {
+ BufferBase* buffer = it.first;
+ dawn::BufferUsageBit usage = it.second;
+
+ if (usage & ~buffer->GetUsage()) {
+ return DAWN_VALIDATION_ERROR("Buffer missing usage for the pass");
+ }
+
+ bool readOnly = (usage & kReadOnlyBufferUsages) == usage;
+ bool singleUse = dawn::HasZeroOrOneBits(usage);
+
+ if (!readOnly && !singleUse) {
+ return DAWN_VALIDATION_ERROR(
+ "Buffer used as writable usage and another usage in pass");
+ }
+ }
+
+ // Textures can only be used as single-write or multiple read.
+ // TODO(cwallez@chromium.org): implement per-subresource tracking
+ for (auto& it : mTextureUsages) {
+ TextureBase* texture = it.first;
+ dawn::TextureUsageBit usage = it.second;
+
+ if (usage & ~texture->GetUsage()) {
+ return DAWN_VALIDATION_ERROR("Texture missing usage for the pass");
+ }
+
+ // For textures the only read-only usage in a pass is Sampled, so checking the
+ // usage constraint simplifies to checking a single usage bit is set.
+ if (!dawn::HasZeroOrOneBits(it.second)) {
+ return DAWN_VALIDATION_ERROR("Texture used with more than one usage in pass");
+ }
+ }
+
+ return {};
+ }
+
+ // Returns the per-pass usage for use by backends for APIs with explicit barriers.
+ PassResourceUsage PassResourceUsageTracker::AcquireResourceUsage() {
+ PassResourceUsage result;
+ result.buffers.reserve(mBufferUsages.size());
+ result.bufferUsages.reserve(mBufferUsages.size());
+ result.textures.reserve(mTextureUsages.size());
+ result.textureUsages.reserve(mTextureUsages.size());
+
+ for (auto& it : mBufferUsages) {
+ result.buffers.push_back(it.first);
+ result.bufferUsages.push_back(it.second);
+ }
+
+ for (auto& it : mTextureUsages) {
+ result.textures.push_back(it.first);
+ result.textureUsages.push_back(it.second);
+ }
+
+ return result;
+ }
+
+} // namespace dawn_native
diff --git a/src/dawn_native/PassResourceUsageTracker.h b/src/dawn_native/PassResourceUsageTracker.h
new file mode 100644
index 0000000..6942058
--- /dev/null
+++ b/src/dawn_native/PassResourceUsageTracker.h
@@ -0,0 +1,56 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_
+#define DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_
+
+#include "dawn_native/Error.h"
+#include "dawn_native/PassResourceUsage.h"
+
+#include "dawn_native/dawn_platform.h"
+
+#include <map>
+
+namespace dawn_native {
+
+ class BufferBase;
+ class TextureBase;
+
+ // Helper class to encapsulate the logic of tracking per-resource usage during the
+ // validation of command buffer passes. It is used both to know if there are validation
+ // errors, and to get a list of resources used per pass for backends that need the
+ // information.
+ class PassResourceUsageTracker {
+ public:
+ void BufferUsedAs(BufferBase* buffer, dawn::BufferUsageBit usage);
+ void TextureUsedAs(TextureBase* texture, dawn::TextureUsageBit usage);
+
+ MaybeError ValidateComputePassUsages() const;
+ MaybeError ValidateRenderPassUsages() const;
+
+ // Returns the per-pass usage for use by backends for APIs with explicit barriers.
+ PassResourceUsage AcquireResourceUsage();
+
+ private:
+ // Performs the per-pass usage validation checks
+ MaybeError ValidateUsages() const;
+
+ std::map<BufferBase*, dawn::BufferUsageBit> mBufferUsages;
+ std::map<TextureBase*, dawn::TextureUsageBit> mTextureUsages;
+ bool mStorageUsedMultipleTimes = false;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_