Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render: Implement more Pixelbender opcodes, and fix matrices #11896

Merged
merged 6 commits into from
Jul 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
608 changes: 422 additions & 186 deletions render/naga-pixelbender/src/lib.rs

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions render/src/pixel_bender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ pub struct PixelBenderReg {
pub kind: PixelBenderRegKind,
}

impl PixelBenderReg {
pub fn is_scalar(&self) -> bool {
self.channels.len() == 1
&& !matches!(
self.channels[0],
PixelBenderRegChannel::M2x2
| PixelBenderRegChannel::M3x3
| PixelBenderRegChannel::M4x4
)
}
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum PixelBenderRegKind {
Float,
Expand Down
2 changes: 2 additions & 0 deletions render/wgpu/src/pixel_bender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,8 @@ pub(super) fn run_pixelbender_shader_impl(
PixelBenderType::TInt4(i1, i2, i3, i4) => {
(vec![*i1 as f32, *i2 as f32, *i3 as f32, *i4 as f32], false)
}
// We treat the input as being in column-major order. Despite what the Flash docs claim,
// this seems to be what Flash Player does.
PixelBenderType::TFloat2x2(arr) => (arr.to_vec(), true),
PixelBenderType::TFloat3x3(arr) => {
// Add a zero after every 3 values to created zero-padded vec4s
Expand Down
Binary file not shown.
129 changes: 129 additions & 0 deletions tests/tests/swfs/avm2/pixelbender_effect_BlurredFocus/BlurredFocus.pbk
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<languageVersion : 1.0;>

kernel BlurredFocus
< namespace : "BlurredFocus";
vendor : "Paperless Post";
version : 1;
>
{
input image4 src;
output pixel4 dst;

parameter float4 bBox
<
minValue:float4(0.0,0.0,0.0,0.0);
maxValue:float4(1000.0,1000.0,1000.0,1000.0);
defaultValue:float4(0.0,600.0,0.0,400.0);
>;

parameter float2 center
<
minValue:float2(-2.0,-2.0);
maxValue:float2(2.0,2.0);
defaultValue:float2(0.5,0.5);
>;

parameter float size
<
minValue:float(0);
maxValue:float(2);
defaultValue:float(1);
>;

parameter float exponent
<
minValue:float(-10.0);
maxValue:float(10.0);
defaultValue:float(0.0);
>;

parameter float factor
<
minValue:float(-10.0);
maxValue:float(10.0);
defaultValue:float(0.0);
>;

parameter float maxBlur
<
minValue:float(0.0);
maxValue:float(10.0);
defaultValue:float(1.0);
>;

void
evaluatePixel()
{
float2 pos = outCoord();
float2 centerPos = float2(mix(bBox[0],bBox[1],center[0]),mix(bBox[2],bBox[3],center[1]));
float dist = distance(centerPos,pos);
dist = dist * (1.0/size);
dist = dist/distance(centerPos,float2(bBox[1],bBox[3]));
float blurFactor = factor * pow(dist,exponent) * maxBlur; // used to control size of sampling area

float2 p0 = float2(pos.x - blurFactor, pos.y - blurFactor);
float2 p1 = float2(pos.x + blurFactor, pos.y - blurFactor);
float2 p2 = float2(pos.x - blurFactor, pos.y + blurFactor);
float2 p3 = float2(pos.x + blurFactor, pos.y + blurFactor);

// corners of unit square surrounding pixel
float4 w0 = sampleNearest(src,p0); // lower left
float4 w1 = sampleNearest(src,p1); // lower right
float4 w2 = sampleNearest(src,p2); // upper left
float4 w3 = sampleNearest(src,p3); // upper right

// partial derivatives with respect to x at points w0 through w3
// i.e slopes of color values only in relation to x axis
// interpolate between previous and next x values
float4 x0 = (sampleNearest(src,float2(p0.x-2.0,p0.y-1.0)) + sampleNearest(src,float2(pos.x,pos.y-1.0)))/2.0;
float4 x1 = (sampleNearest(src,float2(p1.x,p1.y-1.0)) + sampleNearest(src,float2(pos.x+2.0,pos.y-1.0)))/2.0;
float4 x2 = (sampleNearest(src,float2(p2.x-2.0,p2.y+1.0)) + sampleNearest(src,float2(pos.x,pos.y+1.0)))/2.0;
float4 x3 = (sampleNearest(src,float2(p3.x,p3.y+1.0)) + sampleNearest(src,float2(pos.x+2.0,pos.y+1.0)))/2.0;

// partial derivatives with respect to y at points w0 through w3
// i.e slopes of color values only inrelation to y axis
// interpolate between previous and next y values
float4 y0 = (sampleNearest(src,float2(p0.x-1.0,p0.y-2.0)) + sampleNearest(src,float2(pos.x-1.0,pos.y)))/2.0;
float4 y1 = (sampleNearest(src,float2(p1.x+1.0,p1.y-2.0)) + sampleNearest(src,float2(pos.x+1.0,pos.y)))/2.0;
float4 y2 = (sampleNearest(src,float2(p2.x-1.0,p2.y)) + sampleNearest(src,float2(pos.x-1.0,pos.y+2.0)))/2.0;
float4 y3 = (sampleNearest(src,float2(p3.x+1.0,p3.y)) + sampleNearest(src,float2(pos.x+1.0,pos.y+2.0)))/2.0;

// partial derivative cross product at points w0 through w3
// temporary cross products that don't have alpha channels associated with them
float3 z0t = cross(float3(x0.r,x0.g,x0.b),float3(y0.r,y0.g,y0.b));
float3 z1t = cross(float3(x1.r,x1.g,x1.b),float3(y1.r,y1.g,y1.b));
float3 z2t = cross(float3(x2.r,x2.g,x2.b),float3(y2.r,y2.g,y2.b));
float3 z3t = cross(float3(x3.r,x3.g,x3.b),float3(y3.r,y3.g,y3.b));

// add alpha channel back in
float4 z0 = float4(z0t.r,z0t.g,z0t.b,1.0);
float4 z1 = float4(z1t.r,z1t.g,z1t.b,1.0);
float4 z2 = float4(z2t.r,z2t.g,z2t.b,1.0);
float4 z3 = float4(z3t.r,z3t.g,z3t.b,1.0);

// calculate the coefficients
float4 a00 = w0;
float4 a01 = y0;
float4 a02 = -3.0*w0 + 3.0*w2 -2.0*y0 - y2;
float4 a03 = 2.0*w0 - 2.0*w2 + y0 + y2;
float4 a10 = x0;
float4 a11 = z0;
float4 a12 = -3.0*x0 + 3.0*x2 - 2.0*z0 - z2;
float4 a13 = 2.0*x0 - 2.0*x2 + z0 + z2;
float4 a20 = -3.0*w0 + 3.0*w1 - 2.0*x0 - x1;
float4 a21 = -3.0*y0 + 3.0*y1 - 2.0*z0 - z1;
float4 a22 = 9.0*w0 - 9.0*w1 - 9.0*w2 + 9.0*w3 + 6.0*x0 + 3.0*x1 + -6.0*x2 - 3.0*x3 + 6.0*y0 - 6.0*y1 + 3.0*y2 - 3.0*y3 + 4.0*z0 + 2.0*z1 + 2.0*z2 + z3;
float4 a23 = -6.0*w0 + 6.0*w1 + 6.0*w2 - 6.0*w3 - 4.0*x0 - 2.0*x1 + 4.0*x2 + 2.0*x3 -3.0*y0 + 3.0*y1 - 3.0*y2 + 3.0*y3 +-2.0*z0 - z1 - 2.0*z2 - z3;
float4 a30 = 2.0*w0 - 2.0*w1 + x0 + x1;
float4 a31 = 2.0*y0 - 2.0*y1 + z0 + z1;
float4 a32 = -6.0*w0 + 6.0*w1 + 6.0*w2 -6.0*w3 -3.0*x0 - 3.0*x1 +3.0*x2 + 3.0*x3 -4.0*y0 + 4.0*y1 - 2.0*y2 + 2.0*y3 +-2.0*z0 - 2.0*z1 - z2 - z3;
float4 a33 = 4.0*w0 - 4.0*w1 - 4.0*w2 + 4.0*w3 + 2.0*x0 + 2.0*x1 +-2.0*x2 - 2.0*x3 + 2.0*y0 - 2.0*y1 + 2.0*y2 - 2.0*y3 + z0 + z1 + z2 + z3;

dst = a00 + a01*0.5 + a02*pow(0.5,2.0) + a03*pow(0.5,3.0) +
a10*0.5 + a11*pow(0.5,2.0) + a12*pow(0.5,3.0) + a13*pow(0.5,4.0) +
a20*pow(0.5,2.0) + a21*pow(0.5,3.0) + a22*pow(0.5,4.0) + a23*pow(0.5,5.0) +
a30*pow(0.5,3.0) + a31*pow(0.5,4.0) + a32*pow(0.5,5.0) + a33*pow(0.5,6.0);


}
}
37 changes: 37 additions & 0 deletions tests/tests/swfs/avm2/pixelbender_effect_BlurredFocus/Test.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package {
import flash.display.BitmapData;
import flash.display.ShaderJob;
import flash.display.Shader;
import flash.display.Bitmap;
import flash.display.MovieClip;
import flash.display.ShaderParameter;

public class Test {

[Embed(source = "mandelbrot.png")]
public static var MANDELBROT: Class;

// Shader from
[Embed(source = "BlurredFocus.pbj", mimeType="application/octet-stream")]
public static var BLURREDFOCUS_BYTES: Class;

public function Test(main: MovieClip) {
var mandelbrot: Bitmap = new MANDELBROT();
main.addChild(new Bitmap(blurredFocus(mandelbrot.bitmapData)));
}

private function blurredFocus(input: BitmapData): BitmapData {
var out = new BitmapData(input.width, input.height, true, 0xFF00FF00);
var shader = new ShaderJob(new Shader(new BLURREDFOCUS_BYTES()), out);
shader.shader.data.src.input = input;
shader.shader.data.bBox.value = [160, 280, 200, 150];
shader.shader.data.center.value = [0.4, 0.12];
shader.shader.data.size.value = [1.04];
shader.shader.data.exponent.value = [-0.4];
shader.shader.data.factor.value = [3.2];
shader.shader.data.maxBlur.value = [10];
shader.start(true);
return out;
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
num_frames = 1

[image_comparison]
tolerance = 3
max_outliers = 1003

[player_options]
viewport_dimensions = { width = 600, height = 700, scale_factor = 1 }
with_renderer = { optional = false, sample_count = 1 }
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions tests/tests/swfs/avm2/pixelbender_effect_twirl/Test.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package {
import flash.display.BitmapData;
import flash.display.ShaderJob;
import flash.display.Shader;
import flash.display.Bitmap;
import flash.display.MovieClip;
import flash.display.ShaderParameter;

public class Test {

[Embed(source = "Canyonlands.png")]
public static var CANYONLANDS: Class;

// Shader from
[Embed(source = "twirl.pbj", mimeType="application/octet-stream")]
public static var TWIRL_BYTES: Class;

public function Test(main: MovieClip) {
var canyonLands: Bitmap = new CANYONLANDS();
main.addChild(new Bitmap(twirl(canyonLands.bitmapData)));
}

private function twirl(input: BitmapData): BitmapData {
var out = new BitmapData(input.width, input.height, true, 0xFF00FF00);
var shader = new ShaderJob(new Shader(new TWIRL_BYTES()), out);
shader.shader.data.oImage.input = input;
shader.shader.data.radius.value = [143.453];
shader.shader.data.center.value = [348.16, 122.88];
shader.shader.data.twirlAngle.value = [266.4];
shader.shader.data.gaussOrSinc.value = [0];
shader.start(true);
return out;
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Binary file not shown.
Binary file not shown.
9 changes: 9 additions & 0 deletions tests/tests/swfs/avm2/pixelbender_effect_twirl/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
num_frames = 1

[image_comparison]
tolerance = 3
max_outliers = 1003

[player_options]
viewport_dimensions = { width = 600, height = 700, scale_factor = 1 }
with_renderer = { optional = false, sample_count = 1 }
Binary file not shown.
Loading