diff --git a/Cargo.lock b/Cargo.lock index 408aeee9e..7019f3b08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/render/wgpu/Cargo.toml b/render/wgpu/Cargo.toml index 624a77159..a910e7f74 100644 --- a/render/wgpu/Cargo.toml +++ b/render/wgpu/Cargo.toml @@ -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" diff --git a/render/wgpu/shaders/bitmap.wgsl b/render/wgpu/shaders/bitmap.wgsl index ba9d69e28..517fc682f 100644 --- a/render/wgpu/shaders/bitmap.wgsl +++ b/render/wgpu/shaders/bitmap.wgsl @@ -8,19 +8,23 @@ struct VertexOutput { }; #if use_push_constants == true - var transforms: common::Transforms; + var pc: common::PushConstants; + @group(1) @binding(0) var textureTransforms: common::TextureTransforms; + @group(1) @binding(1) var texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var colorTransforms: common::ColorTransforms; + @group(3) @binding(0) var textureTransforms: common::TextureTransforms; + @group(3) @binding(1) var texture: texture_2d; + @group(3) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var colorTransforms: common::ColorTransforms; - -@group(3) @binding(0) var textureTransforms: common::TextureTransforms; -@group(3) @binding(1) var texture: texture_2d; -@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(matrix_[0].xyz, matrix_[1].xyz, matrix_[2].xyz) * vec3(in.position, 1.0)).xy; let pos = common::globals.view_matrix * transforms.world_matrix * vec4(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 { var color: vec4 = 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 ) { diff --git a/render/wgpu/shaders/blend/alpha.wgsl b/render/wgpu/shaders/blend/alpha.wgsl index 22a586021..f6a9a252e 100644 --- a/render/wgpu/shaders/blend/alpha.wgsl +++ b/render/wgpu/shaders/blend/alpha.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/darken.wgsl b/render/wgpu/shaders/blend/darken.wgsl index ec3eae548..6c8a05f88 100644 --- a/render/wgpu/shaders/blend/darken.wgsl +++ b/render/wgpu/shaders/blend/darken.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/difference.wgsl b/render/wgpu/shaders/blend/difference.wgsl index c3f605c92..bb807878c 100644 --- a/render/wgpu/shaders/blend/difference.wgsl +++ b/render/wgpu/shaders/blend/difference.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/erase.wgsl b/render/wgpu/shaders/blend/erase.wgsl index 5ebe22394..c7f055a7f 100644 --- a/render/wgpu/shaders/blend/erase.wgsl +++ b/render/wgpu/shaders/blend/erase.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/hardlight.wgsl b/render/wgpu/shaders/blend/hardlight.wgsl index 3a35cc440..d41c5f0f2 100644 --- a/render/wgpu/shaders/blend/hardlight.wgsl +++ b/render/wgpu/shaders/blend/hardlight.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/invert.wgsl b/render/wgpu/shaders/blend/invert.wgsl index bd92f1191..f9fd41740 100644 --- a/render/wgpu/shaders/blend/invert.wgsl +++ b/render/wgpu/shaders/blend/invert.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/lighten.wgsl b/render/wgpu/shaders/blend/lighten.wgsl index 33cbd9a3c..19e642f3a 100644 --- a/render/wgpu/shaders/blend/lighten.wgsl +++ b/render/wgpu/shaders/blend/lighten.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/multiply.wgsl b/render/wgpu/shaders/blend/multiply.wgsl index 100f592be..986448fc7 100644 --- a/render/wgpu/shaders/blend/multiply.wgsl +++ b/render/wgpu/shaders/blend/multiply.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/overlay.wgsl b/render/wgpu/shaders/blend/overlay.wgsl index afc98c18a..064428e87 100644 --- a/render/wgpu/shaders/blend/overlay.wgsl +++ b/render/wgpu/shaders/blend/overlay.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/blend/screen.wgsl b/render/wgpu/shaders/blend/screen.wgsl index 26f27b3f4..de49bef77 100644 --- a/render/wgpu/shaders/blend/screen.wgsl +++ b/render/wgpu/shaders/blend/screen.wgsl @@ -7,14 +7,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var parent_texture: texture_2d; + @group(1) @binding(1) var current_texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var parent_texture: texture_2d; + @group(2) @binding(1) var current_texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var parent_texture: texture_2d; -@group(2) @binding(1) var current_texture: texture_2d; -@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(in.position.x, in.position.y, 1.0, 1.0); diff --git a/render/wgpu/shaders/color.wgsl b/render/wgpu/shaders/color.wgsl index 71edf5968..ed68519f9 100644 --- a/render/wgpu/shaders/color.wgsl +++ b/render/wgpu/shaders/color.wgsl @@ -8,22 +8,32 @@ struct VertexOutput { }; #if use_push_constants == true - var transforms: common::Transforms; + var pc: common::PushConstants; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var colorTransforms: common::ColorTransforms; #endif -@group(2) @binding(0) var 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(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(color.rgb * alpha, alpha)); + return VertexOutput(pos, in.color); } @fragment fn main_fragment(in: VertexOutput) -> @location(0) vec4 { - return in.color; + var color = in.color; + #if use_push_constants == true + var colorTransforms = pc.colorTransforms; + #endif + if( color.a > 0.0 ) { + color = vec4(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(color.rgb * alpha, alpha); + } + return color; } diff --git a/render/wgpu/shaders/common.wgsl b/render/wgpu/shaders/common.wgsl index 3c50dd976..67fa3579c 100644 --- a/render/wgpu/shaders/common.wgsl +++ b/render/wgpu/shaders/common.wgsl @@ -31,6 +31,11 @@ struct TextureTransforms { matrix_: mat4x4, }; +struct PushConstants { + transforms: Transforms, + colorTransforms: ColorTransforms, +} + /// The vertex format shared among all shaders. struct VertexInput { /// The position of the vertex in object space. diff --git a/render/wgpu/shaders/copy.wgsl b/render/wgpu/shaders/copy.wgsl index 171dd2283..25bc66cce 100644 --- a/render/wgpu/shaders/copy.wgsl +++ b/render/wgpu/shaders/copy.wgsl @@ -9,14 +9,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var textureTransforms: common::TextureTransforms; + @group(1) @binding(1) var texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var textureTransforms: common::TextureTransforms; + @group(2) @binding(1) var texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var textureTransforms: common::TextureTransforms; -@group(2) @binding(1) var texture: texture_2d; -@group(2) @binding(2) var texture_sampler: sampler; - @vertex fn main_vertex(in: common::VertexInput) -> VertexOutput { let matrix_ = textureTransforms.matrix_; diff --git a/render/wgpu/shaders/copy_srgb.wgsl b/render/wgpu/shaders/copy_srgb.wgsl index fe8a1b918..3049bba8c 100644 --- a/render/wgpu/shaders/copy_srgb.wgsl +++ b/render/wgpu/shaders/copy_srgb.wgsl @@ -9,14 +9,16 @@ struct VertexOutput { #if use_push_constants == true var transforms: common::Transforms; + @group(1) @binding(0) var textureTransforms: common::TextureTransforms; + @group(1) @binding(1) var texture: texture_2d; + @group(1) @binding(2) var texture_sampler: sampler; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var textureTransforms: common::TextureTransforms; + @group(2) @binding(1) var texture: texture_2d; + @group(2) @binding(2) var texture_sampler: sampler; #endif -@group(2) @binding(0) var textureTransforms: common::TextureTransforms; -@group(2) @binding(1) var texture: texture_2d; -@group(2) @binding(2) var texture_sampler: sampler; - @vertex fn main_vertex(in: common::VertexInput) -> VertexOutput { let matrix_ = textureTransforms.matrix_; diff --git a/render/wgpu/shaders/gradient/common.wgsl b/render/wgpu/shaders/gradient/common.wgsl index fb589dd51..49ede3932 100644 --- a/render/wgpu/shaders/gradient/common.wgsl +++ b/render/wgpu/shaders/gradient/common.wgsl @@ -7,15 +7,14 @@ struct VertexOutput { }; #if use_push_constants == true - var transforms: common::Transforms; + var pc: common::PushConstants; + @group(1) @binding(0) var textureTransforms: common::TextureTransforms; #else @group(1) @binding(0) var transforms: common::Transforms; + @group(2) @binding(0) var colorTransforms: common::ColorTransforms; + @group(3) @binding(0) var textureTransforms: common::TextureTransforms; #endif -@group(2) @binding(0) var colorTransforms: common::ColorTransforms; - -@group(3) @binding(0) var textureTransforms: common::TextureTransforms; - #if use_storage_buffers == true struct Gradient { colors: array,16u>, @@ -26,7 +25,11 @@ struct VertexOutput { focal_point: f32, }; - @group(3) @binding(1) var gradient: Gradient; + #if use_push_constants == true + @group(1) @binding(1) var gradient: Gradient; + #else + @group(3) @binding(1) var gradient: Gradient; + #endif fn ratio(i: u32) -> f32 { return gradient.ratios[i]; @@ -41,7 +44,11 @@ struct VertexOutput { focal_point: f32, }; - @group(3) @binding(1) var gradient: Gradient; + #if use_push_constants == true + @group(1) @binding(1) var gradient: Gradient; + #else + @group(3) @binding(1) var 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 { @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(matrix_[0].xyz, matrix_[1].xyz, matrix_[2].xyz) * vec3(in.position, 1.0)).xy; let pos = common::globals.view_matrix * transforms.world_matrix * vec4(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 { + #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. diff --git a/render/wgpu/src/backend.rs b/render/wgpu/src/backend.rs index b8483bc25..eff12f73d 100644 --- a/render/wgpu/src/backend.rs +++ b/render/wgpu/src/backend.rs @@ -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::() + mem::size_of::()) as u32; if adapter.features().contains(wgpu::Features::PUSH_CONSTANTS) - && adapter.limits().max_push_constant_size >= mem::size_of::() as u32 + && adapter.limits().max_push_constant_size >= needed_size { - limits.max_push_constant_size = mem::size_of::() as u32; + limits.max_push_constant_size = needed_size; features |= wgpu::Features::PUSH_CONSTANTS; } diff --git a/render/wgpu/src/descriptors.rs b/render/wgpu/src/descriptors.rs index 5542ee361..4275148de 100644 --- a/render/wgpu/src/descriptors.rs +++ b/render/wgpu/src/descriptors.rs @@ -22,7 +22,6 @@ pub struct Descriptors { shaders: Shaders, pipelines: Mutex>>, 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: &[ - &self.bind_layouts.globals, - &self.bind_layouts.transforms, - &self.bind_layouts.bitmap, - ], + 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: &[ - &self.bind_layouts.globals, - &self.bind_layouts.transforms, - &self.bind_layouts.bitmap, - ], + 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 { diff --git a/render/wgpu/src/layouts.rs b/render/wgpu/src/layouts.rs index 1402ab857..00e791b98 100644 --- a/render/wgpu/src/layouts.rs +++ b/render/wgpu/src/layouts.rs @@ -14,33 +14,26 @@ 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 { - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: true, - min_binding_size: wgpu::BufferSize::new( - std::mem::size_of::() as u64 - ), - }, - count: None, - }], - label: uniform_buffer_layout_label.as_deref(), - }) - }; + let transforms = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: wgpu::BufferSize::new( + std::mem::size_of::() as u64 + ), + }, + 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, diff --git a/render/wgpu/src/lib.rs b/render/wgpu/src/lib.rs index 7eda65478..aa9462456 100644 --- a/render/wgpu/src/lib.rs +++ b/render/wgpu/src/lib.rs @@ -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 { diff --git a/render/wgpu/src/pipelines.rs b/render/wgpu/src/pipelines.rs index e4d871be8..919c56603 100644 --- a/render/wgpu/src/pipelines.rs +++ b/render/wgpu/src/pipelines.rs @@ -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::() 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::() 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,15 +155,23 @@ impl Pipelines { &shaders.blend_shaders[blend], msaa_sample_count, &VERTEX_BUFFERS_DESCRIPTION, - &[ - &bind_layouts.globals, - &bind_layouts.transforms, - &bind_layouts.blend, - ], + &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.color_transforms, + &bind_layouts.bitmap, + ] + }; + let bitmap_pipelines: [ShapePipeline; TrivialBlend::LENGTH] = (0..TrivialBlend::LENGTH) .map(|blend| { let blend = TrivialBlend::from_usize(blend); @@ -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::>() @@ -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::() as u32), - }] - } else { - &[] - }, + push_constant_ranges, }); let mask_render_state = |mask_name, stencil_state, write_mask| { diff --git a/render/wgpu/src/surface.rs b/render/wgpu/src/surface.rs index 537d55d9c..1a6853070 100644 --- a/render/wgpu/src/surface.rs +++ b/render/wgpu/src/surface.rs @@ -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,12 +160,12 @@ impl Surface { ], }]), ); + render_pass.set_bind_group(1, ©_bind_group, &[]); } else { render_pass.set_bind_group(1, target.whole_frame_bind_group(descriptors), &[0]); + render_pass.set_bind_group(2, ©_bind_group, &[]); } - render_pass.set_bind_group(2, ©_bind_group, &[]); - render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..)); render_pass.set_index_buffer( descriptors.quad.indices.slice(..), @@ -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,16 +366,16 @@ 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_bind_group(2, &blend_bind_group, &[]); - render_pass.set_vertex_buffer(0, descriptors.quad.vertices.slice(..)); render_pass.set_index_buffer( descriptors.quad.indices.slice(..), diff --git a/render/wgpu/src/surface/commands.rs b/render/wgpu/src/surface/commands.rs index 58182d02c..7fa748119 100644 --- a/render/wgpu/src/surface/commands.rs +++ b/render/wgpu/src/surface/commands.rs @@ -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,20 +195,23 @@ 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]); - } else { - self.color_buffers.write_uniforms( - &self.descriptors.device, - &self.descriptors.bind_layouts.color_transforms, - &mut self.uniform_encoder, - &mut self.render_pass, - 2, - &ColorAdjustments::from(*color_adjustments), - ); + if color_adjustments == &ColorTransform::IDENTITY { + self.render_pass.set_bind_group( + 2, + &self.descriptors.default_color_bind_group, + &[0], + ); + } else { + self.color_buffers.write_uniforms( + &self.descriptors.device, + &self.descriptors.bind_layouts.color_transforms, + &mut self.uniform_encoder, + &mut self.render_pass, + 2, + &ColorAdjustments::from(*color_adjustments), + ); + } } }