Skip to content

Commit 22994fd

Browse files
committed
pixelbender: Implement pbasm, a PixelBender assembler
pbasm is a PixelBender assembler that can be used to craft kernels.
1 parent c3c5280 commit 22994fd

File tree

10 files changed

+1012
-1
lines changed

10 files changed

+1012
-1
lines changed

Cargo.lock

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ members = [
1919
"render",
2020
"render/canvas",
2121
"render/naga-agal",
22+
"render/pbasm",
2223
"render/wgpu",
2324
"render/webgl",
2425

render/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ num-derive = { workspace = true }
3131
byteorder = { workspace = true }
3232
wgpu = { workspace = true, optional = true }
3333
indexmap = { workspace = true }
34+
pest = { version = "2.8.1", optional = true }
35+
pest_derive = { version = "2.8.1", optional = true }
36+
serde_json = { version = "1.0.140", optional = true }
3437

3538
# This crate has a `compile_error!` on apple platforms
3639
[target.'cfg(not(target_vendor = "apple"))'.dependencies.renderdoc]
@@ -50,3 +53,4 @@ tessellator = ["lyon"]
5053
web = ["wasm-bindgen"]
5154
wgpu = ["dep:wgpu"]
5255
serde = ["dep:serde"]
56+
assembly = ["dep:pest", "dep:pest_derive", "dep:serde_json"]

render/pbasm/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "pbasm"
3+
description = "pbasm: The Last PixelBender (Assembler)"
4+
authors = ["Kamil Jarosz <kjarosh256@gmail.com>"]
5+
version = "0.1.0"
6+
edition.workspace = true
7+
homepage.workspace = true
8+
license.workspace = true
9+
repository.workspace = true
10+
11+
[lints]
12+
workspace = true
13+
14+
[dependencies]
15+
clap = { workspace = true }
16+
anyhow = { workspace = true }
17+
ruffle_render = { path = "..", features = ["assembly"] }

render/pbasm/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# pbasm: The Last PixelBender (Assembler)
2+
3+
`pbasm` is a PixelBender assembler with a custom syntax.
4+
5+
## Usage
6+
7+
In order to assemble a `.pbasm` file, run:
8+
9+
```bash
10+
pbasm kernel.pbasm -o kernel.pbj
11+
```
12+
13+
In order to disassemble a `.pbj` file, run:
14+
15+
```bash
16+
pbasm -d kernel.pbj -o kernel.pbasm
17+
```
18+
19+
## Syntax
20+
21+
See [integration tests](./integration_tests/) for syntax examples.
22+
23+
## Notes
24+
25+
`pbasm` aims mainly to be useful for Ruffle developers, which means that it
26+
should be able to produce malformed shaders too, so that we can make sure they
27+
are handled properly.

render/pbasm/src/lib.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use anyhow::{anyhow, Context, Result};
2+
use clap::Parser;
3+
use ruffle_render::pixel_bender::{
4+
assembly::PixelBenderShaderAssembly, disassembly::PixelBenderShaderDisassembly, parse_shader,
5+
};
6+
use std::io::{IsTerminal, Write};
7+
8+
#[derive(Parser, Debug)]
9+
#[clap(name = "pbasm", author, version)]
10+
pub struct Opt {
11+
#[clap(name = "source")]
12+
pub source: String,
13+
14+
#[clap(short = 'd', long = "disassemble")]
15+
pub disassemble: bool,
16+
17+
#[clap(short = 'o', long = "output")]
18+
pub output: Option<String>,
19+
}
20+
21+
fn disassemble(opt: Opt, write: &mut dyn Write) -> Result<()> {
22+
let data = std::fs::read(&opt.source).context("Failed to open source file")?;
23+
let parsed =
24+
parse_shader(&data, false).map_err(|e| anyhow!("Failed to parse the shader: {e}"))?;
25+
write!(write, "{}", PixelBenderShaderDisassembly(&parsed))
26+
.context("Failed to write disassembly")?;
27+
Ok(())
28+
}
29+
30+
fn assemble(opt: Opt, write: &mut dyn Write) -> Result<()> {
31+
let input = std::fs::read_to_string(&opt.source).context("Failed to open source file")?;
32+
let assembly = PixelBenderShaderAssembly::new(&input, write);
33+
assembly.assemble()?;
34+
Ok(())
35+
}
36+
37+
pub fn run_main(opt: Opt) -> Result<()> {
38+
let mut out: Box<dyn Write> = if let Some(output) = opt.output.as_ref().filter(|o| *o != "-") {
39+
Box::new(std::fs::File::create(output).context("Failed to create the output file")?)
40+
} else {
41+
if !opt.disassemble && std::io::stdout().is_terminal() {
42+
return Err(anyhow!(
43+
"Cowardly refusing to output binary data to a terminal"
44+
));
45+
}
46+
Box::new(std::io::stdout())
47+
};
48+
49+
if opt.disassemble {
50+
disassemble(opt, &mut out)?;
51+
} else {
52+
assemble(opt, &mut out)?;
53+
}
54+
55+
Ok(())
56+
}

render/pbasm/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use anyhow::Result;
2+
use clap::Parser;
3+
use pbasm::{run_main, Opt};
4+
5+
fn main() -> Result<()> {
6+
let opt: Opt = Opt::parse();
7+
run_main(opt)
8+
}

render/src/pixel_bender.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#[cfg(test)]
55
mod tests;
66

7+
#[cfg(feature = "assembly")]
8+
pub mod assembly;
79
pub mod disassembly;
810

911
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
@@ -101,7 +103,7 @@ pixel_bender_type_with_opcode! {
101103
}
102104
}
103105

104-
#[derive(Debug, PartialEq, Copy, Clone)]
106+
#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
105107
pub enum PixelBenderRegChannel {
106108
R = 0,
107109
G = 1,

0 commit comments

Comments
 (0)