2022-12-23 22:06:19 +00:00
|
|
|
use crate::blend::ComplexBlend;
|
|
|
|
use enum_map::{enum_map, EnumMap};
|
2023-01-06 22:17:42 +00:00
|
|
|
use naga_oil::compose::{
|
|
|
|
ComposableModuleDescriptor, Composer, ComposerError, NagaModuleDescriptor, ShaderDefValue,
|
|
|
|
};
|
2022-12-25 00:20:57 +00:00
|
|
|
use ruffle_render::tessellator::GradientType;
|
2023-01-06 22:17:42 +00:00
|
|
|
use std::borrow::Cow;
|
|
|
|
use std::collections::HashMap;
|
2022-12-25 00:20:57 +00:00
|
|
|
use swf::GradientSpread;
|
2022-12-23 22:06:19 +00:00
|
|
|
|
2022-09-07 01:41:23 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Shaders {
|
|
|
|
pub color_shader: wgpu::ShaderModule,
|
|
|
|
pub bitmap_shader: wgpu::ShaderModule,
|
2022-12-25 00:20:57 +00:00
|
|
|
pub gradient_shaders: EnumMap<GradientType, EnumMap<GradientSpread, wgpu::ShaderModule>>,
|
2022-09-07 01:41:23 +00:00
|
|
|
pub copy_srgb_shader: wgpu::ShaderModule,
|
2022-09-21 00:44:56 +00:00
|
|
|
pub copy_shader: wgpu::ShaderModule,
|
2022-12-23 22:06:19 +00:00
|
|
|
pub blend_shaders: EnumMap<ComplexBlend, wgpu::ShaderModule>,
|
2022-09-07 01:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Shaders {
|
2023-01-06 22:17:42 +00:00
|
|
|
pub fn new(device: &wgpu::Device) -> Self {
|
|
|
|
let mut composer = composer().expect("Couldn't create shader composer");
|
|
|
|
let mut shader_defs = HashMap::new();
|
|
|
|
shader_defs.insert(
|
|
|
|
"use_push_constants".to_owned(),
|
|
|
|
ShaderDefValue::Bool(device.limits().max_push_constant_size > 0),
|
|
|
|
);
|
|
|
|
let color_shader = make_shader(
|
|
|
|
&device,
|
|
|
|
&mut composer,
|
|
|
|
&shader_defs,
|
|
|
|
"color.wgsl",
|
2023-01-06 17:41:24 +00:00
|
|
|
include_str!("../shaders/color.wgsl"),
|
|
|
|
);
|
2023-01-06 22:17:42 +00:00
|
|
|
let bitmap_shader = make_shader(
|
|
|
|
&device,
|
|
|
|
&mut composer,
|
|
|
|
&shader_defs,
|
|
|
|
"bitmap.wgsl",
|
2023-01-06 17:41:24 +00:00
|
|
|
include_str!("../shaders/bitmap.wgsl"),
|
|
|
|
);
|
2023-01-06 22:17:42 +00:00
|
|
|
let copy_srgb_shader = make_shader(
|
|
|
|
&device,
|
|
|
|
&mut composer,
|
|
|
|
&shader_defs,
|
|
|
|
"copy_srgb.wgsl",
|
2022-09-07 01:41:23 +00:00
|
|
|
include_str!("../shaders/copy_srgb.wgsl"),
|
|
|
|
);
|
2023-01-06 22:17:42 +00:00
|
|
|
let copy_shader = make_shader(
|
|
|
|
&device,
|
|
|
|
&mut composer,
|
|
|
|
&shader_defs,
|
|
|
|
"copy.wgsl",
|
2023-01-06 17:41:24 +00:00
|
|
|
include_str!("../shaders/copy.wgsl"),
|
|
|
|
);
|
2022-12-23 22:06:19 +00:00
|
|
|
|
|
|
|
let blend_shaders = enum_map! {
|
2023-01-06 22:17:42 +00:00
|
|
|
ComplexBlend::Lighten => make_shader(device, &mut composer, &shader_defs, "blend/lighten.wgsl", include_str!("../shaders/blend/lighten.wgsl")),
|
|
|
|
ComplexBlend::Darken => make_shader(device, &mut composer, &shader_defs, "blend/darken.wgsl", include_str!("../shaders/blend/darken.wgsl")),
|
|
|
|
ComplexBlend::Difference => make_shader(device, &mut composer, &shader_defs, "blend/difference.wgsl", include_str!("../shaders/blend/difference.wgsl")),
|
|
|
|
ComplexBlend::Invert => make_shader(device, &mut composer, &shader_defs, "blend/invert.wgsl", include_str!("../shaders/blend/invert.wgsl")),
|
|
|
|
ComplexBlend::Alpha => make_shader(device, &mut composer, &shader_defs, "blend/alpha.wgsl", include_str!("../shaders/blend/alpha.wgsl")),
|
|
|
|
ComplexBlend::Erase => make_shader(device, &mut composer, &shader_defs, "blend/erase.wgsl", include_str!("../shaders/blend/erase.wgsl")),
|
|
|
|
ComplexBlend::Overlay => make_shader(device, &mut composer, &shader_defs, "blend/overlay.wgsl", include_str!("../shaders/blend/overlay.wgsl")),
|
|
|
|
ComplexBlend::HardLight => make_shader(device, &mut composer, &shader_defs, "blend/hardlight.wgsl", include_str!("../shaders/blend/hardlight.wgsl")),
|
2022-12-25 00:20:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let gradient_shaders = enum_map! {
|
2023-01-06 22:17:42 +00:00
|
|
|
GradientType::Focal => create_gradient_shaders(device, &mut composer, &shader_defs, "focal", include_str!("../shaders/gradient/mode/focal.wgsl")),
|
|
|
|
GradientType::Linear => create_gradient_shaders(device, &mut composer, &shader_defs, "linear", include_str!("../shaders/gradient/mode/linear.wgsl")),
|
|
|
|
GradientType::Radial => create_gradient_shaders(device, &mut composer, &shader_defs, "radial", include_str!("../shaders/gradient/mode/radial.wgsl")),
|
2022-12-25 00:20:57 +00:00
|
|
|
};
|
|
|
|
|
2022-09-07 01:41:23 +00:00
|
|
|
Self {
|
|
|
|
color_shader,
|
|
|
|
bitmap_shader,
|
2022-12-25 00:20:57 +00:00
|
|
|
gradient_shaders,
|
2022-09-07 01:41:23 +00:00
|
|
|
copy_srgb_shader,
|
2022-09-21 00:44:56 +00:00
|
|
|
copy_shader,
|
2022-12-23 22:06:19 +00:00
|
|
|
blend_shaders,
|
2022-09-07 01:41:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-06 22:17:42 +00:00
|
|
|
fn composer() -> Result<Composer, ComposerError> {
|
|
|
|
let mut composer = Composer::default();
|
|
|
|
// [NA] Hack to get all capabilities since nobody exposes this type easily
|
|
|
|
let capabilities = composer.capabilities;
|
|
|
|
composer = composer.with_capabilities(!capabilities);
|
|
|
|
composer.add_composable_module(ComposableModuleDescriptor {
|
|
|
|
source: include_str!("../shaders/common.wgsl"),
|
|
|
|
file_path: "common.wgsl",
|
|
|
|
..Default::default()
|
|
|
|
})?;
|
|
|
|
composer.add_composable_module(ComposableModuleDescriptor {
|
|
|
|
source: include_str!("../shaders/gradient/common.wgsl"),
|
|
|
|
file_path: "gradient/common.wgsl",
|
|
|
|
..Default::default()
|
|
|
|
})?;
|
|
|
|
Ok(composer)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn make_shader(
|
2023-01-06 17:41:24 +00:00
|
|
|
device: &wgpu::Device,
|
2023-01-06 22:17:42 +00:00
|
|
|
composer: &mut Composer,
|
|
|
|
shader_defs: &HashMap<String, ShaderDefValue>,
|
2023-01-06 17:41:24 +00:00
|
|
|
name: &str,
|
2023-01-06 22:17:42 +00:00
|
|
|
source: &'static str,
|
2023-01-06 17:41:24 +00:00
|
|
|
) -> wgpu::ShaderModule {
|
2023-01-06 22:17:42 +00:00
|
|
|
device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
|
|
|
label: create_debug_label!("Shader {}", name).as_deref(),
|
|
|
|
source: wgpu::ShaderSource::Naga(Cow::Owned(
|
|
|
|
composer
|
|
|
|
.make_naga_module(NagaModuleDescriptor {
|
|
|
|
source,
|
|
|
|
file_path: name,
|
|
|
|
shader_defs: shader_defs.clone(),
|
|
|
|
..Default::default()
|
|
|
|
})
|
2023-01-20 21:12:48 +00:00
|
|
|
.unwrap_or_else(|e| {
|
|
|
|
panic!(
|
|
|
|
"{name} failed to compile:\n{}\n{:#?}",
|
|
|
|
e.emit_to_string(&composer),
|
|
|
|
e
|
|
|
|
)
|
|
|
|
}),
|
2023-01-06 22:17:42 +00:00
|
|
|
)),
|
|
|
|
})
|
2022-09-07 01:41:23 +00:00
|
|
|
}
|
2022-12-24 23:41:59 +00:00
|
|
|
|
2022-12-25 00:20:57 +00:00
|
|
|
fn create_gradient_shaders(
|
|
|
|
device: &wgpu::Device,
|
2023-01-06 22:17:42 +00:00
|
|
|
composer: &mut Composer,
|
|
|
|
shader_defs: &HashMap<String, ShaderDefValue>,
|
|
|
|
name: &'static str,
|
|
|
|
source: &'static str,
|
2022-12-25 00:20:57 +00:00
|
|
|
) -> EnumMap<GradientSpread, wgpu::ShaderModule> {
|
|
|
|
enum_map! {
|
2023-01-06 22:17:42 +00:00
|
|
|
GradientSpread::Reflect => {
|
|
|
|
let mut temporary_defs = shader_defs.clone();
|
|
|
|
temporary_defs.insert("gradient_repeat_mode".to_owned(), ShaderDefValue::Int(1));
|
|
|
|
make_shader(device, composer, &temporary_defs, &format!("gradient/{name}.wgsl with reflect"), source)
|
|
|
|
},
|
|
|
|
GradientSpread::Repeat => {
|
|
|
|
let mut temporary_defs = shader_defs.clone();
|
|
|
|
temporary_defs.insert("gradient_repeat_mode".to_owned(), ShaderDefValue::Int(2));
|
|
|
|
make_shader(device, composer, &temporary_defs, &format!("gradient/{name}.wgsl with repeat"), source)
|
|
|
|
},
|
|
|
|
GradientSpread::Pad => {
|
|
|
|
let mut temporary_defs = shader_defs.clone();
|
|
|
|
temporary_defs.insert("gradient_repeat_mode".to_owned(), ShaderDefValue::Int(3));
|
|
|
|
make_shader(device, composer, &temporary_defs,&format!("gradient/{name}.wgsl with pad"), source)
|
|
|
|
},
|
2022-12-25 00:20:57 +00:00
|
|
|
}
|
2022-12-24 23:41:59 +00:00
|
|
|
}
|