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

View File

@ -18,7 +18,7 @@ enum-map = "2.4.2"
fnv = "1.0.7" fnv = "1.0.7"
swf = { path = "../../swf" } swf = { path = "../../swf" }
image = { version = "0.24.5", default-features = false } 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" ouroboros = "0.15.5"
typed-arena = "2.0.1" typed-arena = "2.0.1"
once_cell = "1.17.0" once_cell = "1.17.0"

View File

@ -8,19 +8,23 @@ struct VertexOutput {
}; };
#if use_push_constants == true #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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { fn main_vertex(in: common::VertexInput) -> VertexOutput {
#if use_push_constants == true
var transforms = pc.transforms;
#endif
let matrix_ = textureTransforms.matrix_; 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 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); 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 @fragment
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> { fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
var color: vec4<f32> = textureSample(texture, texture_sampler, in.uv); 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. // Texture is premultiplied by alpha.
// Unmultiply alpha, apply color transform, remultiply alpha. // Unmultiply alpha, apply color transform, remultiply alpha.
if( color.a > 0.0 ) { if( color.a > 0.0 ) {

View File

@ -7,14 +7,16 @@ struct VertexOutput {
#if use_push_constants == true #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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); 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 #if use_push_constants == true
var<push_constant> transforms: common::Transforms; var<push_constant> pc: common::PushConstants;
#else #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @group(1) @binding(0) var<uniform> transforms: common::Transforms;
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
#endif #endif
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@vertex @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { 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 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; return VertexOutput(pos, in.color);
let alpha = clamp(color.a, 0.0, 1.0);
return VertexOutput(pos, vec4<f32>(color.rgb * alpha, alpha));
} }
@fragment @fragment
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> { 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>, matrix_: mat4x4<f32>,
}; };
struct PushConstants {
transforms: Transforms,
colorTransforms: ColorTransforms,
}
/// The vertex format shared among all shaders. /// The vertex format shared among all shaders.
struct VertexInput { struct VertexInput {
/// The position of the vertex in object space. /// The position of the vertex in object space.

View File

@ -9,14 +9,16 @@ struct VertexOutput {
#if use_push_constants == true #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { fn main_vertex(in: common::VertexInput) -> VertexOutput {
let matrix_ = textureTransforms.matrix_; let matrix_ = textureTransforms.matrix_;

View File

@ -9,14 +9,16 @@ struct VertexOutput {
#if use_push_constants == true #if use_push_constants == true
var<push_constant> transforms: common::Transforms; 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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #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 @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { fn main_vertex(in: common::VertexInput) -> VertexOutput {
let matrix_ = textureTransforms.matrix_; let matrix_ = textureTransforms.matrix_;

View File

@ -7,15 +7,14 @@ struct VertexOutput {
}; };
#if use_push_constants == true #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 #else
@group(1) @binding(0) var<uniform> transforms: common::Transforms; @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 #endif
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
@group(3) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
#if use_storage_buffers == true #if use_storage_buffers == true
struct Gradient { struct Gradient {
colors: array<vec4<f32>,16u>, colors: array<vec4<f32>,16u>,
@ -26,7 +25,11 @@ struct VertexOutput {
focal_point: f32, 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; @group(3) @binding(1) var<storage> gradient: Gradient;
#endif
fn ratio(i: u32) -> f32 { fn ratio(i: u32) -> f32 {
return gradient.ratios[i]; return gradient.ratios[i];
@ -41,7 +44,11 @@ struct VertexOutput {
focal_point: f32, 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; @group(3) @binding(1) var<uniform> gradient: Gradient;
#endif
fn ratio(i: u32) -> f32 { fn ratio(i: u32) -> f32 {
return gradient.ratios[i / 4u][i % 4u]; return gradient.ratios[i / 4u][i % 4u];
@ -54,6 +61,9 @@ fn find_t(focal_point: f32, uv: vec2<f32>) -> f32 {
@vertex @vertex
fn main_vertex(in: common::VertexInput) -> VertexOutput { fn main_vertex(in: common::VertexInput) -> VertexOutput {
#if use_push_constants == true
var transforms = pc.transforms;
#endif
let matrix_ = textureTransforms.matrix_; 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 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); 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 @fragment
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> { 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; let last = gradient.num_colors - 1u;
// Calculate normalized `t` position in gradient, [0.0, 1.0] being the bounds of the ratios. // 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; limits.max_storage_buffer_binding_size = adapter.limits().max_storage_buffer_binding_size;
let mut features = Default::default(); 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) 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; features |= wgpu::Features::PUSH_CONSTANTS;
} }

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use crate::blend::{ComplexBlend, TrivialBlend}; use crate::blend::{ComplexBlend, TrivialBlend};
use crate::layouts::BindLayouts; use crate::layouts::BindLayouts;
use crate::shaders::Shaders; use crate::shaders::Shaders;
use crate::{MaskState, Transforms, Vertex}; use crate::{MaskState, PushConstants, Transforms, Vertex};
use enum_map::{enum_map, Enum, EnumMap}; use enum_map::{enum_map, Enum, EnumMap};
use ruffle_render::tessellator::GradientType; use ruffle_render::tessellator::GradientType;
use std::mem; use std::mem;
@ -70,6 +70,34 @@ impl Pipelines {
msaa_sample_count: u32, msaa_sample_count: u32,
bind_layouts: &BindLayouts, bind_layouts: &BindLayouts,
) -> Self { ) -> 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( let color_pipelines = create_shape_pipeline(
"Color", "Color",
device, device,
@ -77,13 +105,21 @@ impl Pipelines {
&shaders.color_shader, &shaders.color_shader,
msaa_sample_count, msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION, &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.globals,
&bind_layouts.transforms, &bind_layouts.transforms,
&bind_layouts.color_transforms, &bind_layouts.color_transforms,
], &bind_layouts.gradient,
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING, ]
); };
let gradient_pipelines = enum_map! { let gradient_pipelines = enum_map! {
mode => enum_map! { mode => enum_map! {
@ -94,17 +130,23 @@ impl Pipelines {
&shaders.gradient_shaders[mode][spread], &shaders.gradient_shaders[mode][spread],
msaa_sample_count, msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION, &VERTEX_BUFFERS_DESCRIPTION,
&[ &gradient_bindings,
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.color_transforms,
&bind_layouts.gradient,
],
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING, 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! { let complex_blend_pipelines = enum_map! {
blend => create_shape_pipeline( blend => create_shape_pipeline(
&format!("Complex Blend: {blend:?}"), &format!("Complex Blend: {blend:?}"),
@ -113,13 +155,21 @@ impl Pipelines {
&shaders.blend_shaders[blend], &shaders.blend_shaders[blend],
msaa_sample_count, msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION, &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.globals,
&bind_layouts.transforms, &bind_layouts.transforms,
&bind_layouts.blend, &bind_layouts.color_transforms,
], &bind_layouts.bitmap,
wgpu::BlendState::REPLACE, ]
)
}; };
let bitmap_pipelines: [ShapePipeline; TrivialBlend::LENGTH] = (0..TrivialBlend::LENGTH) let bitmap_pipelines: [ShapePipeline; TrivialBlend::LENGTH] = (0..TrivialBlend::LENGTH)
@ -133,13 +183,9 @@ impl Pipelines {
&shaders.bitmap_shader, &shaders.bitmap_shader,
msaa_sample_count, msaa_sample_count,
&VERTEX_BUFFERS_DESCRIPTION, &VERTEX_BUFFERS_DESCRIPTION,
&[ &bitmap_blend_bindings,
&bind_layouts.globals,
&bind_layouts.transforms,
&bind_layouts.color_transforms,
&bind_layouts.bitmap,
],
blend.blend_state(), blend.blend_state(),
&full_push_constants,
) )
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -208,19 +254,13 @@ fn create_shape_pipeline(
vertex_buffers_layout: &[wgpu::VertexBufferLayout<'_>], vertex_buffers_layout: &[wgpu::VertexBufferLayout<'_>],
bind_group_layouts: &[&wgpu::BindGroupLayout], bind_group_layouts: &[&wgpu::BindGroupLayout],
blend: wgpu::BlendState, blend: wgpu::BlendState,
push_constant_ranges: &[wgpu::PushConstantRange],
) -> 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 {
label: pipeline_layout_label.as_deref(), label: pipeline_layout_label.as_deref(),
bind_group_layouts, bind_group_layouts,
push_constant_ranges: if device.limits().max_push_constant_size > 0 { push_constant_ranges,
&[wgpu::PushConstantRange {
stages: wgpu::ShaderStages::VERTEX,
range: 0..(mem::size_of::<Transforms>() as u32),
}]
} else {
&[]
},
}); });
let mask_render_state = |mask_name, stencil_state, write_mask| { 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(), &[]); render_pass.set_bind_group(0, target.globals().bind_group(), &[]);
if descriptors.limits.max_push_constant_size > 0 { if descriptors.limits.max_push_constant_size > 0 {
render_pass.set_bind_group(1, &descriptors.empty_bind_group, &[]);
render_pass.set_push_constants( render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX, wgpu::ShaderStages::VERTEX,
0, 0,
@ -161,11 +160,11 @@ impl Surface {
], ],
}]), }]),
); );
render_pass.set_bind_group(1, &copy_bind_group, &[]);
} else { } else {
render_pass.set_bind_group(1, target.whole_frame_bind_group(descriptors), &[0]); 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_bind_group(2, &copy_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(
@ -355,7 +354,6 @@ impl Surface {
} }
if descriptors.limits.max_push_constant_size > 0 { if descriptors.limits.max_push_constant_size > 0 {
render_pass.set_bind_group(1, &descriptors.empty_bind_group, &[]);
render_pass.set_push_constants( render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX, wgpu::ShaderStages::VERTEX,
0, 0,
@ -368,15 +366,15 @@ impl Surface {
], ],
}]), }]),
); );
render_pass.set_bind_group(1, &blend_bind_group, &[]);
} else { } else {
render_pass.set_bind_group( render_pass.set_bind_group(
1, 1,
target.whole_frame_bind_group(descriptors), target.whole_frame_bind_group(descriptors),
&[0], &[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_vertex_buffer(0, descriptors.quad.vertices.slice(..));
render_pass.set_index_buffer( render_pass.set_index_buffer(

View File

@ -5,7 +5,8 @@ use crate::mesh::{DrawType, Mesh};
use crate::surface::target::CommandTarget; use crate::surface::target::CommandTarget;
use crate::surface::Surface; use crate::surface::Surface;
use crate::{ 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::backend::ShapeHandle;
use ruffle_render::bitmap::BitmapHandle; 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()); .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) { 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()); .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( 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 { 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( self.render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX, wgpu::ShaderStages::VERTEX_FRAGMENT,
0, 0,
bytemuck::cast_slice(&[Transforms { world_matrix }]), bytemuck::cast_slice(&[PushConstants {
transforms: Transforms { world_matrix },
colors: ColorAdjustments::from(*color_adjustments),
}]),
); );
} else { } else {
self.uniform_buffers.write_uniforms( self.uniform_buffers.write_uniforms(
@ -177,11 +195,13 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
1, 1,
&Transforms { world_matrix }, &Transforms { world_matrix },
); );
}
if color_adjustments == &ColorTransform::IDENTITY { if color_adjustments == &ColorTransform::IDENTITY {
self.render_pass self.render_pass.set_bind_group(
.set_bind_group(2, &self.descriptors.default_color_bind_group, &[0]); 2,
&self.descriptors.default_color_bind_group,
&[0],
);
} else { } else {
self.color_buffers.write_uniforms( self.color_buffers.write_uniforms(
&self.descriptors.device, &self.descriptors.device,
@ -193,6 +213,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
); );
} }
} }
}
pub fn render_bitmap( pub fn render_bitmap(
&mut self, &mut self,