diff options
author | dcastagna <dcastagna@chromium.org> | 2015-02-13 15:07:06 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-13 23:08:09 +0000 |
commit | b27d8d3fd8ac59e01b345192c4ada2aef07cb844 (patch) | |
tree | a086bdc70d558f354c44eca45242d71321df826e /gpu/perftests | |
parent | 99ed184ac0f7faee6b9875cdbfe2d33b7a966ffd (diff) | |
download | chromium_src-b27d8d3fd8ac59e01b345192c4ada2aef07cb844.zip chromium_src-b27d8d3fd8ac59e01b345192c4ada2aef07cb844.tar.gz chromium_src-b27d8d3fd8ac59e01b345192c4ada2aef07cb844.tar.bz2 |
gpu: Add a class MeasurementTimers that measures wall, cpu and gpu time.
The perf test texture_upload_perftest has been updated to use these new measurements.
BUG=423481
Review URL: https://codereview.chromium.org/893673002
Cr-Commit-Position: refs/heads/master@{#316314}
Diffstat (limited to 'gpu/perftests')
-rw-r--r-- | gpu/perftests/measurements.cc | 99 | ||||
-rw-r--r-- | gpu/perftests/measurements.h | 56 | ||||
-rw-r--r-- | gpu/perftests/texture_upload_perftest.cc | 54 |
3 files changed, 184 insertions, 25 deletions
diff --git a/gpu/perftests/measurements.cc b/gpu/perftests/measurements.cc new file mode 100644 index 0000000..270e459 --- /dev/null +++ b/gpu/perftests/measurements.cc @@ -0,0 +1,99 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/perftests/measurements.h" + +#include "testing/perf/perf_test.h" + +namespace gpu { + +Measurement::Measurement() : name(), wall_time(), cpu_time(), gpu_time() { +} +Measurement::Measurement(const Measurement& m) + : name(m.name), + wall_time(m.wall_time), + cpu_time(m.cpu_time), + gpu_time(m.gpu_time) { +} +Measurement::Measurement(const std::string& name, + const base::TimeDelta wall_time, + const base::TimeDelta cpu_time, + const base::TimeDelta gpu_time) + : name(name), wall_time(wall_time), cpu_time(cpu_time), gpu_time(gpu_time) { +} + +void Measurement::PrintResult() const { + perf_test::PrintResult(name, "_wall", "", wall_time.InMillisecondsF(), "ms", + true); + if (cpu_time.InMicroseconds() >= 0) { + perf_test::PrintResult(name, "_cpu", "", cpu_time.InMillisecondsF(), "ms", + true); + } + if (gpu_time.InMicroseconds() >= 0) { + perf_test::PrintResult(name, "_gpu", "", gpu_time.InMillisecondsF(), "ms", + true); + } +} + +Measurement& Measurement::Increment(const Measurement& m) { + wall_time += m.wall_time; + cpu_time += m.cpu_time; + gpu_time += m.gpu_time; + return *this; +} + +Measurement Measurement::Divide(int a) const { + return Measurement(name, wall_time / a, cpu_time / a, gpu_time / a); +} + +Measurement::~Measurement() { +} + +MeasurementTimers::MeasurementTimers(GPUTiming* gpu_timing) + : wall_time_start_(), cpu_time_start_(), gpu_timer_() { + DCHECK(gpu_timing); + wall_time_start_ = base::TimeTicks::NowFromSystemTraceTime(); + if (base::TimeTicks::IsThreadNowSupported()) { + cpu_time_start_ = base::TimeTicks::ThreadNow(); + } else { + static bool logged_once = false; + LOG_IF(WARNING, !logged_once) << "ThreadNow not supported."; + logged_once = true; + } + + if (gpu_timing->IsAvailable()) { + gpu_timer_.reset(new GPUTimer(gpu_timing)); + gpu_timer_->Start(); + } +} + +void MeasurementTimers::Record() { + wall_time_ = base::TimeTicks::NowFromSystemTraceTime() - wall_time_start_; + if (base::TimeTicks::IsThreadNowSupported()) { + cpu_time_ = base::TimeTicks::ThreadNow() - cpu_time_start_; + } + if (gpu_timer_.get()) { + gpu_timer_->End(); + } +} + +Measurement MeasurementTimers::GetAsMeasurement(const std::string& name) { + DCHECK_NE(base::TimeDelta(), + wall_time_); // At least wall_time_ has been set. + + if (!base::TimeTicks::IsThreadNowSupported()) { + cpu_time_ = base::TimeDelta::FromMicroseconds(-1); + } + int64 gpu_time = -1; + if (gpu_timer_.get() != nullptr && gpu_timer_->IsAvailable()) { + gpu_time = gpu_timer_->GetDeltaElapsed(); + } + return Measurement(name, wall_time_, cpu_time_, + base::TimeDelta::FromMicroseconds(gpu_time)); +} + +MeasurementTimers::~MeasurementTimers() { +} + +} // namespace gpu diff --git a/gpu/perftests/measurements.h b/gpu/perftests/measurements.h new file mode 100644 index 0000000..15be422 --- /dev/null +++ b/gpu/perftests/measurements.h @@ -0,0 +1,56 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_PERFTESTS_MEASUREMENTS_H_ +#define GPU_PERFTESTS_MEASUREMENTS_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "gpu/command_buffer/service/gpu_timing.h" +#include "ui/gl/gl_bindings.h" + +namespace gpu { +struct Measurement { + Measurement(); + Measurement(const Measurement& m); + Measurement(const std::string& name, + const base::TimeDelta wall_time, + const base::TimeDelta cpu_time, + const base::TimeDelta gpu_time); + ~Measurement(); + + void PrintResult() const; + Measurement& Increment(const Measurement& m); + Measurement Divide(int a) const; + + std::string name; + base::TimeDelta wall_time; + base::TimeDelta cpu_time; + base::TimeDelta gpu_time; +}; + +// Class to measure wall, cpu and gpu time deltas. +// The deltas are measured from the time of the object +// creation up to when Record is called. +class MeasurementTimers { + public: + explicit MeasurementTimers(GPUTiming* gpu_timing); + void Record(); + Measurement GetAsMeasurement(const std::string& name); + ~MeasurementTimers(); + + private: + base::TimeTicks wall_time_start_; + base::TimeTicks cpu_time_start_; + scoped_ptr<gpu::GPUTimer> gpu_timer_; + + base::TimeDelta wall_time_; + base::TimeDelta cpu_time_; +}; + +} // namespace gpu + +#endif // GPU_PERFTESTS_MEASUREMENTS_H_ diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc index 7166c2a5..f691c9e 100644 --- a/gpu/perftests/texture_upload_perftest.cc +++ b/gpu/perftests/texture_upload_perftest.cc @@ -8,10 +8,8 @@ #include "base/containers/small_map.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "base/timer/elapsed_timer.h" +#include "gpu/perftests/measurements.h" #include "testing/gtest/include/gtest/gtest.h" -#include "testing/perf/perf_test.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" @@ -103,9 +101,18 @@ class TextureUploadPerfTest : public testing::Test { surface_.get(), gfx::PreferIntegratedGpu); + ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); + if (gpu_timing_.Initialize(gl_context_.get())) { + LOG(INFO) << "Gpu timing initialized with timer type: " + << gpu_timing_.GetTimerTypeName(); + gpu_timing_.CheckAndResetTimerErrors(); + gpu_timing_.InvalidateTimerOffset(); + } else { + LOG(WARNING) << "Can't initialize gpu timing"; + } + // Prepare a simple program and a vertex buffer that will be // used to draw a quad on the offscreen surface. - ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader); fragment_shader_ = LoadShader(GL_FRAGMENT_SHADER, kFragmentShader); program_object_ = glCreateProgram(); @@ -153,26 +160,18 @@ class TextureUploadPerfTest : public testing::Test { } protected: - struct Measurement { - Measurement() : name(), wall_time(){}; - Measurement(const std::string& name, const base::TimeDelta wall_time) - : name(name), wall_time(wall_time){}; - std::string name; - base::TimeDelta wall_time; - }; // Upload and draw on the offscren surface. // Return a list of pair. Each pair describe a gl operation and the wall // time elapsed in milliseconds. std::vector<Measurement> UploadAndDraw(const std::vector<uint8>& pixels, const GLenum format, const GLenum type) { - std::vector<Measurement> measurements; ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); - base::ElapsedTimer total_timer; + MeasurementTimers total_timers(&gpu_timing_); GLuint texture_id = 0; - base::ElapsedTimer tex_timer; + MeasurementTimers tex_timers(&gpu_timing_); glActiveTexture(GL_TEXTURE0); glGenTextures(1, &texture_id); glBindTexture(GL_TEXTURE_2D, texture_id); @@ -184,9 +183,9 @@ class TextureUploadPerfTest : public testing::Test { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CheckNoGlError(); - measurements.push_back(Measurement("teximage2d", tex_timer.Elapsed())); + tex_timers.Record(); - base::ElapsedTimer draw_timer; + MeasurementTimers draw_timers(&gpu_timing_); glUseProgram(program_object_); glUniform1i(sampler_location_, 0); @@ -195,13 +194,13 @@ class TextureUploadPerfTest : public testing::Test { glEnableVertexAttribArray(0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - measurements.push_back(Measurement("drawarrays", draw_timer.Elapsed())); + draw_timers.Record(); - base::ElapsedTimer finish_timer; + MeasurementTimers finish_timers(&gpu_timing_); glFinish(); CheckNoGlError(); - measurements.push_back(Measurement("finish", finish_timer.Elapsed())); - measurements.push_back(Measurement("total", total_timer.Elapsed())); + finish_timers.Record(); + total_timers.Record(); glDeleteTextures(1, &texture_id); @@ -214,12 +213,19 @@ class TextureUploadPerfTest : public testing::Test { // the appropriate format conversion. EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format); EXPECT_EQ(pixels, pixels_rendered); + + std::vector<Measurement> measurements; + measurements.push_back(total_timers.GetAsMeasurement("total")); + measurements.push_back(tex_timers.GetAsMeasurement("teximage2d")); + measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); + measurements.push_back(finish_timers.GetAsMeasurement("finish")); return measurements; } const gfx::Size size_; // for the offscreen surface and the texture scoped_refptr<gfx::GLContext> gl_context_; scoped_refptr<gfx::GLSurface> surface_; + GPUTiming gpu_timing_; GLuint vertex_shader_ = 0; GLuint fragment_shader_ = 0; @@ -241,16 +247,14 @@ TEST_F(TextureUploadPerfTest, glTexImage2d) { for (const Measurement& m : run) { auto& agg = aggregates[m.name]; agg.name = m.name; - agg.wall_time += m.wall_time; + agg.Increment(m); } } } for (const auto& entry : aggregates) { - const auto& m = entry.second; - perf_test::PrintResult( - m.name, "", "", (m.wall_time / kUploadPerfTestRuns).InMillisecondsF(), - "ms", true); + const auto m = entry.second.Divide(kUploadPerfTestRuns); + m.PrintResult(); } } |