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>
This commit is contained in:
Corentin Wallez 2021-01-18 09:28:27 +00:00 committed by Commit Bot service account
parent 04772515a8
commit 5c20f1ec9c
4 changed files with 159 additions and 4 deletions

View File

@ -496,6 +496,7 @@ test("dawn_perf_tests") {
"perf_tests/DawnPerfTestPlatform.cpp",
"perf_tests/DawnPerfTestPlatform.h",
"perf_tests/DrawCallPerf.cpp",
"perf_tests/SubresourceTrackingPerf.cpp",
]
libs = []

View File

@ -234,7 +234,7 @@ void DawnPerfTestBase::DoRunLoop(double maxRunTime) {
dawn_platform::Platform* platform = gTestEnv->GetPlatform();
mNumStepsPerformed = 0;
cpuTime = 0;
mCpuTime = 0;
mRunning = true;
wgpu::FenceDescriptor desc = {};
@ -252,7 +252,7 @@ void DawnPerfTestBase::DoRunLoop(double maxRunTime) {
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 @@ void DawnPerfTestBase::OutputResults() {
}
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);

View File

@ -104,7 +104,7 @@ class DawnPerfTestBase {
const unsigned int mMaxStepsInFlight;
unsigned int mStepsToRun = 0;
unsigned int mNumStepsPerformed = 0;
double cpuTime;
double mCpuTime;
std::unique_ptr<utils::Timer> mTimer;
};

View File

@ -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, &copySize);
}
// 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});