Skip to content

Commit

Permalink
gpu in-memory program cache implementation with a memory limit + lru …
Browse files Browse the repository at this point in the history
…eviction.

Wiring: 
- Added bindings for glProgramBinary, glGetProgramBinary, glProgramParameteri 
- Plumbed the shader cache from gl_channel_manager to program_manager 
- Program cache creation after first context is created 

Refactoring: 
- moved DoCompile to ProgramManager 

New: 
- added functionality to ShaderInfo to store if we have a possible pending cache compile 
- exposed attrib_map and uniform_map in ShaderInfo for the cache 
- program_cache base class with in-memory status storage 
- Simple memory_program_cache implementation, stores programs with lru eviction 
- Added caching logic to DoCompileShader and Link in ProgramMAnager 
- MemoryProgramCache, the in-memory cache implementation 
- ProgramCacheLruHelper, an O(1) lru implementation 

Misc: 
- A couple style fixes in modified files 

Design doc: https://docs.google.com/document/d/1Vceem-nF4TCICoeGSh7OMXxfGuJEJYblGXRgN9V9hcE/edit 

BUG=88572


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147932 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
dmurph@chromium.org committed Jul 23, 2012
1 parent 51383d8 commit 65dfc60
Show file tree
Hide file tree
Showing 39 changed files with 2,260 additions and 93 deletions.
1 change: 1 addition & 0 deletions content/common/gpu/gpu_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <deque>
#include <string>
#include <vector>

#include "base/id_map.h"
#include "base/memory/ref_counted.h"
Expand Down
19 changes: 17 additions & 2 deletions content/common/gpu/gpu_channel_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
#include "content/common/gpu/gpu_channel_manager.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "content/common/child_thread.h"
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/sync_point_manager.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_program_cache.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_share_group.h"

GpuChannelManager::GpuChannelManager(ChildThread* gpu_child_thread,
Expand All @@ -24,7 +29,8 @@ GpuChannelManager::GpuChannelManager(ChildThread* gpu_child_thread,
ALLOW_THIS_IN_INITIALIZER_LIST(gpu_memory_manager_(this,
GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit)),
watchdog_(watchdog),
sync_point_manager_(new SyncPointManager) {
sync_point_manager_(new SyncPointManager),
program_cache_(NULL) {
DCHECK(gpu_child_thread);
DCHECK(io_message_loop);
DCHECK(shutdown_event);
Expand All @@ -34,6 +40,16 @@ GpuChannelManager::~GpuChannelManager() {
gpu_channels_.clear();
}

gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
if (!program_cache_.get() &&
(gfx::g_ARB_get_program_binary || gfx::g_OES_get_program_binary) &&
!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuProgramCache)) {
program_cache_.reset(new gpu::gles2::MemoryProgramCache());
}
return program_cache_.get();
}

void GpuChannelManager::RemoveChannel(int client_id) {
gpu_channels_.erase(client_id);
}
Expand Down Expand Up @@ -65,7 +81,6 @@ void GpuChannelManager::AppendAllCommandBufferStubs(
it != gpu_channels_.end(); ++it ) {
it->second->AppendAllCommandBufferStubs(stubs);
}

}

bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
Expand Down
7 changes: 7 additions & 0 deletions content/common/gpu/gpu_channel_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
#ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_
#define CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_

#include <vector>

#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop_proxy.h"
#include "build/build_config.h"
Expand All @@ -26,6 +29,7 @@ class GLShareGroup;
namespace gpu {
namespace gles2 {
class MailboxManager;
class ProgramCache;
}
}

Expand Down Expand Up @@ -80,6 +84,8 @@ class GpuChannelManager : public IPC::Listener,
void AddRoute(int32 routing_id, IPC::Listener* listener);
void RemoveRoute(int32 routing_id);

gpu::gles2::ProgramCache* program_cache();

GpuMemoryManager* gpu_memory_manager() { return &gpu_memory_manager_; }

GpuChannel* LookupChannel(int32 client_id);
Expand Down Expand Up @@ -116,6 +122,7 @@ class GpuChannelManager : public IPC::Listener,
GpuMemoryManager gpu_memory_manager_;
GpuWatchdog* watchdog_;
scoped_refptr<SyncPointManager> sync_point_manager_;
scoped_ptr<gpu::gles2::ProgramCache> program_cache_;

DISALLOW_COPY_AND_ASSIGN(GpuChannelManager);
};
Expand Down
5 changes: 5 additions & 0 deletions content/common/gpu/gpu_command_buffer_stub.cc
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,11 @@ void GpuCommandBufferStub::OnInitialize(
return;
}

if (!context_group_->has_program_cache()) {
context_group_->set_program_cache(
channel_->gpu_channel_manager()->program_cache());
}

// Initialize the decoder with either the view or pbuffer GLContext.
if (!decoder_->Initialize(surface_,
context_,
Expand Down
1 change: 0 additions & 1 deletion content/common/gpu/gpu_command_buffer_stub.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "base/observer_list.h"
#include "content/common/content_export.h"
#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/common/gpu/gpu_memory_allocation.h"
#include "googleurl/src/gurl.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
Expand Down
11 changes: 11 additions & 0 deletions gpu/command_buffer/common/gl_mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ class MockGLInterface : public GLInterface {

MOCK_METHOD2(GetIntegerv, void(GLenum pname, GLint* params));

MOCK_METHOD5(GetProgramBinary, void(
GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat,
GLvoid* binary));

MOCK_METHOD3(GetProgramiv, void(GLuint program, GLenum pname, GLint* params));

MOCK_METHOD4(GetProgramInfoLog, void(
Expand Down Expand Up @@ -307,6 +311,13 @@ class MockGLInterface : public GLInterface {

MOCK_METHOD2(PolygonOffset, void(GLfloat factor, GLfloat units));

MOCK_METHOD4(ProgramBinary, void(
GLuint program, GLenum binaryFormat, const GLvoid* binary,
GLsizei length));

MOCK_METHOD3(ProgramParameteri, void(
GLuint program, GLenum pname, GLint value));

MOCK_METHOD2(QueryCounter, void(GLuint id, GLenum target));

MOCK_METHOD1(ReadBuffer, void(GLenum src));
Expand Down
4 changes: 3 additions & 1 deletion gpu/command_buffer/service/context_group.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "gpu/command_buffer/service/context_group.h"

#include <algorithm>
#include <string>

#include "base/command_line.h"
Expand Down Expand Up @@ -39,6 +40,7 @@ ContextGroup::ContextGroup(
max_fragment_uniform_vectors_(0u),
max_varying_vectors_(0u),
max_vertex_uniform_vectors_(0u),
program_cache_(NULL),
feature_info_(new FeatureInfo()) {
{
TransferBufferManager* manager = new TransferBufferManager();
Expand Down Expand Up @@ -93,7 +95,7 @@ bool ContextGroup::Initialize(const DisallowedFeatures& disallowed_features,
renderbuffer_manager_.reset(new RenderbufferManager(
max_renderbuffer_size, max_samples));
shader_manager_.reset(new ShaderManager());
program_manager_.reset(new ProgramManager());
program_manager_.reset(new ProgramManager(program_cache_));

// Lookup GL things we need to know.
const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
Expand Down
11 changes: 11 additions & 0 deletions gpu/command_buffer/service/context_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TransferBufferManagerInterface;

namespace gles2 {

class ProgramCache;
class BufferManager;
class GLES2Decoder;
class FramebufferManager;
Expand Down Expand Up @@ -112,6 +113,14 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
return program_manager_.get();
}

bool has_program_cache() const {
return program_cache_ != NULL;
}

void set_program_cache(ProgramCache* program_cache) {
program_cache_ = program_cache;
}

ShaderManager* shader_manager() const {
return shader_manager_.get();
}
Expand Down Expand Up @@ -149,6 +158,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
uint32 max_varying_vectors_;
uint32 max_vertex_uniform_vectors_;

ProgramCache* program_cache_;

scoped_ptr<BufferManager> buffer_manager_;

scoped_ptr<FramebufferManager> framebuffer_manager_;
Expand Down
7 changes: 7 additions & 0 deletions gpu/command_buffer/service/gl_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@

#define GL_GLEXT_PROTOTYPES 1

// GL_ARB_get_program_binary
#define PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
// GL_OES_get_program_binary
#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF

// Define this for extra GL error debugging (slower).
// #define GL_ERROR_DEBUGGING
#ifdef GL_ERROR_DEBUGGING
Expand Down
60 changes: 12 additions & 48 deletions gpu/command_buffer/service/gles2_cmd_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4719,7 +4719,16 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
return;
}

if (info->Link()) {
ShaderTranslator* vertex_translator = NULL;
ShaderTranslator* fragment_translator = NULL;
if (use_shader_translator_) {
vertex_translator = vertex_translator_;
fragment_translator = fragment_translator_;
}
if (info->Link(shader_manager(),
vertex_translator,
fragment_translator,
feature_info_)) {
if (info == current_program_.get()) {
program_manager()->ClearUniforms(info);
}
Expand Down Expand Up @@ -5812,58 +5821,13 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
if (!info) {
return;
}
// Translate GL ES 2.0 shader to Desktop GL shader and pass that to
// glShaderSource and then glCompileShader.
const char* shader_src = info->source() ? info->source()->c_str() : "";
ShaderTranslator* translator = NULL;
if (use_shader_translator_) {
translator = info->shader_type() == GL_VERTEX_SHADER ?
vertex_translator_.get() : fragment_translator_.get();

if (!translator->Translate(shader_src)) {
info->SetStatus(false, translator->info_log(), NULL);
return;
}
shader_src = translator->translated_shader();
if (!feature_info_->feature_flags().angle_translated_shader_source)
info->UpdateTranslatedSource(shader_src);
}

glShaderSource(info->service_id(), 1, &shader_src, NULL);
glCompileShader(info->service_id());
if (feature_info_->feature_flags().angle_translated_shader_source) {
GLint max_len = 0;
glGetShaderiv(info->service_id(),
GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
&max_len);
scoped_array<char> temp(new char[max_len]);
GLint len = 0;
glGetTranslatedShaderSourceANGLE(
info->service_id(), max_len, &len, temp.get());
DCHECK(max_len == 0 || len < max_len);
DCHECK(len == 0 || temp[len] == '\0');
info->UpdateTranslatedSource(temp.get());
}

GLint status = GL_FALSE;
glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
if (status) {
info->SetStatus(true, "", translator);
} else {
// We cannot reach here if we are using the shader translator.
// All invalid shaders must be rejected by the translator.
// All translated shaders must compile.
LOG_IF(ERROR, use_shader_translator_)
<< "Shader translator allowed/produced an invalid shader.";
GLint max_len = 0;
glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
scoped_array<char> temp(new char[max_len]);
GLint len = 0;
glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
DCHECK(max_len == 0 || len < max_len);
DCHECK(len == 0 || temp[len] == '\0');
info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
}

program_manager()->DoCompileShader(info, translator, feature_info_);
};

void GLES2DecoderImpl::DoGetShaderiv(
Expand Down
2 changes: 1 addition & 1 deletion gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ void GLES2DecoderTestBase::SpecializedSetup<GetProgramInfoLog, 0>(
attach_cmd.Init(client_program_id_, kClientFragmentShaderId);
EXPECT_EQ(error::kNoError, ExecuteCmd(attach_cmd));

info->Link();
info->Link(NULL, NULL, NULL, NULL);
};

template <>
Expand Down
4 changes: 2 additions & 2 deletions gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <algorithm>
#include <string>
#include <vector>

#include "base/string_number_conversions.h"
#include "gpu/command_buffer/common/gl_mock.h"
Expand Down Expand Up @@ -874,8 +875,7 @@ void GLES2DecoderTestBase::DoTexImage2DSameSize(
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type,
uint32 shared_memory_id, uint32 shared_memory_offset) {
if (GLES2Decoder::IsAngle())
{
if (GLES2Decoder::IsAngle()) {
EXPECT_CALL(*gl_, TexSubImage2D(
target, level, 0, 0, width, height, format, type, _))
.Times(1)
Expand Down
Loading

0 comments on commit 65dfc60

Please sign in to comment.