Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

Commit

Permalink
Merge branch 'render-targets'
Browse files Browse the repository at this point in the history
  • Loading branch information
darthdeus committed Nov 11, 2023
2 parents d93254b + bc50167 commit 8bc8837
Show file tree
Hide file tree
Showing 20 changed files with 574 additions and 299 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ New shader related functions (see their individual docstrings & [fragment shader
to have official `mlua` bindings I'd rather that be done in a more principled approach
where we make sure things are exported in a consistent way.

We're also introducing experimental render targets. This is a feature that
isn't yet complete, and there are some issues with it, but since merging it
doesn't really affect/break existing code it'll be included in v0.3 so that we
don't end up with long running feature branches for no reason. [There is an
example showcasing how this feature will
work](https://github.com/darthdeus/comfy/blob/render-targets/comfy/examples/render-target.rs),
but it's very likely we'll have breaking changes around this API, and would
like to discourage people from depending on this functionality in any way for
now. But do feel free to play around with it!

# v0.2.0

The main change in this release is that `EngineContext` is not necessary to
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
# EXAMPLE=particle_systems
# EXAMPLE=physics
# EXAMPLE=post_processing
EXAMPLE=render-target
# EXAMPLE=sprite
# EXAMPLE=shapes
EXAMPLE=sound
# EXAMPLE=sound
# EXAMPLE=text
# EXAMPLE=timed_draw
# EXAMPLE=version
Expand Down Expand Up @@ -58,6 +59,7 @@ lint:
timings:
cargo clean
cargo build --timings --example sprite
# RUSTFLAGS="-Z threads=8" cargo build --timings --example sprite

serve:
simple-http-server target/generated -c wasm,html,js -i
Expand Down
16 changes: 11 additions & 5 deletions comfy-core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ impl Errors {
}
}

/// Stores an error message with the given ID. This is useful for immediate mode error reporting
/// when you don't want to pollute the log on every frame.
///
/// When `--features dev` is active, errors will show in an egui window in game.
///
/// The `id` parameter can be any string. We're using `Cow<'static, str>` to save on allocations
/// for ids/errors that can be represented as `&'static str`.
pub fn report_error(
id: impl Into<Cow<'static, str>>,
error: impl Into<Cow<'static, str>>,
) {
ERRORS.borrow_mut().data.insert(id.into(), error.into());
}

// pub fn reported_errors_iter(
// ) -> impl Deref<Target = impl Iterator<Item = (&Cow<'static, str>, &Cow<'static, str>)>>
// {
// AtomicRef::map(ERRORS.borrow(), |x| x.data.iter())
// }
/// Clears a previously set error. Use the same ID as when calling `report_error`.
pub fn clear_error(id: impl Into<Cow<'static, str>>) {
ERRORS.borrow_mut().data.remove(&id.into());
}
2 changes: 2 additions & 0 deletions comfy-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ pub struct MeshDraw {
pub mesh: Mesh,
pub texture_params: TextureParams,
pub shader: Option<ShaderInstance>,
pub render_target: Option<RenderTargetId>,
}

pub struct DrawParams<'a> {
Expand Down Expand Up @@ -878,6 +879,7 @@ impl Sound {
pub enum TextureHandle {
Path(u64),
Raw(u64),
RenderTarget(RenderTargetId)
}

impl TextureHandle {
Expand Down
1 change: 1 addition & 0 deletions comfy-core/src/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,7 @@ pub fn draw_mesh_ex(mesh: Mesh, texture_params: TextureParams) {
mesh,
texture_params,
shader: get_current_shader(),
render_target: get_current_render_target(),
});
}

Expand Down
78 changes: 39 additions & 39 deletions comfy-core/src/shaders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ use crate::*;
use std::sync::atomic::AtomicU64;

static SHADER_IDS: AtomicU64 = AtomicU64::new(0);
static GENERATED_RENDER_TARGET_IDS: AtomicU64 = AtomicU64::new(0);

#[derive(Debug)]
pub struct ShaderMap {
shaders: HashMap<ShaderId, Shader>,
pub shaders: HashMap<ShaderId, Shader>,
pub watched_paths: HashMap<String, ShaderId>,
}

Expand Down Expand Up @@ -77,6 +76,21 @@ pub enum Uniform {
Custom(Vec<u8>),
}

static CURRENT_RENDER_TARGET: Lazy<AtomicRefCell<Option<RenderTargetId>>> =
Lazy::new(|| AtomicRefCell::new(None));

pub fn use_render_target(id: RenderTargetId) {
*CURRENT_RENDER_TARGET.borrow_mut() = Some(id);
}

pub fn use_default_render_target() {
*CURRENT_RENDER_TARGET.borrow_mut() = None;
}

pub fn get_current_render_target() -> Option<RenderTargetId> {
*CURRENT_RENDER_TARGET.borrow()
}

static CURRENT_SHADER: Lazy<AtomicRefCell<Option<ShaderInstance>>> =
Lazy::new(|| AtomicRefCell::new(None));

Expand Down Expand Up @@ -135,16 +149,19 @@ pub fn create_shader(
) -> Result<ShaderId> {
let id = gen_shader_id();

if !source.contains("@vertex") {
panic!(
"Missing @vertex function in shader passed to `create_shader`.
Did you forget to call `sprite_shader_from_fragment`?"
);
}

if shaders.exists(id) {
bail!("Shader with name '{}' already exists", name);
}

let bindings = uniform_defs
.iter()
.sorted_by_key(|x| x.0)
.enumerate()
.map(|(i, (name, _))| (name.clone(), i as u32))
.collect::<HashMap<String, u32>>();
let bindings = uniform_defs_to_bindings(&uniform_defs);

shaders.insert_shader(id, Shader {
id,
Expand All @@ -157,30 +174,25 @@ pub fn create_shader(
Ok(id)
}

pub fn uniform_defs_to_bindings(
uniform_defs: &UniformDefs,
) -> HashMap<String, u32> {
uniform_defs
.iter()
.sorted_by_key(|x| x.0)
.enumerate()
.map(|(i, (name, _))| (name.clone(), i as u32))
.collect::<HashMap<String, u32>>()
}

/// Stores both a static source code for a shader as well as path to its file in development. This
/// is used for automatic shader hot reloading.
pub struct ReloadableShaderSource {
pub static_source: String,
pub path: String,
}

/// Update the shader source for the given shader ID. This can be used by users who with to
/// implement their own shader hot reloading.
pub fn update_shader(
shaders: &mut ShaderMap,
id: ShaderId,
fragment_source: &str,
) {
if let Some(shader) = shaders.shaders.get_mut(&id) {
shader.source = build_shader_source(
fragment_source,
&shader.bindings,
&shader.uniform_defs,
);
}
}

fn build_shader_source(
pub fn build_shader_source(
fragment_source: &str,
bindings: &HashMap<String, u32>,
uniform_defs: &UniformDefs,
Expand All @@ -202,20 +214,8 @@ fn build_shader_source(
format!("{}\n{}", uniforms_src, fragment_source)
}

#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RenderTargetId {
Named(String),
Named(&'static str),
Generated(u64),
}

/// Allocates a new render target for later use. If a label is provided
/// it'll be used to set the debug name so graphic debuggers like RenderDoc
/// can display it properly.
pub fn gen_render_target(_label: Option<&str>) -> RenderTargetId {
// TODO: use the label
//
let id = GENERATED_RENDER_TARGET_IDS
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);

RenderTargetId::Generated(id)
}
Loading

0 comments on commit 8bc8837

Please sign in to comment.