mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[rs] Merge #384
384: Add include_spirv macro r=cwfitzgerald,rukai a=kvark Depends on https://github.com/gfx-rs/wgpu/pull/729 Makes out shader loading in the examples a bit tidier. Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
@@ -28,14 +28,14 @@ vulkan = ["wgc/gfx-backend-vulkan"]
|
||||
package = "wgpu-core"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
|
||||
rev = "6bca38feed155aa80776ae5e7dfa4769c655b638"
|
||||
features = ["raw-window-handle"]
|
||||
|
||||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
|
||||
rev = "6bca38feed155aa80776ae5e7dfa4769c655b638"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.5"
|
||||
|
||||
@@ -6,8 +6,6 @@ extern crate rand;
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use wgpu::vertex_attr_array;
|
||||
|
||||
// number of boid particles to simulate
|
||||
|
||||
const NUM_PARTICLES: u32 = 1500;
|
||||
@@ -36,17 +34,9 @@ impl framework::Example for Example {
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
// load (and compile) shaders and create shader modules
|
||||
|
||||
let boids = include_bytes!("boids.comp.spv");
|
||||
let boids_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&boids[..])).unwrap());
|
||||
|
||||
let vs = include_bytes!("shader.vert.spv");
|
||||
let vs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs[..])).unwrap());
|
||||
|
||||
let fs = include_bytes!("shader.frag.spv");
|
||||
let fs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap());
|
||||
let boids_module = device.create_shader_module(wgpu::include_spirv!("boids.comp.spv"));
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("shader.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("shader.frag.spv"));
|
||||
|
||||
// buffer for simulation parameters uniform
|
||||
|
||||
@@ -148,12 +138,12 @@ impl framework::Example for Example {
|
||||
wgpu::VertexBufferDescriptor {
|
||||
stride: 4 * 4,
|
||||
step_mode: wgpu::InputStepMode::Instance,
|
||||
attributes: &vertex_attr_array![0 => Float2, 1 => Float2],
|
||||
attributes: &wgpu::vertex_attr_array![0 => Float2, 1 => Float2],
|
||||
},
|
||||
wgpu::VertexBufferDescriptor {
|
||||
stride: 2 * 4,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![2 => Float2],
|
||||
attributes: &wgpu::vertex_attr_array![2 => Float2],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -234,12 +234,8 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = include_bytes!("shader.vert.spv");
|
||||
let fs_bytes = include_bytes!("shader.frag.spv");
|
||||
let vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap());
|
||||
let fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap());
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("shader.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("shader.frag.spv"));
|
||||
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
|
||||
@@ -47,9 +47,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cs = include_bytes!("shader.comp.spv");
|
||||
let cs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap());
|
||||
let cs_module = device.create_shader_module(wgpu::include_spirv!("shader.comp.spv"));
|
||||
|
||||
let staging_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
|
||||
@@ -32,13 +32,8 @@ async fn run(event_loop: EventLoop<()>, window: Window, swapchain_format: wgpu::
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let vs = include_bytes!("shader.vert.spv");
|
||||
let vs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs[..])).unwrap());
|
||||
|
||||
let fs = include_bytes!("shader.frag.spv");
|
||||
let fs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap());
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("shader.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("shader.frag.spv"));
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[],
|
||||
|
||||
@@ -3,8 +3,6 @@ mod framework;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
use wgpu::vertex_attr_array;
|
||||
|
||||
const TEXTURE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8UnormSrgb;
|
||||
|
||||
#[repr(C)]
|
||||
@@ -105,12 +103,8 @@ impl Example {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
});
|
||||
|
||||
let vs_bytes = include_bytes!("blit.vert.spv");
|
||||
let fs_bytes = include_bytes!("blit.frag.spv");
|
||||
let vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap());
|
||||
let fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap());
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("blit.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("blit.frag.spv"));
|
||||
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
@@ -337,12 +331,8 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = include_bytes!("draw.vert.spv");
|
||||
let fs_bytes = include_bytes!("draw.frag.spv");
|
||||
let vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap());
|
||||
let fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap());
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("draw.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("draw.frag.spv"));
|
||||
|
||||
let draw_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
@@ -374,7 +364,7 @@ impl framework::Example for Example {
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float4],
|
||||
attributes: &wgpu::vertex_attr_array![0 => Float4],
|
||||
}],
|
||||
},
|
||||
sample_count: 1,
|
||||
|
||||
@@ -14,8 +14,6 @@ use std::iter;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
use wgpu::vertex_attr_array;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct Vertex {
|
||||
@@ -81,7 +79,7 @@ impl Example {
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float2, 1 => Float4],
|
||||
attributes: &wgpu::vertex_attr_array![0 => Float2, 1 => Float4],
|
||||
}],
|
||||
},
|
||||
sample_count,
|
||||
@@ -138,12 +136,8 @@ impl framework::Example for Example {
|
||||
log::info!("Press left/right arrow keys to change sample_count.");
|
||||
let sample_count = 4;
|
||||
|
||||
let vs_bytes = include_bytes!("shader.vert.spv");
|
||||
let fs_bytes = include_bytes!("shader.frag.spv");
|
||||
let vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap());
|
||||
let fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap());
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("shader.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("shader.frag.spv"));
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[],
|
||||
|
||||
@@ -5,8 +5,6 @@ mod framework;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
use wgpu::vertex_attr_array;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@@ -426,7 +424,7 @@ impl framework::Example for Example {
|
||||
let vb_desc = wgpu::VertexBufferDescriptor {
|
||||
stride: vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Char4, 1 => Char4],
|
||||
attributes: &wgpu::vertex_attr_array![0 => Char4, 1 => Char4],
|
||||
};
|
||||
|
||||
let shadow_pass = {
|
||||
@@ -466,14 +464,8 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = include_bytes!("bake.vert.spv");
|
||||
let fs_bytes = include_bytes!("bake.frag.spv");
|
||||
let vs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap(),
|
||||
);
|
||||
let fs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap(),
|
||||
);
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("bake.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("bake.frag.spv"));
|
||||
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
@@ -602,14 +594,8 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = include_bytes!("forward.vert.spv");
|
||||
let fs_bytes = include_bytes!("forward.frag.spv");
|
||||
let vs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap(),
|
||||
);
|
||||
let fs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap(),
|
||||
);
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("forward.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("forward.frag.spv"));
|
||||
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
|
||||
@@ -69,12 +69,8 @@ impl framework::Example for Skybox {
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = include_bytes!("shader.vert.spv");
|
||||
let fs_bytes = include_bytes!("shader.frag.spv");
|
||||
let vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap());
|
||||
let fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap());
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("shader.vert.spv"));
|
||||
let fs_module = device.create_shader_module(wgpu::include_spirv!("shader.frag.spv"));
|
||||
|
||||
let aspect = sc_desc.width as f32 / sc_desc.height as f32;
|
||||
let uniforms = Self::generate_uniforms(aspect);
|
||||
|
||||
@@ -97,29 +97,26 @@ impl framework::Example for Example {
|
||||
queue: &wgpu::Queue,
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
let mut uniform_workaround = false;
|
||||
let vs_bytes: &[u8] = include_bytes!("shader.vert.spv");
|
||||
let fs_bytes: &[u8] = match device.capabilities() {
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("shader.vert.spv"));
|
||||
let fs_bytes: Vec<u8> = match device.capabilities() {
|
||||
c if c.contains(wgpu::Capabilities::UNSIZED_BINDING_ARRAY) => {
|
||||
include_bytes!("unsized-non-uniform.frag.spv")
|
||||
include_bytes!("unsized-non-uniform.frag.spv").to_vec()
|
||||
}
|
||||
c if c.contains(wgpu::Capabilities::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING) => {
|
||||
include_bytes!("non-uniform.frag.spv")
|
||||
include_bytes!("non-uniform.frag.spv").to_vec()
|
||||
}
|
||||
c if c.contains(wgpu::Capabilities::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING) => {
|
||||
uniform_workaround = true;
|
||||
include_bytes!("uniform.frag.spv")
|
||||
include_bytes!("uniform.frag.spv").to_vec()
|
||||
}
|
||||
c if c.contains(wgpu::Capabilities::SAMPLED_TEXTURE_BINDING_ARRAY) => {
|
||||
include_bytes!("constant.frag.spv")
|
||||
include_bytes!("constant.frag.spv").to_vec()
|
||||
}
|
||||
_ => {
|
||||
panic!("Graphics adapter does not support any of the capabilities needed for this example");
|
||||
}
|
||||
};
|
||||
let vs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(vs_bytes)).unwrap());
|
||||
let fs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(fs_bytes)).unwrap());
|
||||
let fs_module = device.create_shader_module(wgpu::util::make_spirv(&fs_bytes));
|
||||
|
||||
let vertex_size = std::mem::size_of::<Vertex>();
|
||||
let vertex_data = create_vertices();
|
||||
|
||||
@@ -4,8 +4,7 @@ mod framework;
|
||||
mod point_gen;
|
||||
|
||||
use cgmath::Point3;
|
||||
use std::{io, mem};
|
||||
use wgpu::vertex_attr_array;
|
||||
use std::mem;
|
||||
|
||||
///
|
||||
/// Radius of the terrain.
|
||||
@@ -477,23 +476,15 @@ impl framework::Example for Example {
|
||||
label: Some("Terrain Flipped Bind Group"),
|
||||
});
|
||||
|
||||
// Read shaders from file.
|
||||
let water_vs_bytes = include_bytes!("water_shader.vert.spv");
|
||||
let water_fs_bytes = include_bytes!("water_shader.frag.spv");
|
||||
// Upload/compile them to GPU code.
|
||||
let water_vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(io::Cursor::new(&water_vs_bytes[..])).unwrap());
|
||||
let water_fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(io::Cursor::new(&water_fs_bytes[..])).unwrap());
|
||||
|
||||
let terrain_vs_bytes = include_bytes!("terrain_shader.vert.spv");
|
||||
let terrain_fs_bytes = include_bytes!("terrain_shader.frag.spv");
|
||||
let terrain_vs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(io::Cursor::new(&terrain_vs_bytes[..])).unwrap(),
|
||||
);
|
||||
let terrain_fs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(io::Cursor::new(&terrain_fs_bytes[..])).unwrap(),
|
||||
);
|
||||
let water_vs_module =
|
||||
device.create_shader_module(wgpu::include_spirv!("water_shader.vert.spv"));
|
||||
let water_fs_module =
|
||||
device.create_shader_module(wgpu::include_spirv!("water_shader.frag.spv"));
|
||||
let terrain_vs_module =
|
||||
device.create_shader_module(wgpu::include_spirv!("terrain_shader.vert.spv"));
|
||||
let terrain_fs_module =
|
||||
device.create_shader_module(wgpu::include_spirv!("terrain_shader.frag.spv"));
|
||||
|
||||
// Create the render pipelines. These describe how the data will flow through the GPU, and what
|
||||
// constraints and modifiers it will have.
|
||||
@@ -566,7 +557,7 @@ impl framework::Example for Example {
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: water_vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Short2, 1 => Char4],
|
||||
attributes: &wgpu::vertex_attr_array![0 => Short2, 1 => Char4],
|
||||
}],
|
||||
},
|
||||
sample_count: 1,
|
||||
@@ -613,7 +604,7 @@ impl framework::Example for Example {
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: terrain_vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float3, 1 => Float3, 2 => Uchar4Norm],
|
||||
attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Float3, 2 => Uchar4Norm],
|
||||
}],
|
||||
},
|
||||
sample_count: 1,
|
||||
|
||||
@@ -2,7 +2,8 @@ use crate::{
|
||||
backend::native_gpu_future, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource,
|
||||
BufferDescriptor, Capabilities, CommandEncoderDescriptor, ComputePipelineDescriptor,
|
||||
Extensions, Limits, MapMode, PipelineLayoutDescriptor, RenderPipelineDescriptor,
|
||||
SamplerDescriptor, SwapChainStatus, TextureDescriptor, TextureViewDescriptor,
|
||||
SamplerDescriptor, ShaderModuleSource, SwapChainStatus, TextureDescriptor,
|
||||
TextureViewDescriptor,
|
||||
};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
@@ -402,15 +403,13 @@ impl crate::Context for Context {
|
||||
fn device_create_shader_module(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
spv: &[u32],
|
||||
source: ShaderModuleSource,
|
||||
) -> Self::ShaderModuleId {
|
||||
let desc = wgc::pipeline::ShaderModuleDescriptor {
|
||||
code: wgc::U32Array {
|
||||
bytes: spv.as_ptr(),
|
||||
length: spv.len(),
|
||||
},
|
||||
let desc = match source {
|
||||
ShaderModuleSource::SpirV(spv) => wgc::pipeline::ShaderModuleSource::SpirV(spv),
|
||||
ShaderModuleSource::Wgsl(code) => wgc::pipeline::ShaderModuleSource::Wgsl(code),
|
||||
};
|
||||
gfx_select!(*device => self.device_create_shader_module(*device, &desc, PhantomData))
|
||||
gfx_select!(*device => self.device_create_shader_module(*device, desc, PhantomData))
|
||||
}
|
||||
|
||||
fn device_create_bind_group_layout(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BindingType, BufferDescriptor,
|
||||
CommandEncoderDescriptor, ComputePipelineDescriptor, PipelineLayoutDescriptor,
|
||||
ProgrammableStageDescriptor, RenderPipelineDescriptor, SamplerDescriptor, SwapChainStatus,
|
||||
TextureDescriptor, TextureViewDescriptor, TextureViewDimension,
|
||||
ProgrammableStageDescriptor, RenderPipelineDescriptor, SamplerDescriptor, ShaderModuleSource,
|
||||
SwapChainStatus, TextureDescriptor, TextureViewDescriptor, TextureViewDimension,
|
||||
};
|
||||
|
||||
use futures::FutureExt;
|
||||
@@ -773,9 +773,16 @@ impl crate::Context for Context {
|
||||
fn device_create_shader_module(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
spv: &[u32],
|
||||
source: ShaderModuleSource,
|
||||
) -> Self::ShaderModuleId {
|
||||
let desc = web_sys::GpuShaderModuleDescriptor::new(&js_sys::Uint32Array::from(spv));
|
||||
let desc = match source {
|
||||
ShaderModuleSource::SpirV(spv) => {
|
||||
web_sys::GpuShaderModuleDescriptor::new(&js_sys::Uint32Array::from(spv))
|
||||
}
|
||||
ShaderModuleSource::Wgsl(code) => {
|
||||
panic!("WGSL is not yet supported by the Web backend")
|
||||
}
|
||||
};
|
||||
// TODO: label
|
||||
Sendable(device.0.create_shader_module(&desc))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! A cross-platform graphics and compute library based on WebGPU.
|
||||
|
||||
mod backend;
|
||||
mod util;
|
||||
pub mod util;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
@@ -33,7 +33,6 @@ pub use wgt::{
|
||||
};
|
||||
|
||||
use backend::Context as C;
|
||||
pub use util::read_spirv;
|
||||
|
||||
trait ComputePassInner<Ctx: Context> {
|
||||
fn set_pipeline(&mut self, pipeline: &Ctx::ComputePipelineId);
|
||||
@@ -162,7 +161,7 @@ trait Context: Sized {
|
||||
fn device_create_shader_module(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
spv: &[u32],
|
||||
source: ShaderModuleSource,
|
||||
) -> Self::ShaderModuleId;
|
||||
fn device_create_bind_group_layout(
|
||||
&self,
|
||||
@@ -571,6 +570,20 @@ impl Drop for ShaderModule {
|
||||
}
|
||||
}
|
||||
|
||||
/// Source of a shader module.
|
||||
pub enum ShaderModuleSource<'a> {
|
||||
/// SPIR-V module represented as a slice of words.
|
||||
/// wgpu-rs will try to reflect it and use for validation, but the
|
||||
/// original data is passed to gfx-rs and spirv_cross for translation.
|
||||
SpirV(&'a [u32]),
|
||||
/// WGSL module as a string slice.
|
||||
/// wgpu-rs will parse it and use for validation. It will attempt
|
||||
/// to build a SPIR-V module internally and panic otherwise.
|
||||
///
|
||||
/// Note: WGSL is not yet supported on the Web.
|
||||
Wgsl(&'a str),
|
||||
}
|
||||
|
||||
/// An opaque handle to a pipeline layout.
|
||||
///
|
||||
/// A `PipelineLayout` object describes the available binding groups of a pipeline.
|
||||
@@ -1046,11 +1059,11 @@ impl Device {
|
||||
Context::device_capabilities(&*self.context, &self.id)
|
||||
}
|
||||
|
||||
/// Creates a shader module from SPIR-V source code.
|
||||
pub fn create_shader_module(&self, spv: &[u32]) -> ShaderModule {
|
||||
/// Creates a shader module from either SPIR-V or WGSL source code.
|
||||
pub fn create_shader_module(&self, source: ShaderModuleSource) -> ShaderModule {
|
||||
ShaderModule {
|
||||
context: Arc::clone(&self.context),
|
||||
id: Context::device_create_shader_module(&*self.context, &self.id, spv),
|
||||
id: Context::device_create_shader_module(&*self.context, &self.id, source),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,3 +135,13 @@ fn test_vertex_attr_array() {
|
||||
assert_eq!(attrs[1].offset, std::mem::size_of::<(f32, f32)>() as u64);
|
||||
assert_eq!(attrs[1].shader_location, 3);
|
||||
}
|
||||
|
||||
/// Macro to load a SPIR-V module statically.
|
||||
///
|
||||
/// It ensure the word alignment as well as the magic number.
|
||||
#[macro_export]
|
||||
macro_rules! include_spirv {
|
||||
($path:literal) => {
|
||||
$crate::util::make_spirv(&$crate::util::WordAligned(*include_bytes!($path)).0)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,41 +1,18 @@
|
||||
use std::{io, slice};
|
||||
#[repr(align(4))]
|
||||
pub struct WordAligned<Bytes: ?Sized>(pub Bytes);
|
||||
|
||||
// TODO: This is copy/pasted from gfx-hal, so we need to find a new place to put
|
||||
// this function
|
||||
pub fn read_spirv<R: io::Read + io::Seek>(mut x: R) -> io::Result<Vec<u32>> {
|
||||
let size = x.seek(io::SeekFrom::End(0))?;
|
||||
if size % 4 != 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"input length not divisible by 4",
|
||||
));
|
||||
}
|
||||
if size > usize::max_value() as u64 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "input too long"));
|
||||
}
|
||||
let words = (size / 4) as usize;
|
||||
let mut result = Vec::<u32>::with_capacity(words);
|
||||
x.seek(io::SeekFrom::Start(0))?;
|
||||
unsafe {
|
||||
// Writing all bytes through a pointer with less strict alignment when our type has no
|
||||
// invalid bitpatterns is safe.
|
||||
x.read_exact(slice::from_raw_parts_mut(
|
||||
result.as_mut_ptr() as *mut u8,
|
||||
words * 4,
|
||||
))?;
|
||||
result.set_len(words);
|
||||
}
|
||||
/// Treat the given by slice as a SPIR-V module.
|
||||
/// The pointer has to be aligned to 32-bit boundary and be a valid SPIR-V binary.
|
||||
pub fn make_spirv<'a>(data: &'a [u8]) -> super::ShaderModuleSource<'a> {
|
||||
const MAGIC_NUMBER: u32 = 0x0723_0203;
|
||||
if !result.is_empty() && result[0] == MAGIC_NUMBER.swap_bytes() {
|
||||
for word in &mut result {
|
||||
*word = word.swap_bytes();
|
||||
}
|
||||
}
|
||||
if result.is_empty() || result[0] != MAGIC_NUMBER {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"input missing SPIR-V magic number",
|
||||
));
|
||||
}
|
||||
Ok(result)
|
||||
|
||||
let (pre, words, post) = unsafe { data.align_to::<u32>() };
|
||||
assert_eq!(pre, &[], "data offset is not aligned to words!");
|
||||
assert_eq!(post, &[], "data size is not aligned to words!");
|
||||
assert_eq!(
|
||||
words[0], MAGIC_NUMBER,
|
||||
"wrong magic word {:x}. Make sure you are using a binary SPIRV file.",
|
||||
words[0]
|
||||
);
|
||||
super::ShaderModuleSource::SpirV(words)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user