summaryrefslogtreecommitdiffstats
path: root/gpu/perftests
diff options
context:
space:
mode:
authordcastagna <dcastagna@chromium.org>2015-02-13 15:07:06 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-13 23:08:09 +0000
commitb27d8d3fd8ac59e01b345192c4ada2aef07cb844 (patch)
treea086bdc70d558f354c44eca45242d71321df826e /gpu/perftests
parent99ed184ac0f7faee6b9875cdbfe2d33b7a966ffd (diff)
downloadchromium_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.cc99
-rw-r--r--gpu/perftests/measurements.h56
-rw-r--r--gpu/perftests/texture_upload_perftest.cc54
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();
}
}