blob: 7b9cdb9721d836cb755ad644594aa30acae3cdcd [file] [log] [blame]
// Copyright 2022 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Load rendering shaders.
#[cfg(feature = "wgpu")]
use wgpu::Device;
use crate::ShaderId;
#[cfg(feature = "wgpu")]
use crate::{
recording::{BindType, ImageFormat},
wgpu_engine::WgpuEngine,
Error, RendererOptions,
};
// Shaders for the full pipeline
pub struct FullShaders {
pub pathtag_reduce: ShaderId,
pub pathtag_reduce2: ShaderId,
pub pathtag_scan1: ShaderId,
pub pathtag_scan: ShaderId,
pub pathtag_scan_large: ShaderId,
pub bbox_clear: ShaderId,
pub flatten: ShaderId,
pub draw_reduce: ShaderId,
pub draw_leaf: ShaderId,
pub clip_reduce: ShaderId,
pub clip_leaf: ShaderId,
pub binning: ShaderId,
pub tile_alloc: ShaderId,
pub backdrop: ShaderId,
pub path_count_setup: ShaderId,
pub path_count: ShaderId,
pub coarse: ShaderId,
pub path_tiling_setup: ShaderId,
pub path_tiling: ShaderId,
pub fine_area: Option<ShaderId>,
pub fine_msaa8: Option<ShaderId>,
pub fine_msaa16: Option<ShaderId>,
// 2-level dispatch works for CPU pathtag scan even for large
// inputs, 3-level is not yet implemented.
pub pathtag_is_cpu: bool,
}
#[cfg(feature = "wgpu")]
pub fn full_shaders(
device: &Device,
engine: &mut WgpuEngine,
options: &RendererOptions,
) -> Result<FullShaders, Error> {
use crate::wgpu_engine::CpuShaderType;
use BindType::*;
let mut force_gpu = false;
let force_gpu_from: Option<&str> = None;
// Uncomment this to force use of GPU shaders from the specified shader and later even
// if `engine.use_cpu` is specified.
//let force_gpu_from = Some("binning");
#[cfg(feature = "hot_reload")]
let mut shaders = vello_shaders::compile::ShaderInfo::from_dir(concat!(
env!("CARGO_MANIFEST_DIR"),
"/shader"
));
#[cfg(not(feature = "hot_reload"))]
let shaders = vello_shaders::SHADERS;
macro_rules! add_shader {
($name:ident, $label:expr, $bindings:expr, $cpu:expr) => {{
if force_gpu_from == Some(stringify!($name)) {
force_gpu = true;
}
#[cfg(feature = "hot_reload")]
let source = shaders
.remove(stringify!($name))
.expect(stringify!($name))
.source
.into();
#[cfg(not(feature = "hot_reload"))]
let source = shaders.$name.wgsl.code;
engine.add_shader(
device,
$label,
source,
&$bindings,
if force_gpu {
CpuShaderType::Missing
} else {
$cpu
},
)
}};
($name:ident, $bindings:expr, $cpu:expr) => {{
add_shader!($name, stringify!($name), $bindings, $cpu)
}};
($name:ident, $bindings:expr) => {
add_shader!(
$name,
$bindings,
CpuShaderType::Present(vello_shaders::cpu::$name)
)
};
}
let pathtag_reduce = add_shader!(pathtag_reduce, [Uniform, BufReadOnly, Buffer]);
let pathtag_reduce2 = add_shader!(
pathtag_reduce2,
[BufReadOnly, Buffer],
CpuShaderType::Skipped
);
let pathtag_scan1 = add_shader!(
pathtag_scan1,
[BufReadOnly, BufReadOnly, Buffer],
CpuShaderType::Skipped
);
let pathtag_scan = add_shader!(
pathtag_scan_small,
[Uniform, BufReadOnly, BufReadOnly, Buffer],
CpuShaderType::Present(vello_shaders::cpu::pathtag_scan)
);
let pathtag_scan_large = add_shader!(
pathtag_scan_large,
[Uniform, BufReadOnly, BufReadOnly, Buffer],
CpuShaderType::Skipped
);
let bbox_clear = add_shader!(bbox_clear, [Uniform, Buffer]);
let flatten = add_shader!(
flatten,
[Uniform, BufReadOnly, BufReadOnly, Buffer, Buffer, Buffer]
);
let draw_reduce = add_shader!(draw_reduce, [Uniform, BufReadOnly, Buffer]);
let draw_leaf = add_shader!(
draw_leaf,
[
Uniform,
BufReadOnly,
BufReadOnly,
BufReadOnly,
Buffer,
Buffer,
Buffer,
]
);
let clip_reduce = add_shader!(clip_reduce, [BufReadOnly, BufReadOnly, Buffer, Buffer]);
let clip_leaf = add_shader!(
clip_leaf,
[
Uniform,
BufReadOnly,
BufReadOnly,
BufReadOnly,
BufReadOnly,
Buffer,
Buffer,
]
);
let binning = add_shader!(
binning,
[
Uniform,
BufReadOnly,
BufReadOnly,
BufReadOnly,
Buffer,
Buffer,
Buffer,
Buffer,
]
);
let tile_alloc = add_shader!(
tile_alloc,
[Uniform, BufReadOnly, BufReadOnly, Buffer, Buffer, Buffer]
);
let path_count_setup = add_shader!(path_count_setup, [Buffer, Buffer]);
let path_count = add_shader!(
path_count,
[Uniform, Buffer, BufReadOnly, BufReadOnly, Buffer, Buffer]
);
let backdrop = add_shader!(
backdrop_dyn,
[Uniform, Buffer, BufReadOnly, Buffer],
CpuShaderType::Present(vello_shaders::cpu::backdrop)
);
let coarse = add_shader!(
coarse,
[
Uniform,
BufReadOnly,
BufReadOnly,
BufReadOnly,
BufReadOnly,
BufReadOnly,
Buffer,
Buffer,
Buffer,
]
);
let path_tiling_setup = add_shader!(path_tiling_setup, [Buffer, Buffer, Buffer]);
let path_tiling = add_shader!(
path_tiling,
[
Buffer,
BufReadOnly,
BufReadOnly,
BufReadOnly,
BufReadOnly,
Buffer,
]
);
let fine_resources = [
BindType::Uniform,
BindType::BufReadOnly,
BindType::BufReadOnly,
BindType::BufReadOnly,
BindType::Image(ImageFormat::Rgba8),
BindType::ImageRead(ImageFormat::Rgba8),
BindType::ImageRead(ImageFormat::Rgba8),
// Mask LUT buffer, used only when MSAA is enabled.
BindType::BufReadOnly,
];
let aa_support = &options.antialiasing_support;
let fine_area = if aa_support.area {
Some(add_shader!(
fine_area,
fine_resources[..fine_resources.len() - 1],
CpuShaderType::Missing
))
} else {
None
};
let fine_msaa8 = if aa_support.msaa8 {
Some(add_shader!(
fine_msaa8,
fine_resources,
CpuShaderType::Missing
))
} else {
None
};
let fine_msaa16 = if aa_support.msaa16 {
Some(add_shader!(
fine_msaa16,
fine_resources,
CpuShaderType::Missing
))
} else {
None
};
Ok(FullShaders {
pathtag_reduce,
pathtag_reduce2,
pathtag_scan,
pathtag_scan1,
pathtag_scan_large,
bbox_clear,
flatten,
draw_reduce,
draw_leaf,
clip_reduce,
clip_leaf,
binning,
tile_alloc,
path_count_setup,
path_count,
backdrop,
coarse,
path_tiling_setup,
path_tiling,
fine_area,
fine_msaa8,
fine_msaa16,
pathtag_is_cpu: options.use_cpu,
})
}