Add the SubresourceTrackingPerf perf test.
This is a performance test in preparation of using SubresourceStorage
in dawn_native. On the Vulkan backend with Swiftshader it shows that
SubresourceStorage will bring a small perf regression for simple cases
(<= 10%) but it that complex cases are improved significantly (up to
twice faster).
Also renames a variable to follow the mMemberName convention.
Bug: dawn:441
Change-Id: I3fec80cba39b7d2aaba08fc8fbd8ea913ed5501c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/37041
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index 1c78506..5a3e310 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -496,6 +496,7 @@
"perf_tests/DawnPerfTestPlatform.cpp",
"perf_tests/DawnPerfTestPlatform.h",
"perf_tests/DrawCallPerf.cpp",
+ "perf_tests/SubresourceTrackingPerf.cpp",
]
libs = []
diff --git a/src/tests/perf_tests/DawnPerfTest.cpp b/src/tests/perf_tests/DawnPerfTest.cpp
index 58a0cbe6..1ae3971 100644
--- a/src/tests/perf_tests/DawnPerfTest.cpp
+++ b/src/tests/perf_tests/DawnPerfTest.cpp
@@ -234,7 +234,7 @@
dawn_platform::Platform* platform = gTestEnv->GetPlatform();
mNumStepsPerformed = 0;
- cpuTime = 0;
+ mCpuTime = 0;
mRunning = true;
wgpu::FenceDescriptor desc = {};
@@ -252,7 +252,7 @@
TRACE_EVENT0(platform, General, "Step");
double stepStart = mTimer->GetElapsedTime();
Step();
- cpuTime += mTimer->GetElapsedTime() - stepStart;
+ mCpuTime += mTimer->GetElapsedTime() - stepStart;
mTest->queue.Signal(fence, ++signaledFenceValue);
@@ -340,7 +340,7 @@
}
PrintPerIterationResultFromSeconds("wall_time", mTimer->GetElapsedTime(), true);
- PrintPerIterationResultFromSeconds("cpu_time", cpuTime, true);
+ PrintPerIterationResultFromSeconds("cpu_time", mCpuTime, true);
PrintPerIterationResultFromSeconds("validation_time", totalValidationTime, true);
PrintPerIterationResultFromSeconds("recording_time", totalRecordingTime, true);
diff --git a/src/tests/perf_tests/DawnPerfTest.h b/src/tests/perf_tests/DawnPerfTest.h
index d32e64e..3c1e7a9 100644
--- a/src/tests/perf_tests/DawnPerfTest.h
+++ b/src/tests/perf_tests/DawnPerfTest.h
@@ -104,7 +104,7 @@
const unsigned int mMaxStepsInFlight;
unsigned int mStepsToRun = 0;
unsigned int mNumStepsPerformed = 0;
- double cpuTime;
+ double mCpuTime;
std::unique_ptr<utils::Timer> mTimer;
};
diff --git a/src/tests/perf_tests/SubresourceTrackingPerf.cpp b/src/tests/perf_tests/SubresourceTrackingPerf.cpp
new file mode 100644
index 0000000..8be7e4b
--- /dev/null
+++ b/src/tests/perf_tests/SubresourceTrackingPerf.cpp
@@ -0,0 +1,154 @@
+// Copyright 2021 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 "tests/perf_tests/DawnPerfTest.h"
+
+#include "tests/ParamGenerator.h"
+#include "utils/ComboRenderPipelineDescriptor.h"
+#include "utils/WGPUHelpers.h"
+
+struct SubresourceTrackingParams : AdapterTestParam {
+ SubresourceTrackingParams(const AdapterTestParam& param,
+ uint32_t arrayLayerCountIn,
+ uint32_t mipLevelCountIn)
+ : AdapterTestParam(param),
+ arrayLayerCount(arrayLayerCountIn),
+ mipLevelCount(mipLevelCountIn) {
+ }
+ uint32_t arrayLayerCount;
+ uint32_t mipLevelCount;
+};
+
+std::ostream& operator<<(std::ostream& ostream, const SubresourceTrackingParams& param) {
+ ostream << static_cast<const AdapterTestParam&>(param);
+ ostream << "_arrayLayer_" << param.arrayLayerCount;
+ ostream << "_mipLevel_" << param.mipLevelCount;
+ return ostream;
+}
+
+// Test the performance of Subresource usage and barrier tracking on a case that would generally be
+// difficult. It uses a 2D array texture with mipmaps and updates one of the layers with data from
+// another texture, then generates mipmaps for that layer. It is difficult because it requires
+// tracking the state of individual subresources in the middle of the subresources of that texture.
+class SubresourceTrackingPerf : public DawnPerfTestWithParams<SubresourceTrackingParams> {
+ public:
+ static constexpr unsigned int kNumIterations = 50;
+
+ SubresourceTrackingPerf() : DawnPerfTestWithParams(kNumIterations, 1) {
+ }
+ ~SubresourceTrackingPerf() override = default;
+
+ void SetUp() override {
+ DawnPerfTestWithParams<SubresourceTrackingParams>::SetUp();
+ const SubresourceTrackingParams& params = GetParam();
+
+ wgpu::TextureDescriptor materialDesc;
+ materialDesc.dimension = wgpu::TextureDimension::e2D;
+ materialDesc.size = {1u << (params.mipLevelCount - 1), 1u << (params.mipLevelCount - 1),
+ params.arrayLayerCount};
+ materialDesc.mipLevelCount = params.mipLevelCount;
+ materialDesc.usage = wgpu::TextureUsage::Sampled | wgpu::TextureUsage::RenderAttachment |
+ wgpu::TextureUsage::CopyDst;
+ materialDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ mMaterials = device.CreateTexture(&materialDesc);
+
+ wgpu::TextureDescriptor uploadTexDesc = materialDesc;
+ uploadTexDesc.size.depth = 1;
+ uploadTexDesc.mipLevelCount = 1;
+ uploadTexDesc.usage = wgpu::TextureUsage::CopySrc;
+ mUploadTexture = device.CreateTexture(&uploadTexDesc);
+
+ utils::ComboRenderPipelineDescriptor pipelineDesc(device);
+ pipelineDesc.vertexStage.module = utils::CreateShaderModuleFromWGSL(device, R"(
+ [[builtin(position)]] var<out> Position : vec4<f32>;
+ [[stage(vertex)]] fn main() -> void {
+ Position = vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ )");
+ pipelineDesc.cFragmentStage.module = utils::CreateShaderModuleFromWGSL(device, R"(
+ [[location(0)]] var<out> FragColor : vec4<f32>;
+ [[set(0), binding(0)]] var<uniform_constant> materials : texture_sampled_2d<f32>;
+ [[stage(fragment)]] fn main() -> void {
+ FragColor = vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ )");
+ mPipeline = device.CreateRenderPipeline(&pipelineDesc);
+ }
+
+ private:
+ void Step() override {
+ const SubresourceTrackingParams& params = GetParam();
+
+ uint32_t layerUploaded = params.arrayLayerCount / 2;
+
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+
+ // Copy into the layer of the material array.
+ {
+ wgpu::TextureCopyView sourceView;
+ sourceView.texture = mUploadTexture;
+
+ wgpu::TextureCopyView destView;
+ destView.texture = mMaterials;
+ destView.origin.z = layerUploaded;
+
+ wgpu::Extent3D copySize = {1u << (params.mipLevelCount - 1),
+ 1u << (params.mipLevelCount - 1), 1};
+
+ encoder.CopyTextureToTexture(&sourceView, &destView, ©Size);
+ }
+
+ // Fake commands that would be used to create the mip levels.
+ for (uint32_t level = 1; level < params.mipLevelCount; level++) {
+ wgpu::TextureViewDescriptor rtViewDesc;
+ rtViewDesc.dimension = wgpu::TextureViewDimension::e2D;
+ rtViewDesc.baseMipLevel = level;
+ rtViewDesc.mipLevelCount = 1;
+ rtViewDesc.baseArrayLayer = layerUploaded;
+ rtViewDesc.arrayLayerCount = 1;
+ wgpu::TextureView rtView = mMaterials.CreateView(&rtViewDesc);
+
+ wgpu::TextureViewDescriptor sampleViewDesc = rtViewDesc;
+ sampleViewDesc.baseMipLevel = level - 1;
+ wgpu::TextureView sampleView = mMaterials.CreateView(&sampleViewDesc);
+
+ wgpu::BindGroup bindgroup =
+ utils::MakeBindGroup(device, mPipeline.GetBindGroupLayout(0), {{0, sampleView}});
+
+ utils::ComboRenderPassDescriptor renderPass({rtView});
+ wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
+ pass.SetPipeline(mPipeline);
+ pass.SetBindGroup(0, bindgroup);
+ pass.Draw(3);
+ pass.EndPass();
+ }
+
+ wgpu::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+ }
+
+ wgpu::Texture mUploadTexture;
+ wgpu::Texture mMaterials;
+ wgpu::RenderPipeline mPipeline;
+};
+
+TEST_P(SubresourceTrackingPerf, Run) {
+ RunTest();
+}
+
+DAWN_INSTANTIATE_PERF_TEST_SUITE_P(SubresourceTrackingPerf,
+ {D3D12Backend(), MetalBackend(), OpenGLBackend(),
+ VulkanBackend()},
+ {1, 4, 16, 256},
+ {2, 3, 8});