diff --git a/Cargo.toml b/Cargo.toml index 33823746c6..56c694668c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ bevy_derive = { path = "bevy_derive" } bevy_transform = { path = "bevy_transform" } # rendering -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "a7b0d5ae5bc0934439ef559ed145e93f0117c39a", optional = true } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "d08f83762426c2c42eda74c7ca9c43d8d950fc0a", optional = true } winit = { version = "0.22.0", optional = true } spirv-reflect = "0.2.3" shaderc = "0.6" @@ -40,6 +40,7 @@ type-uuid = "0.1" libloading = "0.5.2" # TODO: replace once_cell with std equivalent if/when this lands: https://github.com/rust-lang/rfcs/pull/2788 once_cell = "1.3.1" +futures = "0.3" [profile.release] debug = true diff --git a/src/render/pipeline/binding.rs b/src/render/pipeline/binding.rs index aef3c810f4..8d1d6e1aae 100644 --- a/src/render/pipeline/binding.rs +++ b/src/render/pipeline/binding.rs @@ -1,5 +1,5 @@ use super::UniformProperty; -use crate::render::texture::TextureViewDimension; +use crate::render::texture::{TextureComponentType, TextureViewDimension, TextureFormat}; #[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct BindingDescriptor { @@ -19,13 +19,19 @@ pub enum BindType { dynamic: bool, readonly: bool, }, - Sampler, + Sampler { + comparison: bool, + }, SampledTexture { multisampled: bool, dimension: TextureViewDimension, + component_type: TextureComponentType, }, StorageTexture { dimension: TextureViewDimension, + component_type: TextureComponentType, + format: TextureFormat, + readonly: bool, }, } diff --git a/src/render/renderer/renderers/wgpu_renderer/mod.rs b/src/render/renderer/renderers/wgpu_renderer/mod.rs index 9dcbe87dc9..5a1788cd60 100644 --- a/src/render/renderer/renderers/wgpu_renderer/mod.rs +++ b/src/render/renderer/renderers/wgpu_renderer/mod.rs @@ -30,7 +30,7 @@ impl AppPlugin for WgpuRendererPlugin { pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) { let window_resize_event = resources.get::>().unwrap(); - let mut wgpu_renderer = WgpuRenderer::new(window_resize_event.get_handle()); + let mut wgpu_renderer = futures::executor::block_on(WgpuRenderer::new(window_resize_event.get_handle())); move |world, resources| { wgpu_renderer.update(world, resources); } diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs index fcae59a804..f28a3cf64b 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs @@ -28,12 +28,12 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) { let buffer = self.wgpu_resources.buffers.get(&resource).unwrap(); self.render_pass - .set_vertex_buffers(start_slot, &[(&buffer, offset)]); + .set_vertex_buffer(start_slot, &buffer, offset, 0); } fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) { let buffer = self.wgpu_resources.buffers.get(&resource).unwrap(); - self.render_pass.set_index_buffer(&buffer, offset); + self.render_pass.set_index_buffer(&buffer, offset, 0); } fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs index 2bce2e721d..13b028ab93 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs @@ -33,13 +33,14 @@ pub struct WgpuRenderer { } impl WgpuRenderer { - pub fn new(window_resize_event: EventHandle) -> Self { + pub async fn new(window_resize_event: EventHandle) -> Self { let adapter = wgpu::Adapter::request( &wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, ) + .await .unwrap(); let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor { @@ -47,7 +48,7 @@ impl WgpuRenderer { anisotropic_filtering: false, }, limits: wgpu::Limits::default(), - }); + }).await; WgpuRenderer { device: Rc::new(RefCell::new(device)), @@ -85,12 +86,12 @@ impl WgpuRenderer { let bind_group_layout_binding = bind_group .bindings .iter() - .map(|binding| wgpu::BindGroupLayoutBinding { + .map(|binding| wgpu::BindGroupLayoutEntry { binding: binding.index, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: (&binding.bind_type).into(), }) - .collect::>(); + .collect::>(); let wgpu_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: bind_group_layout_binding.as_slice(), @@ -182,11 +183,13 @@ impl WgpuRenderer { .depth_stencil_state .as_ref() .map(|d| d.into()), - index_format: pipeline_descriptor.index_format.into(), - vertex_buffers: &owned_vertex_buffer_descriptors - .iter() - .map(|v| v.into()) - .collect::>(), + vertex_state: wgpu::VertexStateDescriptor { + index_format: pipeline_descriptor.index_format.into(), + vertex_buffers: &owned_vertex_buffer_descriptors + .iter() + .map(|v| v.into()) + .collect::>(), + }, sample_count: pipeline_descriptor.sample_count, sample_mask: pipeline_descriptor.sample_mask, alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled, diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs index 366bc6ea1c..e673ee7bce 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs @@ -77,7 +77,7 @@ impl WgpuResources { panic!("expected a Texture resource"); } } - BindType::Sampler => { + BindType::Sampler { .. } => { if let ResourceInfo::Sampler = resource_info { let sampler = self.samplers.get(&resource).unwrap(); wgpu::BindingResource::Sampler(sampler) @@ -251,8 +251,8 @@ impl WgpuResources { wgpu::BufferCopyView { buffer: &temp_buf, offset: 0, - row_pitch: 4 * descriptor.size.width, - image_height: descriptor.size.height, + bytes_per_row: 4 * descriptor.size.width, + rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? }, wgpu::TextureCopyView { texture: &texture, diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_type_converter.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_type_converter.rs index 6f1a7a1156..c7204b3fd8 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_type_converter.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_type_converter.rs @@ -15,8 +15,8 @@ use crate::{ }, render_resource::BufferUsage, texture::{ - AddressMode, Extent3d, FilterMode, SamplerDescriptor, TextureDescriptor, - TextureDimension, TextureFormat, TextureUsage, TextureViewDimension, + AddressMode, Extent3d, FilterMode, SamplerDescriptor, TextureComponentType, + TextureDescriptor, TextureDimension, TextureFormat, TextureUsage, TextureViewDimension, }, }, }; @@ -158,18 +158,40 @@ impl From<&BindType> for wgpu::BindingType { BindType::SampledTexture { dimension, multisampled, + component_type, } => wgpu::BindingType::SampledTexture { dimension: (*dimension).into(), multisampled: *multisampled, + component_type: (*component_type).into(), }, - BindType::Sampler => wgpu::BindingType::Sampler, - BindType::StorageTexture { dimension } => wgpu::BindingType::StorageTexture { + BindType::Sampler { comparison } => wgpu::BindingType::Sampler { + comparison: *comparison, + }, + BindType::StorageTexture { + dimension, + component_type, + format, + readonly, + } => wgpu::BindingType::StorageTexture { dimension: (*dimension).into(), + component_type: (*component_type).into(), + format: (*format).into(), + readonly: *readonly, }, } } } +impl From for wgpu::TextureComponentType { + fn from(texture_component_type: TextureComponentType) -> Self { + match texture_component_type { + TextureComponentType::Float => wgpu::TextureComponentType::Float, + TextureComponentType::Sint => wgpu::TextureComponentType::Sint, + TextureComponentType::Uint => wgpu::TextureComponentType::Uint, + } + } +} + impl From for wgpu::Extent3d { fn from(val: Extent3d) -> Self { wgpu::Extent3d { @@ -224,8 +246,6 @@ impl From for wgpu::TextureFormat { TextureFormat::R8Snorm => wgpu::TextureFormat::R8Snorm, TextureFormat::R8Uint => wgpu::TextureFormat::R8Uint, TextureFormat::R8Sint => wgpu::TextureFormat::R8Sint, - TextureFormat::R16Unorm => wgpu::TextureFormat::R16Unorm, - TextureFormat::R16Snorm => wgpu::TextureFormat::R16Snorm, TextureFormat::R16Uint => wgpu::TextureFormat::R16Uint, TextureFormat::R16Sint => wgpu::TextureFormat::R16Sint, TextureFormat::R16Float => wgpu::TextureFormat::R16Float, @@ -236,8 +256,6 @@ impl From for wgpu::TextureFormat { TextureFormat::R32Uint => wgpu::TextureFormat::R32Uint, TextureFormat::R32Sint => wgpu::TextureFormat::R32Sint, TextureFormat::R32Float => wgpu::TextureFormat::R32Float, - TextureFormat::Rg16Unorm => wgpu::TextureFormat::Rg16Unorm, - TextureFormat::Rg16Snorm => wgpu::TextureFormat::Rg16Snorm, TextureFormat::Rg16Uint => wgpu::TextureFormat::Rg16Uint, TextureFormat::Rg16Sint => wgpu::TextureFormat::Rg16Sint, TextureFormat::Rg16Float => wgpu::TextureFormat::Rg16Float, @@ -253,8 +271,6 @@ impl From for wgpu::TextureFormat { TextureFormat::Rg32Uint => wgpu::TextureFormat::Rg32Uint, TextureFormat::Rg32Sint => wgpu::TextureFormat::Rg32Sint, TextureFormat::Rg32Float => wgpu::TextureFormat::Rg32Float, - TextureFormat::Rgba16Unorm => wgpu::TextureFormat::Rgba16Unorm, - TextureFormat::Rgba16Snorm => wgpu::TextureFormat::Rgba16Snorm, TextureFormat::Rgba16Uint => wgpu::TextureFormat::Rgba16Uint, TextureFormat::Rgba16Sint => wgpu::TextureFormat::Rgba16Sint, TextureFormat::Rgba16Float => wgpu::TextureFormat::Rgba16Float, @@ -314,6 +330,30 @@ impl From for wgpu::CompareFunction { } } +static COMPARE_FUNCTION_NEVER: &wgpu::CompareFunction = &wgpu::CompareFunction::Never; +static COMPARE_FUNCTION_LESS: &wgpu::CompareFunction = &wgpu::CompareFunction::Less; +static COMPARE_FUNCTION_EQUAL: &wgpu::CompareFunction = &wgpu::CompareFunction::Equal; +static COMPARE_FUNCTION_LESSEQUAL: &wgpu::CompareFunction = &wgpu::CompareFunction::LessEqual; +static COMPARE_FUNCTION_GREATER: &wgpu::CompareFunction = &wgpu::CompareFunction::Greater; +static COMPARE_FUNCTION_NOTEQUAL: &wgpu::CompareFunction = &wgpu::CompareFunction::NotEqual; +static COMPARE_FUNCTION_GREATEREQUAL: &wgpu::CompareFunction = &wgpu::CompareFunction::GreaterEqual; +static COMPARE_FUNCTION_ALWAYS: &wgpu::CompareFunction = &wgpu::CompareFunction::Always; + +impl From for &'static wgpu::CompareFunction { + fn from(val: CompareFunction) -> Self { + match val { + CompareFunction::Never => COMPARE_FUNCTION_NEVER, + CompareFunction::Less => COMPARE_FUNCTION_LESS, + CompareFunction::Equal => COMPARE_FUNCTION_EQUAL, + CompareFunction::LessEqual => COMPARE_FUNCTION_LESSEQUAL, + CompareFunction::Greater => COMPARE_FUNCTION_GREATER, + CompareFunction::NotEqual => COMPARE_FUNCTION_NOTEQUAL, + CompareFunction::GreaterEqual => COMPARE_FUNCTION_GREATEREQUAL, + CompareFunction::Always => COMPARE_FUNCTION_ALWAYS, + } + } +} + impl From for wgpu::StencilOperation { fn from(val: StencilOperation) -> Self { match val { @@ -440,7 +480,7 @@ impl From for wgpu::IndexFormat { } } -impl From for wgpu::SamplerDescriptor { +impl From for wgpu::SamplerDescriptor<'_> { fn from(sampler_descriptor: SamplerDescriptor) -> Self { wgpu::SamplerDescriptor { address_mode_u: sampler_descriptor.address_mode_u.into(), @@ -451,7 +491,7 @@ impl From for wgpu::SamplerDescriptor { mipmap_filter: sampler_descriptor.mipmap_filter.into(), lod_min_clamp: sampler_descriptor.lod_min_clamp, lod_max_clamp: sampler_descriptor.lod_max_clamp, - compare_function: sampler_descriptor.compare_function.into(), + compare: sampler_descriptor.compare_function.map(|c| c.into()), } } } @@ -483,9 +523,9 @@ impl From<&Window> for wgpu::SwapChainDescriptor { width: window.width, height: window.height, present_mode: if window.vsync { - wgpu::PresentMode::Vsync + wgpu::PresentMode::Fifo } else { - wgpu::PresentMode::NoVsync + wgpu::PresentMode::Immediate }, } } diff --git a/src/render/shader/shader_reflect.rs b/src/render/shader/shader_reflect.rs index 32c17c17bf..5a77d0eba3 100644 --- a/src/render/shader/shader_reflect.rs +++ b/src/render/shader/shader_reflect.rs @@ -3,7 +3,7 @@ use crate::render::{ BindGroupDescriptor, BindType, BindingDescriptor, InputStepMode, UniformProperty, UniformPropertyType, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, }, - texture::TextureViewDimension, + texture::{TextureComponentType, TextureViewDimension}, }; use spirv_reflect::{ types::{ @@ -183,10 +183,12 @@ fn reflect_binding(binding: &ReflectDescriptorBinding) -> BindingDescriptor { &binding.name, BindType::SampledTexture { dimension: reflect_dimension(type_description), + component_type: TextureComponentType::Float, multisampled: false, }, ), - ReflectDescriptorType::Sampler => (&binding.name, BindType::Sampler), + // TODO: detect comparison "true" case: https://github.com/gpuweb/gpuweb/issues/552 + ReflectDescriptorType::Sampler => (&binding.name, BindType::Sampler { comparison: false }), _ => panic!("unsupported bind type {:?}", binding.descriptor_type), }; @@ -421,6 +423,7 @@ mod tests { bind_type: BindType::SampledTexture { multisampled: false, dimension: TextureViewDimension::D2, + component_type: TextureComponentType::Float, }, }] ), diff --git a/src/render/shader/uniform.rs b/src/render/shader/uniform.rs index 70255fa079..fea3bbe32d 100644 --- a/src/render/shader/uniform.rs +++ b/src/render/shader/uniform.rs @@ -4,7 +4,7 @@ use crate::{ render::{ color::ColorSource, pipeline::{BindType, VertexBufferDescriptor}, - texture::{Texture, TextureViewDimension}, + texture::Texture, }, }; @@ -36,75 +36,6 @@ pub enum FieldBindType { Texture, } -// TODO: Remove this -pub struct UniformInfoIter<'a, T: AsUniforms> { - pub uniforms: &'a T, - pub index: usize, - pub add_sampler: bool, -} - -impl<'a, T> UniformInfoIter<'a, T> -where - T: AsUniforms, -{ - pub fn new(uniforms: &'a T) -> Self { - UniformInfoIter { - uniforms, - index: 0, - add_sampler: false, - } - } -} - -impl<'a, T> Iterator for UniformInfoIter<'a, T> -where - T: AsUniforms, -{ - type Item = UniformInfo<'a>; - fn next(&mut self) -> Option { - let field_infos = T::get_field_infos(); - if self.add_sampler { - self.add_sampler = false; - Some(UniformInfo { - name: field_infos[self.index - 1].sampler_name, - bind_type: BindType::Sampler, - }) - } else { - if self.index >= field_infos.len() { - None - } else { - let index = self.index; - self.index += 1; - let ref field_info = field_infos[index]; - let bind_type = self.uniforms.get_field_bind_type(field_info.name); - if let Some(bind_type) = bind_type { - Some(match bind_type { - FieldBindType::Uniform { .. } => UniformInfo { - bind_type: BindType::Uniform { - dynamic: false, - properties: Vec::new(), - }, - name: field_info.uniform_name, - }, - FieldBindType::Texture => { - self.add_sampler = true; - UniformInfo { - bind_type: BindType::SampledTexture { - dimension: TextureViewDimension::D2, - multisampled: false, - }, - name: field_info.texture_name, - } - } - }) - } else { - self.next() - } - } - } - } -} - pub struct FieldInfo { pub name: &'static str, pub uniform_name: &'static str, diff --git a/src/render/texture/sampler_descriptor.rs b/src/render/texture/sampler_descriptor.rs index 3a1b1cc190..6df75a8590 100644 --- a/src/render/texture/sampler_descriptor.rs +++ b/src/render/texture/sampler_descriptor.rs @@ -11,7 +11,7 @@ pub struct SamplerDescriptor { pub mipmap_filter: FilterMode, pub lod_min_clamp: f32, pub lod_max_clamp: f32, - pub compare_function: CompareFunction, + pub compare_function: Option, } impl From<&Texture> for SamplerDescriptor { @@ -25,7 +25,7 @@ impl From<&Texture> for SamplerDescriptor { mipmap_filter: FilterMode::Nearest, lod_min_clamp: -100.0, lod_max_clamp: 100.0, - compare_function: CompareFunction::Always, + compare_function: Some(CompareFunction::Always), } } } diff --git a/src/render/texture/texture_dimension.rs b/src/render/texture/texture_dimension.rs index f60ac6ef1f..1f90173992 100644 --- a/src/render/texture/texture_dimension.rs +++ b/src/render/texture/texture_dimension.rs @@ -24,7 +24,14 @@ pub struct Extent3d { pub depth: u32, } -#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +#[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub enum TextureComponentType { + Float, + Sint, + Uint, +} + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] pub enum TextureFormat { // Normal 8 bit formats R8Unorm = 0, @@ -33,57 +40,50 @@ pub enum TextureFormat { R8Sint = 3, // Normal 16 bit formats - R16Unorm = 4, - R16Snorm = 5, - R16Uint = 6, - R16Sint = 7, - R16Float = 8, - - Rg8Unorm = 9, - Rg8Snorm = 10, - Rg8Uint = 11, - Rg8Sint = 12, + R16Uint = 4, + R16Sint = 5, + R16Float = 6, + Rg8Unorm = 7, + Rg8Snorm = 8, + Rg8Uint = 9, + Rg8Sint = 10, // Normal 32 bit formats - R32Uint = 13, - R32Sint = 14, - R32Float = 15, - Rg16Unorm = 16, - Rg16Snorm = 17, - Rg16Uint = 18, - Rg16Sint = 19, - Rg16Float = 20, - Rgba8Unorm = 21, - Rgba8UnormSrgb = 22, - Rgba8Snorm = 23, - Rgba8Uint = 24, - Rgba8Sint = 25, - Bgra8Unorm = 26, - Bgra8UnormSrgb = 27, + R32Uint = 11, + R32Sint = 12, + R32Float = 13, + Rg16Uint = 14, + Rg16Sint = 15, + Rg16Float = 16, + Rgba8Unorm = 17, + Rgba8UnormSrgb = 18, + Rgba8Snorm = 19, + Rgba8Uint = 20, + Rgba8Sint = 21, + Bgra8Unorm = 22, + Bgra8UnormSrgb = 23, // Packed 32 bit formats - Rgb10a2Unorm = 28, - Rg11b10Float = 29, + Rgb10a2Unorm = 24, + Rg11b10Float = 25, // Normal 64 bit formats - Rg32Uint = 30, - Rg32Sint = 31, - Rg32Float = 32, - Rgba16Unorm = 33, - Rgba16Snorm = 34, - Rgba16Uint = 35, - Rgba16Sint = 36, - Rgba16Float = 37, + Rg32Uint = 26, + Rg32Sint = 27, + Rg32Float = 28, + Rgba16Uint = 29, + Rgba16Sint = 30, + Rgba16Float = 31, // Normal 128 bit formats - Rgba32Uint = 38, - Rgba32Sint = 39, - Rgba32Float = 40, + Rgba32Uint = 32, + Rgba32Sint = 33, + Rgba32Float = 34, // Depth and stencil formats - Depth32Float = 41, - Depth24Plus = 42, - Depth24PlusStencil8 = 43, + Depth32Float = 35, + Depth24Plus = 36, + Depth24PlusStencil8 = 37, } bitflags::bitflags! {