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"
24 class ShaderTranslatorInitializer
{
26 ShaderTranslatorInitializer() {
27 TRACE_EVENT0("gpu", "ShInitialize");
28 CHECK(ShInitialize());
31 ~ShaderTranslatorInitializer() {
32 TRACE_EVENT0("gpu", "ShFinalize");
37 base::LazyInstance
<ShaderTranslatorInitializer
> g_translator_initializer
=
38 LAZY_INSTANCE_INITIALIZER
;
40 void GetAttributes(ShHandle compiler
, AttributeMap
* var_map
) {
44 const std::vector
<sh::Attribute
>* attribs
= ShGetAttributes(compiler
);
46 for (size_t ii
= 0; ii
< attribs
->size(); ++ii
)
47 (*var_map
)[(*attribs
)[ii
].mappedName
] = (*attribs
)[ii
];
51 void GetUniforms(ShHandle compiler
, UniformMap
* var_map
) {
55 const std::vector
<sh::Uniform
>* uniforms
= ShGetUniforms(compiler
);
57 for (size_t ii
= 0; ii
< uniforms
->size(); ++ii
)
58 (*var_map
)[(*uniforms
)[ii
].mappedName
] = (*uniforms
)[ii
];
62 void GetVaryings(ShHandle compiler
, VaryingMap
* var_map
) {
66 const std::vector
<sh::Varying
>* varyings
= ShGetVaryings(compiler
);
68 for (size_t ii
= 0; ii
< varyings
->size(); ++ii
)
69 (*var_map
)[(*varyings
)[ii
].mappedName
] = (*varyings
)[ii
];
73 void GetNameHashingInfo(ShHandle compiler
, NameMap
* name_map
) {
78 typedef std::map
<std::string
, std::string
> NameMapANGLE
;
79 const NameMapANGLE
* angle_map
= ShGetNameHashingMap(compiler
);
82 for (NameMapANGLE::const_iterator iter
= angle_map
->begin();
83 iter
!= angle_map
->end(); ++iter
) {
84 // Note that in ANGLE, the map is (original_name, hash);
85 // here, we want (hash, original_name).
86 (*name_map
)[iter
->second
] = iter
->first
;
92 ShaderTranslator::DestructionObserver::DestructionObserver() {
95 ShaderTranslator::DestructionObserver::~DestructionObserver() {
98 ShaderTranslator::ShaderTranslator()
100 implementation_is_glsl_es_(false),
101 driver_bug_workarounds_(static_cast<ShCompileOptions
>(0)) {
104 bool ShaderTranslator::Init(
106 ShShaderSpec shader_spec
,
107 const ShBuiltInResources
* resources
,
108 ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type
,
109 ShCompileOptions driver_bug_workarounds
) {
110 // Make sure Init is called only once.
111 DCHECK(compiler_
== NULL
);
112 DCHECK(shader_type
== GL_FRAGMENT_SHADER
|| shader_type
== GL_VERTEX_SHADER
);
113 DCHECK(shader_spec
== SH_GLES2_SPEC
|| shader_spec
== SH_WEBGL_SPEC
);
114 DCHECK(resources
!= NULL
);
116 g_translator_initializer
.Get();
118 ShShaderOutput shader_output
=
119 (glsl_implementation_type
== kGlslES
? SH_ESSL_OUTPUT
: SH_GLSL_OUTPUT
);
122 TRACE_EVENT0("gpu", "ShConstructCompiler");
123 compiler_
= ShConstructCompiler(
124 shader_type
, shader_spec
, shader_output
, resources
);
126 compiler_options_
= *resources
;
127 implementation_is_glsl_es_
= (glsl_implementation_type
== kGlslES
);
128 driver_bug_workarounds_
= driver_bug_workarounds
;
129 return compiler_
!= NULL
;
132 int ShaderTranslator::GetCompileOptions() const {
133 int compile_options
=
134 SH_OBJECT_CODE
| SH_VARIABLES
| SH_ENFORCE_PACKING_RESTRICTIONS
|
135 SH_LIMIT_EXPRESSION_COMPLEXITY
| SH_LIMIT_CALL_STACK_DEPTH
|
136 SH_CLAMP_INDIRECT_ARRAY_BOUNDS
;
138 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
139 switches::kGLShaderIntermOutput
))
140 compile_options
|= SH_INTERMEDIATE_TREE
;
142 compile_options
|= driver_bug_workarounds_
;
144 return compile_options
;
147 bool ShaderTranslator::Translate(const std::string
& shader_source
,
148 std::string
* info_log
,
149 std::string
* translated_source
,
150 AttributeMap
* attrib_map
,
151 UniformMap
* uniform_map
,
152 VaryingMap
* varying_map
,
153 NameMap
* name_map
) const {
154 // Make sure this instance is initialized.
155 DCHECK(compiler_
!= NULL
);
157 bool success
= false;
159 TRACE_EVENT0("gpu", "ShCompile");
160 const char* const shader_strings
[] = { shader_source
.c_str() };
162 compiler_
, shader_strings
, 1, GetCompileOptions());
165 // Get translated shader.
166 if (translated_source
) {
167 *translated_source
= ShGetObjectCode(compiler_
);
169 // Get info for attribs, uniforms, and varyings.
170 GetAttributes(compiler_
, attrib_map
);
171 GetUniforms(compiler_
, uniform_map
);
172 GetVaryings(compiler_
, varying_map
);
173 // Get info for name hashing.
174 GetNameHashingInfo(compiler_
, name_map
);
179 *info_log
= ShGetInfoLog(compiler_
);
185 std::string
ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
187 DCHECK(compiler_
!= NULL
);
188 return std::string(":CompileOptions:" +
189 base::IntToString(GetCompileOptions())) +
190 ShGetBuiltInResourcesString(compiler_
);
193 void ShaderTranslator::AddDestructionObserver(
194 DestructionObserver
* observer
) {
195 destruction_observers_
.AddObserver(observer
);
198 void ShaderTranslator::RemoveDestructionObserver(
199 DestructionObserver
* observer
) {
200 destruction_observers_
.RemoveObserver(observer
);
203 ShaderTranslator::~ShaderTranslator() {
204 FOR_EACH_OBSERVER(DestructionObserver
,
205 destruction_observers_
,
208 if (compiler_
!= NULL
)
209 ShDestruct(compiler_
);