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:
@ -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',
|
||||
|
17
content/public/common/gpu_rendering_stats.cc
Normal file
17
content/public/common/gpu_rendering_stats.cc
Normal file
@ -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
|
27
content/public/common/gpu_rendering_stats.h
Normal file
27
content/public/common/gpu_rendering_stats.h
Normal file
@ -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);
|
||||
};
|
||||
|
Reference in New Issue
Block a user