Skip to content

Commit

Permalink
Shader hot-reload feature
Browse files Browse the repository at this point in the history
  • Loading branch information
attackgoat committed Dec 28, 2022
1 parent 6cdc3a0 commit 6926769
Show file tree
Hide file tree
Showing 36 changed files with 1,255 additions and 213 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.8.0] - 2022-12-28

### Added

- Shader hot-reload feature for compute, graphic and ray-trace pipelines (see examples)
- `Buffer` objects may be created with an alignment specified in `BufferInfo` (useful for shader
binding tables)

### Changed

- `ComputePipeline::create` now takes three arguments: the device, info, and shader
- `ComputePipelineInfo` no longer contains shader information; use `Shader::new_compute` for that
instead

## [0.7.1] - 2022-12-17

### Fixed
Expand Down Expand Up @@ -294,4 +308,5 @@ _See [#25](https://github.com/attackgoat/screen-13/pull/25) for migration detail
[0.6.4]: https://crates.io/crates/screen-13/0.6.4
[0.6.5]: https://crates.io/crates/screen-13/0.6.5
[0.7.0]: https://crates.io/crates/screen-13/0.7.0
[0.7.1]: https://crates.io/crates/screen-13/0.7.1
[0.7.1]: https://crates.io/crates/screen-13/0.7.1
[0.8.0]: https://crates.io/crates/screen-13/0.8.0
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "screen-13"
version = "0.7.1"
version = "0.8.0"
authors = ["John Wells <[email protected]>"]
edition = "2021"
license = "MIT OR Apache-2.0"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ _[QBasic](https://en.wikipedia.org/wiki/QBasic)_.

```toml
[dependencies]
screen-13 = "0.7"
screen-13 = "0.8"
```

## Overview
Expand Down Expand Up @@ -41,6 +41,7 @@ Features of the render graph:
- Automatic Vulkan management (render passes, subpasses, descriptors, pools, _etc._)
- Automatic render pass scheduling, re-ordering, merging, with resource aliasing
- Interoperable with existing Vulkan code
- Optional [shader hot-reload](contrib/screen-13-hot/README.md) from disk

```rust
render_graph
Expand Down
10 changes: 7 additions & 3 deletions contrib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,21 @@ debugging.
A script which exercises all test cases and build conditions which must succeed prior to merging new
code into the main branch.

### [`screen-13-egui/`](screen-13-egui/)
### [`screen-13-egui/`](screen-13-egui/README.md)

Renderer for [egui](https://github.com/emilk/egui); a simple, fast, and highly portable immediate
mode GUI library.

### [`screen-13-fx/`](screen-13-fx/)
### [`screen-13-fx/`](screen-13-fx/README.md)

Pre-defined effects and tools built using _Screen 13_ features. Generally anything that requires
shaders or other physical data which shouldn't be part of the main library.

### [`screen-13-imgui/`](screen-13-imgui/)
### [`screen-13-hot/`](screen-13-hot/README.md)

Adds a hot-reload feature to compute, graphic and ray-trace shader pipelines.

### [`screen-13-imgui/`](screen-13-imgui/README.md)

Renderer for [Dear ImGui](https://github.com/imgui-rs/imgui-rs). Provides a graphical user interface
useful for debug purposes.
3 changes: 3 additions & 0 deletions contrib/rel-mgmt/check
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ diff || fail "Uncommitted changes"
cargo fmt && diff || fail "Unformatted rust code"
cargo fmt --manifest-path contrib/screen-13-egui/Cargo.toml && diff || fail "Unformatted rust code (screen-13-egui)"
cargo fmt --manifest-path contrib/screen-13-fx/Cargo.toml && diff || fail "Unformatted rust code (screen-13-fx)"
cargo fmt --manifest-path contrib/screen-13-hot/Cargo.toml && diff || fail "Unformatted rust code (screen-13-hot)"
cargo fmt --manifest-path contrib/screen-13-imgui/Cargo.toml && diff || fail "Unformatted rust code (screen-13-imgui)"
cargo fmt --manifest-path examples/shader-toy/Cargo.toml && diff || fail "Unformatted rust code (shader-toy)"
cargo fmt --manifest-path examples/skeletal-anim/Cargo.toml && diff || fail "Unformatted rust code (skeletal-anim)"
Expand All @@ -26,6 +27,7 @@ cargo fmt --manifest-path examples/skeletal-anim/Cargo.toml && diff || fail "Unf
cargo check --all-targets --all-features
cargo check --manifest-path contrib/screen-13-egui/Cargo.toml --all-targets --all-features
cargo check --manifest-path contrib/screen-13-fx/Cargo.toml --all-targets --all-features
cargo check --manifest-path contrib/screen-13-hot/Cargo.toml --all-targets --all-features
cargo check --manifest-path contrib/screen-13-imgui/Cargo.toml --all-targets --all-features
cargo check --manifest-path examples/shader-toy/Cargo.toml --all-targets --all-features
cargo check --manifest-path examples/skeletal-anim/Cargo.toml --all-targets --all-features
Expand All @@ -34,6 +36,7 @@ cargo check --manifest-path examples/skeletal-anim/Cargo.toml --all-targets --al
cargo clippy --all-targets --all-features
cargo clippy --manifest-path contrib/screen-13-egui/Cargo.toml --all-targets --all-features
cargo clippy --manifest-path contrib/screen-13-fx/Cargo.toml --all-targets --all-features
cargo clippy --manifest-path contrib/screen-13-hot/Cargo.toml --all-targets --all-features
cargo clippy --manifest-path contrib/screen-13-imgui/Cargo.toml --all-targets --all-features
cargo clippy --manifest-path examples/shader-toy/Cargo.toml --all-targets --all-features
cargo clippy --manifest-path examples/skeletal-anim/Cargo.toml --all-targets --all-features
Expand Down
4 changes: 4 additions & 0 deletions contrib/rel-mgmt/run-all-examples
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,9 @@ cargo run --example transitions
cargo run --example vsm_omni
cargo run --manifest-path examples/skeletal-anim/Cargo.toml

# Hot-reload examples
cargo run --manifest-path contrib/screen-13-hot/Cargo.toml --example glsl
cargo run --manifest-path contrib/screen-13-hot/Cargo.toml --example hlsl

# Run this one in release mode
cargo run --manifest-path examples/shader-toy/Cargo.toml --release
5 changes: 4 additions & 1 deletion contrib/screen-13-fx/src/bitmap_font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,10 @@ impl BitmapFont {
let vertex_buf_len = 120 * text.chars().count() as vk::DeviceSize;
let mut vertex_buf = self
.cache
.lease(BufferInfo::new_mappable(vertex_buf_len, vk::BufferUsageFlags::VERTEX_BUFFER))
.lease(BufferInfo::new_mappable(
vertex_buf_len,
vk::BufferUsageFlags::VERTEX_BUFFER,
))
.unwrap();

let mut vertex_count = 0;
Expand Down
11 changes: 9 additions & 2 deletions contrib/screen-13-fx/src/image_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,18 @@ impl ImageLoader {
pool: HashPool::new(device),
_decode_r_rg: Arc::new(ComputePipeline::create(
device,
include_spirv!("res/shader/compute/decode_bitmap_r_rg.comp", comp).as_slice(),
ComputePipelineInfo::default(),
Shader::new_compute(
include_spirv!("res/shader/compute/decode_bitmap_r_rg.comp", comp).as_slice(),
),
)?),
decode_rgb_rgba: Arc::new(ComputePipeline::create(
device,
include_spirv!("res/shader/compute/decode_bitmap_rgb_rgba.comp", comp).as_slice(),
ComputePipelineInfo::default(),
Shader::new_compute(
include_spirv!("res/shader/compute/decode_bitmap_rgb_rgba.comp", comp)
.as_slice(),
),
)?),
device: Arc::clone(device),
})
Expand Down
10 changes: 8 additions & 2 deletions contrib/screen-13-fx/src/presenter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ impl ComputePresenter {
pub fn new(device: &Arc<Device>) -> Result<Self, DriverError> {
let pipeline1 = Arc::new(ComputePipeline::create(
device,
include_spirv!("res/shader/compute/present1.comp", comp).as_slice(),
ComputePipelineInfo::default(),
Shader::new_compute(
include_spirv!("res/shader/compute/present1.comp", comp).as_slice(),
),
)?);
let pipeline2 = Arc::new(ComputePipeline::create(
device,
include_spirv!("res/shader/compute/present2.comp", comp).as_slice(),
ComputePipelineInfo::default(),
Shader::new_compute(
include_spirv!("res/shader/compute/present2.comp", comp).as_slice(),
),
)?);

Ok(Self([pipeline1, pipeline2]))
Expand Down
5 changes: 3 additions & 2 deletions contrib/screen-13-fx/src/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ impl TransitionPipeline {
Arc::new(
ComputePipeline::create(
&self.device,
match transition_ty {
ComputePipelineInfo::default(),
Shader::new_compute(match transition_ty {
TransitionType::Angular => {
include_spirv!("res/shader/transition/angular.comp", comp).as_slice()
}
Expand Down Expand Up @@ -774,7 +775,7 @@ impl TransitionPipeline {
include_spirv!("res/shader/transition/zoom_right_wipe.comp", comp)
.as_slice()
}
},
}),
)
.unwrap(),
)
Expand Down
Binary file added contrib/screen-13-hot/.github/img/noise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions contrib/screen-13-hot/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "screen-13-hot"
version = "0.1.0"
authors = ["John Wells <[email protected]>"]
edition = "2021"
license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/attackgoat/screen-13"
homepage = "https://github.com/attackgoat/screen-13/contrib/screen-13-hot"
keywords = ["gamedev", "vulkan"]
categories = ["game-development", "multimedia::images", "rendering::engine"]
description = "Hot-reloading shader pipelines for Screen-13"

[dependencies]
anyhow = "1.0"
derive_builder = "0.12"
lazy_static = "1.4"
notify = "5.0"
screen-13 = { path = "../.."}
shader-prepper = "0.3.0-pre.3"
shaderc = "0.8"

[dev-dependencies]
pretty_env_logger = "0.4"
31 changes: 31 additions & 0 deletions contrib/screen-13-hot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Screen 13 Hot

Hot-reloading shader pipelines for _Screen 13_. Supports compute, graphic, and ray-trace shader
pipelines.

Based on shaderc. Feel free to submit PRs for other compilers.

## Quick Start

See the [example code](examples/README.md),

## Basic usage

See the [GLSL](examples/glsl.rs) and [HLSL](examples/hlsl.rs) examples for usage - the hot pipelines
are drop-in replacements for the regular shader pipelines offered by _Screen 13_.

After creating a pipeline two functions are available, `hot` or `cold`. The result of each may be
bound to a render graph for any sort of regular use.

- `hot()`: Returns the pipeline instance which includes any changes found on disk.
- `cold()`: Returns the most recent successful compilation without watching for changes.

## Advanced usage

There are a few options available when creating a `HotShader` instance, which is a wrapper around
regular `Shader` instances. These options allow you to set compilation settings such as optimization
level and warnings-as-errors, among other things.

## More infomation

Run `cargo doc --open` to view detailed API documentation and find available compilation options.
15 changes: 15 additions & 0 deletions contrib/screen-13-hot/examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# _Screen 13 Hot_ Example Code

## Getting Started

Hot-reloading shader pipelines are drop-in replacements for regular shader pipelines. Reference the
below code to get started.

See the [README](../README.md) for more information.

## Example Code

Example | Instructions | Preview
--- | --- | :---:
[glsl.rs](glsl.rs) | <pre>cargo run --example glsl</pre> | <image alt="Preview" src="../.github/img/noise.png" height=149 width=176>
[hlsl.rs](hlsl.rs) | <pre>cargo run --example hlsl</pre> | <image alt="Preview" src="../.github/img/noise.png" height=149 width=176>
44 changes: 44 additions & 0 deletions contrib/screen-13-hot/examples/glsl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use {
lazy_static::lazy_static, screen_13::prelude::*, screen_13_hot::prelude::*, std::path::PathBuf,
};

lazy_static! {
static ref CARGO_MANIFEST_DIR: PathBuf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
}

/// This program draws a noise signal to the swapchain - make changes to fill_image.comp or the
/// noise.glsl file it includes to see those changes update while the program is still running.
///
/// Run with RUST_LOG=info to get notification of shader compilations.
fn main() -> Result<(), DisplayError> {
pretty_env_logger::init();

let event_loop = EventLoop::new().build()?;

// Create a compute pipeline - the same as normal except for "Hot" prefixes and we provide the
// shader source code path instead of the shader source code bytes
let mut pipeline = HotComputePipeline::create(
&event_loop.device,
ComputePipelineInfo::default(),
HotShader::new_compute(CARGO_MANIFEST_DIR.join("examples/res/fill_image.comp")),
)?;

let mut frame_index: u32 = 0;

event_loop.run(|frame| {
frame
.render_graph
.begin_pass("make some noise")
.bind_pipeline(pipeline.hot())
.write_descriptor(0, frame.swapchain_image)
.record_compute(move |compute, _| {
compute.push_constants(&frame_index.to_ne_bytes()).dispatch(
frame.width,
frame.height,
1,
);
});

frame_index += 1;
})
}
49 changes: 49 additions & 0 deletions contrib/screen-13-hot/examples/hlsl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use {
lazy_static::lazy_static, screen_13::prelude::*, screen_13_hot::prelude::*, std::path::PathBuf,
};

lazy_static! {
static ref CARGO_MANIFEST_DIR: PathBuf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
}

/// This program draws a noise signal to the swapchain - make changes to fill_image.hlsl or the
/// noise.hlsl file it includes to see those changes update while the program is still running.
///
/// Run with RUST_LOG=info to get notification of shader compilations.
fn main() -> Result<(), DisplayError> {
pretty_env_logger::init();

let event_loop = EventLoop::new().build()?;

// Create a graphic pipeline - the same as normal except for "Hot" prefixes and we provide the
// shader source code path instead of the shader source code bytes
let fill_image_path = CARGO_MANIFEST_DIR.join("examples/res/fill_image.hlsl");
let mut pipeline = HotGraphicPipeline::create(
&event_loop.device,
GraphicPipelineInfo::default(),
[
HotShader::new_vertex(&fill_image_path).entry_name("vertex_main".to_string()),
HotShader::new_fragment(&fill_image_path).entry_name("fragment_main".to_string()),
],
)?;

let mut frame_index: u32 = 0;

event_loop.run(|frame| {
frame
.render_graph
.begin_pass("make some noise")
.bind_pipeline(pipeline.hot())
.clear_color(0, frame.swapchain_image)
.store_color(0, frame.swapchain_image)
.record_subpass(move |subpass, _| {
subpass
.push_constants_offset(0, &frame_index.to_ne_bytes())
.push_constants_offset(4, &frame.width.to_ne_bytes())
.push_constants_offset(8, &frame.height.to_ne_bytes())
.draw(3, 1, 0, 0);
});

frame_index += 1;
})
}
18 changes: 18 additions & 0 deletions contrib/screen-13-hot/examples/res/fill_image.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#version 460 core

#include "noise.glsl"

layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

layout(push_constant) uniform PushConstants {
layout(offset = 0) uint frame_index;
} push_const;

layout(set = 0, binding = 0, rgba32f) restrict writeonly uniform image2D image;

void main() {
uvec3 data = uvec3(gl_GlobalInvocationID.xy, push_const.frame_index);
vec4 color = vec4(hash(data), 1.0);

imageStore(image, ivec2(gl_GlobalInvocationID.xy), color);
}
Loading

0 comments on commit 6926769

Please sign in to comment.