Harbor

Changelog 7a40f9b3a832

pin opengl shader target

@sky · 1 month ago · parent 5e9b900f204c
22 added 9 modified 0 deleted
gpu/backend/backend.odin +1 -0 modified
120 unchanged lines hidden
121 121 Shader_Format :: enum {
122 122 SPIRV,
123 123 HLSL,
124 + GLSL,
124 125 }
125 126
126 127 Shader_Module_Desc :: struct {
348 unchanged lines hidden
gpu/backend/select.odin +4 -0 modified
5 unchanged lines hidden
6 6 REQUIRED_SHADER_FORMAT :: Shader_Format.SPIRV
7 7 } else when GPU_BACKEND == "d3d11" || GPU_BACKEND == "d3d12" {
8 8 REQUIRED_SHADER_FORMAT :: Shader_Format.HLSL
9 + } else when GPU_BACKEND == "opengl" {
10 + REQUIRED_SHADER_FORMAT :: Shader_Format.GLSL
11 + } else {
12 + #assert(false, "unsupported GPU_BACKEND")
9 13 }
gpu/compiler/executor.odin modified

Diff hidden because this file has more than 800 lines.

gpu/shader/emit_glsl.odin +66 -10 modified
4 unchanged lines hidden
5 5
6 6 // GLSL 450 backend — emits from IR_Module
7 7
8 + Glsl_Flavor :: enum {
9 + Vulkan,
10 + OpenGL,
11 + }
12 +
13 + Glsl_Options :: struct {
14 + flavor: Glsl_Flavor,
15 + }
16 +
17 + GLSL_OPENGL_BINDINGS_PER_GROUP :: 16
18 + GLSL_OPENGL_PUSH_CONSTANT_BINDING :: 15
19 +
8 20 Glsl_Emitter :: struct {
9 21 w: Writer,
10 22 module: ^IR_Module,
11 23 current_fn: ^IR_Function,
12 24 diagnostics: [dynamic]Diagnostic,
25 + flavor: Glsl_Flavor,
13 26 }
14 27
15 28 emit_glsl :: proc(module: ^IR_Module, allocator := context.allocator) -> (string, []Diagnostic) {
29 + return emit_glsl_with_options(module, {}, allocator)
30 + }
31 +
32 + emit_glsl_opengl :: proc(module: ^IR_Module, allocator := context.allocator) -> (string, []Diagnostic) {
33 + return emit_glsl_with_options(module, {flavor = .OpenGL}, allocator)
34 + }
35 +
36 + @(private = "file")
37 + emit_glsl_with_options :: proc(module: ^IR_Module, options: Glsl_Options, allocator := context.allocator) -> (string, []Diagnostic) {
16 38 e := Glsl_Emitter{
17 39 w = writer_init(allocator),
18 40 module = module,
19 41 diagnostics = make([dynamic]Diagnostic, allocator),
42 + flavor = options.flavor,
20 43 }
21 44
22 45 write_line(&e.w, "#version 450")
1 unchanged lines hidden
24 47
25 48 // Specialization constants
26 49 for &sc in module.spec_constants {
27 - // layout(constant_id = N) const type name = default;
28 - write_line(&e.w, "layout(constant_id = ", sc.spec_id, ") const ", resolved_type_to_glsl(sc.type), " ", sc.name, " = ", ir_const_value_to_string(sc.default_value), ";")
50 + if e.flavor == .OpenGL {
51 + write_line(&e.w, "const ", resolved_type_to_glsl(sc.type), " ", sc.name, " = ", ir_const_value_to_string(sc.default_value), ";")
52 + } else {
53 + // layout(constant_id = N) const type name = default;
54 + write_line(&e.w, "layout(constant_id = ", sc.spec_id, ") const ", resolved_type_to_glsl(sc.type), " ", sc.name, " = ", ir_const_value_to_string(sc.default_value), ";")
55 + }
29 56 }
30 57 if len(module.spec_constants) > 0 {
31 58 write_line(&e.w, "")
31 unchanged lines hidden
63 90 emit_glsl_binding :: proc(e: ^Glsl_Emitter, b: ^IR_Binding) {
64 91 switch b.kind {
65 92 case .Texture:
66 - // GLSL 450 uses combined samplers — emit as sampler2D with the original name
67 - write_line(&e.w, "layout(set = ", b.group, ", binding = ", b.binding_num, ") uniform ", resolved_type_to_glsl(b.type), " ", b.combined_name, ";")
93 + if e.flavor == .OpenGL {
94 + binding := glsl_opengl_binding_point(b)
95 + write_line(&e.w, "layout(binding = ", binding, ") uniform ", resolved_type_to_glsl(b.type), " ", b.combined_name, ";")
96 + } else {
97 + // GLSL 450 uses combined samplers — emit as sampler2D with the original name
98 + write_line(&e.w, "layout(set = ", b.group, ", binding = ", b.binding_num, ") uniform ", resolved_type_to_glsl(b.type), " ", b.combined_name, ";")
99 + }
68 100 case .Sampler:
69 101 // Skip — already emitted by the Texture binding as a combined sampler
70 102 return
71 103 case .Uniform:
72 - write_line(&e.w, "layout(set = ", b.group, ", binding = ", b.binding_num, ") uniform ", b.name, "_Block {")
104 + if e.flavor == .OpenGL {
105 + binding := glsl_opengl_binding_point(b)
106 + if binding == GLSL_OPENGL_PUSH_CONSTANT_BINDING {
107 + append(&e.diagnostics, Diagnostic{level = .Error, message = fmt.aprintf("GLSL OpenGL: uniform binding for '%s' collides with reserved push-constant binding %d", b.name, GLSL_OPENGL_PUSH_CONSTANT_BINDING)})
108 + }
109 + write_line(&e.w, "layout(std140, binding = ", binding, ") uniform ", b.name, "_Block {")
110 + } else {
111 + write_line(&e.w, "layout(set = ", b.group, ", binding = ", b.binding_num, ") uniform ", b.name, "_Block {")
112 + }
73 113 indent(&e.w)
74 114 if b.struct_ref != nil {
75 115 for f in b.struct_ref.fields {
13 unchanged lines hidden
89 129 write_line(&e.w, "};")
90 130 }
91 131 case .Buffer:
92 - write_line(&e.w, "layout(set = ", b.group, ", binding = ", b.binding_num, ") buffer ", b.name, "_Block {")
132 + if e.flavor == .OpenGL {
133 + binding := glsl_opengl_binding_point(b)
134 + write_line(&e.w, "layout(std430, binding = ", binding, ") buffer ", b.name, "_Block {")
135 + } else {
136 + write_line(&e.w, "layout(set = ", b.group, ", binding = ", b.binding_num, ") buffer ", b.name, "_Block {")
137 + }
93 138 if b.struct_ref != nil {
94 139 indent(&e.w)
95 140 for f in b.struct_ref.fields {
4 unchanged lines hidden
100 145 }
101 146 write_line(&e.w, "} ", b.name, ";")
102 147 case .Push_Constant:
103 - write_line(&e.w, "layout(push_constant) uniform ", b.name, "_Block {")
148 + if e.flavor == .OpenGL {
149 + write_line(&e.w, "layout(std140, binding = ", GLSL_OPENGL_PUSH_CONSTANT_BINDING, ") uniform ", b.name, "_Block {")
150 + } else {
151 + write_line(&e.w, "layout(push_constant) uniform ", b.name, "_Block {")
152 + }
104 153 if b.struct_ref != nil {
105 154 indent(&e.w)
106 155 for f in b.struct_ref.fields {
118 unchanged lines hidden
225 274 io := fn.outputs[s.io_index]
226 275 out_name: string
227 276 if io.builtin != "" {
228 - out_name = builtin_to_glsl_variable(io.builtin, fn.stage, false)
277 + out_name = builtin_to_glsl_variable(io.builtin, fn.stage, false, e.flavor)
229 278 } else {
230 279 out_name = fmt.aprintf("out_%s", io.name)
231 280 }
184 unchanged lines hidden
416 465
417 466 case ^IR_Builtin_Var:
418 467 fn := e.current_fn
419 - write(&e.w, builtin_to_glsl_variable(d.name, fn != nil ? fn.stage : .None, d.is_input))
468 + write(&e.w, builtin_to_glsl_variable(d.name, fn != nil ? fn.stage : .None, d.is_input, e.flavor))
420 469
421 470 case ^IR_Shared_Ref:
422 471 write(&e.w, d.name)
33 unchanged lines hidden
456 505 return "?"
457 506 }
458 507
459 - builtin_to_glsl_variable :: proc(name: string, stage: Shader_Stage, is_input: bool) -> string {
508 + builtin_to_glsl_variable :: proc(name: string, stage: Shader_Stage, is_input: bool, flavor: Glsl_Flavor = .Vulkan) -> string {
460 509 switch name {
461 510 case "position":
462 511 if stage == .Vertex && !is_input do return "gl_Position"
463 512 if stage == .Fragment && is_input do return "gl_FragCoord"
464 513 return "gl_Position"
465 514 case "vertex_id":
515 + if flavor == .OpenGL do return "gl_VertexID"
466 516 return "gl_VertexIndex"
467 517 case "instance_id":
518 + if flavor == .OpenGL do return "gl_InstanceID"
468 519 return "gl_InstanceIndex"
469 520 case "frag_coord":
470 521 return "gl_FragCoord"
11 unchanged lines hidden
482 533 return name
483 534 }
484 535
536 + glsl_opengl_binding_point :: proc(binding: ^IR_Binding) -> int {
537 + if binding == nil do return 0
538 + return binding.group * GLSL_OPENGL_BINDINGS_PER_GROUP + binding.binding_num
539 + }
540 +
485 541 builtin_to_glsl :: proc(name: string) -> string {
486 542 switch name {
487 543 case "sample": return "texture"
83 unchanged lines hidden
gpu/shader/luma.odin +5 -0 modified
6 unchanged lines hidden
7 7
8 8 Target :: enum {
9 9 GLSL_450,
10 + GLSL_450_OPENGL,
10 11 HLSL_SM6,
11 12 MSL_2_4,
12 13 WGSL,
173 unchanged lines hidden
186 187 str: string
187 188 str, emit_diags = emit_glsl(&ir_module)
188 189 output_bytes = transmute([]u8)str
190 + case .GLSL_450_OPENGL:
191 + str: string
192 + str, emit_diags = emit_glsl_opengl(&ir_module)
193 + output_bytes = transmute([]u8)str
189 194 case .WGSL:
190 195 str: string
191 196 str, emit_diags = emit_wgsl(&ir_module)
302 unchanged lines hidden
gpu/shader/tests/golden/basic_fragment.glsl-opengl +15 -0 added
1 + #version 450
2 +
3 + layout(binding = 0) uniform sampler2D material_tex;
4 +
5 + layout(location = 0) in vec2 in_uv;
6 + layout(location = 1) in vec3 in_normal;
7 + layout(location = 0) out vec4 out__value;
8 +
9 + void main() {
10 + vec4 albedo = texture(material_tex, in_uv);
11 + vec3 n = normalize(in_normal);
12 + vec3 light_dir = normalize(vec3(1.0, 1.0, 0.5));
13 + float light = max(dot(n, light_dir), 0.0);
14 + out__value = vec4((albedo.rgb * light), albedo.a);
15 + }
gpu/shader/tests/golden/basic_vertex.glsl-opengl +22 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform uniforms_Block {
4 + mat4 model;
5 + mat4 view_proj;
6 + mat4 normal_mat;
7 + } uniforms;
8 +
9 + layout(location = 0) in vec3 in_position;
10 + layout(location = 1) in vec3 in_normal;
11 + layout(location = 2) in vec2 in_uv;
12 + layout(location = 0) out vec2 out_uv;
13 + layout(location = 1) out vec3 out_normal;
14 +
15 + void main() {
16 + vec3 pos = in_position;
17 + vec4 world_pos = (uniforms.model * vec4(pos, 1.0));
18 + vec4 clip_pos = (uniforms.view_proj * world_pos);
19 + gl_Position = clip_pos;
20 + out_uv = in_uv;
21 + out_normal = normalize((uniforms.normal_mat * vec4(in_normal, 0.0)).xyz);
22 + }
gpu/shader/tests/golden/compute_basic.glsl-opengl +24 -0 added
1 + #version 450
2 +
3 + shared float scratch[64];
4 +
5 + layout(std430, binding = 0) buffer params_Block {
6 + uint count;
7 + float scale;
8 + } params;
9 + layout(std430, binding = 1) buffer data_Block {
10 + float values[64];
11 + } data;
12 +
13 + layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
14 +
15 + void main() {
16 + uint idx = gl_LocalInvocationID.x;
17 + scratch[idx] = (data.values[idx] * params.scale);
18 + barrier();
19 + if ((idx < 32)) {
20 + scratch[idx] = (scratch[idx] + scratch[(idx + 32)]);
21 + }
22 + barrier();
23 + data.values[idx] = scratch[idx];
24 + }
gpu/shader/tests/golden/derivatives_test.glsl-opengl +15 -0 added
1 + #version 450
2 +
3 + layout(binding = 0) uniform sampler2D albedo_tex;
4 +
5 + layout(location = 0) in vec2 in_uv;
6 + layout(location = 0) out vec4 out__value;
7 +
8 + void main() {
9 + vec4 color = texture(albedo_tex, in_uv);
10 + float dx = dFdx(color.r);
11 + float dy = dFdy(color.r);
12 + float fw = fwidth(color.r);
13 + float edge = step(0.1, fw);
14 + out__value = vec4((color.rgb * (1.0 - edge)), color.a);
15 + }
gpu/shader/tests/golden/discard_select.glsl-opengl +15 -0 added
1 + #version 450
2 +
3 + layout(binding = 0) uniform sampler2D albedo_tex;
4 +
5 + layout(location = 0) in vec2 in_uv;
6 + layout(location = 0) out vec4 out__value;
7 +
8 + void main() {
9 + vec4 color = texture(albedo_tex, in_uv);
10 + if ((color.a < 0.1)) {
11 + discard;
12 + }
13 + float bright = ((color.r > 0.5) ? 1.0 : 0.0);
14 + out__value = vec4((color.rgb * bright), color.a);
15 + }
gpu/shader/tests/golden/group_block.glsl-opengl +26 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform camera_Block {
4 + mat4 view_proj;
5 + vec3 position;
6 + } camera;
7 + layout(std140, binding = 1) uniform lighting_Block {
8 + vec3 direction;
9 + vec3 color;
10 + float intensity;
11 + } lighting;
12 + layout(binding = 16) uniform sampler2D diffuse_tex;
13 + layout(binding = 18) uniform sampler2D normal_tex;
14 +
15 + layout(location = 0) in vec2 in_uv;
16 + layout(location = 0) out vec4 out_color;
17 +
18 + void main() {
19 + vec4 diffuse = texture(diffuse_tex, in_uv);
20 + vec4 normal_sample = texture(normal_tex, in_uv);
21 + vec3 n = normalize(((normal_sample.xyz * 2.0) - vec3(1.0, 1.0, 1.0)));
22 + vec3 l = normalize(lighting.direction);
23 + float ndotl = max(dot(n, l), 0.0);
24 + vec3 lit = (((diffuse.rgb * lighting.color) * ndotl) * lighting.intensity);
25 + out_color = vec4(lit, diffuse.a);
26 + }
gpu/shader/tests/golden/inline_entry.glsl-opengl +12 -0 added
1 + #version 450
2 +
3 + layout(binding = 0) uniform sampler2D material_tex;
4 +
5 + layout(location = 0) in vec2 in_uv;
6 + layout(location = 1) in vec3 in_normal;
7 + layout(location = 0) out vec4 out_color;
8 +
9 + void main() {
10 + vec4 albedo = texture(material_tex, in_uv);
11 + out_color = vec4(albedo.rgb, 1.0);
12 + }
gpu/shader/tests/golden/loop_control.glsl-opengl +38 -0 added
1 + #version 450
2 +
3 + layout(location = 0) in float in_value;
4 + layout(location = 0) out vec4 out__value;
5 +
6 + void main() {
7 + float result = 0.0;
8 + for (int i = 0; i <= 10; i++) {
9 + if (((i % 2) == 0)) {
10 + continue;
11 + }
12 + result = (result + float(i));
13 + }
14 + float total = 0.0;
15 + for (int j = 0; j <= 100; j++) {
16 + if ((j > 5)) {
17 + break;
18 + }
19 + total = (total + 1.0);
20 + }
21 + int k = 0;
22 + while ((k < 100)) {
23 + if ((k > 10)) {
24 + break;
25 + }
26 + k = (k + 1);
27 + }
28 + float sum = 0.0;
29 + int m = 0;
30 + while ((m < 10)) {
31 + m = (m + 1);
32 + if ((m == 5)) {
33 + continue;
34 + }
35 + sum = (sum + 1.0);
36 + }
37 + out__value = vec4(((result + total) + sum), 0.0, 0.0, 1.0);
38 + }
gpu/shader/tests/golden/multi_binding.glsl-opengl +26 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform camera_Block {
4 + mat4 view_proj;
5 + vec3 position;
6 + } camera;
7 + layout(std140, binding = 1) uniform lighting_Block {
8 + vec3 direction;
9 + vec3 color;
10 + float intensity;
11 + } lighting;
12 + layout(binding = 16) uniform sampler2D diffuse_tex;
13 + layout(binding = 18) uniform sampler2D normal_tex;
14 +
15 + layout(location = 0) in vec2 in_uv;
16 + layout(location = 0) out vec4 out_color;
17 +
18 + void main() {
19 + vec4 diffuse = texture(diffuse_tex, in_uv);
20 + vec4 normal_sample = texture(normal_tex, in_uv);
21 + vec3 n = normalize(((normal_sample.xyz * 2.0) - vec3(1.0, 1.0, 1.0)));
22 + vec3 l = normalize(lighting.direction);
23 + float ndotl = max(dot(n, l), 0.0);
24 + vec3 lit = (((diffuse.rgb * lighting.color) * ndotl) * lighting.intensity);
25 + out_color = vec4(lit, diffuse.a);
26 + }
gpu/shader/tests/golden/pbr_fragment.glsl-opengl +44 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform material_Block {
4 + vec3 albedo;
5 + float metallic;
6 + float roughness;
7 + } material;
8 + layout(std140, binding = 1) uniform light_dir_Block {
9 + vec3 light_dir;
10 + };
11 + layout(std140, binding = 2) uniform camera_pos_Block {
12 + vec3 camera_pos;
13 + };
14 + layout(binding = 3) uniform sampler2D albedo_tex;
15 +
16 + vec3 fresnel_schlick(float cos_theta, vec3 f0) {
17 + return (f0 + ((vec3(1.0, 1.0, 1.0) - f0) * pow((1.0 - cos_theta), 5.0)));
18 + }
19 +
20 + vec3 compute_lighting(vec3 normal, vec3 view_dir, vec3 albedo) {
21 + vec3 n = normalize(normal);
22 + vec3 l = normalize(light_dir);
23 + vec3 h = normalize((l + view_dir));
24 + float ndotl = max(dot(n, l), 0.0);
25 + float ndoth = max(dot(n, h), 0.0);
26 + vec3 f0 = mix(vec3(0.04, 0.04, 0.04), albedo, material.metallic);
27 + vec3 f = fresnel_schlick(max(dot(h, view_dir), 0.0), f0);
28 + vec3 specular = (f * pow(ndoth, ((1.0 - material.roughness) * 256.0)));
29 + vec3 diffuse = ((albedo * ndotl) * (vec3(1.0, 1.0, 1.0) - f));
30 + return (diffuse + specular);
31 + }
32 +
33 + layout(location = 0) in vec2 in_uv;
34 + layout(location = 1) in vec3 in_normal;
35 + layout(location = 2) in vec3 in_world_pos;
36 + layout(location = 0) out vec4 out_color;
37 +
38 + void main() {
39 + vec4 tex_color = texture(albedo_tex, in_uv);
40 + vec3 albedo = (tex_color.rgb * material.albedo);
41 + vec3 view_dir = normalize((camera_pos - in_world_pos));
42 + vec3 color = compute_lighting(in_normal, view_dir, albedo);
43 + out_color = vec4(color, tex_color.a);
44 + }
gpu/shader/tests/golden/spec_constant.glsl-opengl +30 -0 added
1 + #version 450
2 +
3 + const int NUM_LIGHTS = 4;
4 + const float BRIGHTNESS = 1.0;
5 + const bool USE_GAMMA = true;
6 +
7 + layout(std140, binding = 0) uniform uniforms_Block {
8 + vec3 base_color;
9 + float ambient;
10 + } uniforms;
11 +
12 + layout(location = 0) in vec3 in_position;
13 +
14 + void main() {
15 + gl_Position = vec4(in_position, 1.0);
16 + }
17 +
18 + layout(location = 0) in vec4 in_frag_coord;
19 + layout(location = 0) out vec4 out_color;
20 +
21 + void main() {
22 + vec3 color = (uniforms.base_color * uniforms.ambient);
23 + int i = 0;
24 + while ((i < NUM_LIGHTS)) {
25 + color = (color + vec3(0.1, 0.1, 0.1));
26 + i = (i + 1);
27 + }
28 + color = (color * BRIGHTNESS);
29 + out_color = vec4(color, 1.0);
30 + }
gpu/shader/tests/golden/splat_test.glsl-opengl +14 -0 added
1 + #version 450
2 +
3 + layout(location = 0) in float in_value;
4 + layout(location = 0) out vec4 out__value;
5 +
6 + void main() {
7 + vec3 zero3 = vec3(0.0, 0.0, 0.0);
8 + vec4 one4 = vec4(1.0, 1.0, 1.0, 1.0);
9 + vec2 half2 = vec2(0.5, 0.5);
10 + vec3 full = vec3(1.0, 2.0, 3.0);
11 + float x = in_value;
12 + vec4 splatted = vec4(x, x, x, x);
13 + out__value = vec4(((((zero3.x + one4.x) + half2.x) + full.x) + splatted.x), 0.0, 0.0, 1.0);
14 + }
gpu/shader/tests/golden/texture_advanced.glsl-opengl +17 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform params_Block {
4 + float bias;
5 + } params;
6 + layout(binding = 0) uniform sampler2D diffuse_tex;
7 + layout(binding = 2) uniform sampler2DShadow shadow_map;
8 +
9 + layout(location = 0) in vec2 in_uv;
10 + layout(location = 1) in vec2 in_shadow_uv;
11 + layout(location = 0) out vec4 out__value;
12 +
13 + void main() {
14 + vec4 mip_color = textureLod(diffuse_tex, in_uv, params.bias);
15 + float shadow = texture(shadow_map, vec3(in_shadow_uv, 0.5));
16 + out__value = vec4((mip_color.rgb * shadow), mip_color.a);
17 + }
gpu/shader/tests/golden/varying_test.glsl-opengl +25 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform uniforms_Block {
4 + mat4 mvp;
5 + } uniforms;
6 +
7 + layout(location = 0) in vec3 in_position;
8 + layout(location = 1) in vec2 in_uv;
9 + layout(location = 0) out vec2 out_uv;
10 + layout(location = 1) out vec3 out_normal;
11 +
12 + void main() {
13 + vec4 clip_pos = (uniforms.mvp * vec4(in_position, 1.0));
14 + gl_Position = clip_pos;
15 + out_uv = in_uv;
16 + out_normal = vec3(0.0, 1.0, 0.0);
17 + }
18 +
19 + layout(location = 0) in vec2 in_uv;
20 + layout(location = 1) in vec3 in_normal;
21 + layout(location = 0) out vec4 out_color;
22 +
23 + void main() {
24 + out_color = vec4(in_uv, 0.0, 1.0);
25 + }
gpu/shader/tests/golden/workflow_branch_output.glsl-opengl +12 -0 added
1 + #version 450
2 +
3 + layout(location = 0) in vec2 in_uv;
4 + layout(location = 0) out vec4 out_color;
5 +
6 + void main() {
7 + if ((in_uv.x > 0.5)) {
8 + out_color = vec4(1.0, in_uv.y, 0.0, 1.0);
9 + } else {
10 + out_color = vec4(0.0, in_uv.y, 1.0, 1.0);
11 + }
12 + }
gpu/shader/tests/golden/workflow_compute_builtins.glsl-opengl +25 -0 added
1 + #version 450
2 +
3 + shared float scratch[64];
4 +
5 + layout(std430, binding = 0) buffer params_Block {
6 + uint count;
7 + float scale;
8 + } params;
9 + layout(std430, binding = 1) buffer data_Block {
10 + float values[64];
11 + } data;
12 +
13 + layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
14 +
15 + void main() {
16 + uint idx = gl_LocalInvocationIndex;
17 + uint gid = gl_GlobalInvocationID.x;
18 + uint lid = gl_LocalInvocationID.x;
19 + uint group_x = gl_WorkGroupID.x;
20 + if ((gid < params.count)) {
21 + scratch[idx] = (data.values[idx] * params.scale);
22 + barrier();
23 + data.values[idx] = (scratch[idx] + float((lid + group_x)));
24 + }
25 + }
gpu/shader/tests/golden/workflow_discard_output.glsl-opengl +12 -0 added
1 + #version 450
2 +
3 + layout(location = 0) in float in_alpha;
4 + layout(location = 0) out vec4 out_color;
5 +
6 + void main() {
7 + if ((in_alpha < 0.01)) {
8 + discard;
9 + } else {
10 + out_color = vec4(in_alpha, in_alpha, in_alpha, 1.0);
11 + }
12 + }
gpu/shader/tests/golden/workflow_fragment.glsl-opengl +12 -0 added
1 + #version 450
2 +
3 + layout(binding = 0) uniform sampler2D material_tex;
4 +
5 + layout(location = 0) in vec2 in_uv;
6 + layout(location = 1) in vec3 in_normal;
7 + layout(location = 0) out vec4 out_color;
8 +
9 + void main() {
10 + vec4 albedo = texture(material_tex, in_uv);
11 + out_color = vec4(albedo.rgb, 1.0);
12 + }
gpu/shader/tests/golden/workflow_fragment_builtins.glsl-opengl +10 -0 added
1 + #version 450
2 +
3 + layout(location = 0) out vec4 out_color;
4 +
5 + void main() {
6 + vec2 coord = gl_FragCoord.xy;
7 + bool facing = gl_FrontFacing;
8 + float face = (facing ? 1.0 : 0.25);
9 + out_color = vec4((coord.x * 0.0), (coord.y * 0.0), face, 1.0);
10 + }
gpu/shader/tests/golden/workflow_overwrite_output.glsl-opengl +11 -0 added
1 + #version 450
2 +
3 + layout(location = 0) in vec2 in_uv;
4 + layout(location = 0) out vec4 out_color;
5 +
6 + void main() {
7 + out_color = vec4(in_uv, 0.0, 1.0);
8 + if ((in_uv.x > 0.5)) {
9 + out_color = vec4(1.0, in_uv.y, 0.0, 1.0);
10 + }
11 + }
gpu/shader/tests/golden/workflow_vertex.glsl-opengl +22 -0 added
1 + #version 450
2 +
3 + layout(std140, binding = 0) uniform uniforms_Block {
4 + mat4 model;
5 + mat4 view_proj;
6 + mat4 normal_mat;
7 + } uniforms;
8 +
9 + layout(location = 0) in vec3 in_position;
10 + layout(location = 1) in vec3 in_normal;
11 + layout(location = 2) in vec2 in_uv;
12 + layout(location = 0) out vec2 out_uv;
13 + layout(location = 1) out vec3 out_normal;
14 +
15 + void main() {
16 + vec3 pos = in_position;
17 + vec4 world_pos = (uniforms.model * vec4(pos, 1.0));
18 + vec4 clip_pos = (uniforms.view_proj * world_pos);
19 + gl_Position = clip_pos;
20 + out_uv = in_uv;
21 + out_normal = normalize((uniforms.normal_mat * vec4(in_normal, 0.0)).xyz);
22 + }
gpu/shader/tests/golden/workflow_vertex_builtins.glsl-opengl added

Inline diff hidden to keep this page fast.

gpu/shader/tests/run_golden.sh modified

Inline diff hidden to keep this page fast.

gpu/shader/tests/validate.sh modified

Inline diff hidden to keep this page fast.

gpu/shaderkit/shaderkit.odin modified

Inline diff hidden to keep this page fast.

gpu/tools/shader/main.odin modified

Inline diff hidden to keep this page fast.