wgpu: Use vertex buffer and staging belt for glow filter

This commit is contained in:
Nathan Adams 2024-01-23 23:26:19 +01:00
parent 2722a6588e
commit 7e0bd48061
2 changed files with 85 additions and 69 deletions

View File

@ -67,67 +67,59 @@ impl<'a> FilterSource<'a> {
]
}
pub fn vertices_with_blur_offset(
&self,
device: &wgpu::Device,
blur_offset: (f32, f32),
) -> wgpu::Buffer {
pub fn vertices_with_blur_offset(&self, blur_offset: (f32, f32)) -> [FilterVertexWithBlur; 4] {
let source_width = self.texture.width() as f32;
let source_height = self.texture.height() as f32;
let source_left = self.point.0;
let source_top = self.point.1;
let source_right = source_left + self.size.0;
let source_bottom = source_top + self.size.1;
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: create_debug_label!("Filter vertices").as_deref(),
contents: bytemuck::cast_slice(&[
FilterVertexWithBlur {
position: [0.0, 0.0],
source_uv: [
source_left as f32 / source_width,
source_top as f32 / source_height,
],
blur_uv: [
(source_left as f32 + blur_offset.0) / source_width,
(source_top as f32 + blur_offset.1) / source_height,
],
},
FilterVertexWithBlur {
position: [1.0, 0.0],
source_uv: [
source_right as f32 / source_width,
source_top as f32 / source_height,
],
blur_uv: [
(source_right as f32 + blur_offset.0) / source_width,
(source_top as f32 + blur_offset.1) / source_height,
],
},
FilterVertexWithBlur {
position: [1.0, 1.0],
source_uv: [
source_right as f32 / source_width,
source_bottom as f32 / source_height,
],
blur_uv: [
(source_right as f32 + blur_offset.0) / source_width,
(source_bottom as f32 + blur_offset.1) / source_height,
],
},
FilterVertexWithBlur {
position: [0.0, 1.0],
source_uv: [
source_left as f32 / source_width,
source_bottom as f32 / source_height,
],
blur_uv: [
(source_left as f32 + blur_offset.0) / source_width,
(source_bottom as f32 + blur_offset.1) / source_height,
],
},
]),
usage: wgpu::BufferUsages::VERTEX,
})
[
FilterVertexWithBlur {
position: [0.0, 0.0],
source_uv: [
source_left as f32 / source_width,
source_top as f32 / source_height,
],
blur_uv: [
(source_left as f32 + blur_offset.0) / source_width,
(source_top as f32 + blur_offset.1) / source_height,
],
},
FilterVertexWithBlur {
position: [1.0, 0.0],
source_uv: [
source_right as f32 / source_width,
source_top as f32 / source_height,
],
blur_uv: [
(source_right as f32 + blur_offset.0) / source_width,
(source_top as f32 + blur_offset.1) / source_height,
],
},
FilterVertexWithBlur {
position: [1.0, 1.0],
source_uv: [
source_right as f32 / source_width,
source_bottom as f32 / source_height,
],
blur_uv: [
(source_right as f32 + blur_offset.0) / source_width,
(source_bottom as f32 + blur_offset.1) / source_height,
],
},
FilterVertexWithBlur {
position: [0.0, 1.0],
source_uv: [
source_left as f32 / source_width,
source_bottom as f32 / source_height,
],
blur_uv: [
(source_left as f32 + blur_offset.0) / source_width,
(source_bottom as f32 + blur_offset.1) / source_height,
],
},
]
}
pub fn vertices_with_highlight_and_shadow(

View File

@ -2,7 +2,9 @@ use crate::backend::RenderTargetMode;
use crate::buffer_pool::TexturePool;
use crate::descriptors::Descriptors;
use crate::filters::blur::BlurFilter;
use crate::filters::{FilterSource, VERTEX_BUFFERS_DESCRIPTION_FILTERS_WITH_BLUR};
use crate::filters::{
FilterSource, FilterVertexWithBlur, VERTEX_BUFFERS_DESCRIPTION_FILTERS_WITH_BLUR,
};
use crate::surface::target::CommandTarget;
use crate::utils::SampleCountMap;
use bytemuck::{Pod, Zeroable};
@ -23,14 +25,16 @@ struct GlowUniform {
pub struct GlowFilter {
bind_group_layout: wgpu::BindGroupLayout,
pipeline_layout: wgpu::PipelineLayout,
buffer: wgpu::Buffer,
buffer_size: wgpu::BufferSize,
vertex_buffer: wgpu::Buffer,
uniform_buffer: wgpu::Buffer,
vertices_size: wgpu::BufferSize,
uniform_size: wgpu::BufferSize,
pipeline: SampleCountMap<OnceLock<wgpu::RenderPipeline>>,
}
impl GlowFilter {
pub fn new(device: &wgpu::Device) -> Self {
let buffer_size = std::mem::size_of::<GlowUniform>() as u64;
let uniform_size = std::mem::size_of::<GlowUniform>() as u64;
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
@ -55,7 +59,7 @@ impl GlowFilter {
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: wgpu::BufferSize::new(buffer_size),
min_binding_size: wgpu::BufferSize::new(uniform_size),
},
count: None,
},
@ -73,9 +77,17 @@ impl GlowFilter {
label: create_debug_label!("Blur filter binds").as_deref(),
});
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
let vertices_size = std::mem::size_of::<[FilterVertexWithBlur; 4]>() as u64;
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: buffer_size,
size: vertices_size,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: uniform_size,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
@ -89,9 +101,11 @@ impl GlowFilter {
Self {
pipeline: Default::default(),
pipeline_layout,
buffer,
vertex_buffer,
uniform_buffer,
bind_group_layout,
buffer_size: wgpu::BufferSize::new(buffer_size).expect("Definitely not zero."),
uniform_size: wgpu::BufferSize::new(uniform_size).expect("Definitely not zero."),
vertices_size: wgpu::BufferSize::new(vertices_size).expect("Definitely not zero."),
}
}
@ -181,9 +195,9 @@ impl GlowFilter {
staging_belt
.write_buffer(
draw_encoder,
&self.buffer,
&self.uniform_buffer,
0,
self.buffer_size,
self.uniform_size,
&descriptors.device,
)
.copy_from_slice(bytemuck::cast_slice(&[GlowUniform {
@ -198,7 +212,17 @@ impl GlowFilter {
knockout: if filter.is_knockout() { 1 } else { 0 },
composite_source: if filter.composite_source() { 1 } else { 0 },
}]));
let vertices = source.vertices_with_blur_offset(&descriptors.device, blur_offset);
staging_belt
.write_buffer(
draw_encoder,
&self.vertex_buffer,
0,
self.vertices_size,
&descriptors.device,
)
.copy_from_slice(bytemuck::cast_slice(&[
source.vertices_with_blur_offset(blur_offset)
]));
let filter_group = descriptors
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
@ -217,7 +241,7 @@ impl GlowFilter {
},
wgpu::BindGroupEntry {
binding: 2,
resource: self.buffer.as_entire_binding(),
resource: self.uniform_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 3,
@ -234,7 +258,7 @@ impl GlowFilter {
render_pass.set_bind_group(0, &filter_group, &[]);
render_pass.set_vertex_buffer(0, vertices.slice(..));
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.set_index_buffer(
descriptors.quad.indices.slice(..),
wgpu::IndexFormat::Uint32,