diff options
author | zmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-19 20:58:26 +0000 |
---|---|---|
committer | zmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-19 20:58:26 +0000 |
commit | 186e1ae7ffd48e96e3de93f09381230d3b0911d5 (patch) | |
tree | 3cae5644f18088676675e9eab2be008423eed9a1 /gpu | |
parent | 0b1e4b50e05c71d5a4d155b90b25125c780c59be (diff) | |
download | chromium_src-186e1ae7ffd48e96e3de93f09381230d3b0911d5.zip chromium_src-186e1ae7ffd48e96e3de93f09381230d3b0911d5.tar.gz chromium_src-186e1ae7ffd48e96e3de93f09381230d3b0911d5.tar.bz2 |
Cache varying variable info in Shader object in command buffer.
Also, check uniform data type and precision match.
BUG=249018
TEST=webgl conformance tests
R=apatrick@chromium.org
Review URL: https://codereview.chromium.org/22330003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218309 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/service/disk_cache_proto.proto | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/memory_program_cache.cc | 50 | ||||
-rw-r--r-- | gpu/command_buffer/service/memory_program_cache.h | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/memory_program_cache_unittest.cc | 44 | ||||
-rw-r--r-- | gpu/command_buffer/service/mocks.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/program_manager.cc | 54 | ||||
-rw-r--r-- | gpu/command_buffer/service/program_manager.h | 5 | ||||
-rw-r--r-- | gpu/command_buffer/service/program_manager_unittest.cc | 97 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_manager.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_manager.h | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_manager_unittest.cc | 18 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_translator.cc | 29 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_translator.h | 11 |
13 files changed, 290 insertions, 47 deletions
diff --git a/gpu/command_buffer/service/disk_cache_proto.proto b/gpu/command_buffer/service/disk_cache_proto.proto index c165443..2c504aa 100644 --- a/gpu/command_buffer/service/disk_cache_proto.proto +++ b/gpu/command_buffer/service/disk_cache_proto.proto @@ -5,12 +5,14 @@ message ShaderInfoProto { optional int32 size = 2; optional string name = 3; optional string key = 4; + optional int32 precision = 5; } message ShaderProto { optional bytes sha = 1; repeated ShaderInfoProto attribs = 2; repeated ShaderInfoProto uniforms = 3; + repeated ShaderInfoProto varyings = 4; } message GpuProgramProto { diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc index e09d132..3bff3dc 100644 --- a/gpu/command_buffer/service/memory_program_cache.cc +++ b/gpu/command_buffer/service/memory_program_cache.cc @@ -15,6 +15,7 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/shader_manager.h" +#include "gpu/command_buffer/service/shader_translator.h" #include "ui/gl/gl_bindings.h" namespace { @@ -40,31 +41,40 @@ namespace { enum ShaderMapType { ATTRIB_MAP = 0, - UNIFORM_MAP + UNIFORM_MAP, + VARYING_MAP }; void StoreShaderInfo(ShaderMapType type, ShaderProto *proto, const ShaderTranslator::VariableMap& map) { ShaderTranslator::VariableMap::const_iterator iter; - for (iter = map.begin(); iter != map.end(); iter++) { - ShaderInfoProto* info; - if (type == UNIFORM_MAP) { - info = proto->add_uniforms(); - } else { - info = proto->add_attribs(); + for (iter = map.begin(); iter != map.end(); ++iter) { + ShaderInfoProto* info = NULL; + switch (type) { + case UNIFORM_MAP: + info = proto->add_uniforms(); + break; + case ATTRIB_MAP: + info = proto->add_attribs(); + break; + case VARYING_MAP: + info = proto->add_varyings(); + break; + default: NOTREACHED(); } info->set_key(iter->first); info->set_type(iter->second.type); info->set_size(iter->second.size); + info->set_precision(iter->second.precision); info->set_name(iter->second.name); } } void RetrieveShaderInfo(const ShaderInfoProto& proto, ShaderTranslator::VariableMap* map) { - ShaderTranslator::VariableInfo info(proto.type(), proto.size(), - proto.name()); + ShaderTranslator::VariableInfo info( + proto.type(), proto.size(), proto.precision(), proto.name()); (*map)[proto.key()] = info; } @@ -73,6 +83,7 @@ void FillShaderProto(ShaderProto* proto, const char* sha, proto->set_sha(sha, gpu::gles2::ProgramCache::kHashLength); StoreShaderInfo(ATTRIB_MAP, proto, shader->attrib_map()); StoreShaderInfo(UNIFORM_MAP, proto, shader->uniform_map()); + StoreShaderInfo(VARYING_MAP, proto, shader->varying_map()); } void RunShaderCallback(const ShaderCacheCallback& callback, @@ -147,8 +158,10 @@ ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram( } shader_a->set_attrib_map(value->attrib_map_0()); shader_a->set_uniform_map(value->uniform_map_0()); + shader_a->set_varying_map(value->varying_map_0()); shader_b->set_attrib_map(value->attrib_map_1()); shader_b->set_uniform_map(value->uniform_map_1()); + shader_b->set_varying_map(value->varying_map_1()); if (!shader_callback.is_null() && !CommandLine::ForCurrentProcess()->HasSwitch( @@ -241,9 +254,11 @@ void MemoryProgramCache::SaveLinkedProgram( a_sha, shader_a->attrib_map(), shader_a->uniform_map(), + shader_a->varying_map(), b_sha, shader_b->attrib_map(), shader_b->uniform_map(), + shader_b->varying_map(), this)); UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", @@ -255,6 +270,7 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { if (proto->ParseFromString(program)) { ShaderTranslator::VariableMap vertex_attribs; ShaderTranslator::VariableMap vertex_uniforms; + ShaderTranslator::VariableMap vertex_varyings; for (int i = 0; i < proto->vertex_shader().attribs_size(); i++) { RetrieveShaderInfo(proto->vertex_shader().attribs(i), &vertex_attribs); @@ -264,8 +280,13 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { RetrieveShaderInfo(proto->vertex_shader().uniforms(i), &vertex_uniforms); } + for (int i = 0; i < proto->vertex_shader().varyings_size(); i++) { + RetrieveShaderInfo(proto->vertex_shader().varyings(i), &vertex_varyings); + } + ShaderTranslator::VariableMap fragment_attribs; ShaderTranslator::VariableMap fragment_uniforms; + ShaderTranslator::VariableMap fragment_varyings; for (int i = 0; i < proto->fragment_shader().attribs_size(); i++) { RetrieveShaderInfo(proto->fragment_shader().attribs(i), @@ -277,6 +298,11 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { &fragment_uniforms); } + for (int i = 0; i < proto->fragment_shader().varyings_size(); i++) { + RetrieveShaderInfo(proto->fragment_shader().varyings(i), + &fragment_varyings); + } + scoped_ptr<char[]> binary(new char[proto->program().length()]); memcpy(binary.get(), proto->program().c_str(), proto->program().length()); @@ -288,9 +314,11 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { proto->vertex_shader().sha().c_str(), vertex_attribs, vertex_uniforms, + vertex_varyings, proto->fragment_shader().sha().c_str(), fragment_attribs, fragment_uniforms, + fragment_varyings, this)); UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", @@ -308,9 +336,11 @@ MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( const char* shader_0_hash, const ShaderTranslator::VariableMap& attrib_map_0, const ShaderTranslator::VariableMap& uniform_map_0, + const ShaderTranslator::VariableMap& varying_map_0, const char* shader_1_hash, const ShaderTranslator::VariableMap& attrib_map_1, const ShaderTranslator::VariableMap& uniform_map_1, + const ShaderTranslator::VariableMap& varying_map_1, MemoryProgramCache* program_cache) : length_(length), format_(format), @@ -319,9 +349,11 @@ MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( shader_0_hash_(shader_0_hash, kHashLength), attrib_map_0_(attrib_map_0), uniform_map_0_(uniform_map_0), + varying_map_0_(varying_map_0), shader_1_hash_(shader_1_hash, kHashLength), attrib_map_1_(attrib_map_1), uniform_map_1_(uniform_map_1), + varying_map_1_(varying_map_1), program_cache_(program_cache) { program_cache_->curr_size_bytes_ += length_; program_cache_->LinkedProgramCacheSuccess(program_hash); diff --git a/gpu/command_buffer/service/memory_program_cache.h b/gpu/command_buffer/service/memory_program_cache.h index b2f23e6..e72f9f5 100644 --- a/gpu/command_buffer/service/memory_program_cache.h +++ b/gpu/command_buffer/service/memory_program_cache.h @@ -57,9 +57,11 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { const char* shader_0_hash, const ShaderTranslator::VariableMap& attrib_map_0, const ShaderTranslator::VariableMap& uniform_map_0, + const ShaderTranslator::VariableMap& varying_map_0, const char* shader_1_hash, const ShaderTranslator::VariableMap& attrib_map_1, const ShaderTranslator::VariableMap& uniform_map_1, + const ShaderTranslator::VariableMap& varying_map_1, MemoryProgramCache* program_cache); GLsizei length() const { @@ -86,6 +88,10 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { return uniform_map_0_; } + const ShaderTranslator::VariableMap& varying_map_0() const { + return varying_map_0_; + } + const std::string& shader_1_hash() const { return shader_1_hash_; } @@ -98,6 +104,10 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { return uniform_map_1_; } + const ShaderTranslator::VariableMap& varying_map_1() const { + return varying_map_1_; + } + private: friend class base::RefCounted<ProgramCacheValue>; @@ -110,9 +120,11 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { const std::string shader_0_hash_; const ShaderTranslator::VariableMap attrib_map_0_; const ShaderTranslator::VariableMap uniform_map_0_; + const ShaderTranslator::VariableMap varying_map_0_; const std::string shader_1_hash_; const ShaderTranslator::VariableMap attrib_map_1_; const ShaderTranslator::VariableMap uniform_map_1_; + const ShaderTranslator::VariableMap varying_map_1_; MemoryProgramCache* const program_cache_; DISALLOW_COPY_AND_ASSIGN(ProgramCacheValue); diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc index 83fc12a..36291c4 100644 --- a/gpu/command_buffer/service/memory_program_cache_unittest.cc +++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc @@ -108,19 +108,27 @@ class MemoryProgramCacheTest : public testing::Test { typedef ShaderTranslator::VariableMap VariableMap; VariableMap vertex_attrib_map; VariableMap vertex_uniform_map; + VariableMap vertex_varying_map; VariableMap fragment_attrib_map; VariableMap fragment_uniform_map; - - vertex_attrib_map["a"] = VariableInfo(1, 34, "a"); - vertex_uniform_map["a"] = VariableInfo(0, 10, "a"); - vertex_uniform_map["b"] = VariableInfo(2, 3114, "b"); - fragment_attrib_map["jjjbb"] = VariableInfo(463, 1114, "jjjbb"); - fragment_uniform_map["k"] = VariableInfo(10, 34413, "k"); + VariableMap fragment_varying_map; + + vertex_attrib_map["a"] = VariableInfo(1, 34, SH_PRECISION_LOWP, "a"); + vertex_uniform_map["a"] = VariableInfo(0, 10, SH_PRECISION_MEDIUMP, "a"); + vertex_uniform_map["b"] = VariableInfo(2, 3114, SH_PRECISION_HIGHP, "b"); + vertex_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, "c"); + fragment_attrib_map["jjjbb"] = + VariableInfo(463, 1114, SH_PRECISION_MEDIUMP, "jjjbb"); + fragment_uniform_map["k"] = + VariableInfo(10, 34413, SH_PRECISION_MEDIUMP, "k"); + fragment_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, "c"); vertex_shader_->set_attrib_map(vertex_attrib_map); vertex_shader_->set_uniform_map(vertex_uniform_map); + vertex_shader_->set_varying_map(vertex_varying_map); fragment_shader_->set_attrib_map(vertex_attrib_map); fragment_shader_->set_uniform_map(vertex_uniform_map); + fragment_shader_->set_varying_map(vertex_varying_map); vertex_shader_->UpdateSource("bbbalsldkdkdkd"); fragment_shader_->UpdateSource("bbbal sldkdkdkas 134 ad"); @@ -262,13 +270,17 @@ TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) { VariableMap vertex_attrib_map = vertex_shader_->attrib_map(); VariableMap vertex_uniform_map = vertex_shader_->uniform_map(); + VariableMap vertex_varying_map = vertex_shader_->varying_map(); VariableMap fragment_attrib_map = fragment_shader_->attrib_map(); VariableMap fragment_uniform_map = fragment_shader_->uniform_map(); + VariableMap fragment_varying_map = fragment_shader_->varying_map(); vertex_shader_->set_attrib_map(VariableMap()); vertex_shader_->set_uniform_map(VariableMap()); + vertex_shader_->set_varying_map(VariableMap()); fragment_shader_->set_attrib_map(VariableMap()); fragment_shader_->set_uniform_map(VariableMap()); + fragment_shader_->set_varying_map(VariableMap()); SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); @@ -286,9 +298,11 @@ TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) { // equality operator #if !defined(OS_ANDROID) EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map()); + EXPECT_EQ(vertex_uniform_map, vertex_shader_->uniform_map()); + EXPECT_EQ(vertex_varying_map, vertex_shader_->varying_map()); + EXPECT_EQ(fragment_attrib_map, fragment_shader_->attrib_map()); + EXPECT_EQ(fragment_uniform_map, fragment_shader_->uniform_map()); + EXPECT_EQ(fragment_varying_map, fragment_shader_->varying_map()); #endif } @@ -311,13 +325,17 @@ TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) { VariableMap vertex_attrib_map = vertex_shader_->attrib_map(); VariableMap vertex_uniform_map = vertex_shader_->uniform_map(); + VariableMap vertex_varying_map = vertex_shader_->varying_map(); VariableMap fragment_attrib_map = fragment_shader_->attrib_map(); VariableMap fragment_uniform_map = fragment_shader_->uniform_map(); + VariableMap fragment_varying_map = fragment_shader_->varying_map(); vertex_shader_->set_attrib_map(VariableMap()); vertex_shader_->set_uniform_map(VariableMap()); + vertex_shader_->set_varying_map(VariableMap()); fragment_shader_->set_attrib_map(VariableMap()); fragment_shader_->set_uniform_map(VariableMap()); + fragment_shader_->set_varying_map(VariableMap()); SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); @@ -338,9 +356,11 @@ TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) { // equality operator #if !defined(OS_ANDROID) EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map()); + EXPECT_EQ(vertex_uniform_map, vertex_shader_->uniform_map()); + EXPECT_EQ(vertex_varying_map, vertex_shader_->varying_map()); + EXPECT_EQ(fragment_attrib_map, fragment_shader_->attrib_map()); + EXPECT_EQ(fragment_uniform_map, fragment_shader_->uniform_map()); + EXPECT_EQ(fragment_varying_map, fragment_shader_->varying_map()); #endif } diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h index fda8722..d05ba39 100644 --- a/gpu/command_buffer/service/mocks.h +++ b/gpu/command_buffer/service/mocks.h @@ -90,6 +90,7 @@ class MockShaderTranslator : public ShaderTranslatorInterface { MOCK_CONST_METHOD0(info_log, const char*()); MOCK_CONST_METHOD0(attrib_map, const VariableMap&()); MOCK_CONST_METHOD0(uniform_map, const VariableMap&()); + MOCK_CONST_METHOD0(varying_map, const VariableMap&()); MOCK_CONST_METHOD0(name_map, const NameMap&()); MOCK_CONST_METHOD0( GetStringForOptionsThatWouldEffectCompilation, std::string()); diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index 8b1eede..c6d15e5 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc @@ -34,6 +34,28 @@ namespace gles2 { namespace { +struct UniformType { + explicit UniformType(const ShaderTranslator::VariableInfo uniform) + : type(uniform.type), + size(uniform.size), + precision(uniform.precision) { } + + UniformType() + : type(0), + size(0), + precision(SH_PRECISION_MEDIUMP) { } + + bool operator==(const UniformType& other) const { + return type == other.type && + size == other.size && + precision == other.precision; + } + + int type; + int size; + int precision; +}; + int ShaderTypeToIndex(GLenum shader_type) { switch (shader_type) { case GL_VERTEX_SHADER: @@ -512,6 +534,10 @@ bool Program::Link(ShaderManager* manager, set_log_info("glBindAttribLocation() conflicts"); return false; } + if (DetectUniformsMismatch()) { + set_log_info("Uniforms with the same name but different type/precision"); + return false; + } TimeTicks before_time = TimeTicks::HighResNow(); bool link = true; @@ -963,6 +989,34 @@ bool Program::DetectAttribLocationBindingConflicts() const { return false; } +bool Program::DetectUniformsMismatch() const { + typedef std::map<std::string, UniformType> UniformMap; + UniformMap uniform_map; + for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { + const ShaderTranslator::VariableMap& shader_uniforms = + attached_shaders_[ii]->uniform_map(); + for (ShaderTranslator::VariableMap::const_iterator iter = + shader_uniforms.begin(); + iter != shader_uniforms.end(); ++iter) { + const std::string& name = iter->first; + UniformType type(iter->second); + UniformMap::iterator map_entry = uniform_map.find(name); + if (map_entry == uniform_map.end()) { + uniform_map[name] = type; + } else { + // If a uniform is already in the map, i.e., it has already been + // declared by other shader, then the type and precision must match. + if (map_entry->second == type) + continue; + // TODO(zmo): uncomment the next line once we fix the incorrect + // shaders for Aura. + // return true; + } + } + } + return false; +} + static uint32 ComputeOffset(const void* start, const void* position) { return static_cast<const uint8*>(position) - static_cast<const uint8*>(start); diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index dca232b..05014ba 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h @@ -186,6 +186,11 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { // We only consider the declared attributes in the program. bool DetectAttribLocationBindingConflicts() const; + // Detects if there are uniforms of the same name but different type + // or precision in vertex/fragment shaders. + // Return true if such cases are detected. + bool DetectUniformsMismatch() const; + // Visible for testing const LocationMap& bind_attrib_location_map() const { return bind_attrib_location_map_; diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc index 90ce0af..ac4caac 100644 --- a/gpu/command_buffer/service/program_manager_unittest.cc +++ b/gpu/command_buffer/service/program_manager_unittest.cc @@ -162,6 +162,9 @@ class ProgramManagerWithShaderTest : public testing::Test { static const GLint kAttrib1Size = 1; static const GLint kAttrib2Size = 1; static const GLint kAttrib3Size = 1; + static const int kAttrib1Precision = SH_PRECISION_MEDIUMP; + static const int kAttrib2Precision = SH_PRECISION_HIGHP; + static const int kAttrib3Precision = SH_PRECISION_LOWP; static const GLint kAttrib1Location = 0; static const GLint kAttrib2Location = 1; static const GLint kAttrib3Location = 2; @@ -178,6 +181,9 @@ class ProgramManagerWithShaderTest : public testing::Test { static const GLint kUniform1Size = 1; static const GLint kUniform2Size = 3; static const GLint kUniform3Size = 2; + static const int kUniform1Precision = SH_PRECISION_LOWP; + static const int kUniform2Precision = SH_PRECISION_MEDIUMP; + static const int kUniform3Precision = SH_PRECISION_HIGHP; static const GLint kUniform1FakeLocation = 0; // These are hard coded static const GLint kUniform2FakeLocation = 1; // to match static const GLint kUniform3FakeLocation = 2; // ProgramManager. @@ -670,22 +676,25 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) { MockShaderTranslator shader_translator; ShaderTranslator::VariableMap attrib_map; ShaderTranslator::VariableMap uniform_map; + ShaderTranslator::VariableMap varying_map; attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib1Type, kAttrib1Size, kAttrib1Name); + kAttrib1Type, kAttrib1Size, kAttrib1Precision, kAttrib1Name); attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib2GoodType, kAttrib2Size, kAttrib2Name); + kAttrib2GoodType, kAttrib2Size, kAttrib2Precision, kAttrib2Name); attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib3Type, kAttrib3Size, kAttrib3Name); + kAttrib3Type, kAttrib3Size, kAttrib3Precision, kAttrib3Name); uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo( - kUniform1Type, kUniform1Size, kUniform1Name); + kUniform1Type, kUniform1Size, kUniform1Precision, kUniform1Name); uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo( - kUniform2GoodType, kUniform2Size, kUniform2Name); + kUniform2GoodType, kUniform2Size, kUniform2Precision, kUniform2Name); uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo( - kUniform3Type, kUniform3Size, kUniform3GoodName); + kUniform3Type, kUniform3Size, kUniform3Precision, kUniform3GoodName); EXPECT_CALL(shader_translator, attrib_map()) .WillRepeatedly(ReturnRef(attrib_map)); EXPECT_CALL(shader_translator, uniform_map()) .WillRepeatedly(ReturnRef(uniform_map)); + EXPECT_CALL(shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(varying_map)); ShaderTranslator::NameMap name_map; EXPECT_CALL(shader_translator, name_map()) .WillRepeatedly(ReturnRef(name_map)); @@ -937,13 +946,19 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { ShaderTranslator::VariableMap attrib_map; for (uint32 ii = 0; ii < kNumAttribs; ++ii) { attrib_map[kAttribs[ii].name] = ShaderTranslatorInterface::VariableInfo( - kAttribs[ii].type, kAttribs[ii].size, kAttribs[ii].name); + kAttribs[ii].type, + kAttribs[ii].size, + SH_PRECISION_MEDIUMP, + kAttribs[ii].name); } ShaderTranslator::VariableMap uniform_map; + ShaderTranslator::VariableMap varying_map; EXPECT_CALL(shader_translator, attrib_map()) .WillRepeatedly(ReturnRef(attrib_map)); EXPECT_CALL(shader_translator, uniform_map()) .WillRepeatedly(ReturnRef(uniform_map)); + EXPECT_CALL(shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(varying_map)); ShaderTranslator::NameMap name_map; EXPECT_CALL(shader_translator, name_map()) .WillRepeatedly(ReturnRef(name_map)); @@ -964,6 +979,7 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { ASSERT_TRUE(variable_info != NULL); EXPECT_EQ(it->second.type, variable_info->type); EXPECT_EQ(it->second.size, variable_info->size); + EXPECT_EQ(it->second.precision, variable_info->precision); EXPECT_EQ(it->second.name, variable_info->name); } fshader->SetStatus(true, "", NULL); @@ -997,6 +1013,73 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { EXPECT_TRUE(LinkAsExpected(program, false)); } +TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) { + // Set up shader + const GLuint kVShaderClientId = 1; + const GLuint kVShaderServiceId = 11; + const GLuint kFShaderClientId = 2; + const GLuint kFShaderServiceId = 12; + + MockShaderTranslator vertex_shader_translator; + ShaderTranslator::VariableMap vertex_attrib_map; + ShaderTranslator::VariableMap vertex_uniform_map; + vertex_uniform_map["a"] = ShaderTranslator::VariableInfo( + 1, 3, SH_PRECISION_MEDIUMP, "a"); + ShaderTranslator::VariableMap vertex_varying_map; + ShaderTranslator::NameMap vertex_name_map; + EXPECT_CALL(vertex_shader_translator, attrib_map()) + .WillRepeatedly(ReturnRef(vertex_attrib_map)); + EXPECT_CALL(vertex_shader_translator, uniform_map()) + .WillRepeatedly(ReturnRef(vertex_uniform_map)); + EXPECT_CALL(vertex_shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(vertex_varying_map)); + EXPECT_CALL(vertex_shader_translator, name_map()) + .WillRepeatedly(ReturnRef(vertex_name_map)); + + MockShaderTranslator frag_shader_translator; + ShaderTranslator::VariableMap frag_attrib_map; + ShaderTranslator::VariableMap frag_uniform_map; + frag_uniform_map["a"] = ShaderTranslator::VariableInfo( + 1, 3, SH_PRECISION_LOWP, "a"); + ShaderTranslator::VariableMap frag_varying_map; + ShaderTranslator::NameMap frag_name_map; + EXPECT_CALL(frag_shader_translator, attrib_map()) + .WillRepeatedly(ReturnRef(frag_attrib_map)); + EXPECT_CALL(frag_shader_translator, uniform_map()) + .WillRepeatedly(ReturnRef(frag_uniform_map)); + EXPECT_CALL(frag_shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(frag_varying_map)); + EXPECT_CALL(frag_shader_translator, name_map()) + .WillRepeatedly(ReturnRef(frag_name_map)); + + // Check we can create shader. + Shader* vshader = shader_manager_.CreateShader( + kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); + Shader* fshader = shader_manager_.CreateShader( + kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); + // Check shader got created. + ASSERT_TRUE(vshader != NULL && fshader != NULL); + // Set Status + vshader->SetStatus(true, "", &vertex_shader_translator); + fshader->SetStatus(true, "", &frag_shader_translator); + + // Set up program + const GLuint kClientProgramId = 6666; + const GLuint kServiceProgramId = 8888; + Program* program = + manager_.CreateProgram(kClientProgramId, kServiceProgramId); + ASSERT_TRUE(program != NULL); + EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); + EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); + + // TODO(zmo): change the expectation from FALSE to TRUE once we turn + // on DetectUniformsMismatch(). + EXPECT_FALSE(program->DetectUniformsMismatch()); + // TODO(zmo): change the link expectation from true to false once we + // turn on DetectUniformsMismatch(). + EXPECT_TRUE(LinkAsExpected(program, true)); +} + TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) { const GLuint kVShaderClientId = 2001; const GLuint kFShaderClientId = 2002; diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc index a95b04c..89f21f9 100644 --- a/gpu/command_buffer/service/shader_manager.cc +++ b/gpu/command_buffer/service/shader_manager.cc @@ -43,10 +43,12 @@ void Shader::SetStatus( if (translator && valid) { attrib_map_ = translator->attrib_map(); uniform_map_ = translator->uniform_map(); + varying_map_ = translator->varying_map(); name_map_ = translator->name_map(); } else { attrib_map_.clear(); uniform_map_.clear(); + varying_map_.clear(); name_map_.clear(); } if (valid && source_.get()) { diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h index bc68868..1324238 100644 --- a/gpu/command_buffer/service/shader_manager.h +++ b/gpu/command_buffer/service/shader_manager.h @@ -98,6 +98,11 @@ class GPU_EXPORT Shader : public base::RefCounted<Shader> { } // Used by program cache. + const ShaderTranslator::VariableMap& varying_map() const { + return varying_map_; + } + + // Used by program cache. void set_attrib_map(const ShaderTranslator::VariableMap& attrib_map) { // copied because cache might be cleared attrib_map_ = ShaderTranslator::VariableMap(attrib_map); @@ -109,6 +114,12 @@ class GPU_EXPORT Shader : public base::RefCounted<Shader> { uniform_map_ = ShaderTranslator::VariableMap(uniform_map); } + // Used by program cache. + void set_varying_map(const ShaderTranslator::VariableMap& varying_map) { + // copied because cache might be cleared + varying_map_ = ShaderTranslator::VariableMap(varying_map); + } + private: typedef ShaderTranslator::VariableMap VariableMap; typedef ShaderTranslator::NameMap NameMap; @@ -148,6 +159,7 @@ class GPU_EXPORT Shader : public base::RefCounted<Shader> { // The type info when the shader was last compiled. VariableMap attrib_map_; VariableMap uniform_map_; + VariableMap varying_map_; // The name hashing info when the shader was last compiled. NameMap name_map_; diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc index a225a3c..642b121 100644 --- a/gpu/command_buffer/service/shader_manager_unittest.cc +++ b/gpu/command_buffer/service/shader_manager_unittest.cc @@ -134,31 +134,39 @@ TEST_F(ShaderManagerTest, GetInfo) { const GLenum kShader1Type = GL_VERTEX_SHADER; const GLenum kAttrib1Type = GL_FLOAT_VEC2; const GLsizei kAttrib1Size = 2; + const int kAttrib1Precision = SH_PRECISION_MEDIUMP; const char* kAttrib1Name = "attr1"; const GLenum kAttrib2Type = GL_FLOAT_VEC3; const GLsizei kAttrib2Size = 4; + const int kAttrib2Precision = SH_PRECISION_HIGHP; const char* kAttrib2Name = "attr2"; const GLenum kUniform1Type = GL_FLOAT_MAT2; const GLsizei kUniform1Size = 3; + const int kUniform1Precision = SH_PRECISION_LOWP; const char* kUniform1Name = "uni1"; const GLenum kUniform2Type = GL_FLOAT_MAT3; const GLsizei kUniform2Size = 5; + const int kUniform2Precision = SH_PRECISION_MEDIUMP; const char* kUniform2Name = "uni2"; + MockShaderTranslator shader_translator; ShaderTranslator::VariableMap attrib_map; attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib1Type, kAttrib1Size, kAttrib1Name); + kAttrib1Type, kAttrib1Size, kAttrib1Precision, kAttrib1Name); attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib2Type, kAttrib2Size, kAttrib2Name); + kAttrib2Type, kAttrib2Size, kAttrib2Precision, kAttrib2Name); ShaderTranslator::VariableMap uniform_map; uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo( - kUniform1Type, kUniform1Size, kUniform1Name); + kUniform1Type, kUniform1Size, kUniform1Precision, kUniform1Name); uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo( - kUniform2Type, kUniform2Size, kUniform2Name); + kUniform2Type, kUniform2Size, kUniform2Precision, kUniform2Name); EXPECT_CALL(shader_translator, attrib_map()) .WillRepeatedly(ReturnRef(attrib_map)); EXPECT_CALL(shader_translator, uniform_map()) .WillRepeatedly(ReturnRef(uniform_map)); + ShaderTranslator::VariableMap varying_map; + EXPECT_CALL(shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(varying_map)); ShaderTranslator::NameMap name_map; EXPECT_CALL(shader_translator, name_map()) .WillRepeatedly(ReturnRef(name_map)); @@ -177,6 +185,7 @@ TEST_F(ShaderManagerTest, GetInfo) { ASSERT_TRUE(variable_info != NULL); EXPECT_EQ(it->second.type, variable_info->type); EXPECT_EQ(it->second.size, variable_info->size); + EXPECT_EQ(it->second.precision, variable_info->precision); EXPECT_EQ(it->second.name, variable_info->name); } for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin(); @@ -186,6 +195,7 @@ TEST_F(ShaderManagerTest, GetInfo) { ASSERT_TRUE(variable_info != NULL); EXPECT_EQ(it->second.type, variable_info->type); EXPECT_EQ(it->second.size, variable_info->size); + EXPECT_EQ(it->second.precision, variable_info->precision); EXPECT_EQ(it->second.name, variable_info->name); } // Check attrib and uniform get cleared. diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc index 5129bfc..f05c450 100644 --- a/gpu/command_buffer/service/shader_translator.cc +++ b/gpu/command_buffer/service/shader_translator.cc @@ -48,6 +48,9 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, case SH_ACTIVE_UNIFORMS: ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &name_len); break; + case SH_VARYINGS: + ShGetInfo(compiler, SH_VARYING_MAX_LENGTH, &name_len); + break; default: NOTREACHED(); } ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_name_len); @@ -61,18 +64,11 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, ANGLEGetInfoType len = 0; int size = 0; ShDataType type = SH_NONE; + ShPrecisionType precision = SH_PRECISION_MEDIUMP; - switch (var_type) { - case SH_ACTIVE_ATTRIBUTES: - ShGetActiveAttrib( - compiler, i, &len, &size, &type, name.get(), mapped_name.get()); - break; - case SH_ACTIVE_UNIFORMS: - ShGetActiveUniform( - compiler, i, &len, &size, &type, name.get(), mapped_name.get()); - break; - default: NOTREACHED(); - } + ShGetVariableInfo(compiler, var_type, i, + &len, &size, &type, &precision, + name.get(), mapped_name.get()); // In theory we should CHECK(len <= name_len - 1) here, but ANGLE needs // to handle long struct field name mapping before we can do this. @@ -81,7 +77,7 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, std::string name_string(name.get(), std::min(len, name_len - 1)); mapped_name.get()[mapped_name_len - 1] = '\0'; - ShaderTranslator::VariableInfo info(type, size, name_string); + ShaderTranslator::VariableInfo info(type, size, precision, name_string); (*var_map)[mapped_name.get()] = info; } } @@ -156,7 +152,7 @@ bool ShaderTranslator::Init( int ShaderTranslator::GetCompileOptions() const { int compile_options = - SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | + SH_OBJECT_CODE | SH_VARIABLES | SH_MAP_LONG_VARIABLE_NAMES | SH_ENFORCE_PACKING_RESTRICTIONS | SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH; @@ -190,6 +186,7 @@ bool ShaderTranslator::Translate(const char* shader) { // Get info for attribs and uniforms. GetVariableInfo(compiler_, SH_ACTIVE_ATTRIBUTES, &attrib_map_); GetVariableInfo(compiler_, SH_ACTIVE_UNIFORMS, &uniform_map_); + GetVariableInfo(compiler_, SH_VARYINGS, &varying_map_); // Get info for name hashing. GetNameHashingInfo(compiler_, &name_map_); } @@ -281,6 +278,11 @@ ShaderTranslator::uniform_map() const { return uniform_map_; } +const ShaderTranslatorInterface::VariableMap& +ShaderTranslator::varying_map() const { + return varying_map_; +} + const ShaderTranslatorInterface::NameMap& ShaderTranslator::name_map() const { return name_map_; @@ -310,6 +312,7 @@ void ShaderTranslator::ClearResults() { info_log_.reset(); attrib_map_.clear(); uniform_map_.clear(); + varying_map_.clear(); name_map_.clear(); } diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h index 957f721..d4524d0 100644 --- a/gpu/command_buffer/service/shader_translator.h +++ b/gpu/command_buffer/service/shader_translator.h @@ -35,23 +35,27 @@ class ShaderTranslatorInterface { struct VariableInfo { VariableInfo() : type(0), - size(0) { + size(0), + precision(SH_PRECISION_MEDIUMP) { } - VariableInfo(int _type, int _size, std::string _name) + VariableInfo(int _type, int _size, int _precision, std::string _name) : type(_type), size(_size), + precision(_precision), name(_name) { } bool operator==( const ShaderTranslatorInterface::VariableInfo& other) const { return type == other.type && size == other.size && + precision == other.precision && strcmp(name.c_str(), other.name.c_str()) == 0; } int type; int size; + int precision; std::string name; // name in the original shader source. }; @@ -82,6 +86,7 @@ class ShaderTranslatorInterface { virtual const VariableMap& attrib_map() const = 0; virtual const VariableMap& uniform_map() const = 0; + virtual const VariableMap& varying_map() const = 0; virtual const NameMap& name_map() const = 0; // Return a string that is unique for a specfic set of options that would @@ -128,6 +133,7 @@ class GPU_EXPORT ShaderTranslator // Overridden from ShaderTranslatorInterface. virtual const VariableMap& attrib_map() const OVERRIDE; virtual const VariableMap& uniform_map() const OVERRIDE; + virtual const VariableMap& varying_map() const OVERRIDE; virtual const NameMap& name_map() const OVERRIDE; virtual std::string GetStringForOptionsThatWouldEffectCompilation() const @@ -149,6 +155,7 @@ class GPU_EXPORT ShaderTranslator scoped_ptr<char[]> info_log_; VariableMap attrib_map_; VariableMap uniform_map_; + VariableMap varying_map_; NameMap name_map_; bool implementation_is_glsl_es_; bool needs_built_in_function_emulation_; |