wgpu: Implement all blend modes
This commit is contained in:
parent
f9333e2626
commit
7904c3d4f0
|
@ -0,0 +1,89 @@
|
||||||
|
/// Shader used for drawing a pending framebuffer onto a parent framebuffer
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) position: vec4<f32>,
|
||||||
|
@location(0) uv: vec2<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BlendOptions {
|
||||||
|
mode: i32,
|
||||||
|
_padding1: f32,
|
||||||
|
_padding2: f32,
|
||||||
|
_padding3: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(2) @binding(0) var parent_texture: texture_2d<f32>;
|
||||||
|
@group(2) @binding(1) var current_texture: texture_2d<f32>;
|
||||||
|
@group(2) @binding(2) var texture_sampler: sampler;
|
||||||
|
@group(2) @binding(3) var<uniform> blend: BlendOptions;
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn main_vertex(in: VertexInput) -> VertexOutput {
|
||||||
|
let pos = globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
|
||||||
|
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
|
||||||
|
return VertexOutput(pos, uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blend_func(src: vec3<f32>, dst: vec3<f32>) -> vec3<f32> {
|
||||||
|
switch (blend.mode) {
|
||||||
|
default: {
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
case 1: { // Multiply
|
||||||
|
return src * dst;
|
||||||
|
}
|
||||||
|
case 2: { // Screen
|
||||||
|
return (dst + src) - (dst * src);
|
||||||
|
}
|
||||||
|
case 3: { // Lighten
|
||||||
|
return max(dst, src);
|
||||||
|
}
|
||||||
|
case 4: { // Darken
|
||||||
|
return min(dst, src);
|
||||||
|
}
|
||||||
|
case 5: { // Difference
|
||||||
|
return abs(dst - src);
|
||||||
|
}
|
||||||
|
case 8: { // Invert
|
||||||
|
return 1.0 - dst;
|
||||||
|
}
|
||||||
|
case 11: { // Overlay
|
||||||
|
var out = src;
|
||||||
|
if (dst.r <= 0.5) { out.r = (2.0 * src.r * dst.r); } else { out.r = (1.0 - 2.0 * (1.0 - dst.r) * (1.0 - src.r)); }
|
||||||
|
if (dst.g <= 0.5) { out.g = (2.0 * src.g * dst.g); } else { out.g = (1.0 - 2.0 * (1.0 - dst.g) * (1.0 - src.g)); }
|
||||||
|
if (dst.b <= 0.5) { out.b = (2.0 * src.b * dst.b); } else { out.b = (1.0 - 2.0 * (1.0 - dst.b) * (1.0 - src.b)); }
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
case 12: { // Hardlight
|
||||||
|
var out = src;
|
||||||
|
if (src.r <= 0.5) { out.r = (2.0 * src.r * dst.r); } else { out.r = (1.0 - 2.0 * (1.0 - dst.r) * (1.0 - src.r)); }
|
||||||
|
if (src.g <= 0.5) { out.g = (2.0 * src.g * dst.g); } else { out.g = (1.0 - 2.0 * (1.0 - dst.g) * (1.0 - src.g)); }
|
||||||
|
if (src.b <= 0.5) { out.b = (2.0 * src.b * dst.b); } else { out.b = (1.0 - 2.0 * (1.0 - dst.b) * (1.0 - src.b)); }
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
|
// dst is the parent pixel we're blending onto - it is either 0 or 1 alpha.
|
||||||
|
var dst: vec4<f32> = textureSample(parent_texture, texture_sampler, in.uv);
|
||||||
|
// src is the pixel that we want to apply - it may have any alpha.
|
||||||
|
var src: vec4<f32> = textureSample(current_texture, texture_sampler, in.uv);
|
||||||
|
|
||||||
|
if (src.a > 0.0) {
|
||||||
|
if (blend.mode == 6) { // Add
|
||||||
|
return vec4<f32>(src.rgb + dst.rgb, 1.0);
|
||||||
|
} else if (blend.mode == 7) { // Subtract
|
||||||
|
return vec4<f32>(dst.rgb - src.rgb, 1.0);
|
||||||
|
} else if (blend.mode == 9) { // Alpha
|
||||||
|
return vec4<f32>(dst.rgb * src.a, src.a * dst.a);
|
||||||
|
} else if (blend.mode == 10) { // Erase
|
||||||
|
return vec4<f32>(dst.rgb * (1.0 - src.a), (1.0 - src.a) * dst.a);
|
||||||
|
} else {
|
||||||
|
return vec4<f32>(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 {
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::mesh::{DrawType, Mesh};
|
use crate::mesh::{DrawType, Mesh};
|
||||||
use crate::surface::{BlendBuffer, DepthBuffer, FrameBuffer, ResolveBuffer, TextureBuffers};
|
use crate::surface::{BlendBuffer, DepthBuffer, FrameBuffer, ResolveBuffer, TextureBuffers};
|
||||||
use crate::{
|
use crate::{
|
||||||
as_texture, ColorAdjustments, Descriptors, Globals, MaskState, Pipelines, TextureTransforms,
|
as_texture, ColorAdjustments, Descriptors, Globals, MaskState, Pipelines, Transforms,
|
||||||
Transforms, UniformBuffer,
|
UniformBuffer,
|
||||||
};
|
};
|
||||||
use ruffle_render::backend::ShapeHandle;
|
use ruffle_render::backend::ShapeHandle;
|
||||||
use ruffle_render::bitmap::BitmapHandle;
|
use ruffle_render::bitmap::BitmapHandle;
|
||||||
|
@ -226,6 +226,11 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
||||||
mask_state = renderer.mask_state;
|
mask_state = renderer.mask_state;
|
||||||
}
|
}
|
||||||
Chunk::Blend(commands, blend_mode) => {
|
Chunk::Blend(commands, blend_mode) => {
|
||||||
|
let parent = match blend_mode {
|
||||||
|
BlendMode::Alpha | BlendMode::Erase => nearest_layer,
|
||||||
|
_ => target,
|
||||||
|
};
|
||||||
|
|
||||||
target.update_blend_buffer(&mut draw_encoder);
|
target.update_blend_buffer(&mut draw_encoder);
|
||||||
|
|
||||||
let frame_buffer = texture_buffers.take_frame_buffer(&descriptors);
|
let frame_buffer = texture_buffers.take_frame_buffer(&descriptors);
|
||||||
|
@ -258,25 +263,17 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let bitmap_bind_group =
|
let blend_bind_group =
|
||||||
descriptors
|
descriptors
|
||||||
.device
|
.device
|
||||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
layout: &descriptors.bind_layouts.bitmap,
|
layout: &descriptors.bind_layouts.blend,
|
||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: wgpu::BindingResource::Buffer(
|
resource: wgpu::BindingResource::TextureView(
|
||||||
wgpu::BufferBinding {
|
parent.blend_buffer.view(),
|
||||||
buffer: &descriptors.quad.texture_transforms,
|
|
||||||
offset: 0,
|
|
||||||
size: wgpu::BufferSize::new(std::mem::size_of::<
|
|
||||||
TextureTransforms,
|
|
||||||
>(
|
|
||||||
)
|
|
||||||
as u64),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
|
@ -288,11 +285,18 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 2,
|
binding: 2,
|
||||||
resource: wgpu::BindingResource::Sampler(
|
resource: wgpu::BindingResource::Sampler(
|
||||||
&descriptors.bitmap_samplers.get_sampler(false, false),
|
descriptors.bitmap_samplers.get_sampler(false, false),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 3,
|
||||||
|
resource: descriptors
|
||||||
|
.blend_buffer(blend_mode)
|
||||||
|
.as_entire_binding(),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut render_pass =
|
let mut render_pass =
|
||||||
draw_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
draw_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
|
@ -314,10 +318,10 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_pass.set_pipeline(pipelines.bitmap.pipeline_for(mask_state));
|
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, texture_buffers.whole_frame_bind_group(), &[0]);
|
||||||
render_pass.set_bind_group(2, &bitmap_bind_group, &[]);
|
render_pass.set_bind_group(2, &blend_bind_group, &[]);
|
||||||
|
|
||||||
render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..));
|
render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..));
|
||||||
render_pass.set_index_buffer(
|
render_pass.set_index_buffer(
|
||||||
|
|
|
@ -4,6 +4,9 @@ use crate::shaders::Shaders;
|
||||||
use crate::{create_buffer_with_data, BitmapSamplers, Pipelines, TextureTransforms, Vertex};
|
use crate::{create_buffer_with_data, BitmapSamplers, Pipelines, TextureTransforms, Vertex};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use swf::BlendMode;
|
||||||
|
|
||||||
|
const MAX_BLEND_MODES: usize = 13;
|
||||||
|
|
||||||
pub struct Descriptors {
|
pub struct Descriptors {
|
||||||
pub adapter: wgpu::Adapter,
|
pub adapter: wgpu::Adapter,
|
||||||
|
@ -13,6 +16,7 @@ pub struct Descriptors {
|
||||||
pub bitmap_samplers: BitmapSamplers,
|
pub bitmap_samplers: BitmapSamplers,
|
||||||
pub bind_layouts: BindLayouts,
|
pub bind_layouts: BindLayouts,
|
||||||
pub quad: Quad,
|
pub quad: Quad,
|
||||||
|
blend_buffers: [wgpu::Buffer; MAX_BLEND_MODES],
|
||||||
copy_pipeline: Mutex<FnvHashMap<wgpu::TextureFormat, Arc<wgpu::RenderPipeline>>>,
|
copy_pipeline: Mutex<FnvHashMap<wgpu::TextureFormat, Arc<wgpu::RenderPipeline>>>,
|
||||||
copy_srgb_pipeline: Mutex<FnvHashMap<wgpu::TextureFormat, Arc<wgpu::RenderPipeline>>>,
|
copy_srgb_pipeline: Mutex<FnvHashMap<wgpu::TextureFormat, Arc<wgpu::RenderPipeline>>>,
|
||||||
shaders: Shaders,
|
shaders: Shaders,
|
||||||
|
@ -27,6 +31,15 @@ impl Descriptors {
|
||||||
let shaders = Shaders::new(&device);
|
let shaders = Shaders::new(&device);
|
||||||
let quad = Quad::new(&device);
|
let quad = Quad::new(&device);
|
||||||
|
|
||||||
|
let blend_buffers = core::array::from_fn(|blend_id| {
|
||||||
|
create_buffer_with_data(
|
||||||
|
&device,
|
||||||
|
bytemuck::cast_slice(&[blend_id, 0, 0, 0]),
|
||||||
|
wgpu::BufferUsages::UNIFORM,
|
||||||
|
create_debug_label!("Blend mode {:?}", blend_id),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
adapter,
|
adapter,
|
||||||
device,
|
device,
|
||||||
|
@ -35,6 +48,7 @@ impl Descriptors {
|
||||||
bitmap_samplers,
|
bitmap_samplers,
|
||||||
bind_layouts,
|
bind_layouts,
|
||||||
quad,
|
quad,
|
||||||
|
blend_buffers,
|
||||||
copy_pipeline: Default::default(),
|
copy_pipeline: Default::default(),
|
||||||
copy_srgb_pipeline: Default::default(),
|
copy_srgb_pipeline: Default::default(),
|
||||||
shaders,
|
shaders,
|
||||||
|
@ -182,6 +196,26 @@ impl Descriptors {
|
||||||
})
|
})
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blend_buffer(&self, blend_mode: BlendMode) -> &wgpu::Buffer {
|
||||||
|
let index = match blend_mode {
|
||||||
|
BlendMode::Normal => 0,
|
||||||
|
BlendMode::Layer => 0,
|
||||||
|
BlendMode::Multiply => 1,
|
||||||
|
BlendMode::Screen => 2,
|
||||||
|
BlendMode::Lighten => 3,
|
||||||
|
BlendMode::Darken => 4,
|
||||||
|
BlendMode::Difference => 5,
|
||||||
|
BlendMode::Add => 6,
|
||||||
|
BlendMode::Subtract => 7,
|
||||||
|
BlendMode::Invert => 8,
|
||||||
|
BlendMode::Alpha => 9,
|
||||||
|
BlendMode::Erase => 10,
|
||||||
|
BlendMode::Overlay => 11,
|
||||||
|
BlendMode::HardLight => 12,
|
||||||
|
};
|
||||||
|
&self.blend_buffers[index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Quad {
|
pub struct Quad {
|
||||||
|
|
|
@ -4,6 +4,7 @@ pub struct BindLayouts {
|
||||||
pub transforms: wgpu::BindGroupLayout,
|
pub transforms: wgpu::BindGroupLayout,
|
||||||
pub bitmap: wgpu::BindGroupLayout,
|
pub bitmap: wgpu::BindGroupLayout,
|
||||||
pub gradient: wgpu::BindGroupLayout,
|
pub gradient: wgpu::BindGroupLayout,
|
||||||
|
pub blend: wgpu::BindGroupLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BindLayouts {
|
impl BindLayouts {
|
||||||
|
@ -71,6 +72,49 @@ impl BindLayouts {
|
||||||
label: bitmap_bind_layout_label.as_deref(),
|
label: bitmap_bind_layout_label.as_deref(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let blend_bind_layout_label = create_debug_label!("Blend bind group layout");
|
||||||
|
let blend = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
multisampled: false,
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: false },
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 1,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
multisampled: false,
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: false },
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 2,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 3,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: None,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
label: blend_bind_layout_label.as_deref(),
|
||||||
|
});
|
||||||
|
|
||||||
let gradient_bind_layout_label = create_debug_label!("Gradient shape bind group");
|
let gradient_bind_layout_label = create_debug_label!("Gradient shape bind group");
|
||||||
let gradient = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let gradient = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
entries: &[
|
entries: &[
|
||||||
|
@ -107,6 +151,7 @@ impl BindLayouts {
|
||||||
transforms,
|
transforms,
|
||||||
bitmap,
|
bitmap,
|
||||||
gradient,
|
gradient,
|
||||||
|
blend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub struct Pipelines {
|
||||||
pub color: ShapePipeline,
|
pub color: ShapePipeline,
|
||||||
pub bitmap: ShapePipeline,
|
pub bitmap: ShapePipeline,
|
||||||
pub gradient: ShapePipeline,
|
pub gradient: ShapePipeline,
|
||||||
|
pub blend: ShapePipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShapePipeline {
|
impl ShapePipeline {
|
||||||
|
@ -64,6 +65,7 @@ impl Pipelines {
|
||||||
msaa_sample_count,
|
msaa_sample_count,
|
||||||
&VERTEX_BUFFERS_DESCRIPTION,
|
&VERTEX_BUFFERS_DESCRIPTION,
|
||||||
&[&bind_layouts.globals, &bind_layouts.transforms],
|
&[&bind_layouts.globals, &bind_layouts.transforms],
|
||||||
|
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
||||||
);
|
);
|
||||||
|
|
||||||
let bitmap_pipelines = create_shape_pipeline(
|
let bitmap_pipelines = create_shape_pipeline(
|
||||||
|
@ -78,6 +80,7 @@ impl Pipelines {
|
||||||
&bind_layouts.transforms,
|
&bind_layouts.transforms,
|
||||||
&bind_layouts.bitmap,
|
&bind_layouts.bitmap,
|
||||||
],
|
],
|
||||||
|
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
||||||
);
|
);
|
||||||
|
|
||||||
let gradient_pipelines = create_shape_pipeline(
|
let gradient_pipelines = create_shape_pipeline(
|
||||||
|
@ -92,12 +95,29 @@ impl Pipelines {
|
||||||
&bind_layouts.transforms,
|
&bind_layouts.transforms,
|
||||||
&bind_layouts.gradient,
|
&bind_layouts.gradient,
|
||||||
],
|
],
|
||||||
|
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
||||||
|
);
|
||||||
|
|
||||||
|
let blend_pipeline = create_shape_pipeline(
|
||||||
|
"Blend",
|
||||||
|
device,
|
||||||
|
format,
|
||||||
|
&shaders.blend_shader,
|
||||||
|
msaa_sample_count,
|
||||||
|
&VERTEX_BUFFERS_DESCRIPTION,
|
||||||
|
&[
|
||||||
|
&bind_layouts.globals,
|
||||||
|
&bind_layouts.transforms,
|
||||||
|
&bind_layouts.blend,
|
||||||
|
],
|
||||||
|
wgpu::BlendState::REPLACE,
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
color: color_pipelines,
|
color: color_pipelines,
|
||||||
bitmap: bitmap_pipelines,
|
bitmap: bitmap_pipelines,
|
||||||
gradient: gradient_pipelines,
|
gradient: gradient_pipelines,
|
||||||
|
blend: blend_pipeline,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,6 +165,7 @@ fn create_pipeline_descriptor<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn create_shape_pipeline(
|
fn create_shape_pipeline(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
|
@ -153,6 +174,7 @@ fn create_shape_pipeline(
|
||||||
msaa_sample_count: u32,
|
msaa_sample_count: u32,
|
||||||
vertex_buffers_layout: &[wgpu::VertexBufferLayout<'_>],
|
vertex_buffers_layout: &[wgpu::VertexBufferLayout<'_>],
|
||||||
bind_group_layouts: &[&wgpu::BindGroupLayout],
|
bind_group_layouts: &[&wgpu::BindGroupLayout],
|
||||||
|
blend: wgpu::BlendState,
|
||||||
) -> ShapePipeline {
|
) -> ShapePipeline {
|
||||||
let pipeline_layout_label = create_debug_label!("{} shape pipeline layout", name);
|
let pipeline_layout_label = create_debug_label!("{} shape pipeline layout", name);
|
||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
@ -181,7 +203,7 @@ fn create_shape_pipeline(
|
||||||
}),
|
}),
|
||||||
&[Some(wgpu::ColorTargetState {
|
&[Some(wgpu::ColorTargetState {
|
||||||
format,
|
format,
|
||||||
blend: Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING),
|
blend: Some(blend),
|
||||||
write_mask,
|
write_mask,
|
||||||
})],
|
})],
|
||||||
vertex_buffers_layout,
|
vertex_buffers_layout,
|
||||||
|
|
|
@ -5,6 +5,7 @@ pub struct Shaders {
|
||||||
pub gradient_shader: wgpu::ShaderModule,
|
pub gradient_shader: wgpu::ShaderModule,
|
||||||
pub copy_srgb_shader: wgpu::ShaderModule,
|
pub copy_srgb_shader: wgpu::ShaderModule,
|
||||||
pub copy_shader: wgpu::ShaderModule,
|
pub copy_shader: wgpu::ShaderModule,
|
||||||
|
pub blend_shader: wgpu::ShaderModule,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shaders {
|
impl Shaders {
|
||||||
|
@ -23,6 +24,7 @@ impl Shaders {
|
||||||
include_str!("../shaders/copy_srgb.wgsl"),
|
include_str!("../shaders/copy_srgb.wgsl"),
|
||||||
);
|
);
|
||||||
let copy_shader = create_shader(device, "copy", include_str!("../shaders/copy.wgsl"));
|
let copy_shader = create_shader(device, "copy", include_str!("../shaders/copy.wgsl"));
|
||||||
|
let blend_shader = create_shader(device, "blend", include_str!("../shaders/blend.wgsl"));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
color_shader,
|
color_shader,
|
||||||
|
@ -30,6 +32,7 @@ impl Shaders {
|
||||||
gradient_shader,
|
gradient_shader,
|
||||||
copy_srgb_shader,
|
copy_srgb_shader,
|
||||||
copy_shader,
|
copy_shader,
|
||||||
|
blend_shader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ impl FrameBuffer {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BlendBuffer {
|
pub struct BlendBuffer {
|
||||||
texture: wgpu::Texture,
|
texture: wgpu::Texture,
|
||||||
|
view: wgpu::TextureView,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlendBuffer {
|
impl BlendBuffer {
|
||||||
|
@ -117,8 +118,13 @@ impl BlendBuffer {
|
||||||
format,
|
format,
|
||||||
usage,
|
usage,
|
||||||
});
|
});
|
||||||
|
let view = texture.create_view(&Default::default());
|
||||||
|
|
||||||
Self { texture }
|
Self { texture, view }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view(&self) -> &wgpu::TextureView {
|
||||||
|
&self.view
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture(&self) -> &wgpu::Texture {
|
pub fn texture(&self) -> &wgpu::Texture {
|
||||||
|
|
Loading…
Reference in New Issue