wgpu: Use push constants for both Transforms and ColorAdjustments, when available

This commit is contained in:
Nathan Adams 2023-01-07 10:19:14 +01:00
parent fb78a39125
commit ae75a3c166
25 changed files with 289 additions and 171 deletions

3
Cargo.lock generated
View File

@ -2601,8 +2601,7 @@ dependencies = [
[[package]]
name = "naga_oil"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb65345f4889a991907548157b1861ec9fd5e5a696b1043d8999854e86e4c7d0"
source = "git+https://github.com/Dinnerbone/naga_oil?rev=c073f6fdf0560a74480140abc50295f9e0d9aa57#c073f6fdf0560a74480140abc50295f9e0d9aa57"
dependencies = [
"bit-set",
"codespan-reporting",

View File

@ -18,7 +18,7 @@ enum-map = "2.4.2"
fnv = "1.0.7"
swf = { path = "../../swf" }
image = { version = "0.24.5", default-features = false }
naga_oil = "0.4.2"
naga_oil = { git = "https://github.com/Dinnerbone/naga_oil", rev = "c073f6fdf0560a74480140abc50295f9e0d9aa57" }
ouroboros = "0.15.5"
typed-arena = "2.0.1"
once_cell = "1.17.0"

View File

@ -8,19 +8,23 @@ struct VertexOutput {
};
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
var<push_constant> pc: common::PushConstants;
@group(1) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(1) @binding(1) var texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@group(3) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(3) @binding(1) var texture: texture_2d<f32>;
@group(3) @binding(2) var texture_sampler: sampler;
#endif
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@group(3) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(3) @binding(1) var texture: texture_2d<f32>;
@group(3) @binding(2) var texture_sampler: sampler;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
#if use_push_constants == true
var transforms = pc.transforms;
#endif
let matrix_ = textureTransforms.matrix_;
let uv = (mat3x3<f32>(matrix_[0].xyz, matrix_[1].xyz, matrix_[2].xyz) * vec3<f32>(in.position, 1.0)).xy;
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
@ -30,6 +34,9 @@ fn main_vertex(in: common::VertexInput) -> VertexOutput {
@fragment
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
var color: vec4<f32> = textureSample(texture, texture_sampler, in.uv);
#if use_push_constants == true
var colorTransforms = pc.colorTransforms;
#endif
// Texture is premultiplied by alpha.
// Unmultiply alpha, apply color transform, remultiply alpha.
if( color.a > 0.0 ) {

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
@group(1) @binding(1) var current_texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@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;
#endif
@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;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);

View File

@ -8,22 +8,32 @@ struct VertexOutput {
};
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
var<push_constant> pc: common::PushConstants;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
#endif
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
#if use_push_constants == true
var transforms = pc.transforms;
#endif
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let color = in.color * colorTransforms.mult_color + colorTransforms.add_color;
let alpha = clamp(color.a, 0.0, 1.0);
return VertexOutput(pos, vec4<f32>(color.rgb * alpha, alpha));
return VertexOutput(pos, in.color);
}
@fragment
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
return in.color;
var color = in.color;
#if use_push_constants == true
var colorTransforms = pc.colorTransforms;
#endif
if( color.a > 0.0 ) {
color = vec4<f32>(color.rgb / color.a, color.a);
color = color * colorTransforms.mult_color + colorTransforms.add_color;
let alpha = clamp(color.a, 0.0, 1.0);
color = vec4<f32>(color.rgb * alpha, alpha);
}
return color;
}

View File

@ -31,6 +31,11 @@ struct TextureTransforms {
matrix_: mat4x4<f32>,
};
struct PushConstants {
transforms: Transforms,
colorTransforms: ColorTransforms,
}
/// The vertex format shared among all shaders.
struct VertexInput {
/// The position of the vertex in object space.

View File

@ -9,14 +9,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(1) @binding(1) var texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@group(2) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(2) @binding(1) var texture: texture_2d<f32>;
@group(2) @binding(2) var texture_sampler: sampler;
#endif
@group(2) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(2) @binding(1) var texture: texture_2d<f32>;
@group(2) @binding(2) var texture_sampler: sampler;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let matrix_ = textureTransforms.matrix_;

View File

@ -9,14 +9,16 @@ struct VertexOutput {
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
@group(1) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(1) @binding(1) var texture: texture_2d<f32>;
@group(1) @binding(2) var texture_sampler: sampler;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@group(2) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(2) @binding(1) var texture: texture_2d<f32>;
@group(2) @binding(2) var texture_sampler: sampler;
#endif
@group(2) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
@group(2) @binding(1) var texture: texture_2d<f32>;
@group(2) @binding(2) var texture_sampler: sampler;
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
let matrix_ = textureTransforms.matrix_;

View File

@ -7,15 +7,14 @@ struct VertexOutput {
};
#if use_push_constants == true
var<push_constant> transforms: common::Transforms;
var<push_constant> pc: common::PushConstants;
@group(1) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
#else
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@group(3) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
#endif
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@group(3) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
#if use_storage_buffers == true
struct Gradient {
colors: array<vec4<f32>,16u>,
@ -26,7 +25,11 @@ struct VertexOutput {
focal_point: f32,
};
#if use_push_constants == true
@group(1) @binding(1) var<storage> gradient: Gradient;
#else
@group(3) @binding(1) var<storage> gradient: Gradient;
#endif
fn ratio(i: u32) -> f32 {
return gradient.ratios[i];
@ -41,7 +44,11 @@ struct VertexOutput {
focal_point: f32,
};
#if use_push_constants == true
@group(1) @binding(1) var<uniform> gradient: Gradient;
#else
@group(3) @binding(1) var<uniform> gradient: Gradient;
#endif
fn ratio(i: u32) -> f32 {
return gradient.ratios[i / 4u][i % 4u];
@ -54,6 +61,9 @@ fn find_t(focal_point: f32, uv: vec2<f32>) -> f32 {
@vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput {
#if use_push_constants == true
var transforms = pc.transforms;
#endif
let matrix_ = textureTransforms.matrix_;
let uv = (mat3x3<f32>(matrix_[0].xyz, matrix_[1].xyz, matrix_[2].xyz) * vec3<f32>(in.position, 1.0)).xy;
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
@ -62,6 +72,9 @@ fn main_vertex(in: common::VertexInput) -> VertexOutput {
@fragment
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
#if use_push_constants == true
var colorTransforms = pc.colorTransforms;
#endif
let last = gradient.num_colors - 1u;
// Calculate normalized `t` position in gradient, [0.0, 1.0] being the bounds of the ratios.

View File

@ -637,10 +637,11 @@ async fn request_device(
limits.max_storage_buffer_binding_size = adapter.limits().max_storage_buffer_binding_size;
let mut features = Default::default();
let needed_size = (mem::size_of::<Transforms>() + mem::size_of::<ColorAdjustments>()) as u32;
if adapter.features().contains(wgpu::Features::PUSH_CONSTANTS)
&& adapter.limits().max_push_constant_size >= mem::size_of::<Transforms>() as u32
&& adapter.limits().max_push_constant_size >= needed_size
{
limits.max_push_constant_size = mem::size_of::<Transforms>() as u32;
limits.max_push_constant_size = needed_size;
features |= wgpu::Features::PUSH_CONSTANTS;
}

View File

@ -22,7 +22,6 @@ pub struct Descriptors {
shaders: Shaders,
pipelines: Mutex<FnvHashMap<(u32, wgpu::TextureFormat), Arc<Pipelines>>>,
pub default_color_bind_group: wgpu::BindGroup,
pub empty_bind_group: wgpu::BindGroup,
}
impl Descriptors {
@ -47,12 +46,6 @@ impl Descriptors {
}],
});
let empty_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bind_layouts.transforms,
entries: &[],
});
Self {
adapter,
device,
@ -66,7 +59,6 @@ impl Descriptors {
shaders,
pipelines: Default::default(),
default_color_bind_group,
empty_bind_group,
}
}
@ -83,11 +75,15 @@ impl Descriptors {
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: create_debug_label!("Copy sRGB pipeline layout").as_deref(),
bind_group_layouts: &[
bind_group_layouts: &if self.limits.max_push_constant_size > 0 {
vec![&self.bind_layouts.globals, &self.bind_layouts.bitmap]
} else {
vec![
&self.bind_layouts.globals,
&self.bind_layouts.transforms,
&self.bind_layouts.bitmap,
],
]
},
push_constant_ranges: if self.device.limits().max_push_constant_size > 0
{
&[wgpu::PushConstantRange {
@ -152,11 +148,15 @@ impl Descriptors {
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: create_debug_label!("Copy pipeline layout").as_deref(),
bind_group_layouts: &[
bind_group_layouts: &if self.limits.max_push_constant_size > 0 {
vec![&self.bind_layouts.globals, &self.bind_layouts.bitmap]
} else {
vec![
&self.bind_layouts.globals,
&self.bind_layouts.transforms,
&self.bind_layouts.bitmap,
],
]
},
push_constant_ranges: if self.device.limits().max_push_constant_size > 0
{
&[wgpu::PushConstantRange {

View File

@ -14,13 +14,7 @@ pub struct BindLayouts {
impl BindLayouts {
pub fn new(device: &wgpu::Device) -> Self {
let uniform_buffer_layout_label = create_debug_label!("Uniform buffer bind group layout");
let transforms = if device.limits().max_storage_buffers_per_shader_stage > 0 {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[],
label: uniform_buffer_layout_label.as_deref(),
})
} else {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
let transforms = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
@ -34,13 +28,12 @@ impl BindLayouts {
count: None,
}],
label: uniform_buffer_layout_label.as_deref(),
})
};
});
let color_transforms = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: true,

View File

@ -52,6 +52,13 @@ pub enum MaskState {
ClearMaskStencil,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
pub struct PushConstants {
transforms: Transforms,
colors: ColorAdjustments,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
pub struct Transforms {

View File

@ -1,7 +1,7 @@
use crate::blend::{ComplexBlend, TrivialBlend};
use crate::layouts::BindLayouts;
use crate::shaders::Shaders;
use crate::{MaskState, Transforms, Vertex};
use crate::{MaskState, PushConstants, Transforms, Vertex};
use enum_map::{enum_map, Enum, EnumMap};
use ruffle_render::tessellator::GradientType;
use std::mem;
@ -70,6 +70,34 @@ impl Pipelines {
msaa_sample_count: u32,
bind_layouts: &BindLayouts,
) -> Self {
let colort_bindings = if device.limits().max_push_constant_size > 0 {
vec![&bind_layouts.globals]
} else {
vec![
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.color_transforms,
]
};
let full_push_constants = &if device.limits().max_push_constant_size > 0 {
vec![wgpu::PushConstantRange {
stages: wgpu::ShaderStages::VERTEX_FRAGMENT,
range: 0..mem::size_of::<PushConstants>() as u32,
}]
} else {
vec![]
};
let partial_push_constants = &if device.limits().max_push_constant_size > 0 {
vec![wgpu::PushConstantRange {
stages: wgpu::ShaderStages::VERTEX,
range: 0..(mem::size_of::<Transforms>() as u32),
}]
} else {
vec![]
};
let color_pipelines = create_shape_pipeline(
"Color",
device,
@ -77,13 +105,21 @@ impl Pipelines {
&shaders.color_shader,
msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION,
&[
&colort_bindings,
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
&full_push_constants,
);
let gradient_bindings = if device.limits().max_push_constant_size > 0 {
vec![&bind_layouts.globals, &bind_layouts.gradient]
} else {
vec![
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.color_transforms,
],
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
);
&bind_layouts.gradient,
]
};
let gradient_pipelines = enum_map! {
mode => enum_map! {
@ -94,17 +130,23 @@ impl Pipelines {
&shaders.gradient_shaders[mode][spread],
msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION,
&[
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.color_transforms,
&bind_layouts.gradient,
],
&gradient_bindings,
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
&full_push_constants,
)
}
};
let complex_blend_bindings = if device.limits().max_push_constant_size > 0 {
vec![&bind_layouts.globals, &bind_layouts.blend]
} else {
vec![
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.blend,
]
};
let complex_blend_pipelines = enum_map! {
blend => create_shape_pipeline(
&format!("Complex Blend: {blend:?}"),
@ -113,13 +155,21 @@ impl Pipelines {
&shaders.blend_shaders[blend],
msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION,
&[
&complex_blend_bindings,
wgpu::BlendState::REPLACE,
&partial_push_constants,
)
};
let bitmap_blend_bindings = if device.limits().max_push_constant_size > 0 {
vec![&bind_layouts.globals, &bind_layouts.bitmap]
} else {
vec![
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.blend,
],
wgpu::BlendState::REPLACE,
)
&bind_layouts.color_transforms,
&bind_layouts.bitmap,
]
};
let bitmap_pipelines: [ShapePipeline; TrivialBlend::LENGTH] = (0..TrivialBlend::LENGTH)
@ -133,13 +183,9 @@ impl Pipelines {
&shaders.bitmap_shader,
msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION,
&[
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.color_transforms,
&bind_layouts.bitmap,
],
&bitmap_blend_bindings,
blend.blend_state(),
&full_push_constants,
)
})
.collect::<Vec<_>>()
@ -208,19 +254,13 @@ fn create_shape_pipeline(
vertex_buffers_layout: &[wgpu::VertexBufferLayout<'_>],
bind_group_layouts: &[&wgpu::BindGroupLayout],
blend: wgpu::BlendState,
push_constant_ranges: &[wgpu::PushConstantRange],
) -> ShapePipeline {
let pipeline_layout_label = create_debug_label!("{} shape pipeline layout", name);
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: pipeline_layout_label.as_deref(),
bind_group_layouts,
push_constant_ranges: if device.limits().max_push_constant_size > 0 {
&[wgpu::PushConstantRange {
stages: wgpu::ShaderStages::VERTEX,
range: 0..(mem::size_of::<Transforms>() as u32),
}]
} else {
&[]
},
push_constant_ranges,
});
let mask_render_state = |mask_name, stencil_state, write_mask| {

View File

@ -148,7 +148,6 @@ impl Surface {
render_pass.set_bind_group(0, target.globals().bind_group(), &[]);
if descriptors.limits.max_push_constant_size > 0 {
render_pass.set_bind_group(1, &descriptors.empty_bind_group, &[]);
render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX,
0,
@ -161,11 +160,11 @@ impl Surface {
],
}]),
);
render_pass.set_bind_group(1, &copy_bind_group, &[]);
} else {
render_pass.set_bind_group(1, target.whole_frame_bind_group(descriptors), &[0]);
}
render_pass.set_bind_group(2, &copy_bind_group, &[]);
}
render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..));
render_pass.set_index_buffer(
@ -355,7 +354,6 @@ impl Surface {
}
if descriptors.limits.max_push_constant_size > 0 {
render_pass.set_bind_group(1, &descriptors.empty_bind_group, &[]);
render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX,
0,
@ -368,15 +366,15 @@ impl Surface {
],
}]),
);
render_pass.set_bind_group(1, &blend_bind_group, &[]);
} else {
render_pass.set_bind_group(
1,
target.whole_frame_bind_group(descriptors),
&[0],
);
}
render_pass.set_bind_group(2, &blend_bind_group, &[]);
}
render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..));
render_pass.set_index_buffer(

View File

@ -5,7 +5,8 @@ use crate::mesh::{DrawType, Mesh};
use crate::surface::target::CommandTarget;
use crate::surface::Surface;
use crate::{
as_texture, ColorAdjustments, Descriptors, MaskState, Pipelines, Transforms, UniformBuffer,
as_texture, ColorAdjustments, Descriptors, MaskState, Pipelines, PushConstants, Transforms,
UniformBuffer,
};
use ruffle_render::backend::ShapeHandle;
use ruffle_render::bitmap::BitmapHandle;
@ -119,7 +120,15 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
.set_pipeline(self.pipelines.gradients[mode][spread].depthless_pipeline());
}
self.render_pass.set_bind_group(3, bind_group, &[]);
self.render_pass.set_bind_group(
if self.descriptors.limits.max_push_constant_size > 0 {
1
} else {
3
},
bind_group,
&[],
);
}
pub fn prep_bitmap(&mut self, bind_group: &'pass wgpu::BindGroup, blend_mode: TrivialBlend) {
@ -131,7 +140,15 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
.set_pipeline(self.pipelines.bitmap[blend_mode].depthless_pipeline());
}
self.render_pass.set_bind_group(3, bind_group, &[]);
self.render_pass.set_bind_group(
if self.descriptors.limits.max_push_constant_size > 0 {
1
} else {
3
},
bind_group,
&[],
);
}
pub fn draw(
@ -161,12 +178,13 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
];
if self.descriptors.limits.max_push_constant_size > 0 {
self.render_pass
.set_bind_group(1, &self.descriptors.empty_bind_group, &[]);
self.render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX,
wgpu::ShaderStages::VERTEX_FRAGMENT,
0,
bytemuck::cast_slice(&[Transforms { world_matrix }]),
bytemuck::cast_slice(&[PushConstants {
transforms: Transforms { world_matrix },
colors: ColorAdjustments::from(*color_adjustments),
}]),
);
} else {
self.uniform_buffers.write_uniforms(
@ -177,11 +195,13 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
1,
&Transforms { world_matrix },
);
}
if color_adjustments == &ColorTransform::IDENTITY {
self.render_pass
.set_bind_group(2, &self.descriptors.default_color_bind_group, &[0]);
self.render_pass.set_bind_group(
2,
&self.descriptors.default_color_bind_group,
&[0],
);
} else {
self.color_buffers.write_uniforms(
&self.descriptors.device,
@ -193,6 +213,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
);
}
}
}
pub fn render_bitmap(
&mut self,