From e8b71b8dc5cd70535308591f1dd2dba5f92f44eb Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 28 Jun 2021 12:38:11 -0400 Subject: [PATCH] [glsl-out] Support extended shadow sampling instructions, and the offset --- src/back/glsl/mod.rs | 49 +++++++++++++++++---- tests/out/glsl/shadow.fs_main.Fragment.glsl | 2 +- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 2366fe81d6..877995b779 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -132,6 +132,9 @@ bitflags::bitflags! { pub struct WriterFlags: u32 { /// Extend output Z from (0,1) to (-1,1). const ADJUST_COORDINATE_SPACE = 0x1; + /// Supports GL_EXT_texture_shadow_lod on the host, which provides + /// additional functions on shadows and arrays of shadows. + const TEXTURE_SHADOW_LOD = 0x2; } } @@ -391,6 +394,16 @@ impl<'a, W: Write> Writer<'a, W> { // preprocessor not the processor ¯\_(ツ)_/¯ self.features.write(self.options.version, &mut self.out)?; + // Write the additional extensions + if self + .options + .writer_flags + .contains(WriterFlags::TEXTURE_SHADOW_LOD) + { + // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_shadow_lod.txt + writeln!(self.out, "#extension GL_EXT_texture_shadow_lod : require")?; + } + // glsl es requires a precision to be specified for floats // TODO: Should this be user configurable? if es { @@ -1677,19 +1690,27 @@ impl<'a, W: Write> Writer<'a, W> { // Furthermore if `depth_ref` is some we need to append it to the coordinate vector Expression::ImageSample { image, - sampler: _, //TODO + sampler: _, //TODO? coordinate, array_index, - offset: _, //TODO + offset, level, depth_ref, } => { - //TODO: handle MS + let dim = match *ctx.info[image].ty.inner_with(&self.module.types) { + TypeInner::Image { dim, .. } => dim, + _ => unreachable!(), + }; // textureLod on sampler2DArrayShadow and samplerCubeShadow does not exist in GLSL. // To emulate this, we will have to use textureGrad with a constant gradient of 0. - let workaround_lod_array_shadow_as_grad = - array_index.is_some() && depth_ref.is_some(); + let workaround_lod_array_shadow_as_grad = (array_index.is_some() + || dim == crate::ImageDimension::Cube) + && depth_ref.is_some() + && !self + .options + .writer_flags + .contains(WriterFlags::TEXTURE_SHADOW_LOD); //Write the function to be used depending on the sample level let fun_name = match level { @@ -1703,8 +1724,12 @@ impl<'a, W: Write> Writer<'a, W> { } crate::SampleLevel::Gradient { .. } => "textureGrad", }; + let offset_name = match offset { + Some(_) => "Offset", + None => "", + }; - write!(self.out, "{}(", fun_name)?; + write!(self.out, "{}{}(", fun_name, offset_name)?; // Write the image that will be used self.write_expr(image, ctx)?; @@ -1745,15 +1770,16 @@ impl<'a, W: Write> Writer<'a, W> { // Zero needs level set to 0 crate::SampleLevel::Zero => { if workaround_lod_array_shadow_as_grad { - write!(self.out, ", vec2(0, 0), vec2(0,0)")?; + write!(self.out, ", vec2(0,0), vec2(0,0)")?; } else { - write!(self.out, ", 0")?; + write!(self.out, ", 0.0")?; } } // Exact and bias require another argument crate::SampleLevel::Exact(expr) => { if workaround_lod_array_shadow_as_grad { - write!(self.out, ", vec2(0, 0), vec2(0,0)")?; + log::warn!("Unable to `textureLod` a shadow array, ignoring the LOD"); + write!(self.out, ", vec2(0,0), vec2(0,0)")?; } else { write!(self.out, ", ")?; self.write_expr(expr, ctx)?; @@ -1771,6 +1797,11 @@ impl<'a, W: Write> Writer<'a, W> { } } + if let Some(constant) = offset { + write!(self.out, ", ")?; + self.write_constant(&self.module.constants[constant])?; + } + // End the function write!(self.out, ")")? } diff --git a/tests/out/glsl/shadow.fs_main.Fragment.glsl b/tests/out/glsl/shadow.fs_main.Fragment.glsl index b49523b983..6446c56443 100644 --- a/tests/out/glsl/shadow.fs_main.Fragment.glsl +++ b/tests/out/glsl/shadow.fs_main.Fragment.glsl @@ -28,7 +28,7 @@ float fetch_shadow(uint light_id, vec4 homogeneous_coords) { } 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 _expr26 = textureGrad(_group_0_binding_2, vec4(light_local, int(light_id), (homogeneous_coords.z / homogeneous_coords.w)), vec2(0, 0), vec2(0,0)); + float _expr26 = textureGrad(_group_0_binding_2, vec4(light_local, int(light_id), (homogeneous_coords.z / homogeneous_coords.w)), vec2(0,0), vec2(0,0)); return _expr26; }