render: Store view_matrix as a global in wgpu renderer, and only change it when changed

This commit is contained in:
Nathan Adams 2020-10-16 17:46:40 +02:00 committed by Mike Welsh
parent a2d53df49c
commit bbd8fc768c
13 changed files with 172 additions and 48 deletions

View File

@ -1,12 +1,12 @@
#version 450 #version 450
layout(set = 0, binding = 2) uniform Colors { layout(set = 1, binding = 2) uniform Colors {
vec4 mult_color; vec4 mult_color;
vec4 add_color; vec4 add_color;
}; };
layout(set = 0, binding = 3) uniform texture2D t_color; layout(set = 1, binding = 3) uniform texture2D t_color;
layout(set = 1, binding = 0) uniform sampler s_color; layout(set = 2, binding = 0) uniform sampler s_color;
layout(location=0) in vec2 frag_uv; layout(location=0) in vec2 frag_uv;

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,14 @@
#version 450 #version 450
layout(set = 0, binding = 0) uniform Transforms { layout(set = 0, binding = 0) uniform Globals {
mat4 view_matrix; mat4 view_matrix;
};
layout(set = 1, binding = 0) uniform Transforms {
mat4 world_matrix; mat4 world_matrix;
}; };
layout(set = 0, binding = 1) uniform Colors { layout(set = 1, binding = 1) uniform Colors {
vec4 mult_color; vec4 mult_color;
vec4 add_color; vec4 add_color;
}; };

Binary file not shown.

View File

@ -1,11 +1,11 @@
#version 450 #version 450
layout(set = 0, binding = 2) uniform Colors { layout(set = 1, binding = 2) uniform Colors {
vec4 mult_color; vec4 mult_color;
vec4 add_color; vec4 add_color;
}; };
layout(std430, set = 0, binding = 3) buffer Gradient { layout(std430, set = 1, binding = 3) buffer Gradient {
vec4 u_colors[16]; vec4 u_colors[16];
float u_ratios[16]; float u_ratios[16];
int u_gradient_type; int u_gradient_type;

View File

@ -1,11 +1,14 @@
#version 450 #version 450
layout(set = 0, binding = 0) uniform Transforms { layout(set = 0, binding = 0) uniform Globals {
mat4 view_matrix; mat4 view_matrix;
};
layout(set = 1, binding = 0) uniform Transforms {
mat4 world_matrix; mat4 world_matrix;
}; };
layout(set = 0, binding = 1) uniform Texture { layout(set = 1, binding = 1) uniform Texture {
mat4 u_matrix; mat4 u_matrix;
}; };

Binary file not shown.

114
render/wgpu/src/globals.rs Normal file
View File

@ -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::<GlobalsUniform>() 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::<GlobalsUniform>() 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::<GlobalsUniform>() as u64,
);
}
pub fn layout(&self) -> &wgpu::BindGroupLayout {
&self.layout
}
pub fn bind_group(&self) -> &wgpu::BindGroup {
&self.bind_group
}
}

View File

@ -20,9 +20,8 @@ use crate::pipelines::Pipelines;
use crate::shapes::{Draw, DrawType, GradientUniforms, IncompleteDrawType, Mesh}; use crate::shapes::{Draw, DrawType, GradientUniforms, IncompleteDrawType, Mesh};
use crate::target::{RenderTarget, RenderTargetFrame, SwapChainTarget}; use crate::target::{RenderTarget, RenderTargetFrame, SwapChainTarget};
use crate::utils::{ use crate::utils::{
build_view_matrix, create_buffer_with_data, format_list, get_backend_names, create_buffer_with_data, format_list, get_backend_names, gradient_spread_mode_index,
gradient_spread_mode_index, ruffle_path_to_lyon_path, swf_bitmap_to_gl_matrix, ruffle_path_to_lyon_path, swf_bitmap_to_gl_matrix, swf_to_gl_matrix,
swf_to_gl_matrix,
}; };
use enum_map::Enum; use enum_map::Enum;
use ruffle_core::color_transform::ColorTransform; use ruffle_core::color_transform::ColorTransform;
@ -33,6 +32,7 @@ type Error = Box<dyn std::error::Error>;
mod utils; mod utils;
mod bitmaps; mod bitmaps;
mod globals;
mod pipelines; mod pipelines;
mod shapes; mod shapes;
pub mod target; pub mod target;
@ -41,6 +41,7 @@ pub mod target;
pub mod clap; pub mod clap;
use crate::bitmaps::BitmapSamplers; use crate::bitmaps::BitmapSamplers;
use crate::globals::Globals;
use ruffle_core::swf::{Matrix, Twips}; use ruffle_core::swf::{Matrix, Twips};
use std::path::Path; use std::path::Path;
pub use wgpu; pub use wgpu;
@ -48,6 +49,7 @@ pub use wgpu;
pub struct Descriptors { pub struct Descriptors {
pub device: wgpu::Device, pub device: wgpu::Device,
queue: wgpu::Queue, queue: wgpu::Queue,
globals: Globals,
pipelines: Pipelines, pipelines: Pipelines,
bitmap_samplers: BitmapSamplers, bitmap_samplers: BitmapSamplers,
msaa_sample_count: u32, msaa_sample_count: u32,
@ -59,11 +61,18 @@ impl Descriptors {
let msaa_sample_count = 4; let msaa_sample_count = 4;
let bitmap_samplers = BitmapSamplers::new(&device); 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 { Ok(Self {
device, device,
queue, queue,
globals,
pipelines, pipelines,
bitmap_samplers, bitmap_samplers,
msaa_sample_count, msaa_sample_count,
@ -80,7 +89,6 @@ pub struct WgpuRenderBackend<T: RenderTarget> {
meshes: Vec<Mesh>, meshes: Vec<Mesh>,
viewport_width: f32, viewport_width: f32,
viewport_height: f32, viewport_height: f32,
view_matrix: [[f32; 4]; 4],
textures: Vec<(swf::CharacterId, Texture)>, textures: Vec<(swf::CharacterId, Texture)>,
mask_state: MaskState, mask_state: MaskState,
num_masks: u32, num_masks: u32,
@ -100,7 +108,6 @@ pub enum MaskState {
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct Transforms { struct Transforms {
view_matrix: [[f32; 4]; 4],
world_matrix: [[f32; 4]; 4], world_matrix: [[f32; 4]; 4],
} }
@ -203,7 +210,7 @@ impl WgpuRenderBackend<SwapChainTarget> {
} }
impl<T: RenderTarget> WgpuRenderBackend<T> { impl<T: RenderTarget> WgpuRenderBackend<T> {
pub fn new(descriptors: Descriptors, target: T) -> Result<Self, Error> { pub fn new(mut descriptors: Descriptors, target: T) -> Result<Self, Error> {
let extent = wgpu::Extent3d { let extent = wgpu::Extent3d {
width: target.width(), width: target.width(),
height: target.height(), height: target.height(),
@ -239,7 +246,10 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
let viewport_width = target.width() as f32; let viewport_width = target.width() as f32;
let viewport_height = target.height() 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 { Ok(Self {
descriptors, descriptors,
@ -250,7 +260,6 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
meshes: Vec::new(), meshes: Vec::new(),
viewport_width, viewport_width,
viewport_height, viewport_height,
view_matrix,
textures: Vec::new(), textures: Vec::new(),
num_masks: 0, num_masks: 0,
@ -785,7 +794,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
self.viewport_width = width as f32; self.viewport_width = width as f32;
self.viewport_height = height 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 { fn register_shape(&mut self, shape: DistilledShape) -> ShapeHandle {
@ -894,6 +903,9 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
}), }),
}), }),
}); });
self.descriptors
.globals
.update_uniform(&self.descriptors.device, encoder);
} }
} }
@ -930,10 +942,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
let transforms_ubo = create_buffer_with_data( let transforms_ubo = create_buffer_with_data(
&self.descriptors.device, &self.descriptors.device,
bytemuck::cast_slice(&[Transforms { bytemuck::cast_slice(&[Transforms { world_matrix }]),
view_matrix: self.view_matrix,
world_matrix,
}]),
wgpu::BufferUsage::UNIFORM, wgpu::BufferUsage::UNIFORM,
create_debug_label!("Bitmap {} transforms transfer buffer", bitmap.0), create_debug_label!("Bitmap {} transforms transfer buffer", bitmap.0),
); );
@ -1026,9 +1035,10 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
.bitmap .bitmap
.pipeline_for(self.mask_state), .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( render_pass.set_bind_group(
1, 2,
self.descriptors.bitmap_samplers.get_bind_group(false, true), self.descriptors.bitmap_samplers.get_bind_group(false, true),
&[], &[],
); );
@ -1094,10 +1104,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
let transforms_temp = create_buffer_with_data( let transforms_temp = create_buffer_with_data(
&self.descriptors.device, &self.descriptors.device,
bytemuck::cast_slice(&[Transforms { bytemuck::cast_slice(&[Transforms { world_matrix }]),
view_matrix: self.view_matrix,
world_matrix,
}]),
wgpu::BufferUsage::COPY_SRC, wgpu::BufferUsage::COPY_SRC,
create_debug_label!("Shape {} transforms transfer buffer", mesh.shape_id), create_debug_label!("Shape {} transforms transfer buffer", mesh.shape_id),
); );
@ -1170,7 +1177,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
.pipeline_for(self.mask_state), .pipeline_for(self.mask_state),
); );
render_pass.set_bind_group( render_pass.set_bind_group(
1, 2,
self.descriptors self.descriptors
.bitmap_samplers .bitmap_samplers
.get_bind_group(*is_repeating, *is_smoothed), .get_bind_group(*is_repeating, *is_smoothed),
@ -1179,7 +1186,8 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
} }
} }
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_vertex_buffer(0, draw.vertex_buffer.slice(..));
render_pass.set_index_buffer(draw.index_buffer.slice(..)); render_pass.set_index_buffer(draw.index_buffer.slice(..));
@ -1230,10 +1238,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
let transforms_ubo = create_buffer_with_data( let transforms_ubo = create_buffer_with_data(
&self.descriptors.device, &self.descriptors.device,
bytemuck::cast_slice(&[Transforms { bytemuck::cast_slice(&[Transforms { world_matrix }]),
view_matrix: self.view_matrix,
world_matrix,
}]),
wgpu::BufferUsage::UNIFORM, wgpu::BufferUsage::UNIFORM,
create_debug_label!("Rectangle transfer buffer"), create_debug_label!("Rectangle transfer buffer"),
); );
@ -1311,7 +1316,8 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
.color .color
.pipeline_for(self.mask_state), .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_vertex_buffer(0, self.quad_vbo.slice(..));
render_pass.set_index_buffer(self.quad_ibo.slice(..)); render_pass.set_index_buffer(self.quad_ibo.slice(..));

View File

@ -26,6 +26,7 @@ impl Pipelines {
device: &wgpu::Device, device: &wgpu::Device,
msaa_sample_count: u32, msaa_sample_count: u32,
sampler_layout: &wgpu::BindGroupLayout, sampler_layout: &wgpu::BindGroupLayout,
globals_layout: &wgpu::BindGroupLayout,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let color_vs = let color_vs =
device.create_shader_module(wgpu::include_spirv!("../shaders/color.vert.spv")); device.create_shader_module(wgpu::include_spirv!("../shaders/color.vert.spv"));
@ -54,6 +55,7 @@ impl Pipelines {
&color_fs, &color_fs,
msaa_sample_count, msaa_sample_count,
&vertex_buffers_description, &vertex_buffers_description,
globals_layout,
), ),
bitmap: create_bitmap_pipeline( bitmap: create_bitmap_pipeline(
&device, &device,
@ -62,6 +64,7 @@ impl Pipelines {
msaa_sample_count, msaa_sample_count,
&vertex_buffers_description, &vertex_buffers_description,
sampler_layout, sampler_layout,
globals_layout,
), ),
gradient: create_gradient_pipeline( gradient: create_gradient_pipeline(
&device, &device,
@ -69,6 +72,7 @@ impl Pipelines {
&gradient_fs, &gradient_fs,
msaa_sample_count, msaa_sample_count,
&vertex_buffers_description, &vertex_buffers_description,
globals_layout,
), ),
}) })
} }
@ -124,6 +128,7 @@ fn create_color_pipelines(
fragment_shader: &wgpu::ShaderModule, fragment_shader: &wgpu::ShaderModule,
msaa_sample_count: u32, msaa_sample_count: u32,
vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>], vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>],
globals_layout: &wgpu::BindGroupLayout,
) -> ShapePipeline { ) -> ShapePipeline {
let bind_layout_label = create_debug_label!("Color shape bind group"); let bind_layout_label = create_debug_label!("Color shape bind group");
let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 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_label = create_debug_label!("Color shape pipeline layout");
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: pipeline_layout_label.as_deref(), label: pipeline_layout_label.as_deref(),
bind_group_layouts: &[&bind_layout], bind_group_layouts: &[globals_layout, &bind_layout],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -300,6 +305,7 @@ fn create_bitmap_pipeline(
msaa_sample_count: u32, msaa_sample_count: u32,
vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>], vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>],
sampler_layout: &wgpu::BindGroupLayout, sampler_layout: &wgpu::BindGroupLayout,
globals_layout: &wgpu::BindGroupLayout,
) -> ShapePipeline { ) -> ShapePipeline {
let bind_layout_label = create_debug_label!("Bitmap shape bind group"); let bind_layout_label = create_debug_label!("Bitmap shape bind group");
let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 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_label = create_debug_label!("Bitmap shape pipeline layout");
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: pipeline_layout_label.as_deref(), 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: &[], push_constant_ranges: &[],
}); });
@ -494,6 +500,7 @@ fn create_gradient_pipeline(
fragment_shader: &wgpu::ShaderModule, fragment_shader: &wgpu::ShaderModule,
msaa_sample_count: u32, msaa_sample_count: u32,
vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>], vertex_buffers_description: &[wgpu::VertexBufferDescriptor<'_>],
globals_layout: &wgpu::BindGroupLayout,
) -> ShapePipeline { ) -> ShapePipeline {
let bind_layout_label = create_debug_label!("Gradient shape bind group"); let bind_layout_label = create_debug_label!("Gradient shape bind group");
let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 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_label = create_debug_label!("Gradient shape pipeline layout");
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: pipeline_layout_label.as_deref(), label: pipeline_layout_label.as_deref(),
bind_group_layouts: &[&bind_layout], bind_group_layouts: &[globals_layout, &bind_layout],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });

View File

@ -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. /// Map for SWF gradient spread mode to the uniform value used by the gradient shader.
pub fn gradient_spread_mode_index(spread: GradientSpread) -> i32 { pub fn gradient_spread_mode_index(spread: GradientSpread) -> i32 {
match spread { match spread {