CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/GPU/ShaderWriter.cpp
Views: 1401
1
#include <cstdarg>
2
#include <cstdio>
3
#include <cstring>
4
5
#include "Common/GPU/Shader.h"
6
#include "Common/GPU/ShaderWriter.h"
7
#include "Common/Log.h"
8
9
const char * const vulkan_glsl_preamble_fs =
10
"#extension GL_ARB_separate_shader_objects : enable\n"
11
"#extension GL_ARB_shading_language_420pack : enable\n"
12
"#extension GL_ARB_conservative_depth : enable\n"
13
"#extension GL_ARB_shader_image_load_store : enable\n"
14
"#define splat3(x) vec3(x)\n"
15
"#define DISCARD discard\n"
16
"precision lowp float;\n"
17
"precision highp int;\n"
18
"\n";
19
20
const char * const hlsl_preamble_fs =
21
"#define vec2 float2\n"
22
"#define vec3 float3\n"
23
"#define vec4 float4\n"
24
"#define uvec3 uint3\n"
25
"#define uvec4 uint4\n"
26
"#define ivec2 int2\n"
27
"#define ivec3 int3\n"
28
"#define ivec4 int4\n"
29
"#define mat4 float4x4\n"
30
"#define mat3x4 float4x3\n" // note how the conventions are backwards
31
"#define splat3(x) float3(x, x, x)\n"
32
"#define mix lerp\n"
33
"#define lowp\n"
34
"#define mediump\n"
35
"#define highp\n"
36
"#define fract frac\n"
37
"#define mod(x, y) fmod(x, y)\n";
38
39
static const char * const hlsl_d3d11_preamble_fs =
40
"#define DISCARD discard\n"
41
"#define DISCARD_BELOW(x) clip(x);\n";
42
static const char * const hlsl_d3d9_preamble_fs =
43
"#define DISCARD clip(-1)\n"
44
"#define DISCARD_BELOW(x) clip(x)\n";
45
46
static const char * const vulkan_glsl_preamble_vs =
47
"#extension GL_ARB_separate_shader_objects : enable\n"
48
"#extension GL_ARB_shading_language_420pack : enable\n"
49
"#define mul(x, y) ((x) * (y))\n"
50
"#define splat3(x) vec3(x)\n"
51
"precision highp float;\n"
52
"\n";
53
54
static const char * const hlsl_preamble_gs =
55
"#define vec2 float2\n"
56
"#define vec3 float3\n"
57
"#define vec4 float4\n"
58
"#define ivec2 int2\n"
59
"#define ivec4 int4\n"
60
"#define mat2 float2x2\n"
61
"#define mat4 float4x4\n"
62
"#define mat3x4 float4x3\n" // note how the conventions are backwards
63
"#define splat3(x) vec3(x, x, x)\n"
64
"#define lowp\n"
65
"#define mediump\n"
66
"#define highp\n"
67
"\n";
68
69
static const char * const vulkan_glsl_preamble_gs =
70
"#extension GL_ARB_separate_shader_objects : enable\n"
71
"#extension GL_ARB_shading_language_420pack : enable\n"
72
"#define mul(x, y) ((x) * (y))\n"
73
"#define splat3(x) vec3(x)\n"
74
"precision highp float;\n"
75
"\n";
76
77
static const char * const hlsl_preamble_vs =
78
"#define vec2 float2\n"
79
"#define vec3 float3\n"
80
"#define vec4 float4\n"
81
"#define ivec2 int2\n"
82
"#define ivec4 int4\n"
83
"#define mat2 float2x2\n"
84
"#define mat4 float4x4\n"
85
"#define mat3x4 float4x3\n" // note how the conventions are backwards
86
"#define splat3(x) vec3(x, x, x)\n"
87
"#define lowp\n"
88
"#define mediump\n"
89
"#define highp\n"
90
"\n";
91
92
static const char * const semanticNames[] = {
93
"POSITION",
94
"COLOR0",
95
"COLOR1",
96
"TEXCOORD0",
97
"TEXCOORD1",
98
"NORMAL",
99
"TANGENT",
100
"BINORMAL",
101
};
102
static_assert(ARRAY_SIZE(semanticNames) == Draw::SEM_MAX, "Missing semantic in semanticNames");
103
104
// Unsafe. But doesn't matter, we'll use big buffers for shader gen.
105
ShaderWriter & ShaderWriter::F(const char *format, ...) {
106
va_list args;
107
va_start(args, format);
108
p_ += vsprintf(p_, format, args);
109
va_end(args);
110
return *this;
111
}
112
113
void ShaderWriter::Preamble(Slice<const char *> extensions) {
114
switch (lang_.shaderLanguage) {
115
case GLSL_VULKAN:
116
C("#version 450\n");
117
if (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) {
118
C("#extension GL_EXT_multiview : enable\n");
119
}
120
// IMPORTANT! Extensions must be the first thing after #version.
121
for (size_t i = 0; i < extensions.size(); i++) {
122
F("%s\n", extensions[i]);
123
}
124
switch (stage_) {
125
case ShaderStage::Vertex:
126
W(vulkan_glsl_preamble_vs);
127
break;
128
case ShaderStage::Fragment:
129
W(vulkan_glsl_preamble_fs);
130
break;
131
case ShaderStage::Geometry:
132
W(vulkan_glsl_preamble_gs);
133
break;
134
default:
135
break;
136
}
137
break;
138
case HLSL_D3D11:
139
case HLSL_D3D9:
140
switch (stage_) {
141
case ShaderStage::Vertex:
142
W(hlsl_preamble_vs);
143
break;
144
case ShaderStage::Fragment:
145
W(hlsl_preamble_fs);
146
if (lang_.shaderLanguage == HLSL_D3D9) {
147
W(hlsl_d3d9_preamble_fs);
148
} else {
149
W(hlsl_d3d11_preamble_fs);
150
}
151
break;
152
case ShaderStage::Geometry:
153
W(hlsl_preamble_gs);
154
break;
155
default:
156
break;
157
}
158
break;
159
default: // OpenGL
160
F("#version %d%s\n", lang_.glslVersionNumber, lang_.gles && lang_.glslES30 ? " es" : "");
161
// IMPORTANT! Extensions must be the first thing after #version.
162
for (size_t i = 0; i < extensions.size(); i++) {
163
F("%s\n", extensions[i]);
164
}
165
// Print some system info - useful to gather information directly from screenshots.
166
if (strlen(lang_.driverInfo) != 0) {
167
F("// Driver: %s\n", lang_.driverInfo);
168
}
169
switch (stage_) {
170
case ShaderStage::Fragment:
171
C("#define DISCARD discard\n");
172
if (lang_.gles) {
173
C("precision lowp float;\n");
174
if (lang_.glslES30) {
175
C("precision highp int;\n");
176
}
177
}
178
break;
179
case ShaderStage::Vertex:
180
if (lang_.gles) {
181
C("precision highp float;\n");
182
}
183
C("#define gl_VertexIndex gl_VertexID\n");
184
break;
185
case ShaderStage::Geometry:
186
if (lang_.gles) {
187
C("precision highp float;\n");
188
}
189
break;
190
default:
191
break;
192
}
193
if (!lang_.gles) {
194
C("#define lowp\n");
195
C("#define mediump\n");
196
C("#define highp\n");
197
}
198
C("#define splat3(x) vec3(x)\n");
199
C("#define mul(x, y) ((x) * (y))\n");
200
break;
201
}
202
}
203
204
void ShaderWriter::BeginVSMain(Slice<InputDef> inputs, Slice<UniformDef> uniforms, Slice<VaryingDef> varyings) {
205
_assert_(this->stage_ == ShaderStage::Vertex);
206
switch (lang_.shaderLanguage) {
207
case HLSL_D3D11:
208
case HLSL_D3D9:
209
{
210
C("struct VS_OUTPUT {\n");
211
for (auto &varying : varyings) {
212
F(" %s %s : %s;\n", varying.type, varying.name, semanticNames[varying.semantic]);
213
}
214
F(" vec4 pos : %s;\n", lang_.shaderLanguage == HLSL_D3D11 ? "SV_Position" : "POSITION");
215
C("};\n");
216
217
C("VS_OUTPUT main( "); // 2 spaces for the rewind
218
if (lang_.shaderLanguage == HLSL_D3D11) {
219
C("uint gl_VertexIndex : SV_VertexID, ");
220
}
221
// List the inputs.
222
for (auto &input : inputs) {
223
F("in %s %s : %s, ", input.type, input.name, semanticNames[input.semantic]);
224
}
225
226
Rewind(2); // Get rid of the last comma.
227
C(") {\n");
228
C(" vec4 gl_Position;\n");
229
for (auto &varying : varyings) {
230
F(" %s %s; // %s\n", varying.type, varying.name, semanticNames[varying.semantic]);
231
}
232
break;
233
}
234
case GLSL_VULKAN:
235
{
236
for (auto &input : inputs) {
237
F("layout(location = %d) in %s %s;\n", input.semantic /*index*/, input.type, input.name);
238
}
239
for (auto &varying : varyings) {
240
F("layout(location = %d) %s out %s %s; // %s\n",
241
varying.index, varying.precision ? varying.precision : "", varying.type, varying.name, semanticNames[varying.semantic]);
242
}
243
C("void main() {\n");
244
break;
245
}
246
default: // OpenGL
247
for (auto &input : inputs) {
248
F("%s %s %s;\n", lang_.attribute, input.type, input.name);
249
}
250
for (auto &varying : varyings) {
251
F("%s %s %s %s; // %s (%d)\n", lang_.varying_vs, varying.precision ? varying.precision : "", varying.type, varying.name, semanticNames[varying.semantic], varying.index);
252
}
253
C("void main() {\n");
254
break;
255
}
256
}
257
258
void ShaderWriter::BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> varyings) {
259
_assert_(this->stage_ == ShaderStage::Fragment);
260
switch (lang_.shaderLanguage) {
261
case HLSL_D3D11:
262
if (!uniforms.is_empty()) {
263
C("cbuffer base : register(b0) {\n");
264
265
for (auto &uniform : uniforms) {
266
F(" %s %s;\n", uniform.type, uniform.name);
267
}
268
269
C("};\n");
270
}
271
272
if (flags_ & ShaderWriterFlags::FS_WRITE_DEPTH) {
273
C("float gl_FragDepth;\n");
274
}
275
276
C("struct PS_OUT {\n");
277
C(" vec4 target : SV_Target0;\n");
278
if (flags_ & ShaderWriterFlags::FS_WRITE_DEPTH) {
279
C(" float depth : SV_Depth;\n");
280
}
281
C("};\n");
282
283
// Let's do the varyings as parameters to main, no struct.
284
C("PS_OUT main(");
285
for (auto &varying : varyings) {
286
F(" %s %s : %s, ", varying.type, varying.name, semanticNames[varying.semantic]);
287
}
288
// Erase the last comma
289
Rewind(2);
290
291
F(") {\n");
292
C(" PS_OUT ps_out;\n");
293
if (flags_ & ShaderWriterFlags::FS_WRITE_DEPTH) {
294
C(" float gl_FragDepth;\n");
295
}
296
break;
297
case HLSL_D3D9:
298
C("struct PS_OUT {\n");
299
C(" vec4 target : SV_Target0;\n");
300
if (flags_ & ShaderWriterFlags::FS_WRITE_DEPTH) {
301
C(" float depth : DEPTH;\n");
302
}
303
C("};\n");
304
305
for (auto &uniform : uniforms) {
306
F(" %s %s : register(c%d);\n", uniform.type, uniform.name, uniform.index);
307
}
308
// Let's do the varyings as parameters to main, no struct.
309
C("PS_OUT main(");
310
for (auto &varying : varyings) {
311
F(" %s %s : %s, ", varying.type, varying.name, semanticNames[varying.semantic]);
312
}
313
// Erase the last comma
314
Rewind(2);
315
316
F(") {\n");
317
C(" PS_OUT ps_out;\n");
318
if (flags_ & ShaderWriterFlags::FS_WRITE_DEPTH) {
319
C(" float gl_FragDepth;\n");
320
}
321
322
break;
323
case GLSL_VULKAN:
324
for (auto &varying : varyings) {
325
F("layout(location = %d) %s in %s %s; // %s\n", varying.index, varying.precision ? varying.precision : "", varying.type, varying.name, semanticNames[varying.semantic]);
326
}
327
C("layout(location = 0, index = 0) out vec4 fragColor0;\n");
328
if (!uniforms.is_empty()) {
329
C("layout(std140, set = 0, binding = 0) uniform bufferVals {\n");
330
for (auto &uniform : uniforms) {
331
F("%s %s;\n", uniform.type, uniform.name);
332
}
333
C("};\n");
334
}
335
C("\nvoid main() {\n");
336
break;
337
338
default: // GLSL OpenGL
339
for (auto &varying : varyings) {
340
F("%s %s %s %s; // %s\n", lang_.varying_fs, varying.precision ? varying.precision : "", varying.type, varying.name, semanticNames[varying.semantic]);
341
}
342
for (auto &uniform : uniforms) {
343
F("uniform %s %s;\n", uniform.type, uniform.name);
344
}
345
if (!strcmp(lang_.fragColor0, "fragColor0")) {
346
C("out vec4 fragColor0;\n");
347
}
348
C("\nvoid main() {\n");
349
break;
350
}
351
}
352
353
void ShaderWriter::BeginGSMain(Slice<VaryingDef> varyings, Slice<VaryingDef> outVaryings) {
354
_assert_(this->stage_ == ShaderStage::Geometry);
355
switch (lang_.shaderLanguage) {
356
case HLSL_D3D11:
357
// Untested, but should work.
358
C("\nstruct GS_OUTPUT {\n");
359
for (auto &varying : outVaryings) {
360
F(" %s %s : %s;\n", varying.type, varying.name, semanticNames[varying.semantic]);
361
}
362
F(" vec4 pos : %s;\n", lang_.shaderLanguage == HLSL_D3D11 ? "SV_Position" : "POSITION");
363
C("};\n");
364
C("#define EmitVertex() emit.Append(gsout)\n");
365
366
C("void main(");
367
for (auto &varying : varyings) {
368
F(" in %s %s : %s, ", varying.type, varying.name, semanticNames[varying.semantic]);
369
}
370
C("inout TriangleStream<GS_OUTPUT> emit) {\n");
371
C(" GS_OUTPUT gsout;\n");
372
break;
373
case GLSL_VULKAN:
374
for (auto &varying : varyings) {
375
F("layout(location = %d) %s in %s %s[]; // %s\n", varying.index, varying.precision ? varying.precision : "", varying.type, varying.name, semanticNames[varying.semantic]);
376
}
377
for (auto &varying : outVaryings) {
378
F("layout(location = %d) %s out %s %s; // %s\n", varying.index, varying.precision ? varying.precision : "", varying.type, varying.name, semanticNames[varying.semantic]);
379
}
380
C("\nvoid main() {\n");
381
break;
382
case GLSL_3xx:
383
C("\nvoid main() {\n");
384
break;
385
default:
386
break;
387
}
388
}
389
390
void ShaderWriter::EndVSMain(Slice<VaryingDef> varyings) {
391
_assert_(this->stage_ == ShaderStage::Vertex);
392
switch (lang_.shaderLanguage) {
393
case HLSL_D3D11:
394
case HLSL_D3D9:
395
C(" VS_OUTPUT vs_out;\n");
396
if (strlen(lang_.viewportYSign)) {
397
F(" gl_Position.y *= %s1.0;\n", lang_.viewportYSign);
398
}
399
C(" vs_out.pos = gl_Position;\n");
400
for (auto &varying : varyings) {
401
F(" vs_out.%s = %s;\n", varying.name, varying.name);
402
}
403
C(" return vs_out;\n");
404
break;
405
case GLSL_VULKAN:
406
default: // OpenGL
407
break;
408
}
409
C("}\n");
410
}
411
412
void ShaderWriter::EndFSMain(const char *vec4_color_variable) {
413
_assert_(this->stage_ == ShaderStage::Fragment);
414
switch (lang_.shaderLanguage) {
415
case HLSL_D3D11:
416
case HLSL_D3D9:
417
F(" ps_out.target = %s;\n", vec4_color_variable);
418
if (flags_ & ShaderWriterFlags::FS_WRITE_DEPTH) {
419
C(" ps_out.depth = gl_FragDepth;\n");
420
}
421
C(" return ps_out;\n");
422
break;
423
case GLSL_VULKAN:
424
default: // OpenGL
425
F(" %s = %s;\n", lang_.fragColor0, vec4_color_variable);
426
break;
427
}
428
C("}\n");
429
}
430
431
void ShaderWriter::EndGSMain() {
432
_assert_(this->stage_ == ShaderStage::Geometry);
433
C("}\n");
434
}
435
436
void ShaderWriter::HighPrecisionFloat() {
437
if ((ShaderLanguageIsOpenGL(lang_.shaderLanguage) && lang_.gles) || lang_.shaderLanguage == GLSL_VULKAN) {
438
C("precision highp float;\n");
439
}
440
}
441
442
void ShaderWriter::LowPrecisionFloat() {
443
if ((ShaderLanguageIsOpenGL(lang_.shaderLanguage) && lang_.gles) || lang_.shaderLanguage == GLSL_VULKAN) {
444
C("precision lowp float;\n");
445
}
446
}
447
448
void ShaderWriter::ConstFloat(const char *name, float value) {
449
switch (lang_.shaderLanguage) {
450
case HLSL_D3D11:
451
case HLSL_D3D9:
452
F("static const float %s = %f;\n", name, value);
453
break;
454
default:
455
F("#define %s %f\n", name, value);
456
break;
457
}
458
}
459
460
void ShaderWriter::DeclareSamplers(Slice<SamplerDef> samplers) {
461
for (int i = 0; i < (int)samplers.size(); i++) {
462
DeclareTexture2D(samplers[i]);
463
DeclareSampler2D(samplers[i]);
464
}
465
samplerDefs_ = samplers;
466
}
467
468
void ShaderWriter::ApplySamplerMetadata(Slice<SamplerDef> samplers) {
469
samplerDefs_ = samplers;
470
}
471
472
void ShaderWriter::DeclareTexture2D(const SamplerDef &def) {
473
switch (lang_.shaderLanguage) {
474
case HLSL_D3D11:
475
F("Texture2D<float4> %s : register(t%d);\n", def.name, def.binding);
476
break;
477
case HLSL_D3D9:
478
F("sampler %s: register(s%d);\n", def.name, def.binding);
479
break;
480
case GLSL_VULKAN:
481
// texBindingBase_ is used for the thin3d descriptor set layout, where they start at 1.
482
if (def.flags & SamplerFlags::ARRAY_ON_VULKAN) {
483
F("layout(set = 0, binding = %d) uniform sampler2DArray %s;\n", def.binding + texBindingBase_, def.name);
484
} else {
485
F("layout(set = 0, binding = %d) uniform sampler2D %s;\n", def.binding + texBindingBase_, def.name);
486
}
487
break;
488
default:
489
F("uniform sampler2D %s;\n", def.name);
490
break;
491
}
492
}
493
494
void ShaderWriter::DeclareSampler2D(const SamplerDef &def) {
495
// We only use separate samplers in HLSL D3D11, where we have no choice.
496
switch (lang_.shaderLanguage) {
497
case HLSL_D3D11:
498
F("SamplerState %sSamp : register(s%d);\n", def.name, def.binding);
499
break;
500
default:
501
break;
502
}
503
}
504
505
ShaderWriter &ShaderWriter::SampleTexture2D(const char *sampName, const char *uv) {
506
const SamplerDef *samp = GetSamplerDef(sampName);
507
switch (lang_.shaderLanguage) {
508
case HLSL_D3D11:
509
F("%s.Sample(%sSamp, %s)", sampName, sampName, uv);
510
break;
511
case HLSL_D3D9:
512
F("tex2D(%s, %s)", sampName, uv);
513
break;
514
default:
515
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
516
if (samp && (samp->flags & SamplerFlags::ARRAY_ON_VULKAN) && lang_.shaderLanguage == GLSL_VULKAN) {
517
const char *index = (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) ? "float(gl_ViewIndex)" : "0.0";
518
F("%s(%s, vec3(%s, %s))", lang_.texture, sampName, uv, index);
519
} else {
520
F("%s(%s, %s)", lang_.texture, sampName, uv);
521
}
522
break;
523
}
524
return *this;
525
}
526
527
ShaderWriter &ShaderWriter::SampleTexture2DOffset(const char *sampName, const char *uv, int offX, int offY) {
528
const SamplerDef *samp = GetSamplerDef(sampName);
529
530
switch (lang_.shaderLanguage) {
531
case HLSL_D3D11:
532
F("%s.Sample(%sSamp, %s, int2(%d, %d))", sampName, sampName, uv, offX, offY);
533
break;
534
case HLSL_D3D9:
535
// Not supported, we do a normal sample here to not crash or something
536
F("tex2D(%s, %s)", sampName, uv);
537
break;
538
default:
539
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
540
if (samp && (samp->flags & SamplerFlags::ARRAY_ON_VULKAN) && lang_.shaderLanguage == GLSL_VULKAN) {
541
const char *index = (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) ? "float(gl_ViewIndex)" : "0.0";
542
F("%sOffset(%s, vec3(%s, %s), ivec2(%d, %d))", lang_.texture, sampName, uv, index, offX, offY);
543
} else {
544
F("%sOffset(%s, %s, ivec2(%d, %d))", lang_.texture, sampName, uv, offX, offY);
545
}
546
break;
547
}
548
return *this;
549
}
550
551
ShaderWriter &ShaderWriter::LoadTexture2D(const char *sampName, const char *uv, int level) {
552
const SamplerDef *samp = GetSamplerDef(sampName);
553
554
switch (lang_.shaderLanguage) {
555
case HLSL_D3D11:
556
F("%s.Load(ivec3(%s, %d))", sampName, uv, level);
557
break;
558
case HLSL_D3D9:
559
// Not supported, we return a bad value
560
C("float4(1.0, 0.0, 1.0, 1.0)");
561
break;
562
default:
563
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
564
if (samp && (samp->flags & SamplerFlags::ARRAY_ON_VULKAN) && lang_.shaderLanguage == GLSL_VULKAN) {
565
const char *index = (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) ? "gl_ViewIndex" : "0";
566
F("texelFetch(%s, vec3(%s, %s), %d)", sampName, uv, index, level);
567
} else {
568
F("texelFetch(%s, %s, %d)", sampName, uv, level);
569
}
570
break;
571
}
572
return *this;
573
}
574
575
ShaderWriter &ShaderWriter::GetTextureSize(const char *szVariable, const char *texName) {
576
switch (lang_.shaderLanguage) {
577
case HLSL_D3D11:
578
F(" float2 %s; %s.GetDimensions(%s.x, %s.y);", szVariable, texName, szVariable, szVariable);
579
break;
580
case HLSL_D3D9:
581
F(" float2 %s; %s.GetDimensions(%s.x, %s.y);", szVariable, texName, szVariable, szVariable);
582
break;
583
default:
584
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
585
F("vec2 %s = textureSize(%s, 0);", szVariable, texName);
586
break;
587
}
588
return *this;
589
}
590
591
const SamplerDef *ShaderWriter::GetSamplerDef(const char *name) const {
592
for (int i = 0; i < (int)samplerDefs_.size(); i++) {
593
if (!strcmp(samplerDefs_[i].name, name)) {
594
return &samplerDefs_[i];
595
}
596
}
597
return nullptr;
598
}
599
600