Naga update, remove spirv_headers dependency

This commit is contained in:
Dzmitry Malyshau 2020-07-21 11:54:42 -04:00
parent 4ed2c0a313
commit 82d149b871
8 changed files with 80 additions and 72 deletions

4
Cargo.lock generated
View File

@ -780,13 +780,14 @@ dependencies = [
[[package]] [[package]]
name = "naga" name = "naga"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/gfx-rs/naga?rev=a9228d2aed38c71388489a95817238ff98198fa3#a9228d2aed38c71388489a95817238ff98198fa3" source = "git+https://github.com/gfx-rs/naga?rev=94802078c3bc5d138f497419ea3e7a869f10916d#94802078c3bc5d138f497419ea3e7a869f10916d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"fxhash", "fxhash",
"log", "log",
"num-traits", "num-traits",
"spirv_headers", "spirv_headers",
"thiserror",
] ]
[[package]] [[package]]
@ -1617,7 +1618,6 @@ dependencies = [
"ron", "ron",
"serde", "serde",
"smallvec", "smallvec",
"spirv_headers",
"thiserror", "thiserror",
"thread-id", "thread-id",
"tracing", "tracing",

View File

@ -12,7 +12,7 @@
use wgc::device::trace; use wgc::device::trace;
use std::{ffi::CString, fmt::Debug, fs, marker::PhantomData, path::Path, ptr}; use std::{borrow::Cow, ffi::CString, fmt::Debug, fs, marker::PhantomData, path::Path, ptr};
#[macro_export] #[macro_export]
macro_rules! gfx_select { macro_rules! gfx_select {
@ -226,16 +226,19 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
self.bind_group_destroy::<B>(id); self.bind_group_destroy::<B>(id);
} }
A::CreateShaderModule { id, data } => { A::CreateShaderModule { id, data } => {
let source = if data.ends_with(".wgsl") {
let code = fs::read_to_string(dir.join(data)).unwrap();
wgc::pipeline::ShaderModuleSource::Wgsl(Cow::Owned(code))
} else {
let byte_vec = fs::read(dir.join(data)).unwrap(); let byte_vec = fs::read(dir.join(data)).unwrap();
let spv = byte_vec let spv = byte_vec
.chunks(4) .chunks(4)
.map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]])) .map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]]))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.device_create_shader_module::<B>( wgc::pipeline::ShaderModuleSource::SpirV(Cow::Owned(spv))
device, };
wgc::pipeline::ShaderModuleSource::SpirV(&spv), self.device_create_shader_module::<B>(device, source, id)
id, .unwrap();
);
} }
A::DestroyShaderModule(id) => { A::DestroyShaderModule(id) => {
self.shader_module_destroy::<B>(id); self.shader_module_destroy::<B>(id);

View File

@ -35,7 +35,6 @@ raw-window-handle = { version = "0.3", optional = true }
ron = { version = "0.5", optional = true } ron = { version = "0.5", optional = true }
serde = { version = "1.0", features = ["serde_derive"], optional = true } serde = { version = "1.0", features = ["serde_derive"], optional = true }
smallvec = "1" smallvec = "1"
spirv_headers = { version = "1.4.2" }
thread-id = { version = "3", optional = true } thread-id = { version = "3", optional = true }
tracing = { version = "0.1", default-features = false, features = ["std"] } tracing = { version = "0.1", default-features = false, features = ["std"] }
tracing-subscriber = { version = "0.2", optional = true } tracing-subscriber = { version = "0.2", optional = true }
@ -43,7 +42,8 @@ thiserror = "1"
[dependencies.naga] [dependencies.naga]
git = "https://github.com/gfx-rs/naga" git = "https://github.com/gfx-rs/naga"
rev = "a9228d2aed38c71388489a95817238ff98198fa3" rev = "94802078c3bc5d138f497419ea3e7a869f10916d"
features = ["spirv"]
[dependencies.gfx-descriptor] [dependencies.gfx-descriptor]
git = "https://github.com/gfx-rs/gfx-extras" git = "https://github.com/gfx-rs/gfx-extras"

View File

@ -35,6 +35,7 @@
buffer. Thanks to the "normalized" property, it doesn't track any bind group buffer. Thanks to the "normalized" property, it doesn't track any bind group
invalidations or index format changes. invalidations or index format changes.
!*/ !*/
#![allow(clippy::reversed_empty_ranges)]
use crate::{ use crate::{
binding_model::PushConstantUploadError, binding_model::PushConstantUploadError,

View File

@ -28,12 +28,10 @@ use thiserror::Error;
use wgt::{BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat}; use wgt::{BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat};
use std::{ use std::{
collections::hash_map::Entry, ffi, iter, marker::PhantomData, mem, ops::Range, ptr, borrow::Cow, collections::hash_map::Entry, ffi, iter, marker::PhantomData, mem, ops::Range,
sync::atomic::Ordering, ptr, sync::atomic::Ordering,
}; };
use spirv_headers::ExecutionModel;
mod life; mod life;
mod queue; mod queue;
#[cfg(any(feature = "trace", feature = "replay"))] #[cfg(any(feature = "trace", feature = "replay"))]
@ -1888,14 +1886,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: id::DeviceId, device_id: id::DeviceId,
source: pipeline::ShaderModuleSource, source: pipeline::ShaderModuleSource,
id_in: Input<G, id::ShaderModuleId>, id_in: Input<G, id::ShaderModuleId>,
) -> id::ShaderModuleId { ) -> Result<id::ShaderModuleId, CreateShaderModuleError> {
span!(_guard, INFO, "Device::create_shader_module"); span!(_guard, INFO, "Device::create_shader_module");
let hub = B::hub(self); let hub = B::hub(self);
let mut token = Token::root(); let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token); let (device_guard, mut token) = hub.devices.read(&mut token);
let device = &device_guard[device_id]; let device = &device_guard[device_id];
let spv_owned;
let spv_flags = if cfg!(debug_assertions) { let spv_flags = if cfg!(debug_assertions) {
naga::back::spv::WriterFlags::DEBUG naga::back::spv::WriterFlags::DEBUG
} else { } else {
@ -1920,10 +1917,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
(spv, module) (spv, module)
} }
pipeline::ShaderModuleSource::Wgsl(code) => { pipeline::ShaderModuleSource::Wgsl(code) => {
let module = naga::front::wgsl::parse_str(code).unwrap(); let module = naga::front::wgsl::parse_str(&code).unwrap();
spv_owned = naga::back::spv::Writer::new(&module.header, spv_flags).write(&module); let spv = naga::back::spv::Writer::new(&module.header, spv_flags).write(&module);
( (
spv_owned.as_slice(), Cow::Owned(spv),
if device.private_features.shader_validation { if device.private_features.shader_validation {
Some(module) Some(module)
} else { } else {
@ -1932,9 +1929,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
) )
} }
pipeline::ShaderModuleSource::Naga(module) => { pipeline::ShaderModuleSource::Naga(module) => {
spv_owned = naga::back::spv::Writer::new(&module.header, spv_flags).write(&module); let spv = naga::back::spv::Writer::new(&module.header, spv_flags).write(&module);
( (
spv_owned.as_slice(), Cow::Owned(spv),
if device.private_features.shader_validation { if device.private_features.shader_validation {
Some(module) Some(module)
} else { } else {
@ -1944,8 +1941,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
}; };
if let Some(ref module) = naga {
naga::proc::Validator::new().validate(module)?;
}
let shader = pipeline::ShaderModule { let shader = pipeline::ShaderModule {
raw: unsafe { device.raw.create_shader_module(spv).unwrap() }, raw: unsafe { device.raw.create_shader_module(&spv).unwrap() },
device_id: Stored { device_id: Stored {
value: device_id, value: device_id,
ref_count: device.life_guard.add_ref(), ref_count: device.life_guard.add_ref(),
@ -1967,7 +1968,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
None => {} None => {}
}; };
id Ok(id)
} }
pub fn shader_module_destroy<B: GfxBackend>(&self, shader_module_id: id::ShaderModuleId) { pub fn shader_module_destroy<B: GfxBackend>(&self, shader_module_id: id::ShaderModuleId) {
@ -2259,7 +2260,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
module, module,
&group_layouts, &group_layouts,
&entry_point_name, &entry_point_name,
ExecutionModel::Vertex, naga::ShaderStage::Vertex,
interface, interface,
) )
.map_err(|error| pipeline::RenderPipelineError::Stage { flag, error })?; .map_err(|error| pipeline::RenderPipelineError::Stage { flag, error })?;
@ -2286,7 +2287,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
module, module,
&group_layouts, &group_layouts,
&entry_point_name, &entry_point_name,
ExecutionModel::Fragment, naga::ShaderStage::Fragment,
interface, interface,
) )
.map_err(|error| { .map_err(|error| {
@ -2486,7 +2487,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
module, module,
&group_layouts, &group_layouts,
&entry_point_name, &entry_point_name,
ExecutionModel::GLCompute, naga::ShaderStage::Compute,
interface, interface,
) )
.map_err(pipeline::ComputePipelineError::Stage)?; .map_err(pipeline::ComputePipelineError::Stage)?;
@ -3012,3 +3013,9 @@ pub enum BufferMapError {
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
#[error("buffer is not mapped")] #[error("buffer is not mapped")]
pub struct BufferNotMappedError; pub struct BufferNotMappedError;
#[derive(Clone, Debug, Error)]
pub enum CreateShaderModuleError {
#[error(transparent)]
Validation(#[from] naga::proc::ValidationError),
}

View File

@ -8,14 +8,14 @@ use crate::{
validation::StageError, validation::StageError,
LifeGuard, RefCount, Stored, LifeGuard, RefCount, Stored,
}; };
use std::borrow::Borrow; use std::borrow::{Borrow, Cow};
use wgt::{BufferAddress, IndexFormat, InputStepMode}; use wgt::{BufferAddress, IndexFormat, InputStepMode};
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
pub enum ShaderModuleSource<'a> { pub enum ShaderModuleSource<'a> {
SpirV(&'a [u32]), SpirV(Cow<'a, [u32]>),
Wgsl(&'a str), Wgsl(Cow<'a, str>),
Naga(naga::Module), Naga(naga::Module),
} }

View File

@ -41,10 +41,7 @@ use crate::{
resource, span, LifeGuard, PrivateFeatures, Stored, SubmissionIndex, resource, span, LifeGuard, PrivateFeatures, Stored, SubmissionIndex,
}; };
use hal::{ use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _};
self, device::Device as _, queue::CommandQueue as _,
window::PresentationSurface as _,
};
use thiserror::Error; use thiserror::Error;
use wgt::{SwapChainDescriptor, SwapChainStatus}; use wgt::{SwapChainDescriptor, SwapChainStatus};
@ -129,12 +126,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(err) => ( Err(err) => (
None, None,
match err { match err {
hal::window::AcquireError::OutOfMemory(_) => return Err(SwapChainError::OutOfMemory), hal::window::AcquireError::OutOfMemory(_) => {
return Err(SwapChainError::OutOfMemory)
}
hal::window::AcquireError::NotReady => unreachable!(), // we always set a timeout hal::window::AcquireError::NotReady => unreachable!(), // we always set a timeout
hal::window::AcquireError::Timeout => SwapChainStatus::Timeout, hal::window::AcquireError::Timeout => SwapChainStatus::Timeout,
hal::window::AcquireError::OutOfDate => SwapChainStatus::Outdated, hal::window::AcquireError::OutOfDate => SwapChainStatus::Outdated,
hal::window::AcquireError::SurfaceLost(_) => SwapChainStatus::Lost, hal::window::AcquireError::SurfaceLost(_) => SwapChainStatus::Lost,
hal::window::AcquireError::DeviceLost(_) => return Err(SwapChainError::DeviceLost), hal::window::AcquireError::DeviceLost(_) => {
return Err(SwapChainError::DeviceLost)
}
}, },
), ),
}; };

View File

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::{binding_model::BindEntryMap, FastHashMap}; use crate::{binding_model::BindEntryMap, FastHashMap};
use spirv_headers as spirv;
use thiserror::Error; use thiserror::Error;
use wgt::{BindGroupLayoutEntry, BindingType}; use wgt::{BindGroupLayoutEntry, BindingType};
@ -60,7 +59,10 @@ pub enum BindingError {
#[error("buffer structure size {0}, added to one element of an unbound array, if it's the last field, ended up greater than the given `min_binding_size`")] #[error("buffer structure size {0}, added to one element of an unbound array, if it's the last field, ended up greater than the given `min_binding_size`")]
WrongBufferSize(wgt::BufferAddress), WrongBufferSize(wgt::BufferAddress),
#[error("view dimension {dim:?} (is array: {is_array}) doesn't match the shader")] #[error("view dimension {dim:?} (is array: {is_array}) doesn't match the shader")]
WrongTextureViewDimension { dim: spirv::Dim, is_array: bool }, WrongTextureViewDimension {
dim: naga::ImageDimension,
is_array: bool,
},
#[error("component type {0:?} of a sampled texture doesn't match the shader")] #[error("component type {0:?} of a sampled texture doesn't match the shader")]
WrongTextureComponentType(Option<naga::ScalarKind>), WrongTextureComponentType(Option<naga::ScalarKind>),
#[error("texture sampling capability doesn't match the shader")] #[error("texture sampling capability doesn't match the shader")]
@ -83,7 +85,7 @@ pub enum InputError {
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
pub enum StageError { pub enum StageError {
#[error("unable to find an entry point matching the {0:?} execution model")] #[error("unable to find an entry point matching the {0:?} execution model")]
MissingEntryPoint(spirv::ExecutionModel), MissingEntryPoint(naga::ShaderStage),
#[error("error matching global binding at index {binding} in set {set} against the pipeline layout: {error}")] #[error("error matching global binding at index {binding} in set {set} against the pipeline layout: {error}")]
Binding { Binding {
set: u32, set: u32,
@ -143,7 +145,14 @@ fn get_aligned_type_size(
None => get_aligned_type_size(module, base, false), None => get_aligned_type_size(module, base, false),
}, },
Ti::Struct { ref members } => members.last().map_or(0, |member| { Ti::Struct { ref members } => members.last().map_or(0, |member| {
member.offset as wgt::BufferAddress + get_aligned_type_size(module, member.ty, false) let offset = match member.origin {
naga::MemberOrigin::BuiltIn(_) => {
log::error!("Missing offset on a struct member");
0 // TODO: make it a proper error
}
naga::MemberOrigin::Offset(offset) => offset as wgt::BufferAddress,
};
offset + get_aligned_type_size(module, member.ty, false)
}), }),
_ => panic!("Unexpected struct field"), _ => panic!("Unexpected struct field"),
} }
@ -155,12 +164,7 @@ fn check_binding(
entry: &BindGroupLayoutEntry, entry: &BindGroupLayoutEntry,
usage: naga::GlobalUse, usage: naga::GlobalUse,
) -> Result<(), BindingError> { ) -> Result<(), BindingError> {
let mut ty_inner = &module.types[var.ty].inner; let allowed_usage = match module.types[var.ty].inner {
//TODO: change naga's IR to avoid a pointer here
if let naga::TypeInner::Pointer { base, class: _ } = *ty_inner {
ty_inner = &module.types[base].inner;
}
let allowed_usage = match *ty_inner {
naga::TypeInner::Struct { ref members } => { naga::TypeInner::Struct { ref members } => {
let (allowed_usage, min_size) = match entry.ty { let (allowed_usage, min_size) = match entry.ty {
BindingType::UniformBuffer { BindingType::UniformBuffer {
@ -224,8 +228,8 @@ fn check_binding(
}; };
if flags.contains(naga::ImageFlags::ARRAYED) { if flags.contains(naga::ImageFlags::ARRAYED) {
match (dim, view_dimension) { match (dim, view_dimension) {
(spirv::Dim::Dim2D, wgt::TextureViewDimension::D2Array) => (), (naga::ImageDimension::D2, wgt::TextureViewDimension::D2Array) => (),
(spirv::Dim::DimCube, wgt::TextureViewDimension::CubeArray) => (), (naga::ImageDimension::Cube, wgt::TextureViewDimension::CubeArray) => (),
_ => { _ => {
return Err(BindingError::WrongTextureViewDimension { return Err(BindingError::WrongTextureViewDimension {
dim, dim,
@ -235,10 +239,10 @@ fn check_binding(
} }
} else { } else {
match (dim, view_dimension) { match (dim, view_dimension) {
(spirv::Dim::Dim1D, wgt::TextureViewDimension::D1) => (), (naga::ImageDimension::D1, wgt::TextureViewDimension::D1) => (),
(spirv::Dim::Dim2D, wgt::TextureViewDimension::D2) => (), (naga::ImageDimension::D2, wgt::TextureViewDimension::D2) => (),
(spirv::Dim::Dim3D, wgt::TextureViewDimension::D3) => (), (naga::ImageDimension::D3, wgt::TextureViewDimension::D3) => (),
(spirv::Dim::DimCube, wgt::TextureViewDimension::Cube) => (), (naga::ImageDimension::Cube, wgt::TextureViewDimension::Cube) => (),
_ => { _ => {
return Err(BindingError::WrongTextureViewDimension { return Err(BindingError::WrongTextureViewDimension {
dim, dim,
@ -658,7 +662,7 @@ pub fn check_stage<'a>(
module: &'a naga::Module, module: &'a naga::Module,
group_layouts: &[&BindEntryMap], group_layouts: &[&BindEntryMap],
entry_point_name: &str, entry_point_name: &str,
execution_model: spirv::ExecutionModel, stage: naga::ShaderStage,
inputs: StageInterface<'a>, inputs: StageInterface<'a>,
) -> Result<StageInterface<'a>, StageError> { ) -> Result<StageInterface<'a>, StageError> {
// Since a shader module can have multiple entry points with the same name, // Since a shader module can have multiple entry points with the same name,
@ -666,16 +670,12 @@ pub fn check_stage<'a>(
let entry_point = module let entry_point = module
.entry_points .entry_points
.iter() .iter()
.find(|entry_point| { .find(|entry_point| entry_point.name == entry_point_name && entry_point.stage == stage)
entry_point.name == entry_point_name && entry_point.exec_model == execution_model .ok_or(StageError::MissingEntryPoint(stage))?;
}) let stage_bit = match stage {
.ok_or(StageError::MissingEntryPoint(execution_model))?; naga::ShaderStage::Vertex => wgt::ShaderStage::VERTEX,
let stage_bit = match execution_model { naga::ShaderStage::Fragment => wgt::ShaderStage::FRAGMENT,
spirv::ExecutionModel::Vertex => wgt::ShaderStage::VERTEX, naga::ShaderStage::Compute => wgt::ShaderStage::COMPUTE,
spirv::ExecutionModel::Fragment => wgt::ShaderStage::FRAGMENT,
spirv::ExecutionModel::GLCompute => wgt::ShaderStage::COMPUTE,
// the entry point wouldn't match otherwise
_ => unreachable!(),
}; };
let function = &module.functions[entry_point.function]; let function = &module.functions[entry_point.function];
@ -707,11 +707,7 @@ pub fn check_stage<'a>(
} }
} }
Some(naga::Binding::Location(location)) => { Some(naga::Binding::Location(location)) => {
let mut ty = &module.types[var.ty].inner; let ty = &module.types[var.ty].inner;
//TODO: change naga's IR to not have pointer for varyings
if let naga::TypeInner::Pointer { base, class: _ } = *ty {
ty = &module.types[base].inner;
}
if usage.contains(naga::GlobalUse::STORE) { if usage.contains(naga::GlobalUse::STORE) {
outputs.insert(location, MaybeOwned::Borrowed(ty)); outputs.insert(location, MaybeOwned::Borrowed(ty));
} else { } else {