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"
25 class ShaderTranslatorInitializer
{
27 ShaderTranslatorInitializer() {
28 TRACE_EVENT0("gpu", "ShInitialize");
29 CHECK(ShInitialize());
32 ~ShaderTranslatorInitializer() {
33 TRACE_EVENT0("gpu", "ShFinalize");
38 base::LazyInstance
<ShaderTranslatorInitializer
> g_translator_initializer
=
39 LAZY_INSTANCE_INITIALIZER
;
41 void GetAttributes(ShHandle compiler
, AttributeMap
* var_map
) {
45 const std::vector
<sh::Attribute
>* attribs
= ShGetAttributes(compiler
);
47 for (size_t ii
= 0; ii
< attribs
->size(); ++ii
)
48 (*var_map
)[(*attribs
)[ii
].mappedName
] = (*attribs
)[ii
];
52 void GetUniforms(ShHandle compiler
, UniformMap
* var_map
) {
56 const std::vector
<sh::Uniform
>* uniforms
= ShGetUniforms(compiler
);
58 for (size_t ii
= 0; ii
< uniforms
->size(); ++ii
)
59 (*var_map
)[(*uniforms
)[ii
].mappedName
] = (*uniforms
)[ii
];
63 void GetVaryings(ShHandle compiler
, VaryingMap
* var_map
) {
67 const std::vector
<sh::Varying
>* varyings
= ShGetVaryings(compiler
);
69 for (size_t ii
= 0; ii
< varyings
->size(); ++ii
)
70 (*var_map
)[(*varyings
)[ii
].mappedName
] = (*varyings
)[ii
];
74 void GetNameHashingInfo(ShHandle compiler
, NameMap
* name_map
) {
79 typedef std::map
<std::string
, std::string
> NameMapANGLE
;
80 const NameMapANGLE
* angle_map
= ShGetNameHashingMap(compiler
);
83 for (NameMapANGLE::const_iterator iter
= angle_map
->begin();
84 iter
!= angle_map
->end(); ++iter
) {
85 // Note that in ANGLE, the map is (original_name, hash);
86 // here, we want (hash, original_name).
87 (*name_map
)[iter
->second
] = iter
->first
;
93 ShaderTranslator::DestructionObserver::DestructionObserver() {
96 ShaderTranslator::DestructionObserver::~DestructionObserver() {
99 ShaderTranslator::ShaderTranslator()
101 implementation_is_glsl_es_(false),
102 driver_bug_workarounds_(static_cast<ShCompileOptions
>(0)) {
105 bool ShaderTranslator::Init(
107 ShShaderSpec shader_spec
,
108 const ShBuiltInResources
* resources
,
109 ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type
,
110 ShCompileOptions driver_bug_workarounds
) {
111 // Make sure Init is called only once.
112 DCHECK(compiler_
== NULL
);
113 DCHECK(shader_type
== GL_FRAGMENT_SHADER
|| shader_type
== GL_VERTEX_SHADER
);
114 DCHECK(shader_spec
== SH_GLES2_SPEC
|| shader_spec
== SH_WEBGL_SPEC
||
115 shader_spec
== SH_GLES3_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
);
116 DCHECK(resources
!= NULL
);
118 g_translator_initializer
.Get();
120 ShShaderOutput shader_output
;
121 if (glsl_implementation_type
== kGlslES
) {
122 shader_output
= SH_ESSL_OUTPUT
;
124 // TODO(kbr): clean up the tests of shader_spec and
125 // gfx::GetGLImplementation(). crbug.com/471960
126 if (shader_spec
== SH_WEBGL2_SPEC
||
127 gfx::GetGLImplementation() ==
128 gfx::kGLImplementationDesktopGLCoreProfile
) {
129 shader_output
= SH_GLSL_410_CORE_OUTPUT
;
131 shader_output
= SH_GLSL_COMPATIBILITY_OUTPUT
;
136 TRACE_EVENT0("gpu", "ShConstructCompiler");
137 compiler_
= ShConstructCompiler(
138 shader_type
, shader_spec
, shader_output
, resources
);
140 implementation_is_glsl_es_
= (glsl_implementation_type
== kGlslES
);
141 driver_bug_workarounds_
= driver_bug_workarounds
;
142 return compiler_
!= NULL
;
145 int ShaderTranslator::GetCompileOptions() const {
146 int compile_options
=
147 SH_OBJECT_CODE
| SH_VARIABLES
| SH_ENFORCE_PACKING_RESTRICTIONS
|
148 SH_LIMIT_EXPRESSION_COMPLEXITY
| SH_LIMIT_CALL_STACK_DEPTH
|
149 SH_CLAMP_INDIRECT_ARRAY_BOUNDS
;
151 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
152 switches::kGLShaderIntermOutput
))
153 compile_options
|= SH_INTERMEDIATE_TREE
;
155 compile_options
|= driver_bug_workarounds_
;
157 return compile_options
;
160 bool ShaderTranslator::Translate(const std::string
& shader_source
,
161 std::string
* info_log
,
162 std::string
* translated_source
,
164 AttributeMap
* attrib_map
,
165 UniformMap
* uniform_map
,
166 VaryingMap
* varying_map
,
167 NameMap
* name_map
) const {
168 // Make sure this instance is initialized.
169 DCHECK(compiler_
!= NULL
);
171 bool success
= false;
173 TRACE_EVENT0("gpu", "ShCompile");
174 const char* const shader_strings
[] = { shader_source
.c_str() };
176 compiler_
, shader_strings
, 1, GetCompileOptions());
179 // Get translated shader.
180 if (translated_source
) {
181 *translated_source
= ShGetObjectCode(compiler_
);
183 // Get shader version.
184 *shader_version
= ShGetShaderVersion(compiler_
);
185 // Get info for attribs, uniforms, and varyings.
186 GetAttributes(compiler_
, attrib_map
);
187 GetUniforms(compiler_
, uniform_map
);
188 GetVaryings(compiler_
, varying_map
);
189 // Get info for name hashing.
190 GetNameHashingInfo(compiler_
, name_map
);
195 *info_log
= ShGetInfoLog(compiler_
);
198 // We don't need results in the compiler anymore.
199 ShClearResults(compiler_
);
204 std::string
ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
206 DCHECK(compiler_
!= NULL
);
207 return std::string(":CompileOptions:" +
208 base::IntToString(GetCompileOptions())) +
209 ShGetBuiltInResourcesString(compiler_
);
212 void ShaderTranslator::AddDestructionObserver(
213 DestructionObserver
* observer
) {
214 destruction_observers_
.AddObserver(observer
);
217 void ShaderTranslator::RemoveDestructionObserver(
218 DestructionObserver
* observer
) {
219 destruction_observers_
.RemoveObserver(observer
);
222 ShaderTranslator::~ShaderTranslator() {
223 FOR_EACH_OBSERVER(DestructionObserver
,
224 destruction_observers_
,
227 if (compiler_
!= NULL
)
228 ShDestruct(compiler_
);