diff --git a/render/wgpu/shaders/bitmap.frag b/render/wgpu/shaders/bitmap.frag index 4cdb82436..ee84c8016 100644 --- a/render/wgpu/shaders/bitmap.frag +++ b/render/wgpu/shaders/bitmap.frag @@ -1,12 +1,12 @@ #version 450 -layout(set = 0, binding = 2) uniform Colors { +layout(set = 1, binding = 2) uniform Colors { vec4 mult_color; vec4 add_color; }; -layout(set = 0, binding = 3) uniform texture2D t_color; -layout(set = 1, binding = 0) uniform sampler s_color; +layout(set = 1, binding = 3) uniform texture2D t_color; +layout(set = 2, binding = 0) uniform sampler s_color; layout(location=0) in vec2 frag_uv; diff --git a/render/wgpu/shaders/bitmap.frag.spv b/render/wgpu/shaders/bitmap.frag.spv index 25fba1cc5..713fbc323 100644 Binary files a/render/wgpu/shaders/bitmap.frag.spv and b/render/wgpu/shaders/bitmap.frag.spv differ diff --git a/render/wgpu/shaders/color.frag.spv b/render/wgpu/shaders/color.frag.spv index 545b1ce80..900ccfa4f 100644 Binary files a/render/wgpu/shaders/color.frag.spv and b/render/wgpu/shaders/color.frag.spv differ diff --git a/render/wgpu/shaders/color.vert b/render/wgpu/shaders/color.vert index 0b0f1c06c..441366c7f 100644 --- a/render/wgpu/shaders/color.vert +++ b/render/wgpu/shaders/color.vert @@ -1,11 +1,14 @@ #version 450 -layout(set = 0, binding = 0) uniform Transforms { +layout(set = 0, binding = 0) uniform Globals { mat4 view_matrix; +}; + +layout(set = 1, binding = 0) uniform Transforms { mat4 world_matrix; }; -layout(set = 0, binding = 1) uniform Colors { +layout(set = 1, binding = 1) uniform Colors { vec4 mult_color; vec4 add_color; }; diff --git a/render/wgpu/shaders/color.vert.spv b/render/wgpu/shaders/color.vert.spv index 5b766213c..50184cf38 100644 Binary files a/render/wgpu/shaders/color.vert.spv and b/render/wgpu/shaders/color.vert.spv differ diff --git a/render/wgpu/shaders/gradient.frag b/render/wgpu/shaders/gradient.frag index 56342c2c1..187fd9fc5 100644 --- a/render/wgpu/shaders/gradient.frag +++ b/render/wgpu/shaders/gradient.frag @@ -1,11 +1,11 @@ #version 450 -layout(set = 0, binding = 2) uniform Colors { +layout(set = 1, binding = 2) uniform Colors { vec4 mult_color; vec4 add_color; }; -layout(std430, set = 0, binding = 3) buffer Gradient { +layout(std430, set = 1, binding = 3) buffer Gradient { vec4 u_colors[16]; float u_ratios[16]; int u_gradient_type; diff --git a/render/wgpu/shaders/gradient.frag.spv b/render/wgpu/shaders/gradient.frag.spv index d1f53109e..7df5dc288 100644 Binary files a/render/wgpu/shaders/gradient.frag.spv and b/render/wgpu/shaders/gradient.frag.spv differ diff --git a/render/wgpu/shaders/texture.vert b/render/wgpu/shaders/texture.vert index 00fec4220..7ed878b35 100644 --- a/render/wgpu/shaders/texture.vert +++ b/render/wgpu/shaders/texture.vert @@ -1,11 +1,14 @@ #version 450 -layout(set = 0, binding = 0) uniform Transforms { +layout(set = 0, binding = 0) uniform Globals { mat4 view_matrix; +}; + +layout(set = 1, binding = 0) uniform Transforms { mat4 world_matrix; }; -layout(set = 0, binding = 1) uniform Texture { +layout(set = 1, binding = 1) uniform Texture { mat4 u_matrix; }; diff --git a/render/wgpu/shaders/texture.vert.spv b/render/wgpu/shaders/texture.vert.spv index 410e6f90e..8c3de0487 100644 Binary files a/render/wgpu/shaders/texture.vert.spv and b/render/wgpu/shaders/texture.vert.spv differ diff --git a/render/wgpu/src/globals.rs b/render/wgpu/src/globals.rs new file mode 100644 index 000000000..51a69fb63 --- /dev/null +++ b/render/wgpu/src/globals.rs @@ -0,0 +1,114 @@ +use bytemuck::{Pod, Zeroable}; +use wgpu::util::DeviceExt; + +#[derive(Debug)] +pub struct Globals { + layout: wgpu::BindGroupLayout, + bind_group: wgpu::BindGroup, + buffer: wgpu::Buffer, + viewport_width: u32, + viewport_height: u32, + dirty: bool, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +struct GlobalsUniform { + view_matrix: [[f32; 4]; 4], +} + +unsafe impl Pod for GlobalsUniform {} +unsafe impl Zeroable for GlobalsUniform {} + +impl Globals { + pub fn new(device: &wgpu::Device) -> Self { + let layout_label = create_debug_label!("Globals bind group layout"); + let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: layout_label.as_deref(), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }); + + let buffer_label = create_debug_label!("Globals buffer"); + let buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: buffer_label.as_deref(), + size: std::mem::size_of::() as u64, + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + mapped_at_creation: false, + }); + + let bind_group_label = create_debug_label!("Globals bind group"); + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: bind_group_label.as_deref(), + layout: &layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer { + buffer: &buffer, + offset: 0, + size: wgpu::BufferSize::new(std::mem::size_of::() as u64), + }, + }], + }); + + Self { + layout, + bind_group, + buffer, + viewport_width: 0, + viewport_height: 0, + dirty: true, + } + } + + 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::BufferUsage::COPY_SRC, + }); + + encoder.copy_buffer_to_buffer( + &temp_buffer, + 0, + &self.buffer, + 0, + std::mem::size_of::() as u64, + ); + } + + pub fn layout(&self) -> &wgpu::BindGroupLayout { + &self.layout + } + + pub fn bind_group(&self) -> &wgpu::BindGroup { + &self.bind_group + } +} diff --git a/render/wgpu/src/lib.rs b/render/wgpu/src/lib.rs index da2018438..e840177d6 100644 --- a/render/wgpu/src/lib.rs +++ b/render/wgpu/src/lib.rs @@ -20,9 +20,8 @@ use crate::pipelines::Pipelines; use crate::shapes::{Draw, DrawType, GradientUniforms, IncompleteDrawType, Mesh}; use crate::target::{RenderTarget, RenderTargetFrame, SwapChainTarget}; use crate::utils::{ - build_view_matrix, create_buffer_with_data, format_list, get_backend_names, - gradient_spread_mode_index, ruffle_path_to_lyon_path, swf_bitmap_to_gl_matrix, - swf_to_gl_matrix, + create_buffer_with_data, format_list, get_backend_names, gradient_spread_mode_index, + ruffle_path_to_lyon_path, swf_bitmap_to_gl_matrix, swf_to_gl_matrix, }; use enum_map::Enum; use ruffle_core::color_transform::ColorTransform; @@ -33,6 +32,7 @@ type Error = Box; mod utils; mod bitmaps; +mod globals; mod pipelines; mod shapes; pub mod target; @@ -41,6 +41,7 @@ pub mod target; pub mod clap; use crate::bitmaps::BitmapSamplers; +use crate::globals::Globals; use ruffle_core::swf::{Matrix, Twips}; use std::path::Path; pub use wgpu; @@ -48,6 +49,7 @@ pub use wgpu; pub struct Descriptors { pub device: wgpu::Device, queue: wgpu::Queue, + globals: Globals, pipelines: Pipelines, bitmap_samplers: BitmapSamplers, msaa_sample_count: u32, @@ -59,11 +61,18 @@ impl Descriptors { let msaa_sample_count = 4; let bitmap_samplers = BitmapSamplers::new(&device); - let pipelines = Pipelines::new(&device, msaa_sample_count, bitmap_samplers.layout())?; + let globals = Globals::new(&device); + let pipelines = Pipelines::new( + &device, + msaa_sample_count, + bitmap_samplers.layout(), + globals.layout(), + )?; Ok(Self { device, queue, + globals, pipelines, bitmap_samplers, msaa_sample_count, @@ -80,7 +89,6 @@ pub struct WgpuRenderBackend { meshes: Vec, viewport_width: f32, viewport_height: f32, - view_matrix: [[f32; 4]; 4], textures: Vec<(swf::CharacterId, Texture)>, mask_state: MaskState, num_masks: u32, @@ -100,7 +108,6 @@ pub enum MaskState { #[repr(C)] #[derive(Copy, Clone, Debug)] struct Transforms { - view_matrix: [[f32; 4]; 4], world_matrix: [[f32; 4]; 4], } @@ -203,7 +210,7 @@ impl WgpuRenderBackend { } impl WgpuRenderBackend { - pub fn new(descriptors: Descriptors, target: T) -> Result { + pub fn new(mut descriptors: Descriptors, target: T) -> Result { let extent = wgpu::Extent3d { width: target.width(), height: target.height(), @@ -239,7 +246,10 @@ impl WgpuRenderBackend { let viewport_width = target.width() as f32; let viewport_height = target.height() as f32; - let view_matrix = build_view_matrix(target.width(), target.height()); + + descriptors + .globals + .set_resolution(target.width(), target.height()); Ok(Self { descriptors, @@ -250,7 +260,6 @@ impl WgpuRenderBackend { meshes: Vec::new(), viewport_width, viewport_height, - view_matrix, textures: Vec::new(), num_masks: 0, @@ -785,7 +794,7 @@ impl RenderBackend for WgpuRenderBackend { self.viewport_width = width as f32; self.viewport_height = height as f32; - self.view_matrix = build_view_matrix(width, height); + self.descriptors.globals.set_resolution(width, height); } fn register_shape(&mut self, shape: DistilledShape) -> ShapeHandle { @@ -894,6 +903,9 @@ impl RenderBackend for WgpuRenderBackend { }), }), }); + self.descriptors + .globals + .update_uniform(&self.descriptors.device, encoder); } } @@ -930,10 +942,7 @@ impl RenderBackend for WgpuRenderBackend { let transforms_ubo = create_buffer_with_data( &self.descriptors.device, - bytemuck::cast_slice(&[Transforms { - view_matrix: self.view_matrix, - world_matrix, - }]), + bytemuck::cast_slice(&[Transforms { world_matrix }]), wgpu::BufferUsage::UNIFORM, create_debug_label!("Bitmap {} transforms transfer buffer", bitmap.0), ); @@ -1026,9 +1035,10 @@ impl RenderBackend for WgpuRenderBackend { .bitmap .pipeline_for(self.mask_state), ); - render_pass.set_bind_group(0, &bind_group, &[]); + render_pass.set_bind_group(0, self.descriptors.globals.bind_group(), &[]); + render_pass.set_bind_group(1, &bind_group, &[]); render_pass.set_bind_group( - 1, + 2, self.descriptors.bitmap_samplers.get_bind_group(false, true), &[], ); @@ -1094,10 +1104,7 @@ impl RenderBackend for WgpuRenderBackend { let transforms_temp = create_buffer_with_data( &self.descriptors.device, - bytemuck::cast_slice(&[Transforms { - view_matrix: self.view_matrix, - world_matrix, - }]), + bytemuck::cast_slice(&[Transforms { world_matrix }]), wgpu::BufferUsage::COPY_SRC, create_debug_label!("Shape {} transforms transfer buffer", mesh.shape_id), ); @@ -1170,7 +1177,7 @@ impl RenderBackend for WgpuRenderBackend { .pipeline_for(self.mask_state), ); render_pass.set_bind_group( - 1, + 2, self.descriptors .bitmap_samplers .get_bind_group(*is_repeating, *is_smoothed), @@ -1179,7 +1186,8 @@ impl RenderBackend for WgpuRenderBackend { } } - render_pass.set_bind_group(0, &draw.bind_group, &[]); + render_pass.set_bind_group(0, self.descriptors.globals.bind_group(), &[]); + render_pass.set_bind_group(1, &draw.bind_group, &[]); render_pass.set_vertex_buffer(0, draw.vertex_buffer.slice(..)); render_pass.set_index_buffer(draw.index_buffer.slice(..)); @@ -1230,10 +1238,7 @@ impl RenderBackend for WgpuRenderBackend { let transforms_ubo = create_buffer_with_data( &self.descriptors.device, - bytemuck::cast_slice(&[Transforms { - view_matrix: self.view_matrix, - world_matrix, - }]), + bytemuck::cast_slice(&[Transforms { world_matrix }]), wgpu::BufferUsage::UNIFORM, create_debug_label!("Rectangle transfer buffer"), ); @@ -1311,7 +1316,8 @@ impl RenderBackend for WgpuRenderBackend { .color .pipeline_for(self.mask_state), ); - render_pass.set_bind_group(0, &bind_group, &[]); + render_pass.set_bind_group(0, self.descriptors.globals.bind_group(), &[]); + render_pass.set_bind_group(1, &bind_group, &[]); render_pass.set_vertex_buffer(0, self.quad_vbo.slice(..)); render_pass.set_index_buffer(self.quad_ibo.slice(..)); diff --git a/render/wgpu/src/pipelines.rs b/render/wgpu/src/pipelines.rs index bfd3f87ae..2a35a05bc 100644 --- a/render/wgpu/src/pipelines.rs +++ b/render/wgpu/src/pipelines.rs @@ -26,6 +26,7 @@ impl Pipelines { device: &wgpu::Device, msaa_sample_count: u32, sampler_layout: &wgpu::BindGroupLayout, + globals_layout: &wgpu::BindGroupLayout, ) -> Result { let color_vs = device.create_shader_module(wgpu::include_spirv!("../shaders/color.vert.spv")); @@ -54,6 +55,7 @@ impl Pipelines { &color_fs, msaa_sample_count, &vertex_buffers_description, + globals_layout, ), bitmap: create_bitmap_pipeline( &device, @@ -62,6 +64,7 @@ impl Pipelines { msaa_sample_count, &vertex_buffers_description, sampler_layout, + globals_layout, ), gradient: create_gradient_pipeline( &device, @@ -69,6 +72,7 @@ impl Pipelines { &gradient_fs, msaa_sample_count, &vertex_buffers_description, + globals_layout, ), }) } @@ -124,6 +128,7 @@ fn create_color_pipelines( fragment_shader: &wgpu::ShaderModule, msaa_sample_count: u32, vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>], + globals_layout: &wgpu::BindGroupLayout, ) -> ShapePipeline { let bind_layout_label = create_debug_label!("Color shape bind group"); let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -153,7 +158,7 @@ fn create_color_pipelines( let pipeline_layout_label = create_debug_label!("Color shape pipeline layout"); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: pipeline_layout_label.as_deref(), - bind_group_layouts: &[&bind_layout], + bind_group_layouts: &[globals_layout, &bind_layout], push_constant_ranges: &[], }); @@ -300,6 +305,7 @@ fn create_bitmap_pipeline( msaa_sample_count: u32, vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>], sampler_layout: &wgpu::BindGroupLayout, + globals_layout: &wgpu::BindGroupLayout, ) -> ShapePipeline { let bind_layout_label = create_debug_label!("Bitmap shape bind group"); let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -348,7 +354,7 @@ fn create_bitmap_pipeline( let pipeline_layout_label = create_debug_label!("Bitmap shape pipeline layout"); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: pipeline_layout_label.as_deref(), - bind_group_layouts: &[&bind_layout, sampler_layout], + bind_group_layouts: &[globals_layout, &bind_layout, sampler_layout], push_constant_ranges: &[], }); @@ -494,6 +500,7 @@ fn create_gradient_pipeline( fragment_shader: &wgpu::ShaderModule, msaa_sample_count: u32, vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>], + globals_layout: &wgpu::BindGroupLayout, ) -> ShapePipeline { let bind_layout_label = create_debug_label!("Gradient shape bind group"); let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -542,7 +549,7 @@ fn create_gradient_pipeline( let pipeline_layout_label = create_debug_label!("Gradient shape pipeline layout"); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: pipeline_layout_label.as_deref(), - bind_group_layouts: &[&bind_layout], + bind_group_layouts: &[globals_layout, &bind_layout], push_constant_ranges: &[], }); diff --git a/render/wgpu/src/utils.rs b/render/wgpu/src/utils.rs index 52d0d28ea..48b2dcbbb 100644 --- a/render/wgpu/src/utils.rs +++ b/render/wgpu/src/utils.rs @@ -169,15 +169,6 @@ pub fn swf_bitmap_to_gl_matrix( ] } -pub fn build_view_matrix(viewport_width: u32, viewport_height: u32) -> [[f32; 4]; 4] { - [ - [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], - ] -} - /// Map for SWF gradient spread mode to the uniform value used by the gradient shader. pub fn gradient_spread_mode_index(spread: GradientSpread) -> i32 { match spread {