wgpu: Split off Frame into CommandRenderer and Frame - command renderer translates commands into draw calls on frame
This commit is contained in:
parent
22ba32b785
commit
91f3230a45
|
@ -1,3 +1,4 @@
|
|||
use crate::commands::CommandRenderer;
|
||||
use crate::descriptors::DescriptorsTargetData;
|
||||
use crate::frame::Frame;
|
||||
use crate::target::RenderTargetFrame;
|
||||
|
@ -756,14 +757,16 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
&self.descriptors.onscreen.pipelines,
|
||||
&self.descriptors,
|
||||
UniformBuffer::new(&mut self.uniform_buffers_storage),
|
||||
self.quad_vbo.slice(..),
|
||||
self.quad_ibo.slice(..),
|
||||
&self.meshes,
|
||||
render_pass,
|
||||
&mut uniform_encoder,
|
||||
&self.bitmap_registry,
|
||||
);
|
||||
commands.execute(&mut frame);
|
||||
commands.execute(&mut CommandRenderer::new(
|
||||
&mut frame,
|
||||
&self.meshes,
|
||||
&self.bitmap_registry,
|
||||
self.quad_vbo.slice(..),
|
||||
self.quad_ibo.slice(..),
|
||||
));
|
||||
|
||||
// If we have an sRGB surface, copy from our linear intermediate buffer to the sRGB surface.
|
||||
let copy_encoder = if let Some(copy_srgb_bind_group) = &self.copy_srgb_bind_group {
|
||||
|
@ -774,6 +777,8 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
copy_srgb_bind_group,
|
||||
self.target.width() as f32,
|
||||
self.target.height() as f32,
|
||||
self.quad_vbo.slice(..),
|
||||
self.quad_ibo.slice(..),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
@ -1072,14 +1077,16 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
&self.descriptors.offscreen.pipelines,
|
||||
&self.descriptors,
|
||||
UniformBuffer::new(&mut self.uniform_buffers_storage),
|
||||
self.quad_vbo.slice(..),
|
||||
self.quad_ibo.slice(..),
|
||||
&self.meshes,
|
||||
render_pass,
|
||||
&mut uniform_encoder,
|
||||
&self.bitmap_registry,
|
||||
);
|
||||
commands.execute(&mut frame);
|
||||
commands.execute(&mut CommandRenderer::new(
|
||||
&mut frame,
|
||||
&self.meshes,
|
||||
&self.bitmap_registry,
|
||||
self.quad_vbo.slice(..),
|
||||
self.quad_ibo.slice(..),
|
||||
));
|
||||
frame.finish();
|
||||
|
||||
target.submit(
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
use crate::frame::Frame;
|
||||
use crate::pipelines::BlendMode as ActualBlendMode;
|
||||
use crate::{ColorAdjustments, DrawType, MaskState, Mesh, RegistryData};
|
||||
use fnv::FnvHashMap;
|
||||
use ruffle_render::backend::ShapeHandle;
|
||||
use ruffle_render::bitmap::BitmapHandle;
|
||||
use ruffle_render::commands::CommandHandler;
|
||||
use ruffle_render::transform::Transform;
|
||||
use swf::{BlendMode, Color};
|
||||
|
||||
pub struct CommandRenderer<'a, 'b> {
|
||||
frame: &'b mut Frame<'a>,
|
||||
bitmap_registry: &'a FnvHashMap<BitmapHandle, RegistryData>,
|
||||
meshes: &'a Vec<Mesh>,
|
||||
quad_vertices: wgpu::BufferSlice<'a>,
|
||||
quad_indices: wgpu::BufferSlice<'a>,
|
||||
blend_modes: Vec<BlendMode>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> CommandRenderer<'a, 'b> {
|
||||
pub fn new(
|
||||
frame: &'b mut Frame<'a>,
|
||||
meshes: &'a Vec<Mesh>,
|
||||
bitmap_registry: &'a FnvHashMap<BitmapHandle, RegistryData>,
|
||||
quad_vertices: wgpu::BufferSlice<'a>,
|
||||
quad_indices: wgpu::BufferSlice<'a>,
|
||||
) -> Self {
|
||||
Self {
|
||||
frame,
|
||||
bitmap_registry,
|
||||
meshes,
|
||||
quad_vertices,
|
||||
quad_indices,
|
||||
blend_modes: vec![BlendMode::Normal],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> CommandHandler for CommandRenderer<'a, 'b> {
|
||||
fn render_bitmap(&mut self, bitmap: BitmapHandle, transform: &Transform, smoothing: bool) {
|
||||
if let Some(entry) = self.bitmap_registry.get(&bitmap) {
|
||||
let texture = &entry.texture_wrapper;
|
||||
|
||||
self.frame.apply_transform(
|
||||
&(transform.matrix
|
||||
* ruffle_render::matrix::Matrix {
|
||||
a: texture.width as f32,
|
||||
d: texture.height as f32,
|
||||
..Default::default()
|
||||
}),
|
||||
ColorAdjustments::from(transform.color_transform),
|
||||
);
|
||||
|
||||
self.frame.draw_bitmap(
|
||||
self.quad_vertices,
|
||||
self.quad_indices,
|
||||
6,
|
||||
&texture.bind_group,
|
||||
false,
|
||||
smoothing,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_shape(&mut self, shape: ShapeHandle, transform: &Transform) {
|
||||
self.frame.apply_transform(
|
||||
&transform.matrix,
|
||||
ColorAdjustments::from(transform.color_transform),
|
||||
);
|
||||
|
||||
let mesh = &self.meshes[shape.0];
|
||||
let mask_state = self.frame.mask_state();
|
||||
for draw in &mesh.draws {
|
||||
let num_indices = if mask_state != MaskState::DrawMaskStencil
|
||||
&& mask_state != MaskState::ClearMaskStencil
|
||||
{
|
||||
draw.num_indices
|
||||
} else {
|
||||
// Omit strokes when drawing a mask stencil.
|
||||
draw.num_mask_indices
|
||||
};
|
||||
if num_indices == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
match &draw.draw_type {
|
||||
DrawType::Color => {
|
||||
self.frame.draw_color(
|
||||
draw.vertex_buffer.slice(..),
|
||||
draw.index_buffer.slice(..),
|
||||
num_indices,
|
||||
);
|
||||
}
|
||||
DrawType::Gradient { bind_group, .. } => {
|
||||
self.frame.draw_gradient(
|
||||
draw.vertex_buffer.slice(..),
|
||||
draw.index_buffer.slice(..),
|
||||
num_indices,
|
||||
bind_group,
|
||||
);
|
||||
}
|
||||
DrawType::Bitmap {
|
||||
is_repeating,
|
||||
is_smoothed,
|
||||
bind_group,
|
||||
..
|
||||
} => {
|
||||
self.frame.draw_bitmap(
|
||||
draw.vertex_buffer.slice(..),
|
||||
draw.index_buffer.slice(..),
|
||||
num_indices,
|
||||
bind_group,
|
||||
*is_repeating,
|
||||
*is_smoothed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_rect(&mut self, color: Color, matrix: &ruffle_render::matrix::Matrix) {
|
||||
self.frame.apply_transform(
|
||||
&matrix,
|
||||
ColorAdjustments {
|
||||
mult_color: [
|
||||
f32::from(color.r) / 255.0,
|
||||
f32::from(color.g) / 255.0,
|
||||
f32::from(color.b) / 255.0,
|
||||
f32::from(color.a) / 255.0,
|
||||
],
|
||||
add_color: [0.0, 0.0, 0.0, 0.0],
|
||||
},
|
||||
);
|
||||
|
||||
self.frame
|
||||
.draw_color(self.quad_vertices, self.quad_indices, 6);
|
||||
}
|
||||
|
||||
fn push_mask(&mut self) {
|
||||
debug_assert!(
|
||||
self.frame.mask_state() == MaskState::NoMask
|
||||
|| self.frame.mask_state() == MaskState::DrawMaskedContent
|
||||
);
|
||||
self.frame.set_mask_state(MaskState::DrawMaskStencil);
|
||||
self.frame.set_mask_count(self.frame.num_masks() + 1);
|
||||
}
|
||||
|
||||
fn activate_mask(&mut self) {
|
||||
debug_assert!(
|
||||
self.frame.num_masks() > 0 && self.frame.mask_state() == MaskState::DrawMaskStencil
|
||||
);
|
||||
self.frame.set_mask_state(MaskState::DrawMaskedContent);
|
||||
}
|
||||
|
||||
fn deactivate_mask(&mut self) {
|
||||
debug_assert!(
|
||||
self.frame.num_masks() > 0 && self.frame.mask_state() == MaskState::DrawMaskedContent
|
||||
);
|
||||
self.frame.set_mask_state(MaskState::ClearMaskStencil);
|
||||
}
|
||||
|
||||
fn pop_mask(&mut self) {
|
||||
debug_assert!(
|
||||
self.frame.num_masks() > 0 && self.frame.mask_state() == MaskState::ClearMaskStencil
|
||||
);
|
||||
let num_masks = self.frame.num_masks() - 1;
|
||||
self.frame.set_mask_count(num_masks);
|
||||
if num_masks == 0 {
|
||||
self.frame.set_mask_state(MaskState::NoMask);
|
||||
} else {
|
||||
self.frame.set_mask_state(MaskState::DrawMaskedContent);
|
||||
};
|
||||
}
|
||||
|
||||
fn push_blend_mode(&mut self, blend: BlendMode) {
|
||||
self.blend_modes.push(blend);
|
||||
self.frame.set_blend_mode(blend.into());
|
||||
}
|
||||
|
||||
fn pop_blend_mode(&mut self) {
|
||||
self.blend_modes.pop();
|
||||
self.frame.set_blend_mode(
|
||||
self.blend_modes
|
||||
.last()
|
||||
.map(|b| ActualBlendMode::from(*b))
|
||||
.unwrap_or(ActualBlendMode::Normal),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,16 +1,7 @@
|
|||
use crate::pipelines::BlendMode as ActualBlendMode;
|
||||
use crate::target::RenderTargetFrame;
|
||||
use crate::Pipelines;
|
||||
use crate::{
|
||||
ColorAdjustments, Descriptors, DrawType, Globals, MaskState, Mesh, RegistryData, Transforms,
|
||||
UniformBuffer,
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use ruffle_render::backend::ShapeHandle;
|
||||
use ruffle_render::bitmap::BitmapHandle;
|
||||
use ruffle_render::commands::CommandHandler;
|
||||
use ruffle_render::transform::Transform;
|
||||
use swf::{BlendMode, Color};
|
||||
use crate::{ColorAdjustments, Descriptors, Globals, MaskState, Transforms, UniformBuffer};
|
||||
|
||||
pub struct Frame<'a> {
|
||||
pipelines: &'a Pipelines,
|
||||
|
@ -20,26 +11,16 @@ pub struct Frame<'a> {
|
|||
num_masks: u32,
|
||||
uniform_encoder: &'a mut wgpu::CommandEncoder,
|
||||
render_pass: wgpu::RenderPass<'a>,
|
||||
blend_modes: Vec<BlendMode>,
|
||||
blend_mode: ActualBlendMode,
|
||||
bitmap_registry: &'a FnvHashMap<BitmapHandle, RegistryData>,
|
||||
quad_vertices: wgpu::BufferSlice<'a>,
|
||||
quad_indices: wgpu::BufferSlice<'a>,
|
||||
meshes: &'a Vec<Mesh>,
|
||||
}
|
||||
|
||||
impl<'a> Frame<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
pipelines: &'a Pipelines,
|
||||
descriptors: &'a Descriptors,
|
||||
uniform_buffers: UniformBuffer<'a, Transforms>,
|
||||
quad_vertices: wgpu::BufferSlice<'a>,
|
||||
quad_indices: wgpu::BufferSlice<'a>,
|
||||
meshes: &'a Vec<Mesh>,
|
||||
render_pass: wgpu::RenderPass<'a>,
|
||||
uniform_encoder: &'a mut wgpu::CommandEncoder,
|
||||
bitmap_registry: &'a FnvHashMap<BitmapHandle, RegistryData>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pipelines,
|
||||
|
@ -49,15 +30,11 @@ impl<'a> Frame<'a> {
|
|||
num_masks: 0,
|
||||
uniform_encoder,
|
||||
render_pass,
|
||||
blend_modes: vec![BlendMode::Normal],
|
||||
blend_mode: ActualBlendMode::Normal,
|
||||
bitmap_registry,
|
||||
quad_vertices,
|
||||
quad_indices,
|
||||
meshes,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn swap_srgb<T: RenderTargetFrame>(
|
||||
&mut self,
|
||||
globals: &Globals,
|
||||
|
@ -65,6 +42,8 @@ impl<'a> Frame<'a> {
|
|||
copy_srgb_bind_group: &wgpu::BindGroup,
|
||||
width: f32,
|
||||
height: f32,
|
||||
quad_vertices: wgpu::BufferSlice<'a>,
|
||||
quad_indices: wgpu::BufferSlice<'a>,
|
||||
) -> wgpu::CommandBuffer {
|
||||
let mut copy_encoder =
|
||||
self.descriptors
|
||||
|
@ -115,8 +94,8 @@ impl<'a> Frame<'a> {
|
|||
.get_bind_group(false, false),
|
||||
&[],
|
||||
);
|
||||
render_pass.set_vertex_buffer(0, self.quad_vertices);
|
||||
render_pass.set_index_buffer(self.quad_indices, wgpu::IndexFormat::Uint32);
|
||||
render_pass.set_vertex_buffer(0, quad_vertices);
|
||||
render_pass.set_index_buffer(quad_indices, wgpu::IndexFormat::Uint32);
|
||||
render_pass.draw_indexed(0..6, 0, 0..1);
|
||||
drop(render_pass);
|
||||
|
||||
|
@ -127,7 +106,7 @@ impl<'a> Frame<'a> {
|
|||
self.uniform_buffers.finish()
|
||||
}
|
||||
|
||||
fn draw_color(
|
||||
pub fn draw_color(
|
||||
&mut self,
|
||||
vertices: wgpu::BufferSlice<'a>,
|
||||
indices: wgpu::BufferSlice<'a>,
|
||||
|
@ -146,7 +125,7 @@ impl<'a> Frame<'a> {
|
|||
self.render_pass.draw_indexed(0..num_indices, 0, 0..1);
|
||||
}
|
||||
|
||||
fn draw_gradient(
|
||||
pub fn draw_gradient(
|
||||
&mut self,
|
||||
vertices: wgpu::BufferSlice<'a>,
|
||||
indices: wgpu::BufferSlice<'a>,
|
||||
|
@ -167,7 +146,7 @@ impl<'a> Frame<'a> {
|
|||
self.render_pass.draw_indexed(0..num_indices, 0, 0..1);
|
||||
}
|
||||
|
||||
fn draw_bitmap(
|
||||
pub fn draw_bitmap(
|
||||
&mut self,
|
||||
vertices: wgpu::BufferSlice<'a>,
|
||||
indices: wgpu::BufferSlice<'a>,
|
||||
|
@ -197,7 +176,7 @@ impl<'a> Frame<'a> {
|
|||
self.render_pass.draw_indexed(0..num_indices, 0, 0..1);
|
||||
}
|
||||
|
||||
fn apply_transform(
|
||||
pub fn apply_transform(
|
||||
&mut self,
|
||||
matrix: &ruffle_render::matrix::Matrix,
|
||||
color_adjustments: ColorAdjustments,
|
||||
|
@ -226,150 +205,26 @@ impl<'a> Frame<'a> {
|
|||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CommandHandler for Frame<'a> {
|
||||
fn render_bitmap(&mut self, bitmap: BitmapHandle, transform: &Transform, smoothing: bool) {
|
||||
if let Some(entry) = self.bitmap_registry.get(&bitmap) {
|
||||
let texture = &entry.texture_wrapper;
|
||||
|
||||
self.apply_transform(
|
||||
&(transform.matrix
|
||||
* ruffle_render::matrix::Matrix {
|
||||
a: texture.width as f32,
|
||||
d: texture.height as f32,
|
||||
..Default::default()
|
||||
}),
|
||||
ColorAdjustments::from(transform.color_transform),
|
||||
);
|
||||
|
||||
self.draw_bitmap(
|
||||
self.quad_vertices,
|
||||
self.quad_indices,
|
||||
6,
|
||||
&texture.bind_group,
|
||||
false,
|
||||
smoothing,
|
||||
);
|
||||
}
|
||||
pub fn set_mask_state(&mut self, state: MaskState) {
|
||||
self.mask_state = state;
|
||||
}
|
||||
|
||||
fn render_shape(&mut self, shape: ShapeHandle, transform: &Transform) {
|
||||
self.apply_transform(
|
||||
&transform.matrix,
|
||||
ColorAdjustments::from(transform.color_transform),
|
||||
);
|
||||
pub fn set_mask_count(&mut self, num: u32) {
|
||||
self.num_masks = num;
|
||||
|
||||
let mesh = &self.meshes[shape.0];
|
||||
for draw in &mesh.draws {
|
||||
let num_indices = if self.mask_state != MaskState::DrawMaskStencil
|
||||
&& self.mask_state != MaskState::ClearMaskStencil
|
||||
{
|
||||
draw.num_indices
|
||||
} else {
|
||||
// Omit strokes when drawing a mask stencil.
|
||||
draw.num_mask_indices
|
||||
};
|
||||
if num_indices == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
match &draw.draw_type {
|
||||
DrawType::Color => {
|
||||
self.draw_color(
|
||||
draw.vertex_buffer.slice(..),
|
||||
draw.index_buffer.slice(..),
|
||||
num_indices,
|
||||
);
|
||||
}
|
||||
DrawType::Gradient { bind_group, .. } => {
|
||||
self.draw_gradient(
|
||||
draw.vertex_buffer.slice(..),
|
||||
draw.index_buffer.slice(..),
|
||||
num_indices,
|
||||
bind_group,
|
||||
);
|
||||
}
|
||||
DrawType::Bitmap {
|
||||
is_repeating,
|
||||
is_smoothed,
|
||||
bind_group,
|
||||
..
|
||||
} => {
|
||||
self.draw_bitmap(
|
||||
draw.vertex_buffer.slice(..),
|
||||
draw.index_buffer.slice(..),
|
||||
num_indices,
|
||||
bind_group,
|
||||
*is_repeating,
|
||||
*is_smoothed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_rect(&mut self, color: Color, matrix: &ruffle_render::matrix::Matrix) {
|
||||
self.apply_transform(
|
||||
&matrix,
|
||||
ColorAdjustments {
|
||||
mult_color: [
|
||||
f32::from(color.r) / 255.0,
|
||||
f32::from(color.g) / 255.0,
|
||||
f32::from(color.b) / 255.0,
|
||||
f32::from(color.a) / 255.0,
|
||||
],
|
||||
add_color: [0.0, 0.0, 0.0, 0.0],
|
||||
},
|
||||
);
|
||||
|
||||
self.draw_color(self.quad_vertices, self.quad_indices, 6);
|
||||
}
|
||||
|
||||
fn push_mask(&mut self) {
|
||||
debug_assert!(
|
||||
self.mask_state == MaskState::NoMask || self.mask_state == MaskState::DrawMaskedContent
|
||||
);
|
||||
self.num_masks += 1;
|
||||
self.mask_state = MaskState::DrawMaskStencil;
|
||||
|
||||
self.render_pass.set_stencil_reference(self.num_masks - 1);
|
||||
}
|
||||
|
||||
fn activate_mask(&mut self) {
|
||||
debug_assert!(self.num_masks > 0 && self.mask_state == MaskState::DrawMaskStencil);
|
||||
self.mask_state = MaskState::DrawMaskedContent;
|
||||
self.render_pass.set_stencil_reference(self.num_masks);
|
||||
}
|
||||
|
||||
fn deactivate_mask(&mut self) {
|
||||
debug_assert!(self.num_masks > 0 && self.mask_state == MaskState::DrawMaskedContent);
|
||||
self.mask_state = MaskState::ClearMaskStencil;
|
||||
self.render_pass.set_stencil_reference(self.num_masks);
|
||||
pub fn set_blend_mode(&mut self, blend_mode: ActualBlendMode) {
|
||||
self.blend_mode = blend_mode;
|
||||
}
|
||||
|
||||
fn pop_mask(&mut self) {
|
||||
debug_assert!(self.num_masks > 0 && self.mask_state == MaskState::ClearMaskStencil);
|
||||
self.num_masks -= 1;
|
||||
self.mask_state = if self.num_masks == 0 {
|
||||
MaskState::NoMask
|
||||
} else {
|
||||
self.render_pass.set_stencil_reference(self.num_masks);
|
||||
MaskState::DrawMaskedContent
|
||||
};
|
||||
pub fn mask_state(&self) -> MaskState {
|
||||
self.mask_state
|
||||
}
|
||||
|
||||
fn push_blend_mode(&mut self, blend: BlendMode) {
|
||||
self.blend_modes.push(blend);
|
||||
self.blend_mode = blend.into();
|
||||
}
|
||||
|
||||
fn pop_blend_mode(&mut self) {
|
||||
self.blend_modes.pop();
|
||||
self.blend_mode = self
|
||||
.blend_modes
|
||||
.last()
|
||||
.map(|b| ActualBlendMode::from(*b))
|
||||
.unwrap_or(ActualBlendMode::Normal);
|
||||
pub fn num_masks(&self) -> u32 {
|
||||
self.num_masks
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ mod uniform_buffer;
|
|||
pub mod backend;
|
||||
#[cfg(feature = "clap")]
|
||||
pub mod clap;
|
||||
mod commands;
|
||||
pub mod descriptors;
|
||||
mod frame;
|
||||
mod layouts;
|
||||
|
@ -59,7 +60,7 @@ struct TextureTransforms {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
||||
struct ColorAdjustments {
|
||||
pub struct ColorAdjustments {
|
||||
mult_color: [f32; 4],
|
||||
add_color: [f32; 4],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue