diff options
author | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-29 16:49:24 +0000 |
---|---|---|
committer | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-29 16:49:24 +0000 |
commit | ff9e2a07893e137627884f74550ccf0cce132f8d (patch) | |
tree | 1303167913125fb9793c25ef20c600f295ab545a /gpu/command_buffer | |
parent | cd5d0b1ca6b112db4f58c8d606f47c6bee2cf1a7 (diff) | |
download | chromium_src-ff9e2a07893e137627884f74550ccf0cce132f8d.zip chromium_src-ff9e2a07893e137627884f74550ccf0cce132f8d.tar.gz chromium_src-ff9e2a07893e137627884f74550ccf0cce132f8d.tar.bz2 |
Hooked up functionality for getting info for attribs and uniforms.
Review URL: http://codereview.chromium.org/3436030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60951 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r-- | gpu/command_buffer/service/shader_translator.cc | 62 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_translator.h | 14 | ||||
-rw-r--r-- | gpu/command_buffer/service/shader_translator_unittest.cc | 180 |
3 files changed, 247 insertions, 9 deletions
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc index dd3ea24..f64fd58 100644 --- a/gpu/command_buffer/service/shader_translator.cc +++ b/gpu/command_buffer/service/shader_translator.cc @@ -20,6 +20,45 @@ bool InitializeShaderTranslator() { } return initialized; } + +using gpu::gles2::ShaderTranslator; +void GetVariableInfo(ShHandle compiler, EShInfo var_type, + ShaderTranslator::VariableMap* var_map) { + int name_len = 0; + switch (var_type) { + case SH_ACTIVE_ATTRIBUTES: + ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &name_len); + break; + case SH_ACTIVE_UNIFORMS: + ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &name_len); + break; + default: NOTREACHED(); + } + if (name_len <= 1) return; + scoped_array<char> name(new char[name_len]); + + int num_vars = 0; + ShGetInfo(compiler, var_type, &num_vars); + for (int i = 0; i < num_vars; ++i) { + int size = 0; + EShDataType type = SH_NONE; + + switch (var_type) { + case SH_ACTIVE_ATTRIBUTES: + ShGetActiveAttrib(compiler, i, NULL, &size, &type, name.get()); + break; + case SH_ACTIVE_UNIFORMS: + ShGetActiveUniform(compiler, i, NULL, &size, &type, name.get()); + break; + default: NOTREACHED(); + } + + ShaderTranslator::VariableInfo info = {0}; + info.type = type; + info.size = size; + (*var_map)[name.get()] = info; + } +} } // namespace namespace gpu { @@ -54,23 +93,28 @@ bool ShaderTranslator::Translate(const char* shader) { ClearResults(); bool success = false; - int compile_options = EShOptObjectCode; + int compile_options = EShOptObjectCode | EShOptAttribsUniforms; if (ShCompile(compiler_, &shader, 1, compile_options)) { + success = true; // Get translated shader. int obj_code_len = 0; ShGetInfo(compiler_, SH_OBJECT_CODE_LENGTH, &obj_code_len); - translated_shader_.reset(new char[obj_code_len]); - ShGetObjectCode(compiler_, translated_shader_.get()); - - // TODO(alokp): Get attribs and uniforms. - success = true; + if (obj_code_len > 1) { + translated_shader_.reset(new char[obj_code_len]); + ShGetObjectCode(compiler_, translated_shader_.get()); + } + // Get info for attribs and uniforms. + GetVariableInfo(compiler_, SH_ACTIVE_ATTRIBUTES, &attrib_map_); + GetVariableInfo(compiler_, SH_ACTIVE_UNIFORMS, &uniform_map_); } // Get info log. int info_log_len = 0; ShGetInfo(compiler_, SH_INFO_LOG_LENGTH, &info_log_len); - info_log_.reset(new char[info_log_len]); - ShGetInfoLog(compiler_, info_log_.get()); + if (info_log_len > 1) { + info_log_.reset(new char[info_log_len]); + ShGetInfoLog(compiler_, info_log_.get()); + } return success; } @@ -78,6 +122,8 @@ bool ShaderTranslator::Translate(const char* shader) { void ShaderTranslator::ClearResults() { translated_shader_.reset(); info_log_.reset(); + attrib_map_.clear(); + uniform_map_.clear(); } } // namespace gles2 diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h index 3dc0a05..26e8dc6 100644 --- a/gpu/command_buffer/service/shader_translator.h +++ b/gpu/command_buffer/service/shader_translator.h @@ -5,6 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_SHADER_TRANSLATOR_H_ #define GPU_COMMAND_BUFFER_SERVICE_SHADER_TRANSLATOR_H_ +#include <map> +#include <string> + #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "third_party/angle/include/GLSLANG/ShaderLang.h" @@ -32,7 +35,14 @@ class ShaderTranslator { const char* translated_shader() { return translated_shader_.get(); } const char* info_log() { return info_log_.get(); } - // TODO(alokp): Add functions for returning attribs and uniforms. + struct VariableInfo { + int type; + int size; + }; + // Mapping between variable name and info. + typedef std::map<std::string, VariableInfo> VariableMap; + const VariableMap& attrib_map() { return attrib_map_; } + const VariableMap& uniform_map() { return uniform_map_; } private: void ClearResults(); @@ -41,6 +51,8 @@ class ShaderTranslator { ShHandle compiler_; scoped_array<char> translated_shader_; scoped_array<char> info_log_; + VariableMap attrib_map_; + VariableMap uniform_map_; }; } // namespace gles2 diff --git a/gpu/command_buffer/service/shader_translator_unittest.cc b/gpu/command_buffer/service/shader_translator_unittest.cc new file mode 100644 index 0000000..251b95c --- /dev/null +++ b/gpu/command_buffer/service/shader_translator_unittest.cc @@ -0,0 +1,180 @@ +// Copyright (c) 2010 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 "gpu/command_buffer/service/shader_translator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace gpu { +namespace gles2 { + +class ShaderTranslatorTest : public testing::Test { + public: + ShaderTranslatorTest() { + } + + ~ShaderTranslatorTest() { + } + + protected: + virtual void SetUp() { + TBuiltInResource resources; + ShInitBuiltInResource(&resources); + + ASSERT_TRUE(vertex_translator_.Init(EShLangVertex, &resources)); + ASSERT_TRUE(fragment_translator_.Init(EShLangFragment, &resources)); + // Post-init the results must be empty. + // Vertex translator results. + EXPECT_TRUE(vertex_translator_.translated_shader() == NULL); + EXPECT_TRUE(vertex_translator_.info_log() == NULL); + EXPECT_TRUE(vertex_translator_.attrib_map().empty()); + EXPECT_TRUE(vertex_translator_.uniform_map().empty()); + // Fragment translator results. + EXPECT_TRUE(fragment_translator_.translated_shader() == NULL); + EXPECT_TRUE(fragment_translator_.info_log() == NULL); + EXPECT_TRUE(fragment_translator_.attrib_map().empty()); + EXPECT_TRUE(fragment_translator_.uniform_map().empty()); + } + virtual void TearDown() {} + + ShaderTranslator vertex_translator_; + ShaderTranslator fragment_translator_; +}; + +TEST_F(ShaderTranslatorTest, ValidVertexShader) { + const char* shader = + "void main() {\n" + " gl_Position = vec4(1.0);\n" + "}"; + + // A valid shader should be successfully translated. + EXPECT_TRUE(vertex_translator_.Translate(shader)); + // Info log must be NULL. + EXPECT_TRUE(vertex_translator_.info_log() == NULL); + // Translated shader must be valid and non-empty. + EXPECT_TRUE(vertex_translator_.translated_shader() != NULL); + EXPECT_GT(strlen(vertex_translator_.translated_shader()), 0u); + // There should be no attributes or uniforms. + EXPECT_TRUE(vertex_translator_.attrib_map().empty()); + EXPECT_TRUE(vertex_translator_.uniform_map().empty()); +} + +TEST_F(ShaderTranslatorTest, InvalidVertexShader) { + const char* shader = "foo-bar"; + + // An invalid shader should fail. + EXPECT_FALSE(vertex_translator_.Translate(shader)); + // Info log must be valid and non-empty. + EXPECT_TRUE(vertex_translator_.info_log() != NULL); + EXPECT_GT(strlen(vertex_translator_.info_log()), 0u); + // Translated shader must be NULL. + EXPECT_TRUE(vertex_translator_.translated_shader() == NULL); + // There should be no attributes or uniforms. + EXPECT_TRUE(vertex_translator_.attrib_map().empty()); + EXPECT_TRUE(vertex_translator_.uniform_map().empty()); +} + +TEST_F(ShaderTranslatorTest, ValidFragmentShader) { + const char* shader = + "void main() {\n" + " gl_FragColor = vec4(1.0);\n" + "}"; + + // A valid shader should be successfully translated. + EXPECT_TRUE(fragment_translator_.Translate(shader)); + // Info log must be NULL. + EXPECT_TRUE(fragment_translator_.info_log() == NULL); + // Translated shader must be valid and non-empty. + EXPECT_TRUE(fragment_translator_.translated_shader() != NULL); + EXPECT_GT(strlen(fragment_translator_.translated_shader()), 0u); + // There should be no attributes or uniforms. + EXPECT_TRUE(fragment_translator_.attrib_map().empty()); + EXPECT_TRUE(fragment_translator_.uniform_map().empty()); +} + +TEST_F(ShaderTranslatorTest, InvalidFragmentShader) { + const char* shader = "foo-bar"; + + // An invalid shader should fail. + EXPECT_FALSE(fragment_translator_.Translate(shader)); + // Info log must be valid and non-empty. + EXPECT_TRUE(fragment_translator_.info_log() != NULL); + EXPECT_GT(strlen(fragment_translator_.info_log()), 0u); + // Translated shader must be NULL. + EXPECT_TRUE(fragment_translator_.translated_shader() == NULL); + // There should be no attributes or uniforms. + EXPECT_TRUE(fragment_translator_.attrib_map().empty()); + EXPECT_TRUE(fragment_translator_.uniform_map().empty()); +} + +TEST_F(ShaderTranslatorTest, GetAttributes) { + const char* shader = + "attribute vec4 vPosition;\n" + "void main() {\n" + " gl_Position = vPosition;\n" + "}"; + + EXPECT_TRUE(vertex_translator_.Translate(shader)); + // Info log must be NULL. + EXPECT_TRUE(vertex_translator_.info_log() == NULL); + // Translated shader must be valid and non-empty. + EXPECT_TRUE(vertex_translator_.translated_shader() != NULL); + EXPECT_GT(strlen(vertex_translator_.translated_shader()), 0u); + // There should be no uniforms. + EXPECT_TRUE(vertex_translator_.uniform_map().empty()); + // There should be one attribute with following characteristics: + // name:vPosition type:SH_FLOAT_VEC4 size:1. + const ShaderTranslator::VariableMap& attrib_map = + vertex_translator_.attrib_map(); + EXPECT_EQ(1u, attrib_map.size()); + ShaderTranslator::VariableMap::const_iterator iter = + attrib_map.find("vPosition"); + EXPECT_TRUE(iter != attrib_map.end()); + EXPECT_EQ(SH_FLOAT_VEC4, iter->second.type); + EXPECT_EQ(1, iter->second.size); +} + +TEST_F(ShaderTranslatorTest, GetUniforms) { + const char* shader = + "precision mediump float;\n" + "struct Foo {\n" + " vec4 color[1];\n" + "};\n" + "struct Bar {\n" + " Foo foo;\n" + "};\n" + "uniform Bar bar[2];\n" + "void main() {\n" + " gl_FragColor = bar[0].foo.color[0] + bar[1].foo.color[0];\n" + "}"; + + EXPECT_TRUE(fragment_translator_.Translate(shader)); + // Info log must be NULL. + EXPECT_TRUE(fragment_translator_.info_log() == NULL); + // Translated shader must be valid and non-empty. + EXPECT_TRUE(fragment_translator_.translated_shader() != NULL); + EXPECT_GT(strlen(fragment_translator_.translated_shader()), 0u); + // There should be no attributes. + EXPECT_TRUE(fragment_translator_.attrib_map().empty()); + // There should be two uniforms with following characteristics: + // 1. name:bar[0].foo.color[0] type:SH_FLOAT_VEC4 size:1 + // 2. name:bar[1].foo.color[0] type:SH_FLOAT_VEC4 size:1 + const ShaderTranslator::VariableMap& uniform_map = + fragment_translator_.uniform_map(); + EXPECT_EQ(2u, uniform_map.size()); + // First uniform. + ShaderTranslator::VariableMap::const_iterator iter = + uniform_map.find("bar[0].foo.color[0]"); + EXPECT_TRUE(iter != uniform_map.end()); + EXPECT_EQ(SH_FLOAT_VEC4, iter->second.type); + EXPECT_EQ(1, iter->second.size); + // Second uniform. + iter = uniform_map.find("bar[1].foo.color[0]"); + EXPECT_TRUE(iter != uniform_map.end()); + EXPECT_EQ(SH_FLOAT_VEC4, iter->second.type); + EXPECT_EQ(1, iter->second.size); +} + +} // namespace gles2 +} // namespace gpu + |