Upgrade to wgpu 0.11 (#2933)

Upgrades both the old and new renderer to wgpu 0.11 (and naga 0.7). This builds on @zicklag's work here #2556.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
Carter Anderson 2021-10-08 19:55:24 +00:00
parent 40fccd29ca
commit 43e8a156fb
44 changed files with 286 additions and 267 deletions

View file

@ -14,6 +14,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
readme = "README.md" readme = "README.md"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
resolver = "2"
[workspace] [workspace]
exclude = ["benches"] exclude = ["benches"]

View file

@ -7,7 +7,7 @@ use crate::{
LoadOp, Operations, PassDescriptor, RenderPassColorAttachment, LoadOp, Operations, PassDescriptor, RenderPassColorAttachment,
RenderPassDepthStencilAttachment, TextureAttachment, RenderPassDepthStencilAttachment, TextureAttachment,
}, },
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage}, texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages},
Color, Color,
}; };
use bevy_ecs::{reflect::ReflectComponent, world::World}; use bevy_ecs::{reflect::ReflectComponent, world::World};
@ -126,7 +126,7 @@ pub(crate) fn add_base_graph(config: &BaseRenderGraphConfig, world: &mut World)
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24 format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24
* bit depth for better performance */ * bit depth for better performance */
usage: TextureUsage::OUTPUT_ATTACHMENT, usage: TextureUsages::OUTPUT_ATTACHMENT,
}, },
), ),
); );
@ -220,7 +220,7 @@ pub(crate) fn add_base_graph(config: &BaseRenderGraphConfig, world: &mut World)
sample_count: msaa.samples, sample_count: msaa.samples,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::default(), format: TextureFormat::default(),
usage: TextureUsage::OUTPUT_ATTACHMENT, usage: TextureUsages::OUTPUT_ATTACHMENT,
}, },
), ),
); );

View file

@ -52,7 +52,7 @@ impl Node for WindowSwapChainNode {
let render_resource_context = render_context.resources_mut(); let render_resource_context = render_context.resources_mut();
// create window swapchain when window is resized or created // reconfigure surface window is resized or created
if self if self
.window_created_event_reader .window_created_event_reader
.iter(window_created_events) .iter(window_created_events)
@ -62,10 +62,10 @@ impl Node for WindowSwapChainNode {
.iter(window_resized_events) .iter(window_resized_events)
.any(|e| e.id == window.id()) .any(|e| e.id == window.id())
{ {
render_resource_context.create_swap_chain(window); render_resource_context.configure_surface(window);
} }
let swap_chain_texture = render_resource_context.next_swap_chain_texture(window); let swap_chain_texture = render_resource_context.next_surface_frame(window);
output.set( output.set(
WINDOW_TEXTURE, WINDOW_TEXTURE,
RenderResourceId::Texture(swap_chain_texture), RenderResourceId::Texture(swap_chain_texture),

View file

@ -31,15 +31,15 @@ impl HeadlessRenderResourceContext {
} }
impl RenderResourceContext for HeadlessRenderResourceContext { impl RenderResourceContext for HeadlessRenderResourceContext {
fn create_swap_chain(&self, _window: &Window) {} fn configure_surface(&self, _window: &Window) {}
fn next_swap_chain_texture(&self, _window: &Window) -> TextureId { fn next_surface_frame(&self, _window: &Window) -> TextureId {
TextureId::new() TextureId::new()
} }
fn drop_swap_chain_texture(&self, _render_resource: TextureId) {} fn drop_surface_frame(&self, _render_resource: TextureId) {}
fn drop_all_swap_chain_textures(&self) {} fn drop_all_surface_frames(&self) {}
fn create_sampler(&self, _sampler_descriptor: &SamplerDescriptor) -> SamplerId { fn create_sampler(&self, _sampler_descriptor: &SamplerDescriptor) -> SamplerId {
SamplerId::new() SamplerId::new()

View file

@ -12,10 +12,10 @@ use downcast_rs::{impl_downcast, Downcast};
use std::ops::Range; use std::ops::Range;
pub trait RenderResourceContext: Downcast + Send + Sync + 'static { pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
fn create_swap_chain(&self, window: &Window); fn configure_surface(&self, window: &Window);
fn next_swap_chain_texture(&self, window: &Window) -> TextureId; fn next_surface_frame(&self, window: &Window) -> TextureId;
fn drop_swap_chain_texture(&self, resource: TextureId); fn drop_surface_frame(&self, resource: TextureId);
fn drop_all_swap_chain_textures(&self); fn drop_all_surface_frames(&self);
fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> SamplerId; fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> SamplerId;
fn create_texture(&self, texture_descriptor: TextureDescriptor) -> TextureId; fn create_texture(&self, texture_descriptor: TextureDescriptor) -> TextureId;
fn create_buffer(&self, buffer_info: BufferInfo) -> BufferId; fn create_buffer(&self, buffer_info: BufferInfo) -> BufferId;

View file

@ -106,9 +106,9 @@ pub fn glsl_to_spirv(
impl Into<shaderc::ShaderKind> for ShaderStage { impl Into<shaderc::ShaderKind> for ShaderStage {
fn into(self) -> shaderc::ShaderKind { fn into(self) -> shaderc::ShaderKind {
match self { match self {
ShaderStage::Vertex => shaderc::ShaderKind::Vertex, ShaderStages::VERTEX => shaderc::ShaderKind::Vertex,
ShaderStage::Fragment => shaderc::ShaderKind::Fragment, ShaderStages::FRAGMENT => shaderc::ShaderKind::Fragment,
ShaderStage::Compute => shaderc::ShaderKind::Compute, ShaderStages::COMPUTE => shaderc::ShaderKind::Compute,
} }
} }
} }

View file

@ -1,4 +1,4 @@
use super::{Extent3d, Texture, TextureDimension, TextureFormat, TextureUsage}; use super::{Extent3d, Texture, TextureDimension, TextureFormat, TextureUsages};
/// Describes a texture /// Describes a texture
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
@ -8,7 +8,7 @@ pub struct TextureDescriptor {
pub sample_count: u32, pub sample_count: u32,
pub dimension: TextureDimension, pub dimension: TextureDimension,
pub format: TextureFormat, pub format: TextureFormat,
pub usage: TextureUsage, pub usage: TextureUsages,
} }
impl From<&Texture> for TextureDescriptor { impl From<&Texture> for TextureDescriptor {
@ -19,7 +19,7 @@ impl From<&Texture> for TextureDescriptor {
sample_count: 1, sample_count: 1,
dimension: texture.dimension, dimension: texture.dimension,
format: texture.format, format: texture.format,
usage: TextureUsage::SAMPLED | TextureUsage::COPY_DST, usage: TextureUsages::SAMPLED | TextureUsages::COPY_DST,
} }
} }
} }
@ -36,7 +36,7 @@ impl Default for TextureDescriptor {
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::Rgba8UnormSrgb, format: TextureFormat::Rgba8UnormSrgb,
usage: TextureUsage::SAMPLED | TextureUsage::COPY_DST, usage: TextureUsages::SAMPLED | TextureUsages::COPY_DST,
} }
} }
} }

View file

@ -276,7 +276,7 @@ impl Default for TextureFormat {
bitflags::bitflags! { bitflags::bitflags! {
#[repr(transparent)] #[repr(transparent)]
pub struct TextureUsage: u32 { pub struct TextureUsages: u32 {
const COPY_SRC = 1; const COPY_SRC = 1;
const COPY_DST = 2; const COPY_DST = 2;
const SAMPLED = 4; const SAMPLED = 4;

View file

@ -21,7 +21,7 @@ struct Rect {
vec2 end; vec2 end;
}; };
layout(set = 1, binding = 1) buffer TextureAtlas_textures { layout(set = 1, binding = 1) readonly buffer TextureAtlas_textures {
Rect[] Textures; Rect[] Textures;
}; };

View file

@ -29,7 +29,7 @@ bevy_winit = { path = "../bevy_winit", optional = true, version = "0.5.0" }
bevy_utils = { path = "../bevy_utils", version = "0.5.0" } bevy_utils = { path = "../bevy_utils", version = "0.5.0" }
# other # other
wgpu = "0.9" wgpu = { version = "0.11.0", features = ["spirv"] }
futures-lite = "1.4.0" futures-lite = "1.4.0"
crossbeam-channel = "0.5.0" crossbeam-channel = "0.5.0"
crossbeam-utils = "0.8.1" crossbeam-utils = "0.8.1"

View file

@ -29,9 +29,7 @@ impl WgpuResourceDiagnosticsPlugin {
DiagnosticId::from_u128(305855369913076220671125671543184691267); DiagnosticId::from_u128(305855369913076220671125671543184691267);
pub const SHADER_MODULES: DiagnosticId = pub const SHADER_MODULES: DiagnosticId =
DiagnosticId::from_u128(287681470908132753275843248383768232237); DiagnosticId::from_u128(287681470908132753275843248383768232237);
pub const SWAP_CHAINS: DiagnosticId = pub const SURFACE_FRAMES: DiagnosticId =
DiagnosticId::from_u128(199253035828743332241465305105689014605);
pub const SWAP_CHAIN_OUTPUTS: DiagnosticId =
DiagnosticId::from_u128(112048874168736161226721327099863374234); DiagnosticId::from_u128(112048874168736161226721327099863374234);
pub const TEXTURES: DiagnosticId = pub const TEXTURES: DiagnosticId =
DiagnosticId::from_u128(305955424195390184883220102469231911115); DiagnosticId::from_u128(305955424195390184883220102469231911115);
@ -47,10 +45,8 @@ impl WgpuResourceDiagnosticsPlugin {
10, 10,
)); ));
diagnostics.add(Diagnostic::new(Self::SWAP_CHAINS, "swap_chains", 10));
diagnostics.add(Diagnostic::new( diagnostics.add(Diagnostic::new(
Self::SWAP_CHAIN_OUTPUTS, Self::SURFACE_FRAMES,
"swap_chain_outputs", "swap_chain_outputs",
10, 10,
)); ));
@ -99,19 +95,10 @@ impl WgpuResourceDiagnosticsPlugin {
); );
diagnostics.add_measurement( diagnostics.add_measurement(
Self::SWAP_CHAINS, Self::SURFACE_FRAMES,
render_resource_context render_resource_context
.resources .resources
.window_swap_chains .surface_textures
.read()
.len() as f64,
);
diagnostics.add_measurement(
Self::SWAP_CHAIN_OUTPUTS,
render_resource_context
.resources
.swap_chain_frames
.read() .read()
.len() as f64, .len() as f64,
); );

View file

@ -29,15 +29,12 @@ pub enum WgpuFeature {
TimestampQuery, TimestampQuery,
PipelineStatisticsQuery, PipelineStatisticsQuery,
MappablePrimaryBuffers, MappablePrimaryBuffers,
SampledTextureBindingArray,
SampledTextureArrayDynamicIndexing,
SampledTextureArrayNonUniformIndexing,
UnsizedBindingArray, UnsizedBindingArray,
MultiDrawIndirect, MultiDrawIndirect,
MultiDrawIndirectCount, MultiDrawIndirectCount,
PushConstants, PushConstants,
AddressModeClampToBorder, AddressModeClampToBorder,
NonFillPolygonMode, PolygonModeLine,
TextureCompressionEtc2, TextureCompressionEtc2,
TextureCompressionAstcLdr, TextureCompressionAstcLdr,
TextureAdapterSpecificFormatFeatures, TextureAdapterSpecificFormatFeatures,
@ -70,6 +67,8 @@ pub struct WgpuLimits {
pub max_vertex_buffers: u32, pub max_vertex_buffers: u32,
pub max_vertex_attributes: u32, pub max_vertex_attributes: u32,
pub max_vertex_buffer_array_stride: u32, pub max_vertex_buffer_array_stride: u32,
pub min_storage_buffer_offset_alignment: u32,
pub min_uniform_buffer_offset_alignment: u32,
} }
impl Default for WgpuLimits { impl Default for WgpuLimits {
@ -96,6 +95,8 @@ impl Default for WgpuLimits {
max_vertex_buffers: default.max_vertex_buffers, max_vertex_buffers: default.max_vertex_buffers,
max_vertex_attributes: default.max_vertex_attributes, max_vertex_attributes: default.max_vertex_attributes,
max_vertex_buffer_array_stride: default.max_vertex_buffer_array_stride, max_vertex_buffer_array_stride: default.max_vertex_buffer_array_stride,
min_storage_buffer_offset_alignment: default.min_storage_buffer_offset_alignment,
min_uniform_buffer_offset_alignment: default.min_uniform_buffer_offset_alignment,
} }
} }
} }

View file

@ -231,8 +231,15 @@ fn get_texture_view<'a>(
panic!("Color attachment {} does not exist.", name); panic!("Color attachment {} does not exist.", name);
} }
}, },
TextureAttachment::Id(render_resource) => refs.textures.get(render_resource).unwrap_or_else(|| &refs.swap_chain_frames.get(render_resource).unwrap().output.view), TextureAttachment::Id(render_resource) => refs
TextureAttachment::Input(_) => panic!("Encountered unset `TextureAttachment::Input`. The `RenderGraph` executor should always set `TextureAttachment::Inputs` to `TextureAttachment::RenderResource` before running. This is a bug, please report it!"), .textures
.get(render_resource)
.unwrap_or_else(|| &refs.surface_textures.get(render_resource).unwrap().0),
TextureAttachment::Input(_) => panic!(
"Encountered unset `TextureAttachment::Input`. The `RenderGraph` executor should \
always set `TextureAttachment::Inputs` to `TextureAttachment::RenderResource` before \
running. This is a bug, please report it!"
),
} }
} }

View file

@ -31,7 +31,8 @@ pub struct WgpuRenderResourceContext {
} }
pub const COPY_BYTES_PER_ROW_ALIGNMENT: usize = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as usize; pub const COPY_BYTES_PER_ROW_ALIGNMENT: usize = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as usize;
pub const BIND_BUFFER_ALIGNMENT: usize = wgpu::BIND_BUFFER_ALIGNMENT as usize; // TODO: fix this?
pub const BIND_BUFFER_ALIGNMENT: usize = 256;
pub const COPY_BUFFER_ALIGNMENT: usize = wgpu::COPY_BUFFER_ALIGNMENT as usize; pub const COPY_BUFFER_ALIGNMENT: usize = wgpu::COPY_BUFFER_ALIGNMENT as usize;
pub const PUSH_CONSTANT_ALIGNMENT: u32 = wgpu::PUSH_CONSTANT_ALIGNMENT; pub const PUSH_CONSTANT_ALIGNMENT: u32 = wgpu::PUSH_CONSTANT_ALIGNMENT;
@ -94,6 +95,7 @@ impl WgpuRenderResourceContext {
y: source_origin[1], y: source_origin[1],
z: source_origin[2], z: source_origin[2],
}, },
aspect: wgpu::TextureAspect::All,
}, },
wgpu::ImageCopyTexture { wgpu::ImageCopyTexture {
texture: destination, texture: destination,
@ -103,6 +105,7 @@ impl WgpuRenderResourceContext {
y: destination_origin[1], y: destination_origin[1],
z: destination_origin[2], z: destination_origin[2],
}, },
aspect: wgpu::TextureAspect::All,
}, },
size.wgpu_into(), size.wgpu_into(),
) )
@ -134,6 +137,7 @@ impl WgpuRenderResourceContext {
y: source_origin[1], y: source_origin[1],
z: source_origin[2], z: source_origin[2],
}, },
aspect: wgpu::TextureAspect::All,
}, },
wgpu::ImageCopyBuffer { wgpu::ImageCopyBuffer {
buffer: destination, buffer: destination,
@ -181,6 +185,7 @@ impl WgpuRenderResourceContext {
y: destination_origin[1], y: destination_origin[1],
z: destination_origin[2], z: destination_origin[2],
}, },
aspect: wgpu::TextureAspect::All,
}, },
size.wgpu_into(), size.wgpu_into(),
); );
@ -206,11 +211,11 @@ impl WgpuRenderResourceContext {
let shader_stage = if binding.shader_stage let shader_stage = if binding.shader_stage
== BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT == BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT
{ {
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT
} else if binding.shader_stage == BindingShaderStage::VERTEX { } else if binding.shader_stage == BindingShaderStage::VERTEX {
wgpu::ShaderStage::VERTEX wgpu::ShaderStages::VERTEX
} else if binding.shader_stage == BindingShaderStage::FRAGMENT { } else if binding.shader_stage == BindingShaderStage::FRAGMENT {
wgpu::ShaderStage::FRAGMENT wgpu::ShaderStages::FRAGMENT
} else { } else {
panic!("Invalid binding shader stage.") panic!("Invalid binding shader stage.")
}; };
@ -230,14 +235,15 @@ impl WgpuRenderResourceContext {
bind_group_layouts.insert(descriptor.id, bind_group_layout); bind_group_layouts.insert(descriptor.id, bind_group_layout);
} }
fn try_next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> Option<TextureId> { fn try_next_surface_frame(&self, window_id: bevy_window::WindowId) -> Option<TextureId> {
let mut window_swap_chains = self.resources.window_swap_chains.write(); let mut window_surfaces = self.resources.window_surfaces.write();
let mut swap_chain_outputs = self.resources.swap_chain_frames.write(); let mut surface_frames = self.resources.surface_textures.write();
let window_swap_chain = window_swap_chains.get_mut(&window_id).unwrap(); let window_surface = window_surfaces.get_mut(&window_id).unwrap();
let next_texture = window_swap_chain.get_current_frame().ok()?; let next_texture = window_surface.get_current_texture().ok()?;
let view = next_texture.texture.create_view(&Default::default());
let id = TextureId::new(); let id = TextureId::new();
swap_chain_outputs.insert(id, next_texture); surface_frames.insert(id, (view, next_texture));
Some(id) Some(id)
} }
} }
@ -339,7 +345,6 @@ impl RenderResourceContext for WgpuRenderResourceContext {
.create_shader_module(&wgpu::ShaderModuleDescriptor { .create_shader_module(&wgpu::ShaderModuleDescriptor {
label: None, label: None,
source: wgpu::ShaderSource::SpirV(spirv), source: wgpu::ShaderSource::SpirV(spirv),
flags: Default::default(),
}); });
shader_modules.insert(shader_handle.clone_weak(), shader_module); shader_modules.insert(shader_handle.clone_weak(), shader_module);
} }
@ -358,43 +363,39 @@ impl RenderResourceContext for WgpuRenderResourceContext {
self.create_shader_module_from_source(shader_handle, shader); self.create_shader_module_from_source(shader_handle, shader);
} }
fn create_swap_chain(&self, window: &Window) { fn configure_surface(&self, window: &Window) {
let surfaces = self.resources.window_surfaces.read(); let surfaces = self.resources.window_surfaces.read();
let mut window_swap_chains = self.resources.window_swap_chains.write();
let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into(); let surface_configuration: wgpu::SurfaceConfiguration = window.wgpu_into();
let surface = surfaces let surface = surfaces
.get(&window.id()) .get(&window.id())
.expect("No surface found for window."); .expect("No surface found for window.");
let swap_chain = self surface.configure(&self.device, &surface_configuration);
.device
.create_swap_chain(surface, &swap_chain_descriptor);
window_swap_chains.insert(window.id(), swap_chain);
} }
fn next_swap_chain_texture(&self, window: &bevy_window::Window) -> TextureId { fn next_surface_frame(&self, window: &bevy_window::Window) -> TextureId {
if let Some(texture_id) = self.try_next_swap_chain_texture(window.id()) { if let Some(texture_id) = self.try_next_surface_frame(window.id()) {
texture_id texture_id
} else { } else {
self.resources self.resources.window_surfaces.write().remove(&window.id());
.window_swap_chains self.configure_surface(window);
.write() self.try_next_surface_frame(window.id())
.remove(&window.id());
self.create_swap_chain(window);
self.try_next_swap_chain_texture(window.id())
.expect("Failed to acquire next swap chain texture!") .expect("Failed to acquire next swap chain texture!")
} }
} }
fn drop_swap_chain_texture(&self, texture: TextureId) { fn drop_surface_frame(&self, texture: TextureId) {
let mut swap_chain_outputs = self.resources.swap_chain_frames.write(); let mut surface_frames = self.resources.surface_textures.write();
swap_chain_outputs.remove(&texture); surface_frames.remove(&texture);
} }
fn drop_all_swap_chain_textures(&self) { fn drop_all_surface_frames(&self) {
let mut swap_chain_outputs = self.resources.swap_chain_frames.write(); let mut surface_frames = self.resources.surface_textures.write();
swap_chain_outputs.clear(); for (_, (_, texture)) in surface_frames.drain() {
texture.present();
}
surface_frames.clear();
} }
fn set_asset_resource_untyped( fn set_asset_resource_untyped(

View file

@ -24,13 +24,13 @@ pub struct WgpuRenderer {
impl WgpuRenderer { impl WgpuRenderer {
pub async fn new(options: WgpuOptions) -> Self { pub async fn new(options: WgpuOptions) -> Self {
let backend = match options.backend { let backend = match options.backend {
WgpuBackend::Auto => wgpu::BackendBit::PRIMARY, WgpuBackend::Auto => wgpu::Backends::PRIMARY,
WgpuBackend::Vulkan => wgpu::BackendBit::VULKAN, WgpuBackend::Vulkan => wgpu::Backends::VULKAN,
WgpuBackend::Metal => wgpu::BackendBit::METAL, WgpuBackend::Metal => wgpu::Backends::METAL,
WgpuBackend::Dx12 => wgpu::BackendBit::DX12, WgpuBackend::Dx12 => wgpu::Backends::DX12,
WgpuBackend::Dx11 => wgpu::BackendBit::DX11, WgpuBackend::Dx11 => wgpu::Backends::DX11,
WgpuBackend::Gl => wgpu::BackendBit::GL, WgpuBackend::Gl => wgpu::Backends::GL,
WgpuBackend::BrowserWgpu => wgpu::BackendBit::BROWSER_WEBGPU, WgpuBackend::BrowserWgpu => wgpu::Backends::BROWSER_WEBGPU,
}; };
let instance = wgpu::Instance::new(backend); let instance = wgpu::Instance::new(backend);
@ -42,6 +42,7 @@ impl WgpuRenderer {
WgpuPowerOptions::LowPower => wgpu::PowerPreference::LowPower, WgpuPowerOptions::LowPower => wgpu::PowerPreference::LowPower,
}, },
compatible_surface: None, compatible_surface: None,
..Default::default()
}) })
.await .await
.expect("Unable to find a GPU! Make sure you have installed required drivers!"); .expect("Unable to find a GPU! Make sure you have installed required drivers!");
@ -56,12 +57,14 @@ impl WgpuRenderer {
#[cfg(not(feature = "trace"))] #[cfg(not(feature = "trace"))]
let trace_path = None; let trace_path = None;
let adapter_limits = adapter.limits();
let (device, queue) = adapter let (device, queue) = adapter
.request_device( .request_device(
&wgpu::DeviceDescriptor { &wgpu::DeviceDescriptor {
label: options.device_label.as_ref().map(|a| a.as_ref()), label: options.device_label.as_ref().map(|a| a.as_ref()),
features: options.features.wgpu_into(), features: options.features.wgpu_into(),
limits: options.limits.wgpu_into(), limits: adapter_limits,
}, },
trace_path, trace_path,
) )
@ -129,7 +132,7 @@ impl WgpuRenderer {
let render_resource_context = world let render_resource_context = world
.get_resource::<Box<dyn RenderResourceContext>>() .get_resource::<Box<dyn RenderResourceContext>>()
.unwrap(); .unwrap();
render_resource_context.drop_all_swap_chain_textures(); render_resource_context.drop_all_surface_frames();
render_resource_context.remove_stale_bind_groups(); render_resource_context.remove_stale_bind_groups();
} }
} }

View file

@ -47,7 +47,8 @@ pub struct WgpuBindGroupInfo {
pub struct WgpuResourcesReadLock<'a> { pub struct WgpuResourcesReadLock<'a> {
pub buffers: RwLockReadGuard<'a, HashMap<BufferId, Arc<wgpu::Buffer>>>, pub buffers: RwLockReadGuard<'a, HashMap<BufferId, Arc<wgpu::Buffer>>>,
pub textures: RwLockReadGuard<'a, HashMap<TextureId, wgpu::TextureView>>, pub textures: RwLockReadGuard<'a, HashMap<TextureId, wgpu::TextureView>>,
pub swap_chain_frames: RwLockReadGuard<'a, HashMap<TextureId, wgpu::SwapChainFrame>>, pub surface_textures:
RwLockReadGuard<'a, HashMap<TextureId, (wgpu::TextureView, wgpu::SurfaceTexture)>>,
pub render_pipelines: pub render_pipelines:
RwLockReadGuard<'a, HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>, RwLockReadGuard<'a, HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>,
pub bind_groups: RwLockReadGuard<'a, HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>, pub bind_groups: RwLockReadGuard<'a, HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>,
@ -59,7 +60,7 @@ impl<'a> WgpuResourcesReadLock<'a> {
WgpuResourceRefs { WgpuResourceRefs {
buffers: &self.buffers, buffers: &self.buffers,
textures: &self.textures, textures: &self.textures,
swap_chain_frames: &self.swap_chain_frames, surface_textures: &self.surface_textures,
render_pipelines: &self.render_pipelines, render_pipelines: &self.render_pipelines,
bind_groups: &self.bind_groups, bind_groups: &self.bind_groups,
used_bind_group_sender: &self.used_bind_group_sender, used_bind_group_sender: &self.used_bind_group_sender,
@ -73,7 +74,7 @@ impl<'a> WgpuResourcesReadLock<'a> {
pub struct WgpuResourceRefs<'a> { pub struct WgpuResourceRefs<'a> {
pub buffers: &'a HashMap<BufferId, Arc<wgpu::Buffer>>, pub buffers: &'a HashMap<BufferId, Arc<wgpu::Buffer>>,
pub textures: &'a HashMap<TextureId, wgpu::TextureView>, pub textures: &'a HashMap<TextureId, wgpu::TextureView>,
pub swap_chain_frames: &'a HashMap<TextureId, wgpu::SwapChainFrame>, pub surface_textures: &'a HashMap<TextureId, (wgpu::TextureView, wgpu::SurfaceTexture)>,
pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>, pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
pub bind_groups: &'a HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>, pub bind_groups: &'a HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>,
pub used_bind_group_sender: &'a Sender<BindGroupId>, pub used_bind_group_sender: &'a Sender<BindGroupId>,
@ -84,8 +85,8 @@ pub struct WgpuResources {
pub buffer_infos: Arc<RwLock<HashMap<BufferId, BufferInfo>>>, pub buffer_infos: Arc<RwLock<HashMap<BufferId, BufferInfo>>>,
pub texture_descriptors: Arc<RwLock<HashMap<TextureId, TextureDescriptor>>>, pub texture_descriptors: Arc<RwLock<HashMap<TextureId, TextureDescriptor>>>,
pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>, pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>,
pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>, pub surface_textures:
pub swap_chain_frames: Arc<RwLock<HashMap<TextureId, wgpu::SwapChainFrame>>>, Arc<RwLock<HashMap<TextureId, (wgpu::TextureView, wgpu::SurfaceTexture)>>>,
pub buffers: Arc<RwLock<HashMap<BufferId, Arc<wgpu::Buffer>>>>, pub buffers: Arc<RwLock<HashMap<BufferId, Arc<wgpu::Buffer>>>>,
pub texture_views: Arc<RwLock<HashMap<TextureId, wgpu::TextureView>>>, pub texture_views: Arc<RwLock<HashMap<TextureId, wgpu::TextureView>>>,
pub textures: Arc<RwLock<HashMap<TextureId, wgpu::Texture>>>, pub textures: Arc<RwLock<HashMap<TextureId, wgpu::Texture>>>,
@ -103,7 +104,7 @@ impl WgpuResources {
WgpuResourcesReadLock { WgpuResourcesReadLock {
buffers: self.buffers.read(), buffers: self.buffers.read(),
textures: self.texture_views.read(), textures: self.texture_views.read(),
swap_chain_frames: self.swap_chain_frames.read(), surface_textures: self.surface_textures.read(),
render_pipelines: self.render_pipelines.read(), render_pipelines: self.render_pipelines.read(),
bind_groups: self.bind_groups.read(), bind_groups: self.bind_groups.read(),
used_bind_group_sender: self.bind_group_counter.used_bind_group_sender.clone(), used_bind_group_sender: self.bind_group_counter.used_bind_group_sender.clone(),

View file

@ -13,7 +13,7 @@ use bevy_render::{
texture::{ texture::{
AddressMode, Extent3d, FilterMode, SamplerBorderColor, SamplerDescriptor, AddressMode, Extent3d, FilterMode, SamplerBorderColor, SamplerDescriptor,
StorageTextureAccess, TextureDescriptor, TextureDimension, TextureFormat, StorageTextureAccess, TextureDescriptor, TextureDimension, TextureFormat,
TextureSampleType, TextureUsage, TextureViewDimension, TextureSampleType, TextureUsages, TextureViewDimension,
}, },
}; };
use bevy_window::Window; use bevy_window::Window;
@ -83,11 +83,11 @@ impl WgpuFrom<&VertexAttribute> for wgpu::VertexAttribute {
} }
} }
impl WgpuFrom<InputStepMode> for wgpu::InputStepMode { impl WgpuFrom<InputStepMode> for wgpu::VertexStepMode {
fn from(val: InputStepMode) -> Self { fn from(val: InputStepMode) -> Self {
match val { match val {
InputStepMode::Vertex => wgpu::InputStepMode::Vertex, InputStepMode::Vertex => wgpu::VertexStepMode::Vertex,
InputStepMode::Instance => wgpu::InputStepMode::Instance, InputStepMode::Instance => wgpu::VertexStepMode::Instance,
} }
} }
} }
@ -95,7 +95,7 @@ impl WgpuFrom<InputStepMode> for wgpu::InputStepMode {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct OwnedWgpuVertexBufferLayout { pub struct OwnedWgpuVertexBufferLayout {
pub array_stride: wgpu::BufferAddress, pub array_stride: wgpu::BufferAddress,
pub step_mode: wgpu::InputStepMode, pub step_mode: wgpu::VertexStepMode,
pub attributes: Vec<wgpu::VertexAttribute>, pub attributes: Vec<wgpu::VertexAttribute>,
} }
@ -137,9 +137,9 @@ impl WgpuFrom<Color> for wgpu::Color {
} }
} }
impl WgpuFrom<BufferUsage> for wgpu::BufferUsage { impl WgpuFrom<BufferUsage> for wgpu::BufferUsages {
fn from(val: BufferUsage) -> Self { fn from(val: BufferUsage) -> Self {
wgpu::BufferUsage::from_bits(val.bits()).unwrap() wgpu::BufferUsages::from_bits(val.bits()).unwrap()
} }
} }
@ -190,7 +190,9 @@ impl WgpuFrom<&BindType> for wgpu::BindingType {
} => wgpu::BindingType::Buffer { } => wgpu::BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: *has_dynamic_offset, has_dynamic_offset: *has_dynamic_offset,
min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new), // FIXME: The line below cause a validation error
// min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new),
min_binding_size: None,
}, },
BindType::StorageBuffer { BindType::StorageBuffer {
has_dynamic_offset, has_dynamic_offset,
@ -200,7 +202,9 @@ impl WgpuFrom<&BindType> for wgpu::BindingType {
read_only: *readonly, read_only: *readonly,
}, },
has_dynamic_offset: *has_dynamic_offset, has_dynamic_offset: *has_dynamic_offset,
min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new), // FIXME: The line below cause a validation error
// min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new),
min_binding_size: None,
}, },
BindType::Texture { BindType::Texture {
view_dimension, view_dimension,
@ -346,9 +350,9 @@ impl WgpuFrom<TextureFormat> for wgpu::TextureFormat {
} }
} }
impl WgpuFrom<TextureUsage> for wgpu::TextureUsage { impl WgpuFrom<TextureUsages> for wgpu::TextureUsages {
fn from(val: TextureUsage) -> Self { fn from(val: TextureUsages) -> Self {
wgpu::TextureUsage::from_bits(val.bits()).unwrap() wgpu::TextureUsages::from_bits(val.bits()).unwrap()
} }
} }
@ -526,9 +530,9 @@ impl WgpuFrom<PrimitiveState> for wgpu::PrimitiveState {
} }
} }
impl WgpuFrom<ColorWrite> for wgpu::ColorWrite { impl WgpuFrom<ColorWrite> for wgpu::ColorWrites {
fn from(val: ColorWrite) -> Self { fn from(val: ColorWrite) -> Self {
wgpu::ColorWrite::from_bits(val.bits()).unwrap() wgpu::ColorWrites::from_bits(val.bits()).unwrap()
} }
} }
@ -640,10 +644,10 @@ impl WgpuFrom<SamplerBorderColor> for wgpu::SamplerBorderColor {
} }
} }
impl WgpuFrom<&Window> for wgpu::SwapChainDescriptor { impl WgpuFrom<&Window> for wgpu::SurfaceConfiguration {
fn from(window: &Window) -> Self { fn from(window: &Window) -> Self {
wgpu::SwapChainDescriptor { wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: TextureFormat::default().wgpu_into(), format: TextureFormat::default().wgpu_into(),
width: window.physical_width().max(1), width: window.physical_width().max(1),
height: window.physical_height().max(1), height: window.physical_height().max(1),
@ -664,21 +668,12 @@ impl WgpuFrom<WgpuFeature> for wgpu::Features {
WgpuFeature::TimestampQuery => wgpu::Features::TIMESTAMP_QUERY, WgpuFeature::TimestampQuery => wgpu::Features::TIMESTAMP_QUERY,
WgpuFeature::PipelineStatisticsQuery => wgpu::Features::PIPELINE_STATISTICS_QUERY, WgpuFeature::PipelineStatisticsQuery => wgpu::Features::PIPELINE_STATISTICS_QUERY,
WgpuFeature::MappablePrimaryBuffers => wgpu::Features::MAPPABLE_PRIMARY_BUFFERS, WgpuFeature::MappablePrimaryBuffers => wgpu::Features::MAPPABLE_PRIMARY_BUFFERS,
WgpuFeature::SampledTextureBindingArray => {
wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY
}
WgpuFeature::SampledTextureArrayDynamicIndexing => {
wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING
}
WgpuFeature::SampledTextureArrayNonUniformIndexing => {
wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
}
WgpuFeature::UnsizedBindingArray => wgpu::Features::UNSIZED_BINDING_ARRAY, WgpuFeature::UnsizedBindingArray => wgpu::Features::UNSIZED_BINDING_ARRAY,
WgpuFeature::MultiDrawIndirect => wgpu::Features::MULTI_DRAW_INDIRECT, WgpuFeature::MultiDrawIndirect => wgpu::Features::MULTI_DRAW_INDIRECT,
WgpuFeature::MultiDrawIndirectCount => wgpu::Features::MULTI_DRAW_INDIRECT_COUNT, WgpuFeature::MultiDrawIndirectCount => wgpu::Features::MULTI_DRAW_INDIRECT_COUNT,
WgpuFeature::PushConstants => wgpu::Features::PUSH_CONSTANTS, WgpuFeature::PushConstants => wgpu::Features::PUSH_CONSTANTS,
WgpuFeature::AddressModeClampToBorder => wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER, WgpuFeature::AddressModeClampToBorder => wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
WgpuFeature::NonFillPolygonMode => wgpu::Features::NON_FILL_POLYGON_MODE, WgpuFeature::PolygonModeLine => wgpu::Features::POLYGON_MODE_LINE,
WgpuFeature::TextureCompressionEtc2 => wgpu::Features::TEXTURE_COMPRESSION_ETC2, WgpuFeature::TextureCompressionEtc2 => wgpu::Features::TEXTURE_COMPRESSION_ETC2,
WgpuFeature::TextureCompressionAstcLdr => wgpu::Features::TEXTURE_COMPRESSION_ASTC_LDR, WgpuFeature::TextureCompressionAstcLdr => wgpu::Features::TEXTURE_COMPRESSION_ASTC_LDR,
WgpuFeature::TextureAdapterSpecificFormatFeatures => { WgpuFeature::TextureAdapterSpecificFormatFeatures => {
@ -724,6 +719,8 @@ impl WgpuFrom<WgpuLimits> for wgpu::Limits {
max_vertex_buffers: val.max_vertex_buffers, max_vertex_buffers: val.max_vertex_buffers,
max_vertex_attributes: val.max_vertex_attributes, max_vertex_attributes: val.max_vertex_attributes,
max_vertex_buffer_array_stride: val.max_vertex_buffer_array_stride, max_vertex_buffer_array_stride: val.max_vertex_buffer_array_stride,
min_storage_buffer_offset_alignment: val.min_storage_buffer_offset_alignment,
min_uniform_buffer_offset_alignment: val.min_uniform_buffer_offset_alignment,
} }
} }
} }

View file

@ -13,7 +13,7 @@ use bevy::{
}, },
texture::{ texture::{
Extent3d, SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat, Extent3d, SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat,
TextureUsage, TextureUsages,
}, },
}, },
window::WindowId, window::WindowId,
@ -65,7 +65,7 @@ fn add_render_to_texture_graph(graph: &mut RenderGraph, size: Extent3d) {
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: Default::default(), format: Default::default(),
usage: TextureUsage::OUTPUT_ATTACHMENT | TextureUsage::SAMPLED, usage: TextureUsages::OUTPUT_ATTACHMENT | TextureUsages::SAMPLED,
}, },
Some(SamplerDescriptor::default()), Some(SamplerDescriptor::default()),
Some(RENDER_TEXTURE_HANDLE), Some(RENDER_TEXTURE_HANDLE),
@ -81,7 +81,7 @@ fn add_render_to_texture_graph(graph: &mut RenderGraph, size: Extent3d) {
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
usage: TextureUsage::OUTPUT_ATTACHMENT | TextureUsage::SAMPLED, usage: TextureUsages::OUTPUT_ATTACHMENT | TextureUsages::SAMPLED,
}, },
None, None,
None, None,

View file

@ -10,7 +10,7 @@ fn main() {
.insert_resource(WgpuOptions { .insert_resource(WgpuOptions {
features: WgpuFeatures { features: WgpuFeatures {
// The Wireframe requires NonFillPolygonMode feature // The Wireframe requires NonFillPolygonMode feature
features: vec![WgpuFeature::NonFillPolygonMode], features: vec![WgpuFeature::PolygonModeLine],
}, },
..Default::default() ..Default::default()
}) })

View file

@ -57,7 +57,7 @@ impl RenderAsset for CustomMaterial {
let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
contents: color.as_std140().as_bytes(), contents: color.as_std140().as_bytes(),
label: None, label: None,
usage: BufferUsage::UNIFORM | BufferUsage::COPY_DST, usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
}); });
let bind_group = render_device.create_bind_group(&BindGroupDescriptor { let bind_group = render_device.create_bind_group(&BindGroupDescriptor {
entries: &[BindGroupEntry { entries: &[BindGroupEntry {
@ -136,7 +136,7 @@ impl FromWorld for CustomPipeline {
let material_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { let material_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
entries: &[BindGroupLayoutEntry { entries: &[BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: false, has_dynamic_offset: false,
@ -163,7 +163,7 @@ impl FromWorld for CustomPipeline {
vertex: VertexState { vertex: VertexState {
buffers: &[VertexBufferLayout { buffers: &[VertexBufferLayout {
array_stride: 32, array_stride: 32,
step_mode: InputStepMode::Vertex, step_mode: VertexStepMode::Vertex,
attributes: &[ attributes: &[
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically)) // Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute { VertexAttribute {
@ -205,7 +205,7 @@ impl FromWorld for CustomPipeline {
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
}), }),
write_mask: ColorWrite::ALL, write_mask: ColorWrites::ALL,
}], }],
}), }),
depth_stencil: Some(DepthStencilState { depth_stencil: Some(DepthStencilState {

View file

@ -7,7 +7,7 @@ use bevy::{
base::MainPass, CameraNode, PassNode, RenderGraph, WindowSwapChainNode, base::MainPass, CameraNode, PassNode, RenderGraph, WindowSwapChainNode,
WindowTextureNode, WindowTextureNode,
}, },
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage}, texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages},
}, },
window::{CreateWindow, WindowDescriptor, WindowId}, window::{CreateWindow, WindowDescriptor, WindowId},
}; };
@ -88,7 +88,7 @@ fn setup_pipeline(
window_id, window_id,
TextureDescriptor { TextureDescriptor {
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
usage: TextureUsage::OUTPUT_ATTACHMENT, usage: TextureUsages::OUTPUT_ATTACHMENT,
sample_count: msaa.samples, sample_count: msaa.samples,
..Default::default() ..Default::default()
}, },
@ -165,7 +165,7 @@ fn setup_pipeline(
sample_count: msaa.samples, sample_count: msaa.samples,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::default(), format: TextureFormat::default(),
usage: TextureUsage::OUTPUT_ATTACHMENT, usage: TextureUsages::OUTPUT_ATTACHMENT,
}, },
), ),
); );

View file

@ -246,7 +246,7 @@ pub fn prepare_core_views_system(
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24 format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24
* bit depth for better performance */ * bit depth for better performance */
usage: TextureUsage::RENDER_ATTACHMENT, usage: TextureUsages::RENDER_ATTACHMENT,
}, },
); );
commands.entity(entity).insert(ViewDepthTexture { commands.entity(entity).insert(ViewDepthTexture {

View file

@ -22,7 +22,11 @@ impl Node for MainPassDriverNode {
if let Some(camera_2d) = extracted_cameras.entities.get(CameraPlugin::CAMERA_2D) { if let Some(camera_2d) = extracted_cameras.entities.get(CameraPlugin::CAMERA_2D) {
let extracted_camera = world.entity(*camera_2d).get::<ExtractedCamera>().unwrap(); let extracted_camera = world.entity(*camera_2d).get::<ExtractedCamera>().unwrap();
let extracted_window = extracted_windows.get(&extracted_camera.window_id).unwrap(); let extracted_window = extracted_windows.get(&extracted_camera.window_id).unwrap();
let swap_chain_texture = extracted_window.swap_chain_frame.as_ref().unwrap().clone(); let swap_chain_texture = extracted_window
.swap_chain_texture
.as_ref()
.unwrap()
.clone();
graph.run_sub_graph( graph.run_sub_graph(
crate::draw_2d_graph::NAME, crate::draw_2d_graph::NAME,
vec![ vec![
@ -36,7 +40,11 @@ impl Node for MainPassDriverNode {
let extracted_camera = world.entity(*camera_3d).get::<ExtractedCamera>().unwrap(); let extracted_camera = world.entity(*camera_3d).get::<ExtractedCamera>().unwrap();
let depth_texture = world.entity(*camera_3d).get::<ViewDepthTexture>().unwrap(); let depth_texture = world.entity(*camera_3d).get::<ViewDepthTexture>().unwrap();
let extracted_window = extracted_windows.get(&extracted_camera.window_id).unwrap(); let extracted_window = extracted_windows.get(&extracted_camera.window_id).unwrap();
let swap_chain_texture = extracted_window.swap_chain_frame.as_ref().unwrap().clone(); let swap_chain_texture = extracted_window
.swap_chain_texture
.as_ref()
.unwrap()
.clone();
graph.run_sub_graph( graph.run_sub_graph(
crate::draw_3d_graph::NAME, crate::draw_3d_graph::NAME,
vec![ vec![

View file

@ -32,4 +32,4 @@ thiserror = "1.0"
anyhow = "1.0.4" anyhow = "1.0.4"
base64 = "0.13.0" base64 = "0.13.0"
percent-encoding = "2.1" percent-encoding = "2.1"
wgpu = "0.9" wgpu = "0.11.0"

View file

@ -30,4 +30,4 @@ bitflags = "1.2"
# direct dependency required for derive macro # direct dependency required for derive macro
bytemuck = { version = "1", features = ["derive"] } bytemuck = { version = "1", features = ["derive"] }
crevice = { path = "../../crates/crevice", version = "0.6.0" } crevice = { path = "../../crates/crevice", version = "0.6.0" }
wgpu = "0.9" wgpu = { version = "0.11.0", features = ["spirv"] }

View file

@ -6,7 +6,9 @@ use bevy_reflect::TypeUuid;
use bevy_render2::{ use bevy_render2::{
color::Color, color::Color,
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets}, render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
render_resource::{BindGroup, Buffer, BufferInitDescriptor, BufferUsage, Sampler, TextureView}, render_resource::{
BindGroup, Buffer, BufferInitDescriptor, BufferUsages, Sampler, TextureView,
},
renderer::RenderDevice, renderer::RenderDevice,
texture::Image, texture::Image,
}; };
@ -222,7 +224,7 @@ impl RenderAsset for StandardMaterial {
let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
label: Some("pbr_standard_material_uniform_buffer"), label: Some("pbr_standard_material_uniform_buffer"),
usage: BufferUsage::UNIFORM | BufferUsage::COPY_DST, usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
contents: value_std140.as_bytes(), contents: value_std140.as_bytes(),
}); });
let bind_group = render_device.create_bind_group(&BindGroupDescriptor { let bind_group = render_device.create_bind_group(&BindGroupDescriptor {

View file

@ -6,7 +6,7 @@ struct View {
world_position: vec3<f32>; world_position: vec3<f32>;
}; };
[[group(0), binding(0)]] [[group(0), binding(0)]]
var view: View; var<uniform> view: View;
[[block]] [[block]]
@ -18,7 +18,7 @@ struct Mesh {
}; };
[[group(1), binding(0)]] [[group(1), binding(0)]]
var mesh: Mesh; var<uniform> mesh: Mesh;
struct Vertex { struct Vertex {
[[location(0)]] position: vec3<f32>; [[location(0)]] position: vec3<f32>;

View file

@ -122,7 +122,7 @@ impl FromWorld for ShadowShaders {
// View // View
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::VERTEX | ShaderStage::FRAGMENT, visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: true, has_dynamic_offset: true,
@ -147,7 +147,7 @@ impl FromWorld for ShadowShaders {
vertex: VertexState { vertex: VertexState {
buffers: &[VertexBufferLayout { buffers: &[VertexBufferLayout {
array_stride: 32, array_stride: 32,
step_mode: InputStepMode::Vertex, step_mode: VertexStepMode::Vertex,
attributes: &[ attributes: &[
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically)) // Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute { VertexAttribute {
@ -411,8 +411,8 @@ pub fn prepare_lights(
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: SHADOW_FORMAT, format: SHADOW_FORMAT,
usage: TextureUsage::RENDER_ATTACHMENT | TextureUsage::SAMPLED,
label: Some("point_light_shadow_map_texture"), label: Some("point_light_shadow_map_texture"),
usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING,
}, },
); );
let directional_light_depth_texture = texture_cache.get( let directional_light_depth_texture = texture_cache.get(
@ -427,8 +427,8 @@ pub fn prepare_lights(
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: SHADOW_FORMAT, format: SHADOW_FORMAT,
usage: TextureUsage::RENDER_ATTACHMENT | TextureUsage::SAMPLED,
label: Some("directional_light_shadow_map_texture"), label: Some("directional_light_shadow_map_texture"),
usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING,
}, },
); );
let mut view_lights = Vec::new(); let mut view_lights = Vec::new();

View file

@ -136,7 +136,7 @@ impl FromWorld for PbrShaders {
// View // View
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::VERTEX | ShaderStage::FRAGMENT, visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: true, has_dynamic_offset: true,
@ -149,7 +149,7 @@ impl FromWorld for PbrShaders {
// Lights // Lights
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: true, has_dynamic_offset: true,
@ -162,7 +162,7 @@ impl FromWorld for PbrShaders {
// Point Shadow Texture Cube Array // Point Shadow Texture Cube Array
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 2, binding: 2,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Depth, sample_type: TextureSampleType::Depth,
@ -173,7 +173,7 @@ impl FromWorld for PbrShaders {
// Point Shadow Texture Array Sampler // Point Shadow Texture Array Sampler
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 3, binding: 3,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: true, comparison: true,
filtering: true, filtering: true,
@ -183,7 +183,7 @@ impl FromWorld for PbrShaders {
// Directional Shadow Texture Array // Directional Shadow Texture Array
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 4, binding: 4,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Depth, sample_type: TextureSampleType::Depth,
@ -194,7 +194,7 @@ impl FromWorld for PbrShaders {
// Directional Shadow Texture Array Sampler // Directional Shadow Texture Array Sampler
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 5, binding: 5,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: true, comparison: true,
filtering: true, filtering: true,
@ -209,7 +209,7 @@ impl FromWorld for PbrShaders {
entries: &[ entries: &[
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: false, has_dynamic_offset: false,
@ -222,7 +222,7 @@ impl FromWorld for PbrShaders {
// Base Color Texture // Base Color Texture
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Float { filterable: true }, sample_type: TextureSampleType::Float { filterable: true },
@ -233,7 +233,7 @@ impl FromWorld for PbrShaders {
// Base Color Texture Sampler // Base Color Texture Sampler
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 2, binding: 2,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: false, comparison: false,
filtering: true, filtering: true,
@ -243,7 +243,7 @@ impl FromWorld for PbrShaders {
// Emissive Texture // Emissive Texture
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 3, binding: 3,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Float { filterable: true }, sample_type: TextureSampleType::Float { filterable: true },
@ -254,7 +254,7 @@ impl FromWorld for PbrShaders {
// Emissive Texture Sampler // Emissive Texture Sampler
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 4, binding: 4,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: false, comparison: false,
filtering: true, filtering: true,
@ -264,7 +264,7 @@ impl FromWorld for PbrShaders {
// Metallic Roughness Texture // Metallic Roughness Texture
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 5, binding: 5,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Float { filterable: true }, sample_type: TextureSampleType::Float { filterable: true },
@ -275,7 +275,7 @@ impl FromWorld for PbrShaders {
// Metallic Roughness Texture Sampler // Metallic Roughness Texture Sampler
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 6, binding: 6,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: false, comparison: false,
filtering: true, filtering: true,
@ -285,7 +285,7 @@ impl FromWorld for PbrShaders {
// Occlusion Texture // Occlusion Texture
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 7, binding: 7,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Float { filterable: true }, sample_type: TextureSampleType::Float { filterable: true },
@ -296,7 +296,7 @@ impl FromWorld for PbrShaders {
// Occlusion Texture Sampler // Occlusion Texture Sampler
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 8, binding: 8,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: false, comparison: false,
filtering: true, filtering: true,
@ -310,7 +310,7 @@ impl FromWorld for PbrShaders {
let mesh_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { let mesh_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
entries: &[BindGroupLayoutEntry { entries: &[BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::VERTEX | ShaderStage::FRAGMENT, visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: true, has_dynamic_offset: true,
@ -334,7 +334,7 @@ impl FromWorld for PbrShaders {
vertex: VertexState { vertex: VertexState {
buffers: &[VertexBufferLayout { buffers: &[VertexBufferLayout {
array_stride: 32, array_stride: 32,
step_mode: InputStepMode::Vertex, step_mode: VertexStepMode::Vertex,
attributes: &[ attributes: &[
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically)) // Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute { VertexAttribute {
@ -376,7 +376,7 @@ impl FromWorld for PbrShaders {
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
}), }),
write_mask: ColorWrite::ALL, write_mask: ColorWrites::ALL,
}], }],
}), }),
depth_stencil: Some(DepthStencilState { depth_stencil: Some(DepthStencilState {
@ -426,6 +426,7 @@ impl FromWorld for PbrShaders {
texture: &texture, texture: &texture,
mip_level: 0, mip_level: 0,
origin: Origin3d::ZERO, origin: Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
}, },
&image.data, &image.data,
ImageDataLayout { ImageDataLayout {

View file

@ -18,9 +18,9 @@ struct Mesh {
let MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u; let MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u;
[[group(0), binding(0)]] [[group(0), binding(0)]]
var view: View; var<uniform> view: View;
[[group(2), binding(0)]] [[group(2), binding(0)]]
var mesh: Mesh; var<uniform> mesh: Mesh;
struct Vertex { struct Vertex {
[[location(0)]] position: vec3<f32>; [[location(0)]] position: vec3<f32>;
@ -136,7 +136,7 @@ struct Lights {
[[group(0), binding(1)]] [[group(0), binding(1)]]
var lights: Lights; var<uniform> lights: Lights;
[[group(0), binding(2)]] [[group(0), binding(2)]]
var point_shadow_textures: texture_depth_cube_array; var point_shadow_textures: texture_depth_cube_array;
[[group(0), binding(3)]] [[group(0), binding(3)]]
@ -147,7 +147,7 @@ var directional_shadow_textures: texture_depth_2d_array;
var directional_shadow_textures_sampler: sampler_comparison; var directional_shadow_textures_sampler: sampler_comparison;
[[group(1), binding(0)]] [[group(1), binding(0)]]
var material: StandardMaterial; var<uniform> material: StandardMaterial;
[[group(1), binding(1)]] [[group(1), binding(1)]]
var base_color_texture: texture_2d<f32>; var base_color_texture: texture_2d<f32>;
[[group(1), binding(2)]] [[group(1), binding(2)]]
@ -293,7 +293,7 @@ fn reinhard(color: vec3<f32>) -> vec3<f32> {
} }
fn reinhard_extended(color: vec3<f32>, max_white: f32) -> vec3<f32> { fn reinhard_extended(color: vec3<f32>, max_white: f32) -> vec3<f32> {
let numerator = color * (1.0f + (color / vec3<f32>(max_white * max_white))); let numerator = color * (1.0 + (color / vec3<f32>(max_white * max_white)));
return numerator / (1.0 + color); return numerator / (1.0 + color);
} }
@ -310,14 +310,14 @@ fn change_luminance(c_in: vec3<f32>, l_out: f32) -> vec3<f32> {
fn reinhard_luminance(color: vec3<f32>) -> vec3<f32> { fn reinhard_luminance(color: vec3<f32>) -> vec3<f32> {
let l_old = luminance(color); let l_old = luminance(color);
let l_new = l_old / (1.0f + l_old); let l_new = l_old / (1.0 + l_old);
return change_luminance(color, l_new); return change_luminance(color, l_new);
} }
fn reinhard_extended_luminance(color: vec3<f32>, max_white_l: f32) -> vec3<f32> { fn reinhard_extended_luminance(color: vec3<f32>, max_white_l: f32) -> vec3<f32> {
let l_old = luminance(color); let l_old = luminance(color);
let numerator = l_old * (1.0f + (l_old / (max_white_l * max_white_l))); let numerator = l_old * (1.0 + (l_old / (max_white_l * max_white_l)));
let l_new = numerator / (1.0f + l_old); let l_new = numerator / (1.0 + l_old);
return change_luminance(color, l_new); return change_luminance(color, l_new);
} }

View file

@ -29,8 +29,8 @@ bevy_utils = { path = "../../crates/bevy_utils", version = "0.5.0" }
image = { version = "0.23.12", default-features = false } image = { version = "0.23.12", default-features = false }
# misc # misc
wgpu = "0.9" wgpu = { version = "0.11.0", features = ["spirv"] }
naga = { version = "0.5", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] } naga = { version = "0.7.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
bitflags = "1.2.1" bitflags = "1.2.1"
smallvec = { version = "1.6", features = ["union", "const_generics"] } smallvec = { version = "1.6", features = ["union", "const_generics"] }

View file

@ -25,7 +25,7 @@ use bevy_app::{App, AppLabel, Plugin};
use bevy_asset::AssetServer; use bevy_asset::AssetServer;
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use wgpu::BackendBit; use wgpu::Backends;
#[derive(Default)] #[derive(Default)]
pub struct RenderPlugin; pub struct RenderPlugin;
@ -86,7 +86,7 @@ impl Plugin for RenderPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let (instance, device, queue) = let (instance, device, queue) =
futures_lite::future::block_on(renderer::initialize_renderer( futures_lite::future::block_on(renderer::initialize_renderer(
BackendBit::PRIMARY, wgpu::util::backend_bits_from_env().unwrap_or(Backends::PRIMARY),
&wgpu::RequestAdapterOptions { &wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance, power_preference: wgpu::PowerPreference::HighPerformance,
..Default::default() ..Default::default()

View file

@ -11,7 +11,9 @@ use bevy_math::*;
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use bevy_utils::EnumVariantMeta; use bevy_utils::EnumVariantMeta;
use std::{borrow::Cow, collections::BTreeMap}; use std::{borrow::Cow, collections::BTreeMap};
use wgpu::{util::BufferInitDescriptor, BufferUsage, IndexFormat, PrimitiveTopology, VertexFormat}; use wgpu::{
util::BufferInitDescriptor, BufferUsages, IndexFormat, PrimitiveTopology, VertexFormat,
};
pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
@ -553,14 +555,14 @@ impl RenderAsset for Mesh {
) -> Result<Self::PreparedAsset, PrepareAssetError<Self::ExtractedAsset>> { ) -> Result<Self::PreparedAsset, PrepareAssetError<Self::ExtractedAsset>> {
let vertex_buffer_data = mesh.get_vertex_buffer_data(); let vertex_buffer_data = mesh.get_vertex_buffer_data();
let vertex_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { let vertex_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
usage: BufferUsage::VERTEX, usage: BufferUsages::VERTEX,
label: None, label: None,
contents: &vertex_buffer_data, contents: &vertex_buffer_data,
}); });
let index_info = mesh.get_index_buffer_bytes().map(|data| GpuIndexInfo { let index_info = mesh.get_index_buffer_bytes().map(|data| GpuIndexInfo {
buffer: render_device.create_buffer_with_data(&BufferInitDescriptor { buffer: render_device.create_buffer_with_data(&BufferInitDescriptor {
usage: BufferUsage::INDEX, usage: BufferUsages::INDEX,
contents: data, contents: data,
label: None, label: None,
}), }),

View file

@ -3,14 +3,14 @@ use crate::{
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
}; };
use bevy_core::{cast_slice, Pod}; use bevy_core::{cast_slice, Pod};
use wgpu::BufferUsage; use wgpu::BufferUsages;
pub struct BufferVec<T: Pod> { pub struct BufferVec<T: Pod> {
values: Vec<T>, values: Vec<T>,
buffer: Option<Buffer>, buffer: Option<Buffer>,
capacity: usize, capacity: usize,
item_size: usize, item_size: usize,
buffer_usage: BufferUsage, buffer_usage: BufferUsages,
} }
impl<T: Pod> Default for BufferVec<T> { impl<T: Pod> Default for BufferVec<T> {
@ -19,14 +19,14 @@ impl<T: Pod> Default for BufferVec<T> {
values: Vec::new(), values: Vec::new(),
buffer: None, buffer: None,
capacity: 0, capacity: 0,
buffer_usage: BufferUsage::all(), buffer_usage: BufferUsages::all(),
item_size: std::mem::size_of::<T>(), item_size: std::mem::size_of::<T>(),
} }
} }
} }
impl<T: Pod> BufferVec<T> { impl<T: Pod> BufferVec<T> {
pub fn new(buffer_usage: BufferUsage) -> Self { pub fn new(buffer_usage: BufferUsages) -> Self {
Self { Self {
buffer_usage, buffer_usage,
..Default::default() ..Default::default()
@ -63,7 +63,7 @@ impl<T: Pod> BufferVec<T> {
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor { self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
label: None, label: None,
size: size as wgpu::BufferAddress, size: size as wgpu::BufferAddress,
usage: BufferUsage::COPY_DST | self.buffer_usage, usage: BufferUsages::COPY_DST | self.buffer_usage,
mapped_at_creation: false, mapped_at_creation: false,
})); }));
} }

View file

@ -17,14 +17,14 @@ pub use wgpu::{
util::BufferInitDescriptor, AddressMode, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, util::BufferInitDescriptor, AddressMode, BindGroupDescriptor, BindGroupEntry, BindGroupLayout,
BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent,
BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBindingType, BufferSize, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBindingType, BufferSize,
BufferUsage, ColorTargetState, ColorWrite, CompareFunction, ComputePassDescriptor, BufferUsages, ColorTargetState, ColorWrites, CompareFunction, ComputePassDescriptor,
ComputePipelineDescriptor, DepthBiasState, DepthStencilState, Extent3d, Face, FilterMode, ComputePipelineDescriptor, DepthBiasState, DepthStencilState, Extent3d, Face, FilterMode,
FragmentState, FrontFace, IndexFormat, InputStepMode, LoadOp, MultisampleState, Operations, FragmentState, FrontFace, IndexFormat, LoadOp, MultisampleState, Operations, PipelineLayout,
PipelineLayout, PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology, PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology,
RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor,
RenderPipelineDescriptor, SamplerDescriptor, ShaderFlags, ShaderModule, ShaderModuleDescriptor, RenderPipelineDescriptor, SamplerDescriptor, ShaderModule, ShaderModuleDescriptor,
ShaderSource, ShaderStage, StencilFaceState, StencilOperation, StencilState, ShaderSource, ShaderStages, StencilFaceState, StencilOperation, StencilState,
StorageTextureAccess, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat, StorageTextureAccess, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat,
TextureSampleType, TextureUsage, TextureViewDescriptor, TextureViewDimension, VertexAttribute, TextureSampleType, TextureUsages, TextureViewDescriptor, TextureViewDimension, VertexAttribute,
VertexBufferLayout, VertexFormat, VertexState, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode,
}; };

View file

@ -45,7 +45,12 @@ pub struct TextureViewId(Uuid);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum TextureViewValue { pub enum TextureViewValue {
TextureView(Arc<wgpu::TextureView>), TextureView(Arc<wgpu::TextureView>),
SwapChainFrame(Arc<wgpu::SwapChainFrame>), SurfaceTexture {
// NOTE: The order of these fields is important because the view must be dropped before the
// frame is dropped
view: Arc<wgpu::TextureView>,
texture: Arc<wgpu::SurfaceTexture>,
},
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -59,6 +64,14 @@ impl TextureView {
pub fn id(&self) -> TextureViewId { pub fn id(&self) -> TextureViewId {
self.id self.id
} }
#[inline]
pub fn take_surface_texture(self) -> Option<wgpu::SurfaceTexture> {
match self.value {
TextureViewValue::TextureView(_) => None,
TextureViewValue::SurfaceTexture { texture, .. } => Arc::try_unwrap(texture).ok(),
}
}
} }
impl From<wgpu::TextureView> for TextureView { impl From<wgpu::TextureView> for TextureView {
@ -70,11 +83,14 @@ impl From<wgpu::TextureView> for TextureView {
} }
} }
impl From<wgpu::SwapChainFrame> for TextureView { impl From<wgpu::SurfaceTexture> for TextureView {
fn from(value: wgpu::SwapChainFrame) -> Self { fn from(value: wgpu::SurfaceTexture) -> Self {
let texture = Arc::new(value);
let view = Arc::new(texture.texture.create_view(&Default::default()));
TextureView { TextureView {
id: TextureViewId(Uuid::new_v4()), id: TextureViewId(Uuid::new_v4()),
value: TextureViewValue::SwapChainFrame(Arc::new(value)), value: TextureViewValue::SurfaceTexture { texture, view },
} }
} }
} }
@ -86,7 +102,7 @@ impl Deref for TextureView {
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match &self.value { match &self.value {
TextureViewValue::TextureView(value) => value, TextureViewValue::TextureView(value) => value,
TextureViewValue::SwapChainFrame(value) => &value.output.view, TextureViewValue::SurfaceTexture { view, .. } => view,
} }
} }
} }

View file

@ -4,7 +4,7 @@ use crate::{
}; };
use crevice::std140::{self, AsStd140, DynamicUniform, Std140}; use crevice::std140::{self, AsStd140, DynamicUniform, Std140};
use std::num::NonZeroU64; use std::num::NonZeroU64;
use wgpu::{BindingResource, BufferBinding, BufferDescriptor, BufferUsage}; use wgpu::{BindingResource, BufferBinding, BufferDescriptor, BufferUsages};
pub struct UniformVec<T: AsStd140> { pub struct UniformVec<T: AsStd140> {
values: Vec<T>, values: Vec<T>,
@ -78,7 +78,7 @@ impl<T: AsStd140> UniformVec<T> {
self.uniform_buffer = Some(device.create_buffer(&BufferDescriptor { self.uniform_buffer = Some(device.create_buffer(&BufferDescriptor {
label: None, label: None,
size: size as wgpu::BufferAddress, size: size as wgpu::BufferAddress,
usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM,
mapped_at_creation: false, mapped_at_creation: false,
})); }));
} }

View file

@ -1,14 +1,14 @@
mod graph_runner; mod graph_runner;
mod render_device; mod render_device;
use bevy_utils::tracing::info; use bevy_utils::tracing::{info, info_span};
pub use graph_runner::*; pub use graph_runner::*;
pub use render_device::*; pub use render_device::*;
use crate::render_graph::RenderGraph; use crate::{render_graph::RenderGraph, view::ExtractedWindows};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use std::sync::Arc; use std::sync::Arc;
use wgpu::{BackendBit, CommandEncoder, DeviceDescriptor, Instance, Queue, RequestAdapterOptions}; use wgpu::{Backends, CommandEncoder, DeviceDescriptor, Instance, Queue, RequestAdapterOptions};
pub fn render_system(world: &mut World) { pub fn render_system(world: &mut World) {
world.resource_scope(|world, mut graph: Mut<RenderGraph>| { world.resource_scope(|world, mut graph: Mut<RenderGraph>| {
@ -24,13 +24,25 @@ pub fn render_system(world: &mut World) {
world, world,
) )
.unwrap(); .unwrap();
{
let span = info_span!("present_frames");
let _guard = span.enter();
let mut windows = world.get_resource_mut::<ExtractedWindows>().unwrap();
for window in windows.values_mut() {
if let Some(texture_view) = window.swap_chain_texture.take() {
if let Some(surface_texture) = texture_view.take_surface_texture() {
surface_texture.present();
}
}
}
}
} }
pub type RenderQueue = Arc<Queue>; pub type RenderQueue = Arc<Queue>;
pub type RenderInstance = Instance; pub type RenderInstance = Instance;
pub async fn initialize_renderer( pub async fn initialize_renderer(
backends: BackendBit, backends: Backends,
request_adapter_options: &RequestAdapterOptions<'_>, request_adapter_options: &RequestAdapterOptions<'_>,
device_descriptor: &DeviceDescriptor<'_>, device_descriptor: &DeviceDescriptor<'_>,
) -> (RenderInstance, RenderDevice, RenderQueue) { ) -> (RenderInstance, RenderDevice, RenderQueue) {

View file

@ -145,12 +145,8 @@ impl RenderDevice {
/// ///
/// - A old [`SwapChainFrame`] is still alive referencing an old swapchain. /// - A old [`SwapChainFrame`] is still alive referencing an old swapchain.
/// - Texture format requested is unsupported on the swap chain. /// - Texture format requested is unsupported on the swap chain.
pub fn create_swap_chain( pub fn configure_surface(&self, surface: &wgpu::Surface, config: &wgpu::SurfaceConfiguration) {
&self, surface.configure(&self.device, config)
surface: &wgpu::Surface,
desc: &wgpu::SwapChainDescriptor,
) -> wgpu::SwapChain {
self.device.create_swap_chain(surface, desc)
} }
pub fn wgpu_device(&self) -> &wgpu::Device { pub fn wgpu_device(&self) -> &wgpu::Device {

View file

@ -1,10 +1,10 @@
use bevy_asset::{AssetLoader, LoadContext, LoadedAsset}; use bevy_asset::{AssetLoader, LoadContext, LoadedAsset};
use bevy_reflect::{TypeUuid, Uuid}; use bevy_reflect::{TypeUuid, Uuid};
use bevy_utils::{tracing::error, BoxedFuture}; use bevy_utils::{tracing::error, BoxedFuture};
use naga::{valid::ModuleInfo, Module, ShaderStage}; use naga::{valid::ModuleInfo, Module};
use std::{borrow::Cow, collections::HashMap, marker::Copy}; use std::{borrow::Cow, marker::Copy};
use thiserror::Error; use thiserror::Error;
use wgpu::{ShaderFlags, ShaderModuleDescriptor, ShaderSource}; use wgpu::{ShaderModuleDescriptor, ShaderSource};
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct ShaderId(Uuid); pub struct ShaderId(Uuid);
@ -20,8 +20,8 @@ impl ShaderId {
pub enum ShaderReflectError { pub enum ShaderReflectError {
#[error(transparent)] #[error(transparent)]
WgslParse(#[from] naga::front::wgsl::ParseError), WgslParse(#[from] naga::front::wgsl::ParseError),
#[error(transparent)] #[error("GLSL Parse Error: {0:?}")]
GlslParse(#[from] naga::front::glsl::ParseError), GlslParse(Vec<naga::front::glsl::Error>),
#[error(transparent)] #[error(transparent)]
SpirVParse(#[from] naga::front::spv::Error), SpirVParse(#[from] naga::front::spv::Error),
#[error(transparent)] #[error(transparent)]
@ -33,7 +33,7 @@ pub enum ShaderReflectError {
#[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"] #[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"]
pub enum Shader { pub enum Shader {
Wgsl(Cow<'static, str>), Wgsl(Cow<'static, str>),
Glsl(Cow<'static, str>), Glsl(Cow<'static, str>, naga::ShaderStage),
SpirV(Vec<u8>), SpirV(Vec<u8>),
// TODO: consider the following // TODO: consider the following
// PrecompiledSpirVMacros(HashMap<HashSet<String>, Vec<u32>>) // PrecompiledSpirVMacros(HashMap<HashSet<String>, Vec<u32>>)
@ -54,6 +54,7 @@ impl ShaderReflection {
flags: naga::back::spv::WriterFlags::empty(), flags: naga::back::spv::WriterFlags::empty(),
..naga::back::spv::Options::default() ..naga::back::spv::Options::default()
}, },
None,
) )
} }
@ -67,17 +68,11 @@ impl Shader {
let module = match &self { let module = match &self {
// TODO: process macros here // TODO: process macros here
Shader::Wgsl(source) => naga::front::wgsl::parse_str(source)?, Shader::Wgsl(source) => naga::front::wgsl::parse_str(source)?,
Shader::Glsl(source) => { Shader::Glsl(source, shader_stage) => {
let mut entry_points = HashMap::default(); let mut parser = naga::front::glsl::Parser::default();
entry_points.insert("vertex".to_string(), ShaderStage::Vertex); parser
entry_points.insert("fragment".to_string(), ShaderStage::Fragment); .parse(&naga::front::glsl::Options::from(*shader_stage), source)
naga::front::glsl::parse_str( .map_err(ShaderReflectError::GlslParse)?
source,
&naga::front::glsl::Options {
entry_points,
defines: Default::default(),
},
)?
} }
Shader::SpirV(source) => naga::front::spv::parse_u8_slice( Shader::SpirV(source) => naga::front::spv::parse_u8_slice(
source, source,
@ -103,8 +98,8 @@ impl Shader {
Shader::Wgsl(source.into()) Shader::Wgsl(source.into())
} }
pub fn from_glsl(source: impl Into<Cow<'static, str>>) -> Shader { pub fn from_glsl(source: impl Into<Cow<'static, str>>, stage: naga::ShaderStage) -> Shader {
Shader::Glsl(source.into()) Shader::Glsl(source.into(), stage)
} }
pub fn from_spirv(source: Vec<u8>) -> Shader { pub fn from_spirv(source: Vec<u8>) -> Shader {
@ -143,11 +138,10 @@ impl AssetLoader for ShaderLoader {
impl<'a> From<&'a Shader> for ShaderModuleDescriptor<'a> { impl<'a> From<&'a Shader> for ShaderModuleDescriptor<'a> {
fn from(shader: &'a Shader) -> Self { fn from(shader: &'a Shader) -> Self {
ShaderModuleDescriptor { ShaderModuleDescriptor {
flags: ShaderFlags::default(),
label: None, label: None,
source: match shader { source: match shader {
Shader::Wgsl(source) => ShaderSource::Wgsl(source.clone()), Shader::Wgsl(source) => ShaderSource::Wgsl(source.clone()),
Shader::Glsl(_source) => { Shader::Glsl(_source, _stage) => {
let reflection = shader.reflect().unwrap(); let reflection = shader.reflect().unwrap();
let wgsl = reflection.get_wgsl().unwrap(); let wgsl = reflection.get_wgsl().unwrap();
ShaderSource::Wgsl(wgsl.into()) ShaderSource::Wgsl(wgsl.into())

View file

@ -42,7 +42,7 @@ impl Default for Image {
label: None, label: None,
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
}, },
sampler_descriptor: wgpu::SamplerDescriptor::default(), sampler_descriptor: wgpu::SamplerDescriptor::default(),
} }
@ -369,6 +369,7 @@ impl RenderAsset for Image {
texture: &texture, texture: &texture,
mip_level: 0, mip_level: 0,
origin: Origin3d::ZERO, origin: Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
}, },
&image.data, &image.data,
ImageDataLayout { ImageDataLayout {

View file

@ -6,7 +6,7 @@ use crate::{
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_utils::{tracing::debug, HashMap}; use bevy_utils::{tracing::debug, HashMap, HashSet};
use bevy_window::{RawWindowHandleWrapper, WindowId, Windows}; use bevy_window::{RawWindowHandleWrapper, WindowId, Windows};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use wgpu::TextureFormat; use wgpu::TextureFormat;
@ -34,7 +34,7 @@ pub struct ExtractedWindow {
pub physical_width: u32, pub physical_width: u32,
pub physical_height: u32, pub physical_height: u32,
pub vsync: bool, pub vsync: bool,
pub swap_chain_frame: Option<TextureView>, pub swap_chain_texture: Option<TextureView>,
pub size_changed: bool, pub size_changed: bool,
} }
@ -74,12 +74,12 @@ fn extract_windows(mut render_world: ResMut<RenderWorld>, windows: Res<Windows>)
physical_width: new_width, physical_width: new_width,
physical_height: new_height, physical_height: new_height,
vsync: window.vsync(), vsync: window.vsync(),
swap_chain_frame: None, swap_chain_texture: None,
size_changed: false, size_changed: false,
}); });
// NOTE: Drop the swap chain frame here // NOTE: Drop the swap chain frame here
extracted_window.swap_chain_frame = None; extracted_window.swap_chain_texture = None;
extracted_window.size_changed = new_width != extracted_window.physical_width extracted_window.size_changed = new_width != extracted_window.physical_width
|| new_height != extracted_window.physical_height; || new_height != extracted_window.physical_height;
@ -100,7 +100,8 @@ fn extract_windows(mut render_world: ResMut<RenderWorld>, windows: Res<Windows>)
#[derive(Default)] #[derive(Default)]
pub struct WindowSurfaces { pub struct WindowSurfaces {
surfaces: HashMap<WindowId, wgpu::Surface>, surfaces: HashMap<WindowId, wgpu::Surface>,
swap_chains: HashMap<WindowId, wgpu::SwapChain>, /// List of windows that we have already called the initial `configure_surface` for
configured_windows: HashSet<WindowId>,
} }
pub fn prepare_windows( pub fn prepare_windows(
@ -122,11 +123,11 @@ pub fn prepare_windows(
render_instance.create_surface(&window.handle.get_handle()) render_instance.create_surface(&window.handle.get_handle())
}); });
let swap_chain_descriptor = wgpu::SwapChainDescriptor { let swap_chain_descriptor = wgpu::SurfaceConfiguration {
format: TextureFormat::bevy_default(), format: TextureFormat::bevy_default(),
width: window.physical_width, width: window.physical_width,
height: window.physical_height, height: window.physical_height,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
present_mode: if window.vsync { present_mode: if window.vsync {
wgpu::PresentMode::Fifo wgpu::PresentMode::Fifo
} else { } else {
@ -134,34 +135,22 @@ pub fn prepare_windows(
}, },
}; };
if window.size_changed { // Do the initial surface configuration if it hasn't been configured yet
window_surfaces.swap_chains.insert( if window_surfaces.configured_windows.insert(window.id) {
window.id, render_device.configure_surface(surface, &swap_chain_descriptor);
render_device.create_swap_chain(surface, &swap_chain_descriptor),
);
} }
let swap_chain = window_surfaces let frame = match surface.get_current_texture() {
.swap_chains
.entry(window.id)
.or_insert_with(|| render_device.create_swap_chain(surface, &swap_chain_descriptor));
let frame = match swap_chain.get_current_frame() {
Ok(swap_chain_frame) => swap_chain_frame, Ok(swap_chain_frame) => swap_chain_frame,
Err(wgpu::SwapChainError::Outdated) => { Err(wgpu::SurfaceError::Outdated) => {
let new_swap_chain = render_device.configure_surface(surface, &swap_chain_descriptor);
render_device.create_swap_chain(surface, &swap_chain_descriptor); surface
let frame = new_swap_chain .get_current_texture()
.get_current_frame() .expect("Error reconfiguring surface")
.expect("Error recreating swap chain");
window_surfaces
.swap_chains
.insert(window.id, new_swap_chain);
frame
} }
err => err.expect("Failed to acquire next swap chain texture!"), err => err.expect("Failed to acquire next swap chain texture!"),
}; };
window.swap_chain_frame = Some(TextureView::from(frame)); window.swap_chain_texture = Some(TextureView::from(frame));
} }
} }

View file

@ -39,7 +39,7 @@ impl FromWorld for SpriteShaders {
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
entries: &[BindGroupLayoutEntry { entries: &[BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::VERTEX | ShaderStage::FRAGMENT, visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: true, has_dynamic_offset: true,
@ -56,7 +56,7 @@ impl FromWorld for SpriteShaders {
entries: &[ entries: &[
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture { ty: BindingType::Texture {
multisampled: false, multisampled: false,
sample_type: TextureSampleType::Float { filterable: false }, sample_type: TextureSampleType::Float { filterable: false },
@ -66,7 +66,7 @@ impl FromWorld for SpriteShaders {
}, },
BindGroupLayoutEntry { BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: ShaderStage::FRAGMENT, visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler { ty: BindingType::Sampler {
comparison: false, comparison: false,
filtering: true, filtering: true,
@ -89,7 +89,7 @@ impl FromWorld for SpriteShaders {
vertex: VertexState { vertex: VertexState {
buffers: &[VertexBufferLayout { buffers: &[VertexBufferLayout {
array_stride: 20, array_stride: 20,
step_mode: InputStepMode::Vertex, step_mode: VertexStepMode::Vertex,
attributes: &[ attributes: &[
VertexAttribute { VertexAttribute {
format: VertexFormat::Float32x3, format: VertexFormat::Float32x3,
@ -123,7 +123,7 @@ impl FromWorld for SpriteShaders {
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
}), }),
write_mask: ColorWrite::ALL, write_mask: ColorWrites::ALL,
}], }],
}), }),
layout: Some(&pipeline_layout), layout: Some(&pipeline_layout),
@ -231,8 +231,8 @@ pub struct SpriteMeta {
impl Default for SpriteMeta { impl Default for SpriteMeta {
fn default() -> Self { fn default() -> Self {
Self { Self {
vertices: BufferVec::new(BufferUsage::VERTEX), vertices: BufferVec::new(BufferUsages::VERTEX),
indices: BufferVec::new(BufferUsage::INDEX), indices: BufferVec::new(BufferUsages::INDEX),
view_bind_group: None, view_bind_group: None,
quad: Quad { quad: Quad {
size: Vec2::new(1.0, 1.0), size: Vec2::new(1.0, 1.0),

View file

@ -4,7 +4,7 @@ struct View {
world_position: vec3<f32>; world_position: vec3<f32>;
}; };
[[group(0), binding(0)]] [[group(0), binding(0)]]
var view: View; var<uniform> view: View;
struct VertexOutput { struct VertexOutput {
[[location(0)]] uv: vec2<f32>; [[location(0)]] uv: vec2<f32>;