Fix OpenGL shader error: flatten colored_lights to avoid ARB_arrays_of_arrays (#6267)

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
JoansitohandClaude Sonnet 5.5 committed 2026-11-01 20:18:33 +01:00
1 parent 904ef97e51
commit 7affb5b478
5 files changed
+51 -9

No files matched your search

+1 -1
View File
@@ -73,4 +73,4 @@ workspace = true
[dev-dependencies]
horizon-items = { path = "../horizon-items", features = ["test-support"] }
naga = { version = "30.0.1", features = ["wgsl-in", "hlsl-out", "msl-out", "spv-out"] }
naga = { version = "30.0.1", features = ["wgsl-in", "hlsl-out", "glsl-out", "msl-out", "spv-out"] }
@@ -13,7 +13,8 @@ use std::collections::HashMap;
/// Lights the shaders read: `Globals.dynamic_lights` in gfx.rs, terrain.wgsl and entity.wgsl.
pub const MAX: usize = 16;
/// Camera-relative position and radius; RGB intensity in a second vec4.
/// Camera-relative position and radius; RGB intensity in a second vec4. The shaders read it as a flat
/// `array<vec4<f32>, 32>` (nested arrays need ARB_arrays_of_arrays, absent from GL below 4.3).
pub type Colored = [[f32; 4]; 2];
/// Nearest validated native visual lights; never enters gameplay lighting.
+3 -3
View File
@@ -22,7 +22,7 @@ struct Globals {
outline_params: vec4<f32>,
// Horizon Extras' dynamic lights: camera-relative position and level (dynamic_light.rs).
dynamic_lights: array<vec4<f32>, 16>,
colored_lights: array<array<vec4<f32>, 2>, 16>,
colored_lights: array<vec4<f32>, 32>,
colored_count: vec4<u32>,
emissive_layers: array<vec4<u32>, 32>,
emissive_count: vec4<u32>,
@@ -97,8 +97,8 @@ fn dynamic_block_light(pos: vec3<f32>) -> f32 {
fn native_colored_light(pos: vec3<f32>) -> vec3<f32> {
var rgb = vec3(0.0);
for (var i = 0u; i < min(globals.colored_count.x, 16u); i++) {
let at = globals.colored_lights[i][0];
let color = globals.colored_lights[i][1];
let at = globals.colored_lights[i * 2u];
let color = globals.colored_lights[i * 2u + 1u];
rgb += color.rgb * max(0.0, 1.0 - distance(pos, at.xyz) / at.w) * color.a;
}
return min(rgb, vec3(1.0));
+42 -1
View File
@@ -8807,7 +8807,7 @@ mod tests {
/// Every WGSL shader file translates to HLSL as wgpu's DirectX 12 backend
/// writes it for FXC (shader model 5.1), entry point by entry point.
#[test]
fn shaders_translate_to_hlsl_for_directx_12() {
fn shaders_translate_to_hlsl_for_directx_12_and_glsl_for_opengl() {
fn wgsl_files(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
for entry in std::fs::read_dir(dir).unwrap() {
let path = entry.unwrap().path();
@@ -8848,6 +8848,7 @@ mod tests {
sources.push((path, text));
}
}
let mut glsl_checked = 0;
for (path, text) in sources {
// entity.wgsl comes after the overlay's constants (entity_shader).
let module = naga::front::wgsl::parse_str(&text)
@@ -8880,8 +8881,48 @@ mod tests {
.write(&module, &info, None)
.unwrap_or_else(|e| panic!("{} {}: {e}", path.display(), entry.name));
assert!(!hlsl.is_empty());
// OpenGL below 4.3 lacks ARB_arrays_of_arrays (#6267): no nested array may reach it.
// Compute and storage-buffer shaders (culling, frame generation) never run on GL.
if entry.stage == naga::ShaderStage::Compute
|| text.contains("var<storage")
|| text.contains("var<workgroup>")
{
continue;
}
for version in [330, 400] {
let mut glsl = String::new();
let glsl_result = naga::back::glsl::Writer::new(
&mut glsl,
&module,
&info,
&naga::back::glsl::Options {
version: naga::back::glsl::Version::Desktop(version),
..Default::default()
},
&naga::back::glsl::PipelineOptions {
shader_stage: entry.stage,
entry_point: entry.name.clone(),
multiview: None,
},
Default::default(),
)
.and_then(|mut w| w.write());
// Some shaders use features GLSL cannot express (depth textureLoad): GL does
// not run them. The ones it does run must translate, checked below.
if glsl_result.is_err() {
continue;
}
glsl_checked += 1;
assert!(
!glsl.contains("ARB_arrays_of_arrays"),
"{} {} needs ARB_arrays_of_arrays on GLSL {version}",
path.display(),
entry.name
);
}
}
}
assert!(glsl_checked >= 10, "{glsl_checked} GLSL translations");
}
#[test]
fn gl_sprite_arrays_are_neither_2d_textures_nor_cube_maps() {
@@ -24,7 +24,7 @@ struct Globals {
outline_params: vec4<f32>,
// Horizon Extras' dynamic lights: camera-relative position and level (dynamic_light.rs).
dynamic_lights: array<vec4<f32>, 16>,
colored_lights: array<array<vec4<f32>, 2>, 16>,
colored_lights: array<vec4<f32>, 32>,
colored_count: vec4<u32>,
emissive_layers: array<vec4<u32>, 32>,
emissive_count: vec4<u32>,
@@ -249,8 +249,8 @@ fn dynamic_block_light(pos: vec3<f32>) -> f32 {
fn native_colored_light(pos: vec3<f32>) -> vec3<f32> {
var rgb = vec3(0.0);
for (var i = 0u; i < min(globals.colored_count.x, 16u); i++) {
let at = globals.colored_lights[i][0];
let color = globals.colored_lights[i][1];
let at = globals.colored_lights[i * 2u];
let color = globals.colored_lights[i * 2u + 1u];
rgb += color.rgb * max(0.0, 1.0 - distance(pos, at.xyz) / at.w) * color.a;
}
return min(rgb, vec3(1.0));