diff --git a/render/wgpu/shaders/blend.wgsl b/render/wgpu/shaders/blend.wgsl index 4f5fba328..f41548615 100644 --- a/render/wgpu/shaders/blend.wgsl +++ b/render/wgpu/shaders/blend.wgsl @@ -84,6 +84,11 @@ fn main_fragment(in: VertexOutput) -> @location(0) vec4 { return vec4(src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a) + src.a * dst.a * blend_func(src.rgb / src.a, dst.rgb/ dst.a), src.a + dst.a * (1.0 - src.a)); } } else { + if (true) { + // This needs to be in a branch because... reasons. Bug in naga. + // https://github.com/gfx-rs/naga/issues/2168 + discard; + } return dst; } } diff --git a/render/wgpu/src/commands.rs b/render/wgpu/src/commands.rs index bfcd9885a..dc29000c5 100644 --- a/render/wgpu/src/commands.rs +++ b/render/wgpu/src/commands.rs @@ -1,5 +1,6 @@ use crate::mesh::{DrawType, Mesh}; -use crate::surface::{BlendBuffer, DepthBuffer, FrameBuffer, ResolveBuffer, TextureBuffers}; +use crate::surface::{BlendBuffer, DepthBuffer, FrameBuffer, ResolveBuffer}; +use crate::utils::create_buffer_with_data; use crate::{ as_texture, ColorAdjustments, Descriptors, Globals, MaskState, Pipelines, Transforms, UniformBuffer, @@ -11,31 +12,146 @@ use ruffle_render::transform::Transform; use swf::{BlendMode, Color}; pub struct CommandTarget<'pass> { - frame_buffer: &'pass FrameBuffer, - blend_buffer: &'pass BlendBuffer, - resolve_buffer: Option<&'pass ResolveBuffer>, - depth: &'pass DepthBuffer, + frame_buffer: FrameBuffer, + blend_buffer: BlendBuffer, + resolve_buffer: Option, + depth: DepthBuffer, + globals: &'pass Globals, + size: wgpu::Extent3d, + format: wgpu::TextureFormat, + sample_count: u32, + _whole_frame_buffer: wgpu::Buffer, + whole_frame_bind_group: wgpu::BindGroup, } impl<'pass> CommandTarget<'pass> { pub fn new( - frame_buffer: &'pass FrameBuffer, - blend_buffer: &'pass BlendBuffer, - resolve_buffer: Option<&'pass ResolveBuffer>, - depth: &'pass DepthBuffer, + globals: &'pass Globals, + descriptors: &Descriptors, + size: wgpu::Extent3d, + format: wgpu::TextureFormat, + sample_count: u32, ) -> Self { + let transform = Transforms { + world_matrix: [ + [size.width as f32, 0.0, 0.0, 0.0], + [0.0, size.height as f32, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + [0.0, 0.0, 0.0, 1.0], + ], + color_adjustments: ColorAdjustments { + mult_color: [1.0, 1.0, 1.0, 1.0], + add_color: [0.0, 0.0, 0.0, 0.0], + }, + }; + let transforms_buffer = create_buffer_with_data( + &descriptors.device, + bytemuck::cast_slice(&[transform]), + wgpu::BufferUsages::UNIFORM, + create_debug_label!("Whole-frame transforms buffer"), + ); + let whole_frame_bind_group = + descriptors + .device + .create_bind_group(&wgpu::BindGroupDescriptor { + layout: &descriptors.bind_layouts.transforms, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &transforms_buffer, + offset: 0, + size: wgpu::BufferSize::new(std::mem::size_of::() as u64), + }), + }], + label: create_debug_label!("Whole-frame transforms bind group").as_deref(), + }); + + let frame_buffer = FrameBuffer::new( + &descriptors, + create_debug_label!("Frame buffer"), + sample_count, + size, + format, + if sample_count > 1 { + wgpu::TextureUsages::RENDER_ATTACHMENT + } else { + wgpu::TextureUsages::RENDER_ATTACHMENT + | wgpu::TextureUsages::COPY_SRC + | wgpu::TextureUsages::TEXTURE_BINDING + }, + ); + + let blend_buffer = BlendBuffer::new( + &descriptors, + create_debug_label!("Blend buffer"), + size, + format, + wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + ); + + let resolve_buffer = if sample_count > 1 { + Some(ResolveBuffer::new( + &descriptors, + create_debug_label!("Resolve buffer"), + size, + format, + wgpu::TextureUsages::COPY_SRC + | wgpu::TextureUsages::TEXTURE_BINDING + | wgpu::TextureUsages::RENDER_ATTACHMENT, + )) + } else { + None + }; + + let depth = DepthBuffer::new( + &descriptors.device, + create_debug_label!("Depth buffer"), + sample_count, + size, + ); + Self { frame_buffer, blend_buffer, resolve_buffer, depth, + globals, + size, + format, + sample_count, + _whole_frame_buffer: transforms_buffer, + whole_frame_bind_group, } } + pub fn create_child( + &self, + globals: &'pass Globals, + descriptors: &Descriptors, + width: u32, + height: u32, + ) -> Self { + Self::new( + globals, + descriptors, + wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + self.format, + self.sample_count, + ) + } + + pub fn whole_frame_bind_group(&self) -> &wgpu::BindGroup { + &self.whole_frame_bind_group + } + pub fn color_attachments( &self, clear: Option, - ) -> Option> { + ) -> Option { Some(wgpu::RenderPassColorAttachment { view: &self.frame_buffer.view(), resolve_target: self.resolve_buffer.as_ref().map(|b| b.view()), @@ -50,10 +166,7 @@ impl<'pass> CommandTarget<'pass> { }) } - pub fn depth_attachment( - &self, - clear: bool, - ) -> Option> { + pub fn depth_attachment(&self, clear: bool) -> Option { Some(wgpu::RenderPassDepthStencilAttachment { view: self.depth.view(), depth_ops: Some(wgpu::Operations { @@ -138,9 +251,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob #[allow(clippy::too_many_arguments)] pub fn execute( - globals: &'frame Globals, pipelines: &'frame Pipelines, - texture_buffers: &'frame mut TextureBuffers, target: &'pass CommandTarget<'pass>, meshes: &'global Vec, descriptors: &'global Descriptors, @@ -172,7 +283,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob color_attachments: &[target.color_attachments(clear_color.take())], depth_stencil_attachment: target.depth_attachment(first && clear_depth), }); - render_pass.set_bind_group(0, globals.bind_group(), &[]); + render_pass.set_bind_group(0, target.globals.bind_group(), &[]); let mut renderer = CommandRenderer::new( &pipelines, &meshes, @@ -236,22 +347,21 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob }; target.update_blend_buffer(&mut draw_encoder); - - let frame_buffer = texture_buffers.take_frame_buffer(&descriptors); - let resolve_buffer = texture_buffers.take_resolve_buffer(&descriptors); - let blend_buffer = texture_buffers.take_blend_buffer(&descriptors); - - let child = CommandTarget::new( - &frame_buffer, - &blend_buffer, - resolve_buffer.as_ref(), - &target.depth, + let child_globals = Globals::new( + &descriptors.device, + &descriptors.bind_layouts.globals, + target.size.width, + target.size.height, + ); + let child = target.create_child( + &child_globals, + &descriptors, + target.size.width, + target.size.height, ); CommandRenderer::execute( - &globals, &pipelines, - texture_buffers, &child, &meshes, &descriptors, @@ -306,9 +416,9 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob draw_encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, color_attachments: &[target.color_attachments(clear_color.take())], - depth_stencil_attachment: child.depth_attachment(false), + depth_stencil_attachment: target.depth_attachment(false), }); - render_pass.set_bind_group(0, globals.bind_group(), &[]); + render_pass.set_bind_group(0, target.globals.bind_group(), &[]); match mask_state { MaskState::NoMask => {} @@ -325,7 +435,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob render_pass.set_pipeline(pipelines.blend.pipeline_for(mask_state)); - render_pass.set_bind_group(1, texture_buffers.whole_frame_bind_group(), &[0]); + render_pass.set_bind_group(1, target.whole_frame_bind_group(), &[0]); render_pass.set_bind_group(2, &blend_bind_group, &[]); render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..)); diff --git a/render/wgpu/src/surface.rs b/render/wgpu/src/surface.rs index 72201bcc2..4e0090ef7 100644 --- a/render/wgpu/src/surface.rs +++ b/render/wgpu/src/surface.rs @@ -2,10 +2,7 @@ use crate::commands::{CommandRenderer, CommandTarget}; use crate::mesh::Mesh; use crate::uniform_buffer::BufferStorage; use crate::utils::remove_srgb; -use crate::{ - create_buffer_with_data, ColorAdjustments, Descriptors, Globals, Pipelines, TextureTransforms, - Transforms, UniformBuffer, -}; +use crate::{Descriptors, Globals, Pipelines, TextureTransforms, Transforms, UniformBuffer}; use ruffle_render::commands::CommandList; use std::sync::Arc; @@ -163,165 +160,10 @@ impl DepthBuffer { } } -#[derive(Debug)] -pub struct TextureBuffers { - size: wgpu::Extent3d, - format: wgpu::TextureFormat, - sample_count: u32, - _whole_frame_buffer: wgpu::Buffer, - whole_frame_bind_group: wgpu::BindGroup, -} - -impl TextureBuffers { - pub fn new( - descriptors: &Descriptors, - size: wgpu::Extent3d, - format: wgpu::TextureFormat, - sample_count: u32, - ) -> Self { - let transform = Transforms { - world_matrix: [ - [size.width as f32, 0.0, 0.0, 0.0], - [0.0, size.height as f32, 0.0, 0.0], - [0.0, 0.0, 1.0, 0.0], - [0.0, 0.0, 0.0, 1.0], - ], - color_adjustments: ColorAdjustments { - mult_color: [1.0, 1.0, 1.0, 1.0], - add_color: [0.0, 0.0, 0.0, 0.0], - }, - }; - let transforms_buffer = create_buffer_with_data( - &descriptors.device, - bytemuck::cast_slice(&[transform]), - wgpu::BufferUsages::UNIFORM, - create_debug_label!("Whole-frame transforms buffer"), - ); - let whole_frame_bind_group = - descriptors - .device - .create_bind_group(&wgpu::BindGroupDescriptor { - layout: &descriptors.bind_layouts.transforms, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { - buffer: &transforms_buffer, - offset: 0, - size: wgpu::BufferSize::new(std::mem::size_of::() as u64), - }), - }], - label: create_debug_label!("Whole-frame transforms bind group").as_deref(), - }); - - Self { - size, - format, - sample_count, - _whole_frame_buffer: transforms_buffer, - whole_frame_bind_group, - } - } - - pub fn whole_frame_bind_group(&self) -> &wgpu::BindGroup { - &self.whole_frame_bind_group - } - - pub fn take_frame_buffer(&mut self, descriptors: &Descriptors) -> FrameBuffer { - self.create_frame_buffer(descriptors) - } - - fn create_frame_buffer(&self, descriptors: &Descriptors) -> FrameBuffer { - let label = if cfg!(feature = "render_debug_labels") { - static COUNTER: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(1); - let id = COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - Some(format!("Frame buffer {}", id)) - } else { - None - }; - FrameBuffer::new( - &descriptors, - label, - self.sample_count, - self.size, - self.format, - if self.sample_count > 1 { - wgpu::TextureUsages::RENDER_ATTACHMENT - } else { - wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::COPY_SRC - | wgpu::TextureUsages::TEXTURE_BINDING - }, - ) - } - - pub fn take_blend_buffer(&mut self, descriptors: &Descriptors) -> BlendBuffer { - self.create_blend_buffer(descriptors) - } - - fn create_blend_buffer(&self, descriptors: &Descriptors) -> BlendBuffer { - let label = if cfg!(feature = "render_debug_labels") { - static COUNTER: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(1); - let id = COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - Some(format!("Blend buffer {}", id)) - } else { - None - }; - BlendBuffer::new( - &descriptors, - label, - self.size, - self.format, - wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - ) - } - - pub fn take_resolve_buffer(&mut self, descriptors: &Descriptors) -> Option { - if self.sample_count > 1 { - Some(self.create_resolve_buffer( - descriptors, - wgpu::TextureUsages::COPY_SRC - | wgpu::TextureUsages::TEXTURE_BINDING - | wgpu::TextureUsages::RENDER_ATTACHMENT, - )) - } else { - None - } - } - - fn create_resolve_buffer( - &self, - descriptors: &Descriptors, - usage: wgpu::TextureUsages, - ) -> ResolveBuffer { - let label = if cfg!(feature = "render_debug_labels") { - static COUNTER: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(1); - let id = COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - Some(format!("Resolve buffer {}", id)) - } else { - None - }; - ResolveBuffer::new(&descriptors, label, self.size, self.format, usage) - } - - pub fn take_depth_buffer(&mut self, descriptors: &Descriptors) -> DepthBuffer { - self.create_depth_buffer(descriptors) - } - - fn create_depth_buffer(&self, descriptors: &Descriptors) -> DepthBuffer { - let label = if cfg!(feature = "render_debug_labels") { - static COUNTER: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(1); - let id = COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - Some(format!("depth buffer {}", id)) - } else { - None - }; - DepthBuffer::new(&descriptors.device, label, self.sample_count, self.size) - } -} - #[derive(Debug)] pub struct Surface { - buffers: TextureBuffers, + size: wgpu::Extent3d, + sample_count: u32, pipelines: Arc, globals: Globals, format: wgpu::TextureFormat, @@ -352,7 +194,8 @@ impl Surface { let pipelines = descriptors.pipelines(sample_count, frame_buffer_format); Self { - buffers: TextureBuffers::new(&descriptors, size, frame_buffer_format, sample_count), + size, + sample_count, pipelines, globals, format: frame_buffer_format, @@ -379,24 +222,18 @@ impl Surface { label: uniform_encoder_label.as_deref(), }); - let frame_buffer = self.buffers.take_frame_buffer(&descriptors); - let blend_buffer = self.buffers.take_blend_buffer(&descriptors); - let resolve_buffer = self.buffers.take_resolve_buffer(&descriptors); - let depth_buffer = self.buffers.take_depth_buffer(&descriptors); - let target = CommandTarget::new( - &frame_buffer, - &blend_buffer, - resolve_buffer.as_ref(), - &depth_buffer, + &self.globals, + &descriptors, + self.size, + self.format, + self.sample_count, ); let mut buffers = vec![]; CommandRenderer::execute( - &self.globals, &self.pipelines, - &mut self.buffers, &target, &meshes, &descriptors, @@ -426,12 +263,7 @@ impl Surface { }, wgpu::BindGroupEntry { binding: 1, - resource: wgpu::BindingResource::TextureView( - &resolve_buffer - .as_ref() - .map(|b| b.view()) - .unwrap_or_else(|| frame_buffer.view()), - ), + resource: wgpu::BindingResource::TextureView(&target.color_view()), }, wgpu::BindGroupEntry { binding: 2, @@ -473,7 +305,7 @@ impl Surface { render_pass.set_pipeline(&pipeline); render_pass.set_bind_group(0, self.globals.bind_group(), &[]); - render_pass.set_bind_group(1, &self.buffers.whole_frame_bind_group, &[0]); + render_pass.set_bind_group(1, &target.whole_frame_bind_group(), &[0]); render_pass.set_bind_group(2, ©_bind_group, &[]); render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..));