1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "util/shader_utils.h"
8
9 #include <cstring>
10 #include <fstream>
11 #include <iostream>
12 #include <vector>
13
14 #include "common/utilities.h"
15 #include "util/test_utils.h"
16
17 namespace
18 {
ReadEntireFile(const std::string & filePath,std::string * contentsOut)19 bool ReadEntireFile(const std::string &filePath, std::string *contentsOut)
20 {
21 constexpr uint32_t kMaxBufferSize = 2000;
22 char buffer[kMaxBufferSize] = {};
23 if (!angle::ReadEntireFileToString(filePath.c_str(), buffer, kMaxBufferSize) ||
24 strlen(buffer) == 0)
25 return false;
26 *contentsOut = buffer;
27 return true;
28 }
29
CompileProgramInternal(const char * vsSource,const char * tcsSource,const char * tesSource,const char * gsSource,const char * fsSource,const std::function<void (GLuint)> & preLinkCallback)30 GLuint CompileProgramInternal(const char *vsSource,
31 const char *tcsSource,
32 const char *tesSource,
33 const char *gsSource,
34 const char *fsSource,
35 const std::function<void(GLuint)> &preLinkCallback)
36 {
37 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
38 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
39
40 if (vs == 0 || fs == 0)
41 {
42 glDeleteShader(fs);
43 glDeleteShader(vs);
44 return 0;
45 }
46
47 GLuint program = glCreateProgram();
48
49 glAttachShader(program, vs);
50 glDeleteShader(vs);
51
52 glAttachShader(program, fs);
53 glDeleteShader(fs);
54
55 GLuint tcs = 0;
56 GLuint tes = 0;
57 GLuint gs = 0;
58
59 if (strlen(tcsSource) > 0)
60 {
61 tcs = CompileShader(GL_TESS_CONTROL_SHADER_EXT, tcsSource);
62 if (tcs == 0)
63 {
64 glDeleteShader(vs);
65 glDeleteShader(fs);
66 glDeleteProgram(program);
67 return 0;
68 }
69
70 glAttachShader(program, tcs);
71 glDeleteShader(tcs);
72 }
73
74 if (strlen(tesSource) > 0)
75 {
76 tes = CompileShader(GL_TESS_EVALUATION_SHADER_EXT, tesSource);
77 if (tes == 0)
78 {
79 glDeleteShader(vs);
80 glDeleteShader(fs);
81 glDeleteShader(tcs);
82 glDeleteProgram(program);
83 return 0;
84 }
85
86 glAttachShader(program, tes);
87 glDeleteShader(tes);
88 }
89
90 if (strlen(gsSource) > 0)
91 {
92 gs = CompileShader(GL_GEOMETRY_SHADER_EXT, gsSource);
93 if (gs == 0)
94 {
95 glDeleteShader(vs);
96 glDeleteShader(fs);
97 glDeleteShader(tcs);
98 glDeleteShader(tes);
99 glDeleteProgram(program);
100 return 0;
101 }
102
103 glAttachShader(program, gs);
104 glDeleteShader(gs);
105 }
106
107 if (preLinkCallback)
108 {
109 preLinkCallback(program);
110 }
111
112 glLinkProgram(program);
113
114 return CheckLinkStatusAndReturnProgram(program, true);
115 }
116
117 const void *gCallbackChainUserParam;
118
DebugMessageCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)119 void KHRONOS_APIENTRY DebugMessageCallback(GLenum source,
120 GLenum type,
121 GLuint id,
122 GLenum severity,
123 GLsizei length,
124 const GLchar *message,
125 const void *userParam)
126 {
127 std::string sourceText = gl::GetDebugMessageSourceString(source);
128 std::string typeText = gl::GetDebugMessageTypeString(type);
129 std::string severityText = gl::GetDebugMessageSeverityString(severity);
130 std::cerr << sourceText << ", " << typeText << ", " << severityText << ": " << message << "\n";
131
132 GLDEBUGPROC callbackChain = reinterpret_cast<GLDEBUGPROC>(const_cast<void *>(userParam));
133 if (callbackChain)
134 {
135 callbackChain(source, type, id, severity, length, message, gCallbackChainUserParam);
136 }
137 }
138
GetPerfCounterValue(const CounterNameToIndexMap & counterIndexMap,std::vector<angle::PerfMonitorTriplet> & triplets,const char * name,GLuint * counterOut)139 void GetPerfCounterValue(const CounterNameToIndexMap &counterIndexMap,
140 std::vector<angle::PerfMonitorTriplet> &triplets,
141 const char *name,
142 GLuint *counterOut)
143 {
144 auto iter = counterIndexMap.find(name);
145 ASSERT(iter != counterIndexMap.end());
146 GLuint counterIndex = iter->second;
147
148 for (const angle::PerfMonitorTriplet &triplet : triplets)
149 {
150 ASSERT(triplet.group == 0);
151 if (triplet.counter == counterIndex)
152 {
153 *counterOut = triplet.value;
154 return;
155 }
156 }
157
158 UNREACHABLE();
159 }
160 } // namespace
161
CompileShader(GLenum type,const char * source)162 GLuint CompileShader(GLenum type, const char *source)
163 {
164 GLuint shader = glCreateShader(type);
165
166 const char *sourceArray[1] = {source};
167 glShaderSource(shader, 1, sourceArray, nullptr);
168 glCompileShader(shader);
169
170 GLint compileResult;
171 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
172
173 if (compileResult == 0)
174 {
175 GLint infoLogLength;
176 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
177
178 // Info log length includes the null terminator, so 1 means that the info log is an empty
179 // string.
180 if (infoLogLength > 1)
181 {
182 std::vector<GLchar> infoLog(infoLogLength);
183 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
184 std::cerr << "shader compilation failed: " << &infoLog[0];
185 }
186 else
187 {
188 std::cerr << "shader compilation failed. <Empty log message>";
189 }
190
191 std::cerr << std::endl;
192
193 glDeleteShader(shader);
194 shader = 0;
195 }
196
197 return shader;
198 }
199
CompileShaderFromFile(GLenum type,const std::string & sourcePath)200 GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
201 {
202 std::string source;
203 if (!ReadEntireFile(sourcePath, &source))
204 {
205 std::cerr << "Error reading shader file: " << sourcePath << "\n";
206 return 0;
207 }
208
209 return CompileShader(type, source.c_str());
210 }
211
CheckLinkStatusAndReturnProgram(GLuint program,bool outputErrorMessages)212 GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
213 {
214 if (glGetError() != GL_NO_ERROR)
215 return 0;
216
217 GLint linkStatus;
218 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
219 if (linkStatus == 0)
220 {
221 if (outputErrorMessages)
222 {
223 GLint infoLogLength;
224 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
225
226 // Info log length includes the null terminator, so 1 means that the info log is an
227 // empty string.
228 if (infoLogLength > 1)
229 {
230 std::vector<GLchar> infoLog(infoLogLength);
231 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
232 &infoLog[0]);
233
234 std::cerr << "program link failed: " << &infoLog[0];
235 }
236 else
237 {
238 std::cerr << "program link failed. <Empty log message>";
239 }
240 }
241
242 glDeleteProgram(program);
243 return 0;
244 }
245
246 return program;
247 }
248
GetProgramShader(GLuint program,GLint requestedType)249 GLuint GetProgramShader(GLuint program, GLint requestedType)
250 {
251 static constexpr GLsizei kMaxShaderCount = 16;
252 GLuint attachedShaders[kMaxShaderCount] = {0u};
253 GLsizei count = 0;
254 glGetAttachedShaders(program, kMaxShaderCount, &count, attachedShaders);
255 for (int i = 0; i < count; ++i)
256 {
257 GLint type = 0;
258 glGetShaderiv(attachedShaders[i], GL_SHADER_TYPE, &type);
259 if (type == requestedType)
260 {
261 return attachedShaders[i];
262 }
263 }
264
265 return 0;
266 }
267
CompileProgramWithTransformFeedback(const char * vsSource,const char * fsSource,const std::vector<std::string> & transformFeedbackVaryings,GLenum bufferMode)268 GLuint CompileProgramWithTransformFeedback(
269 const char *vsSource,
270 const char *fsSource,
271 const std::vector<std::string> &transformFeedbackVaryings,
272 GLenum bufferMode)
273 {
274 auto preLink = [&](GLuint program) {
275 if (transformFeedbackVaryings.size() > 0)
276 {
277 std::vector<const char *> constCharTFVaryings;
278
279 for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
280 {
281 constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
282 }
283
284 glTransformFeedbackVaryings(program,
285 static_cast<GLsizei>(transformFeedbackVaryings.size()),
286 &constCharTFVaryings[0], bufferMode);
287 }
288 };
289
290 return CompileProgramInternal(vsSource, "", "", "", fsSource, preLink);
291 }
292
CompileProgram(const char * vsSource,const char * fsSource)293 GLuint CompileProgram(const char *vsSource, const char *fsSource)
294 {
295 return CompileProgramInternal(vsSource, "", "", "", fsSource, nullptr);
296 }
297
CompileProgram(const char * vsSource,const char * fsSource,const std::function<void (GLuint)> & preLinkCallback)298 GLuint CompileProgram(const char *vsSource,
299 const char *fsSource,
300 const std::function<void(GLuint)> &preLinkCallback)
301 {
302 return CompileProgramInternal(vsSource, "", "", "", fsSource, preLinkCallback);
303 }
304
CompileProgramWithGS(const char * vsSource,const char * gsSource,const char * fsSource)305 GLuint CompileProgramWithGS(const char *vsSource, const char *gsSource, const char *fsSource)
306 {
307 return CompileProgramInternal(vsSource, "", "", gsSource, fsSource, nullptr);
308 }
309
CompileProgramWithTESS(const char * vsSource,const char * tcsSource,const char * tesSource,const char * fsSource)310 GLuint CompileProgramWithTESS(const char *vsSource,
311 const char *tcsSource,
312 const char *tesSource,
313 const char *fsSource)
314 {
315 return CompileProgramInternal(vsSource, tcsSource, tesSource, "", fsSource, nullptr);
316 }
317
CompileProgramFromFiles(const std::string & vsPath,const std::string & fsPath)318 GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
319 {
320 std::string vsSource;
321 if (!ReadEntireFile(vsPath, &vsSource))
322 {
323 std::cerr << "Error reading shader: " << vsPath << "\n";
324 return 0;
325 }
326
327 std::string fsSource;
328 if (!ReadEntireFile(fsPath, &fsSource))
329 {
330 std::cerr << "Error reading shader: " << fsPath << "\n";
331 return 0;
332 }
333
334 return CompileProgram(vsSource.c_str(), fsSource.c_str());
335 }
336
CompileComputeProgram(const char * csSource,bool outputErrorMessages)337 GLuint CompileComputeProgram(const char *csSource, bool outputErrorMessages)
338 {
339 GLuint program = glCreateProgram();
340
341 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
342 if (cs == 0)
343 {
344 glDeleteProgram(program);
345 return 0;
346 }
347
348 glAttachShader(program, cs);
349
350 glLinkProgram(program);
351
352 return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
353 }
354
LoadBinaryProgramOES(const std::vector<uint8_t> & binary,GLenum binaryFormat)355 GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
356 {
357 GLuint program = glCreateProgram();
358 glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
359 return CheckLinkStatusAndReturnProgram(program, true);
360 }
361
LoadBinaryProgramES3(const std::vector<uint8_t> & binary,GLenum binaryFormat)362 GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
363 {
364 GLuint program = glCreateProgram();
365 glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
366 return CheckLinkStatusAndReturnProgram(program, true);
367 }
368
LinkAttachedProgram(GLuint program)369 bool LinkAttachedProgram(GLuint program)
370 {
371 glLinkProgram(program);
372 return (CheckLinkStatusAndReturnProgram(program, true) != 0);
373 }
374
EnableDebugCallback(GLDEBUGPROC callbackChain,const void * userParam)375 void EnableDebugCallback(GLDEBUGPROC callbackChain, const void *userParam)
376 {
377 gCallbackChainUserParam = userParam;
378
379 glEnable(GL_DEBUG_OUTPUT);
380 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
381 // Enable medium and high priority messages.
382 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr,
383 GL_TRUE);
384 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr,
385 GL_TRUE);
386 // Disable low and notification priority messages.
387 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, nullptr,
388 GL_FALSE);
389 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr,
390 GL_FALSE);
391 // Disable performance messages to reduce spam.
392 glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE, 0, nullptr,
393 GL_FALSE);
394 glDebugMessageCallbackKHR(DebugMessageCallback, reinterpret_cast<const void *>(callbackChain));
395 }
396
BuildCounterNameToIndexMap()397 CounterNameToIndexMap BuildCounterNameToIndexMap()
398 {
399 GLint numCounters = 0;
400 glGetPerfMonitorCountersAMD(0, &numCounters, nullptr, 0, nullptr);
401 if (glGetError() != GL_NO_ERROR)
402 {
403 return {};
404 }
405
406 std::vector<GLuint> counterIndexes(numCounters, 0);
407 glGetPerfMonitorCountersAMD(0, nullptr, nullptr, numCounters, counterIndexes.data());
408 if (glGetError() != GL_NO_ERROR)
409 {
410 return {};
411 }
412
413 CounterNameToIndexMap indexMap;
414
415 for (GLuint counterIndex : counterIndexes)
416 {
417 static constexpr size_t kBufSize = 1000;
418 char buffer[kBufSize] = {};
419 glGetPerfMonitorCounterStringAMD(0, counterIndex, kBufSize, nullptr, buffer);
420 if (glGetError() != GL_NO_ERROR)
421 {
422 return {};
423 }
424
425 indexMap[buffer] = counterIndex;
426 }
427
428 return indexMap;
429 }
430
GetPerfMonitorTriplets()431 std::vector<angle::PerfMonitorTriplet> GetPerfMonitorTriplets()
432 {
433 GLuint resultSize = 0;
434 glGetPerfMonitorCounterDataAMD(0, GL_PERFMON_RESULT_SIZE_AMD, sizeof(GLuint), &resultSize,
435 nullptr);
436 if (glGetError() != GL_NO_ERROR || resultSize == 0)
437 {
438 return {};
439 }
440
441 std::vector<angle::PerfMonitorTriplet> perfResults(resultSize /
442 sizeof(angle::PerfMonitorTriplet));
443 glGetPerfMonitorCounterDataAMD(
444 0, GL_PERFMON_RESULT_AMD, static_cast<GLsizei>(perfResults.size() * sizeof(perfResults[0])),
445 &perfResults.data()->group, nullptr);
446
447 if (glGetError() != GL_NO_ERROR)
448 {
449 return {};
450 }
451
452 return perfResults;
453 }
454
GetPerfCounters(const CounterNameToIndexMap & indexMap)455 angle::VulkanPerfCounters GetPerfCounters(const CounterNameToIndexMap &indexMap)
456 {
457 std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
458
459 angle::VulkanPerfCounters counters;
460
461 #define ANGLE_UNPACK_PERF_COUNTER(COUNTER) \
462 GetPerfCounterValue(indexMap, perfResults, #COUNTER, &counters.COUNTER);
463
464 ANGLE_VK_PERF_COUNTERS_X(ANGLE_UNPACK_PERF_COUNTER)
465
466 #undef ANGLE_UNPACK_PERF_COUNTER
467
468 return counters;
469 }
470
BuildCounterNameToValueMap()471 CounterNameToIndexMap BuildCounterNameToValueMap()
472 {
473 CounterNameToIndexMap indexMap = BuildCounterNameToIndexMap();
474 std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
475
476 CounterNameToValueMap valueMap;
477
478 for (const auto &iter : indexMap)
479 {
480 const std::string &name = iter.first;
481 GLuint index = iter.second;
482
483 valueMap[name] = perfResults[index].value;
484 }
485
486 return valueMap;
487 }
488
489 namespace angle
490 {
491
492 namespace essl1_shaders
493 {
494
PositionAttrib()495 const char *PositionAttrib()
496 {
497 return "a_position";
498 }
ColorUniform()499 const char *ColorUniform()
500 {
501 return "u_color";
502 }
503
Texture2DUniform()504 const char *Texture2DUniform()
505 {
506 return "u_tex2D";
507 }
508
509 namespace vs
510 {
511
512 // A shader that sets gl_Position to zero.
Zero()513 const char *Zero()
514 {
515 return R"(void main()
516 {
517 gl_Position = vec4(0);
518 })";
519 }
520
521 // A shader that sets gl_Position to attribute a_position.
Simple()522 const char *Simple()
523 {
524 return R"(precision highp float;
525 attribute vec4 a_position;
526
527 void main()
528 {
529 gl_Position = a_position;
530 })";
531 }
532
533 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
534 // v_position.
Passthrough()535 const char *Passthrough()
536 {
537 return R"(precision highp float;
538 attribute vec4 a_position;
539 varying vec4 v_position;
540
541 void main()
542 {
543 gl_Position = a_position;
544 v_position = a_position;
545 })";
546 }
547
548 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
549 // texcoord.
Texture2D()550 const char *Texture2D()
551 {
552 return R"(precision highp float;
553 attribute vec4 a_position;
554 varying vec2 v_texCoord;
555
556 void main()
557 {
558 gl_Position = vec4(a_position.xy, 0.0, 1.0);
559 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
560 })";
561 }
562
563 } // namespace vs
564
565 namespace fs
566 {
567
568 // A shader that renders a simple checker pattern of red and green. X axis and y axis separate the
569 // different colors. Needs varying v_position.
Checkered()570 const char *Checkered()
571 {
572 return R"(precision highp float;
573 varying vec4 v_position;
574
575 void main()
576 {
577 bool isLeft = v_position.x < 0.0;
578 bool isTop = v_position.y < 0.0;
579 if (isLeft)
580 {
581 if (isTop)
582 {
583 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
584 }
585 else
586 {
587 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
588 }
589 }
590 else
591 {
592 if (isTop)
593 {
594 gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
595 }
596 else
597 {
598 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
599 }
600 }
601 })";
602 }
603
604 // A shader that fills with color taken from uniform named "color".
UniformColor()605 const char *UniformColor()
606 {
607 return R"(uniform mediump vec4 u_color;
608 void main(void)
609 {
610 gl_FragColor = u_color;
611 })";
612 }
613
614 // A shader that fills with 100% opaque red.
Red()615 const char *Red()
616 {
617 return R"(precision mediump float;
618
619 void main()
620 {
621 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
622 })";
623 }
624
625 // A shader that fills with 100% opaque green.
Green()626 const char *Green()
627 {
628 return R"(precision mediump float;
629
630 void main()
631 {
632 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
633 })";
634 }
635
636 // A shader that fills with 100% opaque blue.
Blue()637 const char *Blue()
638 {
639 return R"(precision mediump float;
640
641 void main()
642 {
643 gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
644 })";
645 }
646
647 // A shader that samples the texture.
Texture2D()648 const char *Texture2D()
649 {
650 return R"(precision mediump float;
651 uniform sampler2D u_tex2D;
652 varying vec2 v_texCoord;
653
654 void main()
655 {
656 gl_FragColor = texture2D(u_tex2D, v_texCoord);
657 })";
658 }
659
660 } // namespace fs
661 } // namespace essl1_shaders
662
663 namespace essl3_shaders
664 {
665
PositionAttrib()666 const char *PositionAttrib()
667 {
668 return "a_position";
669 }
Texture2DUniform()670 const char *Texture2DUniform()
671 {
672 return "u_tex2D";
673 }
LodUniform()674 const char *LodUniform()
675 {
676 return "u_lod";
677 }
678
679 namespace vs
680 {
681
682 // A shader that sets gl_Position to zero.
Zero()683 const char *Zero()
684 {
685 return R"(#version 300 es
686 void main()
687 {
688 gl_Position = vec4(0);
689 })";
690 }
691
692 // A shader that sets gl_Position to attribute a_position.
Simple()693 const char *Simple()
694 {
695 return R"(#version 300 es
696 in vec4 a_position;
697 void main()
698 {
699 gl_Position = a_position;
700 })";
701 }
702
703 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
704 // v_position.
Passthrough()705 const char *Passthrough()
706 {
707 return R"(#version 300 es
708 in vec4 a_position;
709 out vec4 v_position;
710 void main()
711 {
712 gl_Position = a_position;
713 v_position = a_position;
714 })";
715 }
716
717 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
718 // texcoord.
Texture2DLod()719 const char *Texture2DLod()
720 {
721 return R"(#version 300 es
722 in vec4 a_position;
723 out vec2 v_texCoord;
724
725 void main()
726 {
727 gl_Position = vec4(a_position.xy, 0.0, 1.0);
728 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
729 })";
730 }
731
732 } // namespace vs
733
734 namespace fs
735 {
736
737 // A shader that fills with 100% opaque red.
Red()738 const char *Red()
739 {
740 return R"(#version 300 es
741 precision highp float;
742 out vec4 my_FragColor;
743 void main()
744 {
745 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
746 })";
747 }
748
749 // A shader that fills with 100% opaque green.
Green()750 const char *Green()
751 {
752 return R"(#version 300 es
753 precision highp float;
754 out vec4 my_FragColor;
755 void main()
756 {
757 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
758 })";
759 }
760
761 // A shader that fills with 100% opaque blue.
Blue()762 const char *Blue()
763 {
764 return R"(#version 300 es
765 precision highp float;
766 out vec4 my_FragColor;
767 void main()
768 {
769 my_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
770 })";
771 }
772
773 // A shader that samples the texture at a given lod.
Texture2DLod()774 const char *Texture2DLod()
775 {
776 return R"(#version 300 es
777 precision mediump float;
778 uniform sampler2D u_tex2D;
779 uniform float u_lod;
780 in vec2 v_texCoord;
781 out vec4 my_FragColor;
782
783 void main()
784 {
785 my_FragColor = textureLod(u_tex2D, v_texCoord, u_lod);
786 })";
787 }
788
789 } // namespace fs
790 } // namespace essl3_shaders
791
792 namespace essl31_shaders
793 {
794
PositionAttrib()795 const char *PositionAttrib()
796 {
797 return "a_position";
798 }
799
800 namespace vs
801 {
802
803 // A shader that sets gl_Position to zero.
Zero()804 const char *Zero()
805 {
806 return R"(#version 310 es
807 void main()
808 {
809 gl_Position = vec4(0);
810 })";
811 }
812
813 // A shader that sets gl_Position to attribute a_position.
Simple()814 const char *Simple()
815 {
816 return R"(#version 310 es
817 in vec4 a_position;
818 void main()
819 {
820 gl_Position = a_position;
821 })";
822 }
823
824 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
825 // v_position.
Passthrough()826 const char *Passthrough()
827 {
828 return R"(#version 310 es
829 in vec4 a_position;
830 out vec4 v_position;
831 void main()
832 {
833 gl_Position = a_position;
834 v_position = a_position;
835 })";
836 }
837
838 } // namespace vs
839
840 namespace fs
841 {
842
843 // A shader that fills with 100% opaque red.
Red()844 const char *Red()
845 {
846 return R"(#version 310 es
847 precision highp float;
848 out vec4 my_FragColor;
849 void main()
850 {
851 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
852 })";
853 }
854
855 // A shader that fills with 100% opaque green.
Green()856 const char *Green()
857 {
858 return R"(#version 310 es
859 precision highp float;
860 out vec4 my_FragColor;
861 void main()
862 {
863 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
864 })";
865 }
866
867 // A shader that renders a simple gradient of red to green. Needs varying v_position.
RedGreenGradient()868 const char *RedGreenGradient()
869 {
870 return R"(#version 310 es
871 precision highp float;
872 in vec4 v_position;
873 out vec4 my_FragColor;
874
875 void main()
876 {
877 my_FragColor = vec4(v_position.xy * 0.5 + vec2(0.5), 0.0, 1.0);
878 })";
879 }
880
881 } // namespace fs
882 } // namespace essl31_shaders
883 } // namespace angle
884