Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / gpu / command_buffer / service / shader_translator.cc
blob9e79fd90236fc1562045ee48422e1bddf95ae566
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/debug/trace_event.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/strings/string_number_conversions.h"
17 namespace {
19 using gpu::gles2::ShaderTranslator;
21 class ShaderTranslatorInitializer {
22 public:
23 ShaderTranslatorInitializer() {
24 TRACE_EVENT0("gpu", "ShInitialize");
25 CHECK(ShInitialize());
28 ~ShaderTranslatorInitializer() {
29 TRACE_EVENT0("gpu", "ShFinalize");
30 ShFinalize();
34 base::LazyInstance<ShaderTranslatorInitializer> g_translator_initializer =
35 LAZY_INSTANCE_INITIALIZER;
37 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
38 typedef int ANGLEGetInfoType;
39 #else
40 typedef size_t ANGLEGetInfoType;
41 #endif
43 void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type,
44 ShaderTranslator::VariableMap* var_map) {
45 ANGLEGetInfoType name_len = 0, mapped_name_len = 0;
46 switch (var_type) {
47 case SH_ACTIVE_ATTRIBUTES:
48 ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &name_len);
49 break;
50 case SH_ACTIVE_UNIFORMS:
51 ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &name_len);
52 break;
53 case SH_VARYINGS:
54 ShGetInfo(compiler, SH_VARYING_MAX_LENGTH, &name_len);
55 break;
56 default: NOTREACHED();
58 ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_name_len);
59 if (name_len <= 1 || mapped_name_len <= 1) return;
60 scoped_ptr<char[]> name(new char[name_len]);
61 scoped_ptr<char[]> mapped_name(new char[mapped_name_len]);
63 ANGLEGetInfoType num_vars = 0;
64 ShGetInfo(compiler, var_type, &num_vars);
65 for (ANGLEGetInfoType i = 0; i < num_vars; ++i) {
66 ANGLEGetInfoType len = 0;
67 int size = 0;
68 #if (ANGLE_SH_VERSION >= 126)
69 sh::GLenum type = GL_NONE;
70 #else
71 ShDataType type = SH_NONE;
72 #endif
73 ShPrecisionType precision = SH_PRECISION_UNDEFINED;
74 int static_use = 0;
76 ShGetVariableInfo(compiler, var_type, i,
77 &len, &size, &type, &precision, &static_use,
78 name.get(), mapped_name.get());
80 // In theory we should CHECK(len <= name_len - 1) here, but ANGLE needs
81 // to handle long struct field name mapping before we can do this.
82 // Also, we should modify the ANGLE interface to also return a length
83 // for mapped_name.
84 std::string name_string(name.get(), std::min(len, name_len - 1));
85 mapped_name.get()[mapped_name_len - 1] = '\0';
87 ShaderTranslator::VariableInfo info(
88 type, size, precision, static_use, name_string);
89 (*var_map)[mapped_name.get()] = info;
93 void GetNameHashingInfo(
94 ShHandle compiler, ShaderTranslator::NameMap* name_map) {
95 ANGLEGetInfoType hashed_names_count = 0;
96 ShGetInfo(compiler, SH_HASHED_NAMES_COUNT, &hashed_names_count);
97 if (hashed_names_count == 0)
98 return;
100 ANGLEGetInfoType name_max_len = 0, hashed_name_max_len = 0;
101 ShGetInfo(compiler, SH_NAME_MAX_LENGTH, &name_max_len);
102 ShGetInfo(compiler, SH_HASHED_NAME_MAX_LENGTH, &hashed_name_max_len);
104 scoped_ptr<char[]> name(new char[name_max_len]);
105 scoped_ptr<char[]> hashed_name(new char[hashed_name_max_len]);
107 for (ANGLEGetInfoType i = 0; i < hashed_names_count; ++i) {
108 ShGetNameHashingEntry(compiler, i, name.get(), hashed_name.get());
109 (*name_map)[hashed_name.get()] = name.get();
113 } // namespace
115 namespace gpu {
116 namespace gles2 {
118 ShaderTranslator::DestructionObserver::DestructionObserver() {
121 ShaderTranslator::DestructionObserver::~DestructionObserver() {
124 ShaderTranslator::ShaderTranslator()
125 : compiler_(NULL),
126 implementation_is_glsl_es_(false),
127 driver_bug_workarounds_(static_cast<ShCompileOptions>(0)) {
130 bool ShaderTranslator::Init(
131 #if (ANGLE_SH_VERSION >= 126)
132 GLenum shader_type,
133 #else
134 ShShaderType shader_type,
135 #endif
136 ShShaderSpec shader_spec,
137 const ShBuiltInResources* resources,
138 ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type,
139 ShCompileOptions driver_bug_workarounds) {
140 // Make sure Init is called only once.
141 DCHECK(compiler_ == NULL);
142 #if (ANGLE_SH_VERSION >= 126)
143 DCHECK(shader_type == GL_FRAGMENT_SHADER || shader_type == GL_VERTEX_SHADER);
144 #else
145 DCHECK(shader_type == SH_FRAGMENT_SHADER || shader_type == SH_VERTEX_SHADER);
146 #endif
147 DCHECK(shader_spec == SH_GLES2_SPEC || shader_spec == SH_WEBGL_SPEC);
148 DCHECK(resources != NULL);
150 g_translator_initializer.Get();
152 ShShaderOutput shader_output =
153 (glsl_implementation_type == kGlslES ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT);
156 TRACE_EVENT0("gpu", "ShConstructCompiler");
157 compiler_ = ShConstructCompiler(
158 shader_type, shader_spec, shader_output, resources);
160 compiler_options_ = *resources;
161 implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES);
162 driver_bug_workarounds_ = driver_bug_workarounds;
163 return compiler_ != NULL;
166 int ShaderTranslator::GetCompileOptions() const {
167 int compile_options =
168 SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS |
169 SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH |
170 SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
172 compile_options |= driver_bug_workarounds_;
174 return compile_options;
177 bool ShaderTranslator::Translate(const char* shader) {
178 // Make sure this instance is initialized.
179 DCHECK(compiler_ != NULL);
180 DCHECK(shader != NULL);
181 ClearResults();
183 bool success = false;
185 TRACE_EVENT0("gpu", "ShCompile");
186 success = !!ShCompile(compiler_, &shader, 1, GetCompileOptions());
188 if (success) {
189 // Get translated shader.
190 ANGLEGetInfoType obj_code_len = 0;
191 ShGetInfo(compiler_, SH_OBJECT_CODE_LENGTH, &obj_code_len);
192 if (obj_code_len > 1) {
193 translated_shader_.reset(new char[obj_code_len]);
194 ShGetObjectCode(compiler_, translated_shader_.get());
196 // Get info for attribs and uniforms.
197 GetVariableInfo(compiler_, SH_ACTIVE_ATTRIBUTES, &attrib_map_);
198 GetVariableInfo(compiler_, SH_ACTIVE_UNIFORMS, &uniform_map_);
199 GetVariableInfo(compiler_, SH_VARYINGS, &varying_map_);
200 // Get info for name hashing.
201 GetNameHashingInfo(compiler_, &name_map_);
204 // Get info log.
205 ANGLEGetInfoType info_log_len = 0;
206 ShGetInfo(compiler_, SH_INFO_LOG_LENGTH, &info_log_len);
207 if (info_log_len > 1) {
208 info_log_.reset(new char[info_log_len]);
209 ShGetInfoLog(compiler_, info_log_.get());
210 } else {
211 info_log_.reset();
214 return success;
217 std::string ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
218 const {
219 #if ANGLE_SH_VERSION >= 124
220 DCHECK(compiler_ != NULL);
222 ANGLEGetInfoType resource_len = 0;
223 ShGetInfo(compiler_, SH_RESOURCES_STRING_LENGTH, &resource_len);
224 DCHECK(resource_len > 1);
225 scoped_ptr<char[]> resource_str(new char[resource_len]);
227 ShGetBuiltInResourcesString(compiler_, resource_len, resource_str.get());
229 return std::string(":CompileOptions:" +
230 base::IntToString(GetCompileOptions())) +
231 std::string(resource_str.get());
232 #else
233 #if ANGLE_SH_VERSION >= 123
234 const size_t kNumIntFields = 21;
235 #elif ANGLE_SH_VERSION >= 122
236 const size_t kNumIntFields = 20;
237 #else
238 const size_t kNumIntFields = 16;
239 #endif
240 const size_t kNumEnumFields = 1;
241 const size_t kNumFunctionPointerFields = 1;
242 struct MustMatchShBuiltInResource {
243 typedef khronos_uint64_t (*FunctionPointer)(const char*, size_t);
244 enum Enum {
245 kFirst,
247 int int_fields[kNumIntFields];
248 FunctionPointer pointer_fields[kNumFunctionPointerFields];
249 Enum enum_fields[kNumEnumFields];
251 // If this assert fails most likely that means something below needs updating.
252 COMPILE_ASSERT(
253 sizeof(ShBuiltInResources) == sizeof(MustMatchShBuiltInResource),
254 Fields_Have_Changed_In_ShBuiltInResource_So_Update_Below);
256 return std::string(
257 ":CompileOptions:" +
258 base::IntToString(GetCompileOptions()) +
259 ":MaxVertexAttribs:" +
260 base::IntToString(compiler_options_.MaxVertexAttribs) +
261 ":MaxVertexUniformVectors:" +
262 base::IntToString(compiler_options_.MaxVertexUniformVectors) +
263 ":MaxVaryingVectors:" +
264 base::IntToString(compiler_options_.MaxVaryingVectors) +
265 ":MaxVertexTextureImageUnits:" +
266 base::IntToString(compiler_options_.MaxVertexTextureImageUnits) +
267 ":MaxCombinedTextureImageUnits:" +
268 base::IntToString(compiler_options_.MaxCombinedTextureImageUnits) +
269 ":MaxTextureImageUnits:" +
270 base::IntToString(compiler_options_.MaxTextureImageUnits) +
271 ":MaxFragmentUniformVectors:" +
272 base::IntToString(compiler_options_.MaxFragmentUniformVectors) +
273 ":MaxDrawBuffers:" +
274 base::IntToString(compiler_options_.MaxDrawBuffers) +
275 ":OES_standard_derivatives:" +
276 base::IntToString(compiler_options_.OES_standard_derivatives) +
277 ":OES_EGL_image_external:" +
278 base::IntToString(compiler_options_.OES_EGL_image_external) +
279 ":ARB_texture_rectangle:" +
280 base::IntToString(compiler_options_.ARB_texture_rectangle) +
281 ":EXT_draw_buffers:" +
282 base::IntToString(compiler_options_.EXT_draw_buffers) +
283 ":FragmentPrecisionHigh:" +
284 base::IntToString(compiler_options_.FragmentPrecisionHigh) +
285 ":MaxExpressionComplexity:" +
286 base::IntToString(compiler_options_.MaxExpressionComplexity) +
287 ":MaxCallStackDepth:" +
288 base::IntToString(compiler_options_.MaxCallStackDepth) +
289 ":EXT_frag_depth:" +
290 #if ANGLE_SH_VERSION >= 122
291 base::IntToString(compiler_options_.EXT_frag_depth) +
292 #if ANGLE_SH_VERSION >= 123
293 ":EXT_shader_texture_lod:" +
294 base::IntToString(compiler_options_.EXT_shader_texture_lod) +
295 #endif
296 ":MaxVertexOutputVectors:" +
297 base::IntToString(compiler_options_.MaxVertexOutputVectors) +
298 ":MaxFragmentInputVectors:" +
299 base::IntToString(compiler_options_.MaxFragmentInputVectors) +
300 ":MinProgramTexelOffset:" +
301 base::IntToString(compiler_options_.MinProgramTexelOffset) +
302 ":MaxProgramTexelOffset:" +
303 base::IntToString(compiler_options_.MaxProgramTexelOffset));
304 #else // ANGLE_SH_VERSION < 122
305 base::IntToString(compiler_options_.EXT_frag_depth));
306 #endif
307 #endif
310 const char* ShaderTranslator::translated_shader() const {
311 return translated_shader_.get();
314 const char* ShaderTranslator::info_log() const {
315 return info_log_.get();
318 const ShaderTranslatorInterface::VariableMap&
319 ShaderTranslator::attrib_map() const {
320 return attrib_map_;
323 const ShaderTranslatorInterface::VariableMap&
324 ShaderTranslator::uniform_map() const {
325 return uniform_map_;
328 const ShaderTranslatorInterface::VariableMap&
329 ShaderTranslator::varying_map() const {
330 return varying_map_;
333 const ShaderTranslatorInterface::NameMap&
334 ShaderTranslator::name_map() const {
335 return name_map_;
338 void ShaderTranslator::AddDestructionObserver(
339 DestructionObserver* observer) {
340 destruction_observers_.AddObserver(observer);
343 void ShaderTranslator::RemoveDestructionObserver(
344 DestructionObserver* observer) {
345 destruction_observers_.RemoveObserver(observer);
348 ShaderTranslator::~ShaderTranslator() {
349 FOR_EACH_OBSERVER(DestructionObserver,
350 destruction_observers_,
351 OnDestruct(this));
353 if (compiler_ != NULL)
354 ShDestruct(compiler_);
357 void ShaderTranslator::ClearResults() {
358 translated_shader_.reset();
359 info_log_.reset();
360 attrib_map_.clear();
361 uniform_map_.clear();
362 varying_map_.clear();
363 name_map_.clear();
366 } // namespace gles2
367 } // namespace gpu