librashader/librashader-presets/src/parse/preset.rs

191 lines
6.6 KiB
Rust
Raw Normal View History

2024-02-06 01:32:08 -05:00
use crate::extract_if::MakeExtractIf;
2022-10-20 22:52:34 -04:00
use crate::parse::remove_if;
2022-10-20 23:05:56 -04:00
use crate::parse::value::Value;
2022-10-23 00:59:18 -04:00
use crate::{ParameterConfig, Scale2D, Scaling, ShaderPassConfig, ShaderPreset, TextureConfig};
2022-10-20 22:52:34 -04:00
2022-10-21 21:04:00 -04:00
pub fn resolve_values(mut values: Vec<Value>) -> ShaderPreset {
2022-10-20 23:05:56 -04:00
let textures: Vec<TextureConfig> = values
2023-07-20 00:38:13 -04:00
.extract_if(|f| matches!(*f, Value::Texture { .. }))
2022-10-20 22:52:34 -04:00
.map(|value| {
2022-10-20 23:05:56 -04:00
if let Value::Texture {
name,
filter_mode,
wrap_mode,
mipmap,
path,
} = value
{
2022-10-20 22:52:34 -04:00
TextureConfig {
name,
path,
wrap_mode,
filter_mode,
2022-10-20 23:05:56 -04:00
mipmap,
2022-10-20 22:52:34 -04:00
}
} else {
unreachable!("values should all be of type Texture")
}
2022-10-20 23:05:56 -04:00
})
.collect();
2022-10-21 21:04:00 -04:00
let parameters: Vec<ParameterConfig> = values
2023-07-20 00:38:13 -04:00
.extract_if(|f| matches!(*f, Value::Parameter { .. }))
2022-10-20 23:05:56 -04:00
.map(|value| {
if let Value::Parameter(name, value) = value {
2022-10-21 21:04:00 -04:00
ParameterConfig { name, value }
2022-10-20 23:05:56 -04:00
} else {
unreachable!("values should be all of type parameters")
2022-10-20 22:52:34 -04:00
}
2022-10-20 23:05:56 -04:00
})
.collect();
2022-10-20 22:52:34 -04:00
let mut shaders = Vec::new();
2023-02-05 18:34:30 -05:00
let shader_count =
remove_if(&mut values, |v| matches!(*v, Value::ShaderCount(_))).map_or(0, |value| {
2022-10-20 23:05:56 -04:00
if let Value::ShaderCount(count) = value {
count
} else {
unreachable!("value should be of type shader_count")
}
2023-02-05 18:34:30 -05:00
});
2022-10-20 22:52:34 -04:00
#[cfg(feature = "parse_legacy_glsl")]
2022-10-20 23:05:56 -04:00
let feedback_pass = remove_if(&mut values, |v| matches!(*v, Value::FeedbackPass(_)))
.map(|value| {
if let Value::FeedbackPass(pass) = value {
pass
} else {
unreachable!("value should be of type feedback_pass")
}
2022-10-20 22:52:34 -04:00
})
.unwrap_or(0);
for shader in 0..shader_count {
2022-10-20 23:05:56 -04:00
if let Some(Value::Shader(id, name)) = remove_if(
&mut values,
|v| matches!(*v, Value::Shader(shader_index, _) if shader_index == shader),
) {
let shader_values: Vec<Value> = values
2023-07-20 00:38:13 -04:00
.extract_if(|v| v.shader_index() == Some(shader))
2022-10-20 23:05:56 -04:00
.collect();
2022-10-20 22:52:34 -04:00
let scale_type = shader_values.iter().find_map(|f| match f {
Value::ScaleType(_, value) => Some(*value),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
});
let mut scale_type_x = shader_values.iter().find_map(|f| match f {
Value::ScaleTypeX(_, value) => Some(*value),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
});
let mut scale_type_y = shader_values.iter().find_map(|f| match f {
Value::ScaleTypeY(_, value) => Some(*value),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
});
if scale_type.is_some() {
// scale takes priority
// https://github.com/libretro/RetroArch/blob/fcbd72dbf3579eb31721fbbf0d89a139834bcce9/gfx/video_shader_parse.c#L310
scale_type_x = scale_type;
scale_type_y = scale_type;
}
let scale_valid = scale_type_x.is_some() || scale_type_y.is_some();
let scale = shader_values.iter().find_map(|f| match f {
Value::Scale(_, value) => Some(*value),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
});
let mut scale_x = shader_values.iter().find_map(|f| match f {
Value::ScaleX(_, value) => Some(*value),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
});
let mut scale_y = shader_values.iter().find_map(|f| match f {
Value::ScaleY(_, value) => Some(*value),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
});
if scale.is_some() {
// scale takes priority
// https://github.com/libretro/RetroArch/blob/fcbd72dbf3579eb31721fbbf0d89a139834bcce9/gfx/video_shader_parse.c#L310
scale_x = scale;
scale_y = scale;
}
2022-10-21 21:04:00 -04:00
let shader = ShaderPassConfig {
2022-10-20 22:52:34 -04:00
id,
name,
alias: shader_values.iter().find_map(|f| match f {
Value::Alias(_, value) => Some(value.to_string()),
2022-10-20 23:05:56 -04:00
_ => None,
2022-10-20 22:52:34 -04:00
}),
2022-10-20 23:05:56 -04:00
filter: shader_values
.iter()
.find_map(|f| match f {
Value::FilterMode(_, value) => Some(*value),
_ => None,
})
.unwrap_or_default(),
wrap_mode: shader_values
.iter()
.find_map(|f| match f {
Value::WrapMode(_, value) => Some(*value),
_ => None,
})
.unwrap_or_default(),
frame_count_mod: shader_values
.iter()
.find_map(|f| match f {
Value::FrameCountMod(_, value) => Some(*value),
_ => None,
})
.unwrap_or(0),
2022-10-20 23:05:56 -04:00
srgb_framebuffer: shader_values
.iter()
.find_map(|f| match f {
Value::SrgbFramebuffer(_, value) => Some(*value),
_ => None,
})
.unwrap_or(false),
float_framebuffer: shader_values
.iter()
.find_map(|f| match f {
Value::FloatFramebuffer(_, value) => Some(*value),
_ => None,
})
.unwrap_or(false),
mipmap_input: shader_values
.iter()
.find_map(|f| match f {
Value::MipmapInput(_, value) => Some(*value),
_ => None,
})
.unwrap_or(false),
2022-10-20 22:52:34 -04:00
scaling: Scale2D {
valid: scale_valid,
2022-10-20 23:05:56 -04:00
x: Scaling {
scale_type: scale_type_x.unwrap_or_default(),
factor: scale_x.unwrap_or_default(),
},
y: Scaling {
scale_type: scale_type_y.unwrap_or_default(),
factor: scale_y.unwrap_or_default(),
},
},
2022-10-20 22:52:34 -04:00
};
shaders.push(shader)
}
}
2022-10-21 21:04:00 -04:00
ShaderPreset {
#[cfg(feature = "parse_legacy_glsl")]
2022-10-20 22:52:34 -04:00
feedback_pass,
shader_count,
2022-10-20 22:52:34 -04:00
shaders,
textures,
2022-10-20 23:05:56 -04:00
parameters,
2022-10-20 22:52:34 -04:00
}
2022-10-20 23:05:56 -04:00
}