example-runner-wgpu: add --force-spirv-passthru for testing.

This commit is contained in:
Eduard-Mihai Burtescu 2023-04-17 09:06:11 +03:00 committed by Eduard-Mihai Burtescu
parent 4252427f89
commit 2ed23d0013
3 changed files with 56 additions and 21 deletions

View File

@ -12,8 +12,8 @@ pub fn start(options: &Options) {
}
pub async fn start_internal(
_options: &Options,
shader_binary: wgpu::ShaderModuleDescriptor<'static>,
options: &Options,
shader_binary: wgpu::ShaderModuleDescriptorSpirV<'static>,
) {
let backends = wgpu::util::backend_bits_from_env().unwrap_or(wgpu::Backends::PRIMARY);
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
@ -24,11 +24,16 @@ pub async fn start_internal(
.await
.expect("Failed to find an appropriate adapter");
let mut features = wgpu::Features::TIMESTAMP_QUERY;
if options.force_spirv_passthru {
features |= wgpu::Features::SPIRV_SHADER_PASSTHROUGH;
}
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::TIMESTAMP_QUERY,
features,
limits: wgpu::Limits::default(),
},
None,
@ -40,8 +45,16 @@ pub async fn start_internal(
let timestamp_period = queue.get_timestamp_period();
// Load the shaders from disk
let module = device.create_shader_module(shader_binary);
// FIXME(eddyb) automate this decision by default.
let module = if options.force_spirv_passthru {
unsafe { device.create_shader_module_spirv(&shader_binary) }
} else {
let wgpu::ShaderModuleDescriptorSpirV { label, source } = shader_binary;
device.create_shader_module(wgpu::ShaderModuleDescriptor {
label,
source: wgpu::ShaderSource::SpirV(source),
})
};
let top = 2u32.pow(20);
let src_range = 1..top;

View File

@ -33,9 +33,10 @@ fn mouse_button_index(button: MouseButton) -> usize {
}
async fn run(
event_loop: EventLoop<wgpu::ShaderModuleDescriptor<'static>>,
options: Options,
event_loop: EventLoop<wgpu::ShaderModuleDescriptorSpirV<'static>>,
window: Window,
shader_binary: wgpu::ShaderModuleDescriptor<'static>,
shader_binary: wgpu::ShaderModuleDescriptorSpirV<'static>,
) {
let backends = wgpu::util::backend_bits_from_env()
.unwrap_or(wgpu::Backends::VULKAN | wgpu::Backends::METAL);
@ -69,7 +70,10 @@ async fn run(
.await
.expect("Failed to find an appropriate adapter");
let features = wgpu::Features::PUSH_CONSTANTS;
let mut features = wgpu::Features::PUSH_CONSTANTS;
if options.force_spirv_passthru {
features |= wgpu::Features::SPIRV_SHADER_PASSTHROUGH;
}
let limits = wgpu::Limits {
max_push_constant_size: 128,
..Default::default()
@ -124,6 +128,7 @@ async fn run(
});
let mut render_pipeline = create_pipeline(
&options,
&device,
&pipeline_layout,
surface_with_config.as_ref().map_or_else(
@ -309,6 +314,7 @@ async fn run(
}
Event::UserEvent(new_module) => {
*render_pipeline = create_pipeline(
&options,
&device,
&pipeline_layout,
surface_with_config.as_ref().map_or_else(
@ -326,12 +332,22 @@ async fn run(
}
fn create_pipeline(
options: &Options,
device: &wgpu::Device,
pipeline_layout: &wgpu::PipelineLayout,
surface_format: wgpu::TextureFormat,
shader_binary: wgpu::ShaderModuleDescriptor<'_>,
shader_binary: wgpu::ShaderModuleDescriptorSpirV<'_>,
) -> wgpu::RenderPipeline {
let module = device.create_shader_module(shader_binary);
// FIXME(eddyb) automate this decision by default.
let module = if options.force_spirv_passthru {
unsafe { device.create_shader_module_spirv(&shader_binary) }
} else {
let wgpu::ShaderModuleDescriptorSpirV { label, source } = shader_binary;
device.create_shader_module(wgpu::ShaderModuleDescriptor {
label,
source: wgpu::ShaderSource::SpirV(source),
})
};
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(pipeline_layout),
@ -425,16 +441,17 @@ pub fn start(
})
.expect("couldn't append canvas to document body");
wasm_bindgen_futures::spawn_local(run(
options.clone(),
event_loop,
window,
initial_shader,
));
} else {
futures::executor::block_on(run(
options.clone(),
event_loop,
window,
initial_shader,
));
}
}

View File

@ -90,9 +90,9 @@ pub enum RustGPUShader {
fn maybe_watch(
shader: RustGPUShader,
#[cfg(not(any(target_os = "android", target_arch = "wasm32")))] on_watch: Option<
Box<dyn FnMut(wgpu::ShaderModuleDescriptor<'static>) + Send + 'static>,
Box<dyn FnMut(wgpu::ShaderModuleDescriptorSpirV<'static>) + Send + 'static>,
>,
) -> wgpu::ShaderModuleDescriptor<'static> {
) -> wgpu::ShaderModuleDescriptorSpirV<'static> {
#[cfg(not(any(target_os = "android", target_arch = "wasm32")))]
{
use spirv_builder::{CompileResult, MetadataPrintout, SpirvBuilder};
@ -128,13 +128,15 @@ fn maybe_watch(
};
fn handle_compile_result(
compile_result: CompileResult,
) -> wgpu::ShaderModuleDescriptor<'static> {
) -> wgpu::ShaderModuleDescriptorSpirV<'static> {
let module_path = compile_result.module.unwrap_single();
let data = std::fs::read(module_path).unwrap();
// FIXME(eddyb) this reallocates all the data pointlessly, there is
// not a good reason to use `ShaderModuleDescriptorSpirV` specifically.
let spirv = Cow::Owned(wgpu::util::make_spirv_raw(&data).into_owned());
wgpu::ShaderModuleDescriptor {
wgpu::ShaderModuleDescriptorSpirV {
label: None,
source: wgpu::ShaderSource::SpirV(spirv),
source: spirv,
}
}
handle_compile_result(initial_result)
@ -142,19 +144,22 @@ fn maybe_watch(
#[cfg(any(target_os = "android", target_arch = "wasm32"))]
{
match shader {
RustGPUShader::Simplest => wgpu::include_spirv!(env!("simplest_shader.spv")),
RustGPUShader::Sky => wgpu::include_spirv!(env!("sky_shader.spv")),
RustGPUShader::Compute => wgpu::include_spirv!(env!("compute_shader.spv")),
RustGPUShader::Mouse => wgpu::include_spirv!(env!("mouse_shader.spv")),
RustGPUShader::Simplest => wgpu::include_spirv_raw!(env!("simplest_shader.spv")),
RustGPUShader::Sky => wgpu::include_spirv_raw!(env!("sky_shader.spv")),
RustGPUShader::Compute => wgpu::include_spirv_raw!(env!("compute_shader.spv")),
RustGPUShader::Mouse => wgpu::include_spirv_raw!(env!("mouse_shader.spv")),
}
}
}
#[derive(StructOpt)]
#[derive(StructOpt, Clone)]
#[structopt(name = "example-runner-wgpu")]
pub struct Options {
#[structopt(short, long, default_value = "Sky")]
shader: RustGPUShader,
#[structopt(long)]
force_spirv_passthru: bool,
}
#[cfg_attr(target_os = "android", export_name = "android_main")]