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 2 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
116 changes: 85 additions & 31 deletions tests/in/shadow.wgsl
Original file line number Diff line number Diff line change
@@ -1,61 +1,115 @@
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;

@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;
}

38 changes: 38 additions & 0 deletions tests/out/glsl/shadow.vs_bake.Vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#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;

void main() {
ivec4 position = _p2vs_location0;
mat4x4 _e4 = _group_0_binding_0_vs.view_proj;
mat4x4 _e6 = _group_1_binding_0_vs.world;
gl_Position = ((_e4 * _e6) * vec4(position));
gl_Position.yz = vec2(-gl_Position.y, gl_Position.z * 2.0 - gl_Position.w);
return;
}

Loading