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

View File

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

View File

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