0

Report texture upload time in renderingStats.

BUG=133658
TEST=TEST=Launch Chrome with --enable-gpu-benchmarking, open a tab to a composited page, and type chrome.gpuBenchmarking.renderingStats(). textureUploadCount, and totalTextureUploadTimeInSeconds should be present.


Review URL: https://chromiumcodereview.appspot.com/10868048

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155099 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
reveman@chromium.org
2012-09-06 02:04:52 +00:00
parent 91763a1d7c
commit 63b4659295
14 changed files with 215 additions and 1 deletions

@ -214,6 +214,14 @@ void GpuChannelHost::DestroyCommandBuffer(
#endif
}
bool GpuChannelHost::CollectRenderingStatsForSurface(
int surface_id, content::GpuRenderingStats* stats) {
TRACE_EVENT0("gpu", "GpuChannelHost::CollectRenderingStats");
return Send(new GpuChannelMsg_CollectRenderingStatsForSurface(surface_id,
stats));
}
void GpuChannelHost::AddRoute(
int route_id, base::WeakPtr<IPC::Listener> listener) {
DCHECK(MessageLoopProxy::current());

@ -38,6 +38,10 @@ namespace base {
class MessageLoopProxy;
}
namespace content {
struct GpuRenderingStats;
}
namespace IPC {
class SyncMessageFilter;
}
@ -131,6 +135,10 @@ class GpuChannelHost : public IPC::Sender,
// Destroy a command buffer created by this channel.
void DestroyCommandBuffer(CommandBufferProxy* command_buffer);
// Collect rendering stats from GPU process.
bool CollectRenderingStatsForSurface(
int surface_id, content::GpuRenderingStats* stats);
// Add a route for the current message loop.
void AddRoute(int route_id, base::WeakPtr<IPC::Listener> listener);
void RemoveRoute(int route_id);

@ -400,6 +400,9 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(GpuChannelMsg_EstablishStreamTexture,
OnEstablishStreamTexture)
#endif
IPC_MESSAGE_HANDLER_DELAY_REPLY(
GpuChannelMsg_CollectRenderingStatsForSurface,
OnCollectRenderingStatsForSurface)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled) << msg.type();
@ -537,3 +540,32 @@ void GpuChannel::OnEstablishStreamTexture(
}
#endif
void GpuChannel::OnCollectRenderingStatsForSurface(
int32 surface_id, IPC::Message* reply_message) {
content::GpuRenderingStats stats;
for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
!it.IsAtEnd(); it.Advance()) {
int texture_upload_count =
it.GetCurrentValue()->decoder()->GetTextureUploadCount();
base::TimeDelta total_texture_upload_time =
it.GetCurrentValue()->decoder()->GetTotalTextureUploadTime();
base::TimeDelta total_processing_commands_time =
it.GetCurrentValue()->decoder()->GetTotalProcessingCommandsTime();
stats.global_texture_upload_count += texture_upload_count;
stats.global_total_texture_upload_time += total_texture_upload_time;
stats.global_total_processing_commands_time +=
total_processing_commands_time;
if (it.GetCurrentValue()->surface_id() == surface_id) {
stats.texture_upload_count += texture_upload_count;
stats.total_texture_upload_time += total_texture_upload_time;
stats.total_processing_commands_time += total_processing_commands_time;
}
}
GpuChannelMsg_CollectRenderingStatsForSurface::WriteReplyParams(
reply_message,
stats);
Send(reply_message);
}

@ -157,6 +157,10 @@ class GpuChannel : public IPC::Listener,
int32 primary_id, int32 secondary_id);
#endif
// Collect rendering stats.
void OnCollectRenderingStatsForSurface(
int32 surface_id, IPC::Message* reply_message);
// The lifetime of objects of this class is managed by a GpuChannelManager.
// The GpuChannelManager destroy all the GpuChannels that they own when they
// are destroyed. So a raw pointer is safe.

@ -15,6 +15,7 @@
#include "content/public/common/common_param_traits.h"
#include "content/public/common/gpu_info.h"
#include "content/public/common/gpu_memory_stats.h"
#include "content/public/common/gpu_rendering_stats.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/ipc/gpu_command_buffer_traits.h"
@ -194,6 +195,15 @@ IPC_ENUM_TRAITS(gpu::error::ContextLostReason)
IPC_ENUM_TRAITS(media::VideoCodecProfile)
IPC_STRUCT_TRAITS_BEGIN(content::GpuRenderingStats)
IPC_STRUCT_TRAITS_MEMBER(global_texture_upload_count)
IPC_STRUCT_TRAITS_MEMBER(global_total_texture_upload_time)
IPC_STRUCT_TRAITS_MEMBER(texture_upload_count)
IPC_STRUCT_TRAITS_MEMBER(total_texture_upload_time)
IPC_STRUCT_TRAITS_MEMBER(global_total_processing_commands_time)
IPC_STRUCT_TRAITS_MEMBER(total_processing_commands_time)
IPC_STRUCT_TRAITS_END()
//------------------------------------------------------------------------------
// GPU Messages
// These are messages from the browser to the GPU process.
@ -378,7 +388,14 @@ IPC_MESSAGE_CONTROL4(GpuChannelMsg_EstablishStreamTexture,
/* type */
int32, /* primary_id */
int32 /* secondary_id */)
#endif
// Tells the GPU process to collect rendering stats.
IPC_SYNC_MESSAGE_CONTROL1_1(GpuChannelMsg_CollectRenderingStatsForSurface,
int32 /* surface_id */,
content::GpuRenderingStats /* stats */)
#if defined(OS_ANDROID)
//------------------------------------------------------------------------------
// Stream Texture Messages
// Inform the renderer that a new frame is available.

@ -62,6 +62,8 @@
'public/common/gpu_memory_stats.cc',
'public/common/gpu_memory_stats.h',
'public/common/gpu_performance_stats.h',
'public/common/gpu_rendering_stats.cc',
'public/common/gpu_rendering_stats.h',
'public/common/injection_test_mac.h',
'public/common/injection_test_win.h',
'public/common/javascript_message_type.h',

@ -0,0 +1,17 @@
// Copyright (c) 2012 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 "content/public/common/gpu_rendering_stats.h"
namespace content {
GpuRenderingStats::GpuRenderingStats()
: global_texture_upload_count(0),
texture_upload_count(0) {
}
GpuRenderingStats::~GpuRenderingStats() {
}
} // namespace content

@ -0,0 +1,27 @@
// Copyright (c) 2012 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 CONTENT_PUBLIC_COMMON_RENDERING_STATS_H_
#define CONTENT_PUBLIC_COMMON_RENDERING_STATS_H_
#include "base/time.h"
#include "content/common/content_export.h"
namespace content {
struct CONTENT_EXPORT GpuRenderingStats {
GpuRenderingStats();
~GpuRenderingStats();
int global_texture_upload_count;
base::TimeDelta global_total_texture_upload_time;
int texture_upload_count;
base::TimeDelta total_texture_upload_time;
base::TimeDelta global_total_processing_commands_time;
base::TimeDelta total_processing_commands_time;
};
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_RENDERING_STATS_H_

@ -10,6 +10,7 @@
#include "base/file_util.h"
#include "base/memory/scoped_vector.h"
#include "base/string_number_conversions.h"
#include "content/public/common/gpu_rendering_stats.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/all_rendering_benchmarks.h"
#include "content/renderer/render_view_impl.h"
@ -151,6 +152,9 @@ class GpuBenchmarkingWrapper : public v8::Extension {
WebRenderingStats stats;
render_view_impl->GetRenderingStats(stats);
content::GpuRenderingStats gpu_stats;
render_view_impl->GetGpuRenderingStats(&gpu_stats);
v8::Handle<v8::Object> stats_object = v8::Object::New();
stats_object->Set(v8::String::New("numAnimationFrames"),
v8::Integer::New(stats.numAnimationFrames));
@ -162,6 +166,25 @@ class GpuBenchmarkingWrapper : public v8::Extension {
v8::Number::New(stats.totalPaintTimeInSeconds));
stats_object->Set(v8::String::New("totalRasterizeTimeInSeconds"),
v8::Number::New(stats.totalRasterizeTimeInSeconds));
stats_object->Set(v8::String::New("globalTextureUploadCount"),
v8::Number::New(gpu_stats.global_texture_upload_count));
stats_object->Set(
v8::String::New("globalTotalTextureUploadTimeInSeconds"),
v8::Number::New(
gpu_stats.global_total_texture_upload_time.InSecondsF()));
stats_object->Set(v8::String::New("textureUploadCount"),
v8::Number::New(gpu_stats.texture_upload_count));
stats_object->Set(
v8::String::New("totalTextureUploadTimeInSeconds"),
v8::Number::New(gpu_stats.total_texture_upload_time.InSecondsF()));
stats_object->Set(
v8::String::New("globalTotalProcessingCommandsTimeInSeconds"),
v8::Number::New(
gpu_stats.global_total_processing_commands_time.InSecondsF()));
stats_object->Set(
v8::String::New("totalProcessingCommandsTimeInSeconds"),
v8::Number::New(
gpu_stats.total_processing_commands_time.InSecondsF()));
return stats_object;
}

@ -1830,6 +1830,15 @@ void RenderWidget::GetRenderingStats(WebKit::WebRenderingStats& stats) const {
stats.totalPaintTimeInSeconds += software_stats_.totalPaintTimeInSeconds;
}
bool RenderWidget::GetGpuRenderingStats(
content::GpuRenderingStats* stats) const {
GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
if (!gpu_channel)
return false;
return gpu_channel->CollectRenderingStatsForSurface(surface_id(), stats);
}
void RenderWidget::BeginSmoothScroll(
bool down,
bool scroll_far,

@ -48,6 +48,7 @@ class WebWidget;
}
namespace content {
struct GpuRenderingStats;
class RenderWidgetTest;
}
@ -161,6 +162,12 @@ class CONTENT_EXPORT RenderWidget
// as it blocks on the compositor thread.
void GetRenderingStats(WebKit::WebRenderingStats&) const;
// Fills in a GpuRenderingStats struct containing information about
// GPU rendering, e.g. count of texture uploads performed, time spent
// uploading.
// This call is relatively expensive as it blocks on the GPU process
bool GetGpuRenderingStats(content::GpuRenderingStats*) const;
// Callback for use with BeginSmoothScroll.
typedef base::Callback<void()> SmoothScrollCompletionCallback;

@ -318,6 +318,18 @@ class ScopedResolvedFrameBufferBinder {
DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
};
// This class records texture upload time when in scope.
class ScopedTextureUploadTimer {
public:
explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder);
~ScopedTextureUploadTimer();
private:
GLES2DecoderImpl* decoder_;
base::TimeTicks begin_time_;
DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
};
// Encapsulates an OpenGL texture.
class Texture {
public:
@ -520,6 +532,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual uint32 GetGLError() OVERRIDE;
virtual uint32 GetTextureUploadCount() OVERRIDE;
virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
// Restores the current state to the user's settings.
void RestoreCurrentFramebufferBindings();
void RestoreCurrentRenderbufferBindings();
@ -542,6 +558,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
private:
friend class ScopedGLErrorSuppressor;
friend class ScopedResolvedFrameBufferBinder;
friend class ScopedTextureUploadTimer;
friend class Texture;
friend class RenderBuffer;
friend class FrameBuffer;
@ -1585,6 +1602,11 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
GLsizei viewport_width_, viewport_height_;
GLsizei viewport_max_width_, viewport_max_height_;
// Command buffer stats.
int texture_upload_count_;
base::TimeDelta total_texture_upload_time_;
base::TimeDelta total_processing_commands_time_;
DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
};
@ -1700,6 +1722,17 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
}
}
ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder)
: decoder_(decoder),
begin_time_(base::TimeTicks::HighResNow()) {
}
ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
decoder_->texture_upload_count_++;
decoder_->total_texture_upload_time_ +=
base::TimeTicks::HighResNow() - begin_time_;
}
Texture::Texture(GLES2DecoderImpl* decoder)
: decoder_(decoder),
memory_tracker_(decoder->GetContextGroup()->memory_tracker(),
@ -1990,7 +2023,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
viewport_width_(0),
viewport_height_(0),
viewport_max_width_(0),
viewport_max_height_(0) {
viewport_max_height_(0),
texture_upload_count_(0) {
DCHECK(group);
GLES2DecoderImpl* this_temp = this;
@ -2836,6 +2870,18 @@ bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
return false;
}
uint32 GLES2DecoderImpl::GetTextureUploadCount() {
return texture_upload_count_;
}
base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
return total_texture_upload_time_;
}
base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
return total_processing_commands_time_;
}
void GLES2DecoderImpl::Destroy(bool have_context) {
DCHECK(!have_context || context_->IsCurrent(NULL));
@ -3213,6 +3259,7 @@ error::Error GLES2DecoderImpl::DoCommand(
unsigned int arg_count,
const void* cmd_data) {
error::Error result = error::kNoError;
base::TimeTicks begin_time(base::TimeTicks::HighResNow());
if (log_commands()) {
// TODO(notme): Change this to a LOG/VLOG that works in release. Tried
// LOG(INFO), tried VLOG(1), no luck.
@ -3257,6 +3304,8 @@ error::Error GLES2DecoderImpl::DoCommand(
result = current_decoder_error_;
current_decoder_error_ = error::kNoError;
}
total_processing_commands_time_ +=
base::TimeTicks::HighResNow() - begin_time;
return result;
}
@ -7803,17 +7852,20 @@ void GLES2DecoderImpl::DoTexSubImage2D(
SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
return;
}
ScopedTextureUploadTimer timer(this);
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
return;
}
if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
ScopedTextureUploadTimer timer(this);
// NOTE: In OpenGL ES 2.0 border is always zero and format is always the
// same as internal_foramt. If that changes we'll need to look them up.
WrappedTexImage2D(
target, level, format, width, height, 0, format, type, data);
} else {
ScopedTextureUploadTimer timer(this);
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
}

@ -10,6 +10,7 @@
#include <vector>
#include "base/callback.h"
#include "base/time.h"
#include "build/build_config.h"
#include "gpu/command_buffer/service/common_decoder.h"
#include "ui/gfx/size.h"
@ -173,6 +174,10 @@ class GPU_EXPORT GLES2Decoder : public CommonDecoder {
// A callback for messages from the decoder.
virtual void SetMsgCallback(const MsgCallback& callback) = 0;
virtual uint32 GetTextureUploadCount() = 0;
virtual base::TimeDelta GetTotalTextureUploadTime() = 0;
virtual base::TimeDelta GetTotalProcessingCommandsTime() = 0;
static bool IsAngle();
// Used for testing only

@ -74,6 +74,9 @@ class MockGLES2Decoder : public GLES2Decoder {
bool is_texture_immutable));
MOCK_METHOD0(GetGLError, uint32());
MOCK_METHOD1(SetMsgCallback, void(const MsgCallback& callback));
MOCK_METHOD0(GetTextureUploadCount, uint32());
MOCK_METHOD0(GetTotalTextureUploadTime, base::TimeDelta());
MOCK_METHOD0(GetTotalProcessingCommandsTime, base::TimeDelta());
DISALLOW_COPY_AND_ASSIGN(MockGLES2Decoder);
};