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"
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"
26 class ShaderTranslatorInitializer
{
28 ShaderTranslatorInitializer() {
29 TRACE_EVENT0("gpu", "ShInitialize");
30 CHECK(ShInitialize());
33 ~ShaderTranslatorInitializer() {
34 TRACE_EVENT0("gpu", "ShFinalize");
39 base::LazyInstance
<ShaderTranslatorInitializer
> g_translator_initializer
=
40 LAZY_INSTANCE_INITIALIZER
;
42 void GetAttributes(ShHandle compiler
, AttributeMap
* var_map
) {
46 const std::vector
<sh::Attribute
>* attribs
= ShGetAttributes(compiler
);
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
) {
57 const std::vector
<sh::Uniform
>* uniforms
= ShGetUniforms(compiler
);
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
) {
68 const std::vector
<sh::Varying
>* varyings
= ShGetVaryings(compiler
);
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
) {
80 typedef std::map
<std::string
, std::string
> NameMapANGLE
;
81 const NameMapANGLE
* angle_map
= ShGetNameHashingMap(compiler
);
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
;
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()
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
,
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() };
204 compiler_
, shader_strings
, 1, GetCompileOptions());
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
);
223 *info_log
= ShGetInfoLog(compiler_
);
226 // We don't need results in the compiler anymore.
227 ShClearResults(compiler_
);
232 std::string
ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
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_
,
255 if (compiler_
!= NULL
)
256 ShDestruct(compiler_
);