wgpu: Globals should now belong to the Surface and doesn't need to be mutable anymore

This commit is contained in:
Nathan Adams 2022-09-20 22:36:03 +02:00
parent d2185733b4
commit 915040ba06
3 changed files with 38 additions and 79 deletions

View File

@ -7,8 +7,8 @@ use crate::target::TextureTarget;
use crate::uniform_buffer::BufferStorage; use crate::uniform_buffer::BufferStorage;
use crate::utils::remove_srgb; use crate::utils::remove_srgb;
use crate::{ use crate::{
as_texture, format_list, get_backend_names, BufferDimensions, Descriptors, Error, Globals, as_texture, format_list, get_backend_names, BufferDimensions, Descriptors, Error, RenderTarget,
RenderTarget, SwapChainTarget, Texture, TextureOffscreen, Transforms, SwapChainTarget, Texture, TextureOffscreen, Transforms,
}; };
use gc_arena::MutationContext; use gc_arena::MutationContext;
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
@ -25,11 +25,10 @@ use std::sync::Arc;
use swf::Color; use swf::Color;
use wgpu::Extent3d; use wgpu::Extent3d;
const DEFAULT_SAMPLE_COUNT: u32 = 1; const DEFAULT_SAMPLE_COUNT: u32 = 4;
pub struct WgpuRenderBackend<T: RenderTarget> { pub struct WgpuRenderBackend<T: RenderTarget> {
descriptors: Arc<Descriptors>, descriptors: Arc<Descriptors>,
globals: Globals,
uniform_buffers_storage: BufferStorage<Transforms>, uniform_buffers_storage: BufferStorage<Transforms>,
target: T, target: T,
surface: Surface, surface: Surface,
@ -158,15 +157,11 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
frame_buffer_format, frame_buffer_format,
); );
let mut globals = Globals::new(&descriptors.device, &descriptors.bind_layouts.globals);
globals.set_resolution(target.width(), target.height());
let uniform_buffers_storage = let uniform_buffers_storage =
BufferStorage::from_alignment(descriptors.limits.min_uniform_buffer_offset_alignment); BufferStorage::from_alignment(descriptors.limits.min_uniform_buffer_offset_alignment);
Ok(Self { Ok(Self {
descriptors, descriptors,
globals,
uniform_buffers_storage, uniform_buffers_storage,
target, target,
surface, surface,
@ -282,7 +277,6 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
frame_buffer_format, frame_buffer_format,
); );
self.globals.set_resolution(width, height);
self.viewport_scale_factor = dimensions.scale_factor; self.viewport_scale_factor = dimensions.scale_factor;
} }
@ -404,7 +398,6 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
a: f64::from(clear.a) / 255.0, a: f64::from(clear.a) / 255.0,
}), }),
&self.descriptors, &self.descriptors,
&mut self.globals,
&mut self.uniform_buffers_storage, &mut self.uniform_buffers_storage,
&self.meshes, &self.meshes,
commands, commands,
@ -414,7 +407,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
command_buffers.push(srgb.copy_srgb( command_buffers.push(srgb.copy_srgb(
frame_output.view(), frame_output.view(),
&self.descriptors, &self.descriptors,
&self.globals, &self.surface.globals(),
)); ));
} }
@ -577,9 +570,6 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
buffer_dimensions: texture_offscreen.buffer_dimensions.clone(), buffer_dimensions: texture_offscreen.buffer_dimensions.clone(),
}; };
let (old_width, old_height) = self.globals.resolution();
self.globals.set_resolution(width, height);
let frame_output = target let frame_output = target
.get_next_texture() .get_next_texture()
.expect("TextureTargetFrame.get_next_texture is infallible"); .expect("TextureTargetFrame.get_next_texture is infallible");
@ -588,7 +578,6 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
frame_output.view(), frame_output.view(),
None, None,
&self.descriptors, &self.descriptors,
&mut self.globals,
&mut self.uniform_buffers_storage, &mut self.uniform_buffers_storage,
&self.meshes, &self.meshes,
commands, commands,
@ -612,8 +601,6 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
) )
}); });
self.globals.set_resolution(old_width, old_height);
Ok(image.unwrap()) Ok(image.unwrap())
} }
} }

View File

@ -5,10 +5,7 @@ use wgpu::util::DeviceExt;
#[derive(Debug)] #[derive(Debug)]
pub struct Globals { pub struct Globals {
bind_group: wgpu::BindGroup, bind_group: wgpu::BindGroup,
buffer: wgpu::Buffer, _buffer: wgpu::Buffer,
viewport_width: u32,
viewport_height: u32,
dirty: bool,
} }
#[repr(C)] #[repr(C)]
@ -18,15 +15,24 @@ struct GlobalsUniform {
} }
impl Globals { impl Globals {
pub fn new(device: &wgpu::Device, layout: &wgpu::BindGroupLayout) -> Self { pub fn new(
let buffer_label = create_debug_label!("Globals buffer"); device: &wgpu::Device,
let buffer = device.create_buffer(&wgpu::BufferDescriptor { layout: &wgpu::BindGroupLayout,
label: buffer_label.as_deref(), viewport_width: u32,
size: std::mem::size_of::<GlobalsUniform>() as u64, viewport_height: u32,
usage: wgpu::BufferUsages::UNIFORM ) -> Self {
| wgpu::BufferUsages::COPY_DST let temp_label = create_debug_label!("Globals buffer");
| wgpu::BufferUsages::STORAGE, let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
mapped_at_creation: false, label: temp_label.as_deref(),
contents: bytemuck::cast_slice(&[GlobalsUniform {
view_matrix: [
[1.0 / (viewport_width as f32 / 2.0), 0.0, 0.0, 0.0],
[0.0, -1.0 / (viewport_height as f32 / 2.0), 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[-1.0, 1.0, 0.0, 1.0],
],
}]),
usage: wgpu::BufferUsages::UNIFORM,
}); });
let bind_group_label = create_debug_label!("Globals bind group"); let bind_group_label = create_debug_label!("Globals bind group");
@ -45,53 +51,10 @@ impl Globals {
Self { Self {
bind_group, bind_group,
buffer, _buffer: buffer,
viewport_width: 0,
viewport_height: 0,
dirty: true,
} }
} }
pub fn resolution(&self) -> (u32, u32) {
(self.viewport_width, self.viewport_height)
}
pub fn set_resolution(&mut self, viewport_width: u32, viewport_height: u32) {
if viewport_width != self.viewport_width || viewport_height != self.viewport_height {
self.viewport_width = viewport_width;
self.viewport_height = viewport_height;
self.dirty = true;
}
}
pub fn update_uniform(&mut self, device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder) {
if !self.dirty {
return;
}
self.dirty = false;
let temp_label = create_debug_label!("Temporary globals buffer");
let temp_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: temp_label.as_deref(),
contents: bytemuck::cast_slice(&[GlobalsUniform {
view_matrix: [
[1.0 / (self.viewport_width as f32 / 2.0), 0.0, 0.0, 0.0],
[0.0, -1.0 / (self.viewport_height as f32 / 2.0), 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[-1.0, 1.0, 0.0, 1.0],
],
}]),
usage: wgpu::BufferUsages::COPY_SRC,
});
encoder.copy_buffer_to_buffer(
&temp_buffer,
0,
&self.buffer,
0,
std::mem::size_of::<GlobalsUniform>() as u64,
);
}
pub fn bind_group(&self) -> &wgpu::BindGroup { pub fn bind_group(&self) -> &wgpu::BindGroup {
&self.bind_group &self.bind_group
} }

View File

@ -69,6 +69,7 @@ pub struct Surface {
frame_buffer: Option<FrameBuffer>, frame_buffer: Option<FrameBuffer>,
depth: DepthTexture, depth: DepthTexture,
pipelines: Arc<Pipelines>, pipelines: Arc<Pipelines>,
globals: Globals,
} }
impl Surface { impl Surface {
@ -91,22 +92,28 @@ impl Surface {
None None
}; };
let globals = Globals::new(
&descriptors.device,
&descriptors.bind_layouts.globals,
width,
height,
);
let depth = DepthTexture::new(&descriptors.device, msaa_sample_count, width, height); let depth = DepthTexture::new(&descriptors.device, msaa_sample_count, width, height);
let pipelines = descriptors.pipelines(msaa_sample_count, frame_buffer_format); let pipelines = descriptors.pipelines(msaa_sample_count, frame_buffer_format);
Self { Self {
frame_buffer, frame_buffer,
depth, depth,
pipelines, pipelines,
globals,
} }
} }
#[allow(clippy::too_many_arguments)]
pub fn draw_commands( pub fn draw_commands(
&self, &self,
frame_view: &wgpu::TextureView, frame_view: &wgpu::TextureView,
clear_color: Option<wgpu::Color>, clear_color: Option<wgpu::Color>,
descriptors: &Descriptors, descriptors: &Descriptors,
globals: &mut Globals,
uniform_buffers_storage: &mut BufferStorage<Transforms>, uniform_buffers_storage: &mut BufferStorage<Transforms>,
meshes: &Vec<Mesh>, meshes: &Vec<Mesh>,
commands: CommandList, commands: CommandList,
@ -127,8 +134,6 @@ impl Surface {
label: uniform_encoder_label.as_deref(), label: uniform_encoder_label.as_deref(),
}); });
globals.update_uniform(&descriptors.device, &mut draw_encoder);
let load = match clear_color { let load = match clear_color {
Some(color) => wgpu::LoadOp::Clear(color), Some(color) => wgpu::LoadOp::Clear(color),
None => wgpu::LoadOp::Load, None => wgpu::LoadOp::Load,
@ -157,7 +162,7 @@ impl Surface {
}), }),
label: None, label: None,
}); });
render_pass.set_bind_group(0, globals.bind_group(), &[]); render_pass.set_bind_group(0, self.globals.bind_group(), &[]);
uniform_buffers_storage.recall(); uniform_buffers_storage.recall();
let mut uniform_buffer = UniformBuffer::new(uniform_buffers_storage); let mut uniform_buffer = UniformBuffer::new(uniform_buffers_storage);
@ -177,4 +182,8 @@ impl Surface {
vec![uniform_encoder.finish(), draw_encoder.finish()] vec![uniform_encoder.finish(), draw_encoder.finish()]
} }
pub fn globals(&self) -> &Globals {
&self.globals
}
} }