summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-19 20:58:26 +0000
committerzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-19 20:58:26 +0000
commit186e1ae7ffd48e96e3de93f09381230d3b0911d5 (patch)
tree3cae5644f18088676675e9eab2be008423eed9a1 /gpu
parent0b1e4b50e05c71d5a4d155b90b25125c780c59be (diff)
downloadchromium_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.proto2
-rw-r--r--gpu/command_buffer/service/memory_program_cache.cc50
-rw-r--r--gpu/command_buffer/service/memory_program_cache.h12
-rw-r--r--gpu/command_buffer/service/memory_program_cache_unittest.cc44
-rw-r--r--gpu/command_buffer/service/mocks.h1
-rw-r--r--gpu/command_buffer/service/program_manager.cc54
-rw-r--r--gpu/command_buffer/service/program_manager.h5
-rw-r--r--gpu/command_buffer/service/program_manager_unittest.cc97
-rw-r--r--gpu/command_buffer/service/shader_manager.cc2
-rw-r--r--gpu/command_buffer/service/shader_manager.h12
-rw-r--r--gpu/command_buffer/service/shader_manager_unittest.cc18
-rw-r--r--gpu/command_buffer/service/shader_translator.cc29
-rw-r--r--gpu/command_buffer/service/shader_translator.h11
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_;