From e9fabf59160bd2881108f58760998372ec91017b Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Thu, 8 Aug 2019 17:21:39 +0000 Subject: [PATCH] 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 Reviewed-by: Kai Ninomiya --- BUILD.gn | 2 + src/dawn_native/CommandEncoder.cpp | 116 +----------------- src/dawn_native/PassResourceUsageTracker.cpp | 121 +++++++++++++++++++ src/dawn_native/PassResourceUsageTracker.h | 56 +++++++++ 4 files changed, 182 insertions(+), 113 deletions(-) create mode 100644 src/dawn_native/PassResourceUsageTracker.cpp create mode 100644 src/dawn_native/PassResourceUsageTracker.h diff --git a/BUILD.gn b/BUILD.gn index b07b3b14eb..aed63b154d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -154,6 +154,8 @@ source_set("libdawn_native_sources") { "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 be33223adb..0fff02f92e 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 @@ namespace dawn_native { 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 mBufferUsages; - std::map mTextureUsages; - bool mStorageUsedMultipleTimes = false; - }; - void TrackBindGroupResourceUsage(BindGroupBase* group, PassResourceUsageTracker* tracker) { const auto& layoutInfo = group->GetLayout()->GetBindingInfo(); @@ -1003,7 +893,7 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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 0000000000..4f261127a6 --- /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 0000000000..69420584b3 --- /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 + +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 mBufferUsages; + std::map mTextureUsages; + bool mStorageUsedMultipleTimes = false; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_