Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / shader_translator.cc
blobb852d2aa929cb2aa928a7e04d4d67517f141ab4c
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/shader_translator.h"
7 #include <string.h>
8 #include <GLES2/gl2.h>
9 #include <algorithm>
11 #include "base/at_exit.h"
12 #include "base/command_line.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/trace_event/trace_event.h"
17 #include "gpu/command_buffer/service/gpu_switches.h"
18 #include "ui/gl/gl_implementation.h"
19 #include "ui/gl/gl_version_info.h"
21 namespace gpu {
22 namespace gles2 {
24 namespace {
26 class ShaderTranslatorInitializer {
27 public:
28 ShaderTranslatorInitializer() {
29 TRACE_EVENT0("gpu", "ShInitialize");
30 CHECK(ShInitialize());
33 ~ShaderTranslatorInitializer() {
34 TRACE_EVENT0("gpu", "ShFinalize");
35 ShFinalize();
39 base::LazyInstance<ShaderTranslatorInitializer> g_translator_initializer =
40 LAZY_INSTANCE_INITIALIZER;
42 void GetAttributes(ShHandle compiler, AttributeMap* var_map) {
43 if (!var_map)
44 return;
45 var_map->clear();
46 const std::vector<sh::Attribute>* attribs = ShGetAttributes(compiler);
47 if (attribs) {
48 for (size_t ii = 0; ii < attribs->size(); ++ii)
49 (*var_map)[(*attribs)[ii].mappedName] = (*attribs)[ii];
53 void GetUniforms(ShHandle compiler, UniformMap* var_map) {
54 if (!var_map)
55 return;
56 var_map->clear();
57 const std::vector<sh::Uniform>* uniforms = ShGetUniforms(compiler);
58 if (uniforms) {
59 for (size_t ii = 0; ii < uniforms->size(); ++ii)
60 (*var_map)[(*uniforms)[ii].mappedName] = (*uniforms)[ii];
64 void GetVaryings(ShHandle compiler, VaryingMap* var_map) {
65 if (!var_map)
66 return;
67 var_map->clear();
68 const std::vector<sh::Varying>* varyings = ShGetVaryings(compiler);
69 if (varyings) {
70 for (size_t ii = 0; ii < varyings->size(); ++ii)
71 (*var_map)[(*varyings)[ii].mappedName] = (*varyings)[ii];
75 void GetNameHashingInfo(ShHandle compiler, NameMap* name_map) {
76 if (!name_map)
77 return;
78 name_map->clear();
80 typedef std::map<std::string, std::string> NameMapANGLE;
81 const NameMapANGLE* angle_map = ShGetNameHashingMap(compiler);
82 DCHECK(angle_map);
84 for (NameMapANGLE::const_iterator iter = angle_map->begin();
85 iter != angle_map->end(); ++iter) {
86 // Note that in ANGLE, the map is (original_name, hash);
87 // here, we want (hash, original_name).
88 (*name_map)[iter->second] = iter->first;
92 } // namespace
94 ShShaderOutput ShaderTranslator::GetShaderOutputLanguageForContext(
95 const gfx::GLVersionInfo& version_info) {
96 if (version_info.is_es) {
97 return SH_ESSL_OUTPUT;
100 // Determine the GLSL version based on OpenGL specification.
102 unsigned context_version =
103 version_info.major_version * 100 + version_info.minor_version * 10;
104 if (context_version >= 450) {
105 // OpenGL specs from 4.2 on specify that the core profile is "also
106 // guaranteed to support all previous versions of the OpenGL Shading
107 // Language back to version 1.40". For simplicity, we assume future
108 // specs do not unspecify this. If they did, they could unspecify
109 // glGetStringi(GL_SHADING_LANGUAGE_VERSION, k), too.
110 // Since current context >= 4.5, use GLSL 4.50 core.
111 return SH_GLSL_450_CORE_OUTPUT;
112 } else if (context_version == 440) {
113 return SH_GLSL_440_CORE_OUTPUT;
114 } else if (context_version == 430) {
115 return SH_GLSL_430_CORE_OUTPUT;
116 } else if (context_version == 420) {
117 return SH_GLSL_420_CORE_OUTPUT;
118 } else if (context_version == 410) {
119 return SH_GLSL_410_CORE_OUTPUT;
120 } else if (context_version == 400) {
121 return SH_GLSL_400_CORE_OUTPUT;
122 } else if (context_version == 330) {
123 return SH_GLSL_330_CORE_OUTPUT;
124 } else if (context_version == 320) {
125 return SH_GLSL_150_CORE_OUTPUT;
126 } else if (context_version == 310) {
127 return SH_GLSL_140_OUTPUT;
128 } else if (context_version == 300) {
129 return SH_GLSL_130_OUTPUT;
132 // Before OpenGL 3.0 we use compatibility profile. Also for future
133 // specs between OpenGL 3.3 and OpenGL 4.0, at the time of writing,
134 // we use compatibility profile.
135 return SH_GLSL_COMPATIBILITY_OUTPUT;
138 ShaderTranslator::DestructionObserver::DestructionObserver() {
141 ShaderTranslator::DestructionObserver::~DestructionObserver() {
144 ShaderTranslator::ShaderTranslator()
145 : compiler_(NULL),
146 driver_bug_workarounds_(static_cast<ShCompileOptions>(0)) {
149 bool ShaderTranslator::Init(GLenum shader_type,
150 ShShaderSpec shader_spec,
151 const ShBuiltInResources* resources,
152 ShShaderOutput shader_output_language,
153 ShCompileOptions driver_bug_workarounds) {
154 // Make sure Init is called only once.
155 DCHECK(compiler_ == NULL);
156 DCHECK(shader_type == GL_FRAGMENT_SHADER || shader_type == GL_VERTEX_SHADER);
157 DCHECK(shader_spec == SH_GLES2_SPEC || shader_spec == SH_WEBGL_SPEC ||
158 shader_spec == SH_GLES3_SPEC || shader_spec == SH_WEBGL2_SPEC);
159 DCHECK(resources != NULL);
161 g_translator_initializer.Get();
165 TRACE_EVENT0("gpu", "ShConstructCompiler");
166 compiler_ = ShConstructCompiler(shader_type, shader_spec,
167 shader_output_language, resources);
169 driver_bug_workarounds_ = driver_bug_workarounds;
170 return compiler_ != NULL;
173 int ShaderTranslator::GetCompileOptions() const {
174 int compile_options =
175 SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS |
176 SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH |
177 SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
179 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
180 switches::kGLShaderIntermOutput))
181 compile_options |= SH_INTERMEDIATE_TREE;
183 compile_options |= driver_bug_workarounds_;
185 return compile_options;
188 bool ShaderTranslator::Translate(const std::string& shader_source,
189 std::string* info_log,
190 std::string* translated_source,
191 int* shader_version,
192 AttributeMap* attrib_map,
193 UniformMap* uniform_map,
194 VaryingMap* varying_map,
195 NameMap* name_map) const {
196 // Make sure this instance is initialized.
197 DCHECK(compiler_ != NULL);
199 bool success = false;
201 TRACE_EVENT0("gpu", "ShCompile");
202 const char* const shader_strings[] = { shader_source.c_str() };
203 success = ShCompile(
204 compiler_, shader_strings, 1, GetCompileOptions());
206 if (success) {
207 // Get translated shader.
208 if (translated_source) {
209 *translated_source = ShGetObjectCode(compiler_);
211 // Get shader version.
212 *shader_version = ShGetShaderVersion(compiler_);
213 // Get info for attribs, uniforms, and varyings.
214 GetAttributes(compiler_, attrib_map);
215 GetUniforms(compiler_, uniform_map);
216 GetVaryings(compiler_, varying_map);
217 // Get info for name hashing.
218 GetNameHashingInfo(compiler_, name_map);
221 // Get info log.
222 if (info_log) {
223 *info_log = ShGetInfoLog(compiler_);
226 // We don't need results in the compiler anymore.
227 ShClearResults(compiler_);
229 return success;
232 std::string ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
233 const {
234 DCHECK(compiler_ != NULL);
235 return std::string(":CompileOptions:" +
236 base::IntToString(GetCompileOptions())) +
237 ShGetBuiltInResourcesString(compiler_);
240 void ShaderTranslator::AddDestructionObserver(
241 DestructionObserver* observer) {
242 destruction_observers_.AddObserver(observer);
245 void ShaderTranslator::RemoveDestructionObserver(
246 DestructionObserver* observer) {
247 destruction_observers_.RemoveObserver(observer);
250 ShaderTranslator::~ShaderTranslator() {
251 FOR_EACH_OBSERVER(DestructionObserver,
252 destruction_observers_,
253 OnDestruct(this));
255 if (compiler_ != NULL)
256 ShDestruct(compiler_);
259 } // namespace gles2
260 } // namespace gpu