Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/util/shader_utils.cpp
1693 views
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
{
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
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
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
} // namespace
139
140
GLuint CompileShader(GLenum type, const char *source)
141
{
142
GLuint shader = glCreateShader(type);
143
144
const char *sourceArray[1] = {source};
145
glShaderSource(shader, 1, sourceArray, nullptr);
146
glCompileShader(shader);
147
148
GLint compileResult;
149
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
150
151
if (compileResult == 0)
152
{
153
GLint infoLogLength;
154
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
155
156
// Info log length includes the null terminator, so 1 means that the info log is an empty
157
// string.
158
if (infoLogLength > 1)
159
{
160
std::vector<GLchar> infoLog(infoLogLength);
161
glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
162
std::cerr << "shader compilation failed: " << &infoLog[0];
163
}
164
else
165
{
166
std::cerr << "shader compilation failed. <Empty log message>";
167
}
168
169
std::cerr << std::endl;
170
171
glDeleteShader(shader);
172
shader = 0;
173
}
174
175
return shader;
176
}
177
178
GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
179
{
180
std::string source;
181
if (!ReadEntireFile(sourcePath, &source))
182
{
183
std::cerr << "Error reading shader file: " << sourcePath << "\n";
184
return 0;
185
}
186
187
return CompileShader(type, source.c_str());
188
}
189
190
GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
191
{
192
if (glGetError() != GL_NO_ERROR)
193
return 0;
194
195
GLint linkStatus;
196
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
197
if (linkStatus == 0)
198
{
199
if (outputErrorMessages)
200
{
201
GLint infoLogLength;
202
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
203
204
// Info log length includes the null terminator, so 1 means that the info log is an
205
// empty string.
206
if (infoLogLength > 1)
207
{
208
std::vector<GLchar> infoLog(infoLogLength);
209
glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
210
&infoLog[0]);
211
212
std::cerr << "program link failed: " << &infoLog[0];
213
}
214
else
215
{
216
std::cerr << "program link failed. <Empty log message>";
217
}
218
}
219
220
glDeleteProgram(program);
221
return 0;
222
}
223
224
return program;
225
}
226
227
GLuint GetProgramShader(GLuint program, GLint requestedType)
228
{
229
static constexpr GLsizei kMaxShaderCount = 16;
230
GLuint attachedShaders[kMaxShaderCount] = {0u};
231
GLsizei count = 0;
232
glGetAttachedShaders(program, kMaxShaderCount, &count, attachedShaders);
233
for (int i = 0; i < count; ++i)
234
{
235
GLint type = 0;
236
glGetShaderiv(attachedShaders[i], GL_SHADER_TYPE, &type);
237
if (type == requestedType)
238
{
239
return attachedShaders[i];
240
}
241
}
242
243
return 0;
244
}
245
246
GLuint CompileProgramWithTransformFeedback(
247
const char *vsSource,
248
const char *fsSource,
249
const std::vector<std::string> &transformFeedbackVaryings,
250
GLenum bufferMode)
251
{
252
auto preLink = [&](GLuint program) {
253
if (transformFeedbackVaryings.size() > 0)
254
{
255
std::vector<const char *> constCharTFVaryings;
256
257
for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
258
{
259
constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
260
}
261
262
glTransformFeedbackVaryings(program,
263
static_cast<GLsizei>(transformFeedbackVaryings.size()),
264
&constCharTFVaryings[0], bufferMode);
265
}
266
};
267
268
return CompileProgramInternal(vsSource, "", "", "", fsSource, preLink);
269
}
270
271
GLuint CompileProgram(const char *vsSource, const char *fsSource)
272
{
273
return CompileProgramInternal(vsSource, "", "", "", fsSource, nullptr);
274
}
275
276
GLuint CompileProgram(const char *vsSource,
277
const char *fsSource,
278
const std::function<void(GLuint)> &preLinkCallback)
279
{
280
return CompileProgramInternal(vsSource, "", "", "", fsSource, preLinkCallback);
281
}
282
283
GLuint CompileProgramWithGS(const char *vsSource, const char *gsSource, const char *fsSource)
284
{
285
return CompileProgramInternal(vsSource, "", "", gsSource, fsSource, nullptr);
286
}
287
288
GLuint CompileProgramWithTESS(const char *vsSource,
289
const char *tcsSource,
290
const char *tesSource,
291
const char *fsSource)
292
{
293
return CompileProgramInternal(vsSource, tcsSource, tesSource, "", fsSource, nullptr);
294
}
295
296
GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
297
{
298
std::string vsSource;
299
if (!ReadEntireFile(vsPath, &vsSource))
300
{
301
std::cerr << "Error reading shader: " << vsPath << "\n";
302
return 0;
303
}
304
305
std::string fsSource;
306
if (!ReadEntireFile(fsPath, &fsSource))
307
{
308
std::cerr << "Error reading shader: " << fsPath << "\n";
309
return 0;
310
}
311
312
return CompileProgram(vsSource.c_str(), fsSource.c_str());
313
}
314
315
GLuint CompileComputeProgram(const char *csSource, bool outputErrorMessages)
316
{
317
GLuint program = glCreateProgram();
318
319
GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
320
if (cs == 0)
321
{
322
glDeleteProgram(program);
323
return 0;
324
}
325
326
glAttachShader(program, cs);
327
328
glLinkProgram(program);
329
330
return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
331
}
332
333
GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
334
{
335
GLuint program = glCreateProgram();
336
glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
337
return CheckLinkStatusAndReturnProgram(program, true);
338
}
339
340
GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
341
{
342
GLuint program = glCreateProgram();
343
glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
344
return CheckLinkStatusAndReturnProgram(program, true);
345
}
346
347
bool LinkAttachedProgram(GLuint program)
348
{
349
glLinkProgram(program);
350
return (CheckLinkStatusAndReturnProgram(program, true) != 0);
351
}
352
353
void EnableDebugCallback(GLDEBUGPROC callbackChain, const void *userParam)
354
{
355
gCallbackChainUserParam = userParam;
356
357
glEnable(GL_DEBUG_OUTPUT);
358
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
359
// Enable medium and high priority messages.
360
glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr,
361
GL_TRUE);
362
glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr,
363
GL_TRUE);
364
// Disable low and notification priority messages.
365
glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, nullptr,
366
GL_FALSE);
367
glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr,
368
GL_FALSE);
369
// Disable performance messages to reduce spam.
370
glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE, 0, nullptr,
371
GL_FALSE);
372
glDebugMessageCallbackKHR(DebugMessageCallback, reinterpret_cast<const void *>(callbackChain));
373
}
374
375
namespace angle
376
{
377
378
namespace essl1_shaders
379
{
380
381
const char *PositionAttrib()
382
{
383
return "a_position";
384
}
385
const char *ColorUniform()
386
{
387
return "u_color";
388
}
389
390
const char *Texture2DUniform()
391
{
392
return "u_tex2D";
393
}
394
395
namespace vs
396
{
397
398
// A shader that sets gl_Position to zero.
399
const char *Zero()
400
{
401
return R"(void main()
402
{
403
gl_Position = vec4(0);
404
})";
405
}
406
407
// A shader that sets gl_Position to attribute a_position.
408
const char *Simple()
409
{
410
return R"(precision highp float;
411
attribute vec4 a_position;
412
413
void main()
414
{
415
gl_Position = a_position;
416
})";
417
}
418
419
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
420
// v_position.
421
const char *Passthrough()
422
{
423
return R"(precision highp float;
424
attribute vec4 a_position;
425
varying vec4 v_position;
426
427
void main()
428
{
429
gl_Position = a_position;
430
v_position = a_position;
431
})";
432
}
433
434
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
435
// texcoord.
436
const char *Texture2D()
437
{
438
return R"(precision highp float;
439
attribute vec4 a_position;
440
varying vec2 v_texCoord;
441
442
void main()
443
{
444
gl_Position = vec4(a_position.xy, 0.0, 1.0);
445
v_texCoord = a_position.xy * 0.5 + vec2(0.5);
446
})";
447
}
448
449
} // namespace vs
450
451
namespace fs
452
{
453
454
// A shader that renders a simple checker pattern of red and green. X axis and y axis separate the
455
// different colors. Needs varying v_position.
456
const char *Checkered()
457
{
458
return R"(precision highp float;
459
varying vec4 v_position;
460
461
void main()
462
{
463
bool isLeft = v_position.x < 0.0;
464
bool isTop = v_position.y < 0.0;
465
if (isLeft)
466
{
467
if (isTop)
468
{
469
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
470
}
471
else
472
{
473
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
474
}
475
}
476
else
477
{
478
if (isTop)
479
{
480
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
481
}
482
else
483
{
484
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
485
}
486
}
487
})";
488
}
489
490
// A shader that fills with color taken from uniform named "color".
491
const char *UniformColor()
492
{
493
return R"(uniform mediump vec4 u_color;
494
void main(void)
495
{
496
gl_FragColor = u_color;
497
})";
498
}
499
500
// A shader that fills with 100% opaque red.
501
const char *Red()
502
{
503
return R"(precision mediump float;
504
505
void main()
506
{
507
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
508
})";
509
}
510
511
// A shader that fills with 100% opaque green.
512
const char *Green()
513
{
514
return R"(precision mediump float;
515
516
void main()
517
{
518
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
519
})";
520
}
521
522
// A shader that fills with 100% opaque blue.
523
const char *Blue()
524
{
525
return R"(precision mediump float;
526
527
void main()
528
{
529
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
530
})";
531
}
532
533
// A shader that samples the texture.
534
const char *Texture2D()
535
{
536
return R"(precision mediump float;
537
uniform sampler2D u_tex2D;
538
varying vec2 v_texCoord;
539
540
void main()
541
{
542
gl_FragColor = texture2D(u_tex2D, v_texCoord);
543
})";
544
}
545
546
} // namespace fs
547
} // namespace essl1_shaders
548
549
namespace essl3_shaders
550
{
551
552
const char *PositionAttrib()
553
{
554
return "a_position";
555
}
556
const char *Texture2DUniform()
557
{
558
return "u_tex2D";
559
}
560
const char *LodUniform()
561
{
562
return "u_lod";
563
}
564
565
namespace vs
566
{
567
568
// A shader that sets gl_Position to zero.
569
const char *Zero()
570
{
571
return R"(#version 300 es
572
void main()
573
{
574
gl_Position = vec4(0);
575
})";
576
}
577
578
// A shader that sets gl_Position to attribute a_position.
579
const char *Simple()
580
{
581
return R"(#version 300 es
582
in vec4 a_position;
583
void main()
584
{
585
gl_Position = a_position;
586
})";
587
}
588
589
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
590
// v_position.
591
const char *Passthrough()
592
{
593
return R"(#version 300 es
594
in vec4 a_position;
595
out vec4 v_position;
596
void main()
597
{
598
gl_Position = a_position;
599
v_position = a_position;
600
})";
601
}
602
603
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
604
// texcoord.
605
const char *Texture2DLod()
606
{
607
return R"(#version 300 es
608
in vec4 a_position;
609
out vec2 v_texCoord;
610
611
void main()
612
{
613
gl_Position = vec4(a_position.xy, 0.0, 1.0);
614
v_texCoord = a_position.xy * 0.5 + vec2(0.5);
615
})";
616
}
617
618
} // namespace vs
619
620
namespace fs
621
{
622
623
// A shader that fills with 100% opaque red.
624
const char *Red()
625
{
626
return R"(#version 300 es
627
precision highp float;
628
out vec4 my_FragColor;
629
void main()
630
{
631
my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
632
})";
633
}
634
635
// A shader that fills with 100% opaque green.
636
const char *Green()
637
{
638
return R"(#version 300 es
639
precision highp float;
640
out vec4 my_FragColor;
641
void main()
642
{
643
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
644
})";
645
}
646
647
// A shader that fills with 100% opaque blue.
648
const char *Blue()
649
{
650
return R"(#version 300 es
651
precision highp float;
652
out vec4 my_FragColor;
653
void main()
654
{
655
my_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
656
})";
657
}
658
659
// A shader that samples the texture at a given lod.
660
const char *Texture2DLod()
661
{
662
return R"(#version 300 es
663
precision mediump float;
664
uniform sampler2D u_tex2D;
665
uniform float u_lod;
666
in vec2 v_texCoord;
667
out vec4 my_FragColor;
668
669
void main()
670
{
671
my_FragColor = textureLod(u_tex2D, v_texCoord, u_lod);
672
})";
673
}
674
675
} // namespace fs
676
} // namespace essl3_shaders
677
678
namespace essl31_shaders
679
{
680
681
const char *PositionAttrib()
682
{
683
return "a_position";
684
}
685
686
namespace vs
687
{
688
689
// A shader that sets gl_Position to zero.
690
const char *Zero()
691
{
692
return R"(#version 310 es
693
void main()
694
{
695
gl_Position = vec4(0);
696
})";
697
}
698
699
// A shader that sets gl_Position to attribute a_position.
700
const char *Simple()
701
{
702
return R"(#version 310 es
703
in vec4 a_position;
704
void main()
705
{
706
gl_Position = a_position;
707
})";
708
}
709
710
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
711
// v_position.
712
const char *Passthrough()
713
{
714
return R"(#version 310 es
715
in vec4 a_position;
716
out vec4 v_position;
717
void main()
718
{
719
gl_Position = a_position;
720
v_position = a_position;
721
})";
722
}
723
724
} // namespace vs
725
726
namespace fs
727
{
728
729
// A shader that fills with 100% opaque red.
730
const char *Red()
731
{
732
return R"(#version 310 es
733
precision highp float;
734
out vec4 my_FragColor;
735
void main()
736
{
737
my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
738
})";
739
}
740
741
// A shader that fills with 100% opaque green.
742
const char *Green()
743
{
744
return R"(#version 310 es
745
precision highp float;
746
out vec4 my_FragColor;
747
void main()
748
{
749
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
750
})";
751
}
752
753
// A shader that renders a simple gradient of red to green. Needs varying v_position.
754
const char *RedGreenGradient()
755
{
756
return R"(#version 310 es
757
precision highp float;
758
in vec4 v_position;
759
out vec4 my_FragColor;
760
761
void main()
762
{
763
my_FragColor = vec4(v_position.xy * 0.5 + vec2(0.5), 0.0, 1.0);
764
})";
765
}
766
767
} // namespace fs
768
} // namespace essl31_shaders
769
} // namespace angle
770
771