Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

[glsl-out] Write constant sized array type for uniform #1768

Merged
merged 3 commits into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ impl<'a> GlobalTypeKind<'a> {
size: crate::ArraySize::Dynamic,
..
} => Self::WrappedStruct,
// Naga IR permits globals to be constant sized arrays. Render
// these in GLSL as uniforms.
crate::TypeInner::Array {
size: crate::ArraySize::Constant(..),
..
} => Self::WrappedStruct,
_ => Self::Other,
}
}
Expand Down
118 changes: 87 additions & 31 deletions tests/in/shadow.wgsl
Original file line number Diff line number Diff line change
@@ -1,61 +1,117 @@
struct Globals {
view_proj: mat4x4<f32>;
num_lights: vec4<u32>;
};

@group(0) @binding(0)
@group(0)
@binding(0)
var<uniform> u_globals: Globals;

struct Entity {
world: mat4x4<f32>;
color: vec4<f32>;
};

@group(1)
@binding(0)
var<uniform> u_entity: Entity;

/* Not useful for testing
@stage(vertex)
fn vs_bake(@location(0) position: vec4<i32>) -> @builtin(position) vec4<f32> {
kvark marked this conversation as resolved.
Show resolved Hide resolved
return u_globals.view_proj * u_entity.world * vec4<f32>(position);
}
*/

struct VertexOutput {
@builtin(position) proj_position: vec4<f32>;
@location(0) world_normal: vec3<f32>;
@location(1) world_position: vec4<f32>;
};

@stage(vertex)
fn vs_main(
@location(0) position: vec4<i32>,
@location(1) normal: vec4<i32>,
) -> VertexOutput {
let w = u_entity.world;
let world_pos = u_entity.world * vec4<f32>(position);
var out: VertexOutput;
out.world_normal = mat3x3<f32>(w.x.xyz, w.y.xyz, w.z.xyz) * vec3<f32>(normal.xyz);
out.world_position = world_pos;
out.proj_position = u_globals.view_proj * world_pos;
return out;
}

// fragment shader

struct Light {
proj: mat4x4<f32>;
pos: vec4<f32>;
color: vec4<f32>;
};

struct Lights {
data: array<Light>;
};

@group(0) @binding(1)
var<storage> s_lights: Lights;
@group(0) @binding(2)
@group(0)
@binding(1)
var<storage, read> s_lights: array<Light>;
@group(0)
@binding(1)
var<uniform> u_lights: array<Light, 10>; // Used when storage types are not supported
@group(0)
@binding(2)
var t_shadow: texture_depth_2d_array;
@group(0) @binding(3)
@group(0)
@binding(3)
var sampler_shadow: sampler_comparison;

fn fetch_shadow(light_id: u32, homogeneous_coords: vec4<f32>) -> f32 {
if homogeneous_coords.w <= 0.0 {
if (homogeneous_coords.w <= 0.0) {
return 1.0;
}
// compensate for the Y-flip difference between the NDC and texture coordinates
let flip_correction = vec2<f32>(0.5, -0.5);
let light_local = homogeneous_coords.xy * flip_correction / homogeneous_coords.w + vec2<f32>(0.5, 0.5);
return textureSampleCompareLevel(t_shadow, sampler_shadow, light_local, i32(light_id), homogeneous_coords.z / homogeneous_coords.w);
// compute texture coordinates for shadow lookup
let proj_correction = 1.0 / homogeneous_coords.w;
let light_local = homogeneous_coords.xy * flip_correction * proj_correction + vec2<f32>(0.5, 0.5);
// do the lookup, using HW PCF and comparison
return textureSampleCompareLevel(t_shadow, sampler_shadow, light_local, i32(light_id), homogeneous_coords.z * proj_correction);
}

let c_ambient: vec3<f32> = vec3<f32>(0.05, 0.05, 0.05);
let c_max_lights: u32 = 10u;

@stage(fragment)
fn fs_main(
@location(0) raw_normal: vec3<f32>,
@location(1) position: vec4<f32>
) -> @location(0) vec4<f32> {
let normal: vec3<f32> = normalize(raw_normal);
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let normal = normalize(in.world_normal);
// accumulate color
var color = c_ambient;
var i: u32 = 0u;
loop {
if i >= min(u_globals.num_lights.x, c_max_lights) {
break;
}
let light = s_lights.data[i];
let shadow = fetch_shadow(i, light.proj * position);
let light_dir = normalize(light.pos.xyz - position.xyz);
var color: vec3<f32> = c_ambient;
for(var i = 0u; i < min(u_globals.num_lights.x, c_max_lights); i += 1u) {
let light = s_lights[i];
// project into the light space
let shadow = fetch_shadow(i, light.proj * in.world_position);
// compute Lambertian diffuse term
let light_dir = normalize(light.pos.xyz - in.world_position.xyz);
let diffuse = max(0.0, dot(normal, light_dir));
color = color + shadow * diffuse * light.color.xyz;
continuing {
i = i + 1u;
}
// add light contribution
color += shadow * diffuse * light.color.xyz;
}
// multiply the light by material color
return vec4<f32>(color, 1.0);
return vec4<f32>(color, 1.0) * u_entity.color;
}

// The fragment entrypoint used when storage buffers are not available for the lights
@stage(fragment)
fn fs_main_without_storage(in: VertexOutput) -> @location(0) vec4<f32> {
let normal = normalize(in.world_normal);
var color: vec3<f32> = c_ambient;
for(var i = 0u; i < min(u_globals.num_lights.x, c_max_lights); i += 1u) {
// This line is the only difference from the entrypoint above. It uses the lights
// uniform instead of the lights storage buffer
let light = u_lights[i];
let shadow = fetch_shadow(i, light.proj * in.world_position);
let light_dir = normalize(light.pos.xyz - in.world_position.xyz);
let diffuse = max(0.0, dot(normal, light_dir));
color += shadow * diffuse * light.color.xyz;
}
return vec4<f32>(color, 1.0) * u_entity.color;
}
60 changes: 36 additions & 24 deletions tests/out/glsl/shadow.fs_main.Fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@ precision highp float;
precision highp int;

struct Globals {
mat4x4 view_proj;
uvec4 num_lights;
};
struct Entity {
mat4x4 world;
vec4 color;
};
struct VertexOutput {
vec4 proj_position;
vec3 world_normal;
vec4 world_position;
};
struct Light {
mat4x4 proj;
vec4 pos;
vec4 color;
};
uniform Globals_block_0Fragment { Globals _group_0_binding_0_fs; };

layout(std430) readonly buffer Lights_block_1Fragment {
Light data[];
} _group_0_binding_1_fs;
uniform Entity_block_1Fragment { Entity _group_1_binding_0_fs; };

layout(std430) readonly buffer type_6_block_2Fragment { Light _group_0_binding_1_fs[]; };

uniform highp sampler2DArrayShadow _group_0_binding_2_fs;

Expand All @@ -28,40 +38,42 @@ float fetch_shadow(uint light_id, vec4 homogeneous_coords) {
return 1.0;
}
vec2 flip_correction = vec2(0.5, -0.5);
vec2 light_local = (((homogeneous_coords.xy * flip_correction) / vec2(homogeneous_coords.w)) + vec2(0.5, 0.5));
float _e26 = textureGrad(_group_0_binding_2_fs, vec4(light_local, int(light_id), (homogeneous_coords.z / homogeneous_coords.w)), vec2(0.0), vec2(0.0));
return _e26;
float proj_correction = (1.0 / homogeneous_coords.w);
vec2 light_local = (((homogeneous_coords.xy * flip_correction) * proj_correction) + vec2(0.5, 0.5));
float _e28 = textureGrad(_group_0_binding_2_fs, vec4(light_local, int(light_id), (homogeneous_coords.z * proj_correction)), vec2(0.0), vec2(0.0));
return _e28;
}

void main() {
vec3 raw_normal = _vs2fs_location0;
vec4 position = _vs2fs_location1;
VertexOutput in_ = VertexOutput(gl_FragCoord, _vs2fs_location0, _vs2fs_location1);
vec3 color = vec3(0.05000000074505806, 0.05000000074505806, 0.05000000074505806);
uint i = 0u;
vec3 normal = normalize(raw_normal);
vec3 normal_1 = normalize(in_.world_normal);
bool loop_init = true;
while(true) {
if (!loop_init) {
uint _e40 = i;
i = (_e40 + 1u);
uint _e20 = i;
i = (_e20 + 1u);
}
loop_init = false;
uint _e12 = i;
uint _e15 = _group_0_binding_0_fs.num_lights.x;
if ((_e12 >= min(_e15, 10u))) {
uint _e14 = i;
uint _e17 = _group_0_binding_0_fs.num_lights.x;
if ((_e14 < min(_e17, 10u))) {
} else {
break;
}
uint _e19 = i;
Light light = _group_0_binding_1_fs.data[_e19];
uint _e22 = i;
float _e25 = fetch_shadow(_e22, (light.proj * position));
vec3 light_dir = normalize((light.pos.xyz - position.xyz));
float diffuse = max(0.0, dot(normal, light_dir));
vec3 _e34 = color;
color = (_e34 + ((_e25 * diffuse) * light.color.xyz));
uint _e23 = i;
Light light = _group_0_binding_1_fs[_e23];
uint _e26 = i;
float _e30 = fetch_shadow(_e26, (light.proj * in_.world_position));
vec3 light_dir = normalize((light.pos.xyz - in_.world_position.xyz));
float diffuse = max(0.0, dot(normal_1, light_dir));
vec3 _e40 = color;
color = (_e40 + ((_e30 * diffuse) * light.color.xyz));
}
vec3 _e43 = color;
_fs2p_location0 = vec4(_e43, 1.0);
vec3 _e46 = color;
vec4 _e50 = _group_1_binding_0_fs.color;
_fs2p_location0 = (vec4(_e46, 1.0) * _e50);
return;
}

79 changes: 79 additions & 0 deletions tests/out/glsl/shadow.fs_main_without_storage.Fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#version 310 es

precision highp float;
precision highp int;

struct Globals {
mat4x4 view_proj;
uvec4 num_lights;
};
struct Entity {
mat4x4 world;
vec4 color;
};
struct VertexOutput {
vec4 proj_position;
vec3 world_normal;
vec4 world_position;
};
struct Light {
mat4x4 proj;
vec4 pos;
vec4 color;
};
uniform Globals_block_0Fragment { Globals _group_0_binding_0_fs; };

uniform Entity_block_1Fragment { Entity _group_1_binding_0_fs; };

uniform type_7_block_2Fragment { Light _group_0_binding_1_fs[10]; };

uniform highp sampler2DArrayShadow _group_0_binding_2_fs;

layout(location = 0) smooth in vec3 _vs2fs_location0;
layout(location = 1) smooth in vec4 _vs2fs_location1;
layout(location = 0) out vec4 _fs2p_location0;

float fetch_shadow(uint light_id, vec4 homogeneous_coords) {
if ((homogeneous_coords.w <= 0.0)) {
return 1.0;
}
vec2 flip_correction = vec2(0.5, -0.5);
float proj_correction = (1.0 / homogeneous_coords.w);
vec2 light_local = (((homogeneous_coords.xy * flip_correction) * proj_correction) + vec2(0.5, 0.5));
float _e28 = textureGrad(_group_0_binding_2_fs, vec4(light_local, int(light_id), (homogeneous_coords.z * proj_correction)), vec2(0.0), vec2(0.0));
return _e28;
}

void main() {
VertexOutput in_1 = VertexOutput(gl_FragCoord, _vs2fs_location0, _vs2fs_location1);
vec3 color_1 = vec3(0.05000000074505806, 0.05000000074505806, 0.05000000074505806);
uint i_1 = 0u;
vec3 normal_1 = normalize(in_1.world_normal);
bool loop_init = true;
while(true) {
if (!loop_init) {
uint _e20 = i_1;
i_1 = (_e20 + 1u);
}
loop_init = false;
uint _e14 = i_1;
uint _e17 = _group_0_binding_0_fs.num_lights.x;
if ((_e14 < min(_e17, 10u))) {
} else {
break;
}
uint _e23 = i_1;
Light light = _group_0_binding_1_fs[_e23];
uint _e26 = i_1;
float _e30 = fetch_shadow(_e26, (light.proj * in_1.world_position));
vec3 light_dir = normalize((light.pos.xyz - in_1.world_position.xyz));
float diffuse = max(0.0, dot(normal_1, light_dir));
vec3 _e40 = color_1;
color_1 = (_e40 + ((_e30 * diffuse) * light.color.xyz));
}
vec3 _e46 = color_1;
vec4 _e50 = _group_1_binding_0_fs.color;
_fs2p_location0 = (vec4(_e46, 1.0) * _e50);
return;
}

51 changes: 51 additions & 0 deletions tests/out/glsl/shadow.vs_main.Vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#version 310 es

precision highp float;
precision highp int;

struct Globals {
mat4x4 view_proj;
uvec4 num_lights;
};
struct Entity {
mat4x4 world;
vec4 color;
};
struct VertexOutput {
vec4 proj_position;
vec3 world_normal;
vec4 world_position;
};
struct Light {
mat4x4 proj;
vec4 pos;
vec4 color;
};
uniform Globals_block_0Vertex { Globals _group_0_binding_0_vs; };

uniform Entity_block_1Vertex { Entity _group_1_binding_0_vs; };

layout(location = 0) in ivec4 _p2vs_location0;
layout(location = 1) in ivec4 _p2vs_location1;
layout(location = 0) smooth out vec3 _vs2fs_location0;
layout(location = 1) smooth out vec4 _vs2fs_location1;

void main() {
ivec4 position = _p2vs_location0;
ivec4 normal = _p2vs_location1;
VertexOutput out_ = VertexOutput(vec4(0.0), vec3(0.0), vec4(0.0));
mat4x4 w = _group_1_binding_0_vs.world;
mat4x4 _e7 = _group_1_binding_0_vs.world;
vec4 world_pos = (_e7 * vec4(position));
out_.world_normal = (mat3x3(w[0].xyz, w[1].xyz, w[2].xyz) * vec3(normal.xyz));
out_.world_position = world_pos;
mat4x4 _e25 = _group_0_binding_0_vs.view_proj;
out_.proj_position = (_e25 * world_pos);
VertexOutput _e27 = out_;
gl_Position = _e27.proj_position;
_vs2fs_location0 = _e27.world_normal;
_vs2fs_location1 = _e27.world_position;
gl_Position.yz = vec2(-gl_Position.y, gl_Position.z * 2.0 - gl_Position.w);
return;
}

Loading