revive project: add the template from learnWGPU tutorial

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2023-08-08 00:58:06 +05:30
parent 78b0eaa06b
commit f2bf8321cd
11 changed files with 1323 additions and 696 deletions

View File

@@ -1,8 +1,8 @@
[target.x86_64-unknown-linux-gnu] [target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=lld"] rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[target.i686-unknown-linux-gnu] [target.i686-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=lld"] rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[target.aarch64-unknown-linux-gnu] [target.aarch64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=lld"] rustflags = ["-C", "link-arg=-fuse-ld=mold"]

View File

@@ -3,26 +3,30 @@ on: [push, pull_request, workflow_dispatch]
jobs: jobs:
build: build:
strategy: runs-on: ubuntu-latest
matrix:
os: [ubuntu-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Git checkout - uses: actions/checkout@v3
uses: actions/checkout@v3 - uses: cachix/install-nix-action@v20
- name: Install nix
uses: cachix/install-nix-action@v18
- name: Check formatting
run: nix develop -c cargo fmt --check
- name: Set up cache
uses: actions/cache@v3
with: with:
path: | extra_nix_config: |
~/.cargo/bin/ auto-optimise-store = true
~/.cargo/registry/index/ experimental-features = nix-command flakes
~/.cargo/registry/cache/ - uses: cachix/cachix-action@v12
~/.cargo/git/db/ with:
target/ name: pain
key: ${{ matrix.os }}-torana-${{ hashFiles('**/Cargo.lock') }} authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build
run: nix develop -c cargo build --release - name: fmt checks
run: nix build .#checks.fmt -L
- name: clippy checks
run: nix build .#checks.clippy -L
- name: nextest checks
run: nix build .#checks.nextest -L
- name: doc checks
run: nix build .#checks.doc -L
- name: build
run: nix build .#torana -L

36
.github/workflows/web.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: toranaWeb
on:
workflow_run:
workflows: ["torana"]
types:
- completed
workflow_dispatch:
env:
OUT_LINK: toranaWeb
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v20
with:
extra_nix_config: |
auto-optimise-store = true
experimental-features = nix-command flakes
- uses: cachix/cachix-action@v12
with:
name: pain
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: build
run: nix build .#toranaWeb --out-link $OUT_LINK -L
- name: wasm-bindgen
run: >
nix develop .#toranaWeb
-c wasm-bindgen
--target web $OUT_LINK/bin/torana.wasm
--out-dir www

1316
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,10 +6,26 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bytemuck = { version = "1.12", features = [ "derive" ] } bytemuck = { version = "1.13.1", features = [ "derive" ] }
cfg-if = "1" cfg-if = "1"
env_logger = "0.9" env_logger = "0.9"
image = "0.24" image = "0.24"
log = "0.4" log = "0.4"
wgpu = "0.14" wgpu = "0.17"
winit = "0.27" winit = "0.28.6"
pollster ="0.3.0"
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.6"
console_log = "1.0"
wgpu = { version = "0.17", features = ["webgl"]}
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4.30"
web-sys = { version = "0.3", features = [
"Document",
"Window",
"Element",
]}
[lib]
crate-type = ["cdylib", "rlib"]

186
flake.lock generated
View File

@@ -1,12 +1,72 @@
{ {
"nodes": { "nodes": {
"flake-utils": { "crane": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"locked": { "locked": {
"lastModified": 1659877975, "lastModified": 1691423162,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "narHash": "sha256-cReUZCo83YEEmFcHX8CcOVTZYUrcWgHQO34zxQzy7WI=",
"owner": "ipetkov",
"repo": "crane",
"rev": "b5d9d42ea3fa8fea1805d9af1416fe207d0dd1dc",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -17,31 +77,15 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1674266771, "lastModified": 1691371061,
"narHash": "sha256-Rttg4VUJpCtg5Qxdp+/xncxuEFQjMlKbvEFi5my0oNU=", "narHash": "sha256-BxPbPVlBIoneaXIBiHd0LVzA+L4nmvFCNBU6TmQAiMM=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7c3fc1838288763664291ef847816ddd03fde26b", "rev": "5068bc8fe943bde3c446326da8d0ca9c93d5a682",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "release-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1665296151,
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable", "ref": "nixpkgs-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
@@ -49,22 +93,29 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"crane": "crane",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay", "rust-overlay": "rust-overlay_2",
"utils": "utils" "utils": "utils"
} }
}, },
"rust-overlay": { "rust-overlay": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": [
"nixpkgs": "nixpkgs_2" "crane",
"flake-utils"
],
"nixpkgs": [
"crane",
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1674267882, "lastModified": 1691029059,
"narHash": "sha256-53sIczqxA5BbrhgO6l54DSisDqHvQ3UUwbSqBryA/k0=", "narHash": "sha256-QwVeE9YTgH3LmL7yw2V/hgswL6yorIvYSp4YGI8lZYM=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "1fd6d280c132f4facad8cd023543fb10121e6487", "rev": "99df4908445be37ddb2d332580365fce512a7dcf",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -73,13 +124,82 @@
"type": "github" "type": "github"
} }
}, },
"utils": { "rust-overlay_2": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1691374719,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-HCodqnx1Mi2vN4f3hjRPc7+lSQy18vRn8xWW68GeQOg=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "b520a3889b24aaf909e287d19d406862ced9ffc9",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github" "type": "github"
}, },
"original": { "original": {

164
flake.nix
View File

@@ -1,45 +1,139 @@
{ {
description = "Torana danmaku engine"; description = "torana danmaku";
inputs = { inputs = {
nixpkgs.url = github:nixos/nixpkgs/release-22.11; nixpkgs.url = github:nixos/nixpkgs/nixpkgs-unstable;
rust-overlay.url = github:oxalica/rust-overlay;
crane = {
url = github:ipetkov/crane;
inputs.nixpkgs.follows = "nixpkgs";
};
rust-overlay = {
url = github:oxalica/rust-overlay;
inputs.nixpkgs.follows = "nixpkgs";
};
utils.url = github:numtide/flake-utils; utils.url = github:numtide/flake-utils;
}; };
outputs = { outputs = { self, nixpkgs, utils, crane, rust-overlay, }:
self,
nixpkgs,
utils,
rust-overlay,
}:
utils.lib.eachDefaultSystem utils.lib.eachDefaultSystem
( (
system: let system:
overlays = [rust-overlay.overlays.default]; let
pkgs = import nixpkgs {
pkgs = import nixpkgs { inherit system;
inherit system overlays; overlays = [ rust-overlay.overlays.default ];
};
toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain;
in rec {
devShell = with pkgs;
mkShell {
nativeBuildInputs =
[
cmake
openssl
fontconfig
pkg-config
rust-analyzer
toolchain
]
++ lib.optionals (with stdenv.hostPlatform; (isx86 || isi686 || isAarch64) && isLinux) [llvmPackages.lld]
++ lib.optionals stdenv.hostPlatform.isDarwin [darwin.apple_sdk.frameworks.Cocoa];
}; };
formatter = pkgs.alejandra; runtimeDependencies = with pkgs; [
} freetype
); fontconfig
vulkan-loader
];
xorgInputs = with pkgs; (with xorg; [
libX11
libXcursor
libXrandr
libXi
]) ++ [
# libxkbcommon
# wayland
];
nativeBuildInputs = with pkgs; [
cmake
openssl.dev
fontconfig.dev
pkg-config
]
++ lib.optionals (with stdenv.hostPlatform; (isx86 || isi686 || isAarch64)) [ mold ]
++ lib.optionals stdenv.hostPlatform.isDarwin [ darwin.apple_sdk.frameworks.Cocoa ];
toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain;
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
src = craneLib.cleanCargoSource (craneLib.path ./.);
commonArgs = {
inherit src nativeBuildInputs;
buildInputs = xorgInputs;
doCheck = false;
};
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
torana = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts runtimeDependencies;
nativeBuildInputs = nativeBuildInputs ++ [ pkgs.autoPatchelfHook ];
});
commonArgsWeb = {
inherit src;
cargoExtraArgs = "--target wasm32-unknown-unknown";
doCheck = false;
};
cargoArtifactsWeb = craneLib.buildDepsOnly commonArgsWeb;
toranaWeb = craneLib.buildPackage (commonArgsWeb // {
inherit cargoArtifactsWeb;
});
in
rec {
packages = {
inherit torana toranaWeb toolchain;
default = torana;
# not using flake checks to run them individually
checks = {
clippy = craneLib.cargoClippy (commonArgs // {
inherit cargoArtifacts;
});
fmt = craneLib.cargoFmt {
inherit src;
};
doc = craneLib.cargoDoc (commonArgs // {
inherit cargoArtifacts;
});
nextest = craneLib.cargoNextest (commonArgs // {
inherit cargoArtifacts;
partitions = 1;
partitionType = "count";
});
};
};
devShells = rec {
torana = with pkgs;
mkShell {
name = "torana";
nativeBuildInputs = nativeBuildInputs ++
(with pkgs; [ wasm-bindgen toolchain ]);
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath
(xorgInputs ++ runtimeDependencies);
};
default = torana;
toranaWeb = with pkgs;
mkShell {
name = "toranaWeb";
nativeBuildInputs = with pkgs; [
wasm-bindgen-cli
];
};
};
formatter = pkgs.nixpkgs-fmt;
}
);
} }

View File

@@ -1,3 +1,4 @@
[toolchain] [toolchain]
channel = "nightly-2023-01-21" channel = "nightly-2023-07-15"
components = [ "rustfmt", "clippy" ] components = [ "rustfmt", "clippy", "rust-analyzer", "rust-src" ]
targets = ["wasm32-unknown-unknown"]

5
rustfmt.toml Normal file
View File

@@ -0,0 +1,5 @@
comment_width = 99
format_code_in_doc_comments = true
imports_granularity = "Module"
imports_layout = "Vertical"
wrap_comments = true

View File

@@ -1,3 +1,227 @@
pub fn run() { use std::iter;
println!("alo")
use winit::event::*;
use winit::event_loop::{
ControlFlow,
EventLoop,
};
use winit::window::{
Window,
WindowBuilder,
};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
window: Window,
}
impl State {
async fn new(window: Window) -> Self {
let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
dx12_shader_compiler: Default::default(),
});
let surface = unsafe { instance.create_surface(&window) }.unwrap();
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: Some(&surface),
force_fallback_adapter: false,
})
.await
.unwrap();
println!("Selected GPU: {}", adapter.get_info().name);
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
limits: if cfg!(target_arch = "wasm32") {
wgpu::Limits::downlevel_webgl2_defaults()
} else {
wgpu::Limits::default()
},
},
None,
)
.await
.unwrap();
let surface_caps = surface.get_capabilities(&adapter);
let surface_format = surface_caps
.formats
.iter()
.copied()
.find(|f| f.is_srgb())
.unwrap_or(surface_caps.formats[0]);
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: size.width,
height: size.height,
present_mode: surface_caps.present_modes[0],
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
};
surface.configure(&device, &config);
Self {
surface,
device,
queue,
config,
size,
window,
}
}
fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
#[allow(unused_variables)]
fn input(&mut self, event: &WindowEvent) -> bool {
false
}
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_texture()?;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.6,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true,
},
})],
depth_stencil_attachment: None,
});
self.queue.submit(iter::once(encoder.finish()));
output.present();
Ok(())
}
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub async fn run() {
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
console_log::init_with_level(log::Level::Warn).expect("Couldn't initialize logger");
} else {
env_logger::init();
}
}
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
#[cfg(target_arch = "wasm32")]
{
use winit::dpi::PhysicalSize;
window.set_inner_size(PhysicalSize::new(450, 400));
use winit::platform::web::WindowExtWebSys;
web_sys::window()
.and_then(|win| win.document())
.and_then(|doc| {
let dst = doc.get_element_by_id("wasm-example")?;
let canvas = web_sys::Element::from(window.canvas());
dst.append_child(&canvas).ok()?;
Some(())
})
.expect("Couldn't append canvas to document body.");
}
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
} => *control_flow = ControlFlow::Exit,
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
}
_ => {}
}
}
}
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
state.resize(state.size)
}
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"),
}
}
Event::RedrawEventsCleared => {
state.window().request_redraw();
}
_ => {}
});
} }

5
src/main.rs Normal file
View File

@@ -0,0 +1,5 @@
use torana::run;
fn main() {
pollster::block_on(run());
}