Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f8c6697
WIP RenderTask API
jasmine-nominal Oct 16, 2025
5cc39a3
WIP ComputeCommandBuilder
jasmine-nominal Oct 16, 2025
4ff01a9
Merge commit 'c392d28d30f34b7d2b69b806136b9643379f9284' into render-api
JMS55 Oct 18, 2025
c32863b
More WIP
JMS55 Oct 18, 2025
ec0d216
Lifetime fixes
JMS55 Oct 18, 2025
782c353
Fix type
JMS55 Oct 18, 2025
9d6c1b1
Adjust approach for query data
JMS55 Oct 19, 2025
7217018
Fix lifetime issues
JMS55 Oct 19, 2025
531efb4
More WIP
JMS55 Oct 19, 2025
4970d62
More progress
JMS55 Oct 19, 2025
7873d53
Get render_node_ordering() working
JMS55 Oct 19, 2025
f4a1e35
Make dispatches return option
JMS55 Oct 19, 2025
04114e1
Merge branch 'main' into render-api
JMS55 Oct 19, 2025
2ae97b2
Merge commit '04114e12d98f520060d5ea3ea5a5b4dab13aab88' into render-api
jasmine-nominal Oct 20, 2025
b27f683
Bind group WIP
jasmine-nominal Oct 20, 2025
baf7d5a
Resource cache WIP
jasmine-nominal Oct 20, 2025
0c14c0d
WIP bindings
jasmine-nominal Oct 20, 2025
077cb57
Misc
jasmine-nominal Oct 20, 2025
0d85d55
More WIP
jasmine-nominal Oct 20, 2025
1b8431d
Merge commit '0d85d5558521e2ed670d9fc34cbe5e1d11c50576' into render-api2
JMS55 Oct 20, 2025
d666b97
Fix
jasmine-nominal Oct 22, 2025
c9e3799
Start of binding module
jasmine-nominal Oct 22, 2025
f5a26fa
WIP
jasmine-nominal Oct 22, 2025
ca63cf8
WIP
jasmine-nominal Oct 22, 2025
7042b1d
WIP
jasmine-nominal Oct 22, 2025
79138d8
WIP
jasmine-nominal Oct 22, 2025
530f33a
Merge pull request #37 from jasmine-nominal/render-api2
JMS55 Oct 22, 2025
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
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod main_transparent_pass_3d_node;
pub mod graph {
use bevy_render::render_graph::{RenderLabel, RenderSubGraph};

#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderSubGraph)]
#[derive(Debug, Hash, PartialEq, Eq, Clone, Default, RenderSubGraph)]
pub struct Core3d;

pub mod input {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub mod render_asset;
pub mod render_graph;
pub mod render_phase;
pub mod render_resource;
pub mod render_task;
pub mod renderer;
pub mod settings;
pub mod storage;
Expand Down
17 changes: 9 additions & 8 deletions crates/bevy_render/src/render_graph/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ pub trait RenderGraphExt {
node_label: impl RenderLabel,
) -> &mut Self;
/// Automatically add the required node edges based on the given ordering
fn add_render_graph_edges<const N: usize>(
fn add_render_graph_edges(
&mut self,
sub_graph: impl RenderSubGraph,
edges: impl IntoRenderNodeArray<N>,
edges: impl IntoRenderNodeArray,
) -> &mut Self;

/// Add node edge to the specified graph
Expand Down Expand Up @@ -54,10 +54,10 @@ impl RenderGraphExt for World {
}

#[track_caller]
fn add_render_graph_edges<const N: usize>(
fn add_render_graph_edges(
&mut self,
sub_graph: impl RenderSubGraph,
edges: impl IntoRenderNodeArray<N>,
edges: impl IntoRenderNodeArray,
) -> &mut Self {
let sub_graph = sub_graph.intern();
let mut render_graph = self.get_resource_mut::<RenderGraph>().expect(
Expand Down Expand Up @@ -123,10 +123,10 @@ impl RenderGraphExt for SubApp {
}

#[track_caller]
fn add_render_graph_edges<const N: usize>(
fn add_render_graph_edges(
&mut self,
sub_graph: impl RenderSubGraph,
edges: impl IntoRenderNodeArray<N>,
edges: impl IntoRenderNodeArray,
) -> &mut Self {
World::add_render_graph_edges(self.world_mut(), sub_graph, edges);
self
Expand Down Expand Up @@ -158,10 +158,11 @@ impl RenderGraphExt for App {
self
}

fn add_render_graph_edges<const N: usize>(
#[track_caller]
fn add_render_graph_edges(
&mut self,
sub_graph: impl RenderSubGraph,
edges: impl IntoRenderNodeArray<N>,
edges: impl IntoRenderNodeArray,
) -> &mut Self {
World::add_render_graph_edges(self.world_mut(), sub_graph, edges);
self
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/render_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl RenderGraph {
/// Defining an edge that already exists is not considered an error with this api.
/// It simply won't create a new edge.
#[track_caller]
pub fn add_node_edges<const N: usize>(&mut self, edges: impl IntoRenderNodeArray<N>) {
pub fn add_node_edges(&mut self, edges: impl IntoRenderNodeArray) {
for window in edges.into_array().windows(2) {
let [a, b] = window else {
break;
Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_render/src/render_graph/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ define_label!(
/// A shorthand for `Interned<dyn RenderLabel>`.
pub type InternedRenderLabel = Interned<dyn RenderLabel>;

pub trait IntoRenderNodeArray<const N: usize> {
fn into_array(self) -> [InternedRenderLabel; N];
pub trait IntoRenderNodeArray {
fn into_array(self) -> Vec<InternedRenderLabel>;
}

macro_rules! impl_render_label_tuples {
($N: expr, $(#[$meta:meta])* $(($T: ident, $I: ident)),*) => {
$(#[$meta])*
impl<$($T: RenderLabel),*> IntoRenderNodeArray<$N> for ($($T,)*) {
impl<$($T: RenderLabel),*> IntoRenderNodeArray for ($($T,)*) {
#[inline]
fn into_array(self) -> [InternedRenderLabel; $N] {
fn into_array(self) -> Vec<InternedRenderLabel> {
let ($($I,)*) = self;
[$($I.intern(), )*]
vec![$($I.intern(), )*]
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_render/src/render_resource/bind_group_entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,13 @@ impl<'a> IntoBinding<'a> for BindingResource<'a> {
}
}

impl<'a> IntoBinding<'a> for &'a super::Buffer {
#[inline]
fn into_binding(self) -> BindingResource<'a> {
self.as_entire_binding()
}
}

impl<'a> IntoBinding<'a> for wgpu::BufferBinding<'a> {
#[inline]
fn into_binding(self) -> BindingResource<'a> {
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_render/src/render_resource/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl BindGroupLayoutDescriptor {
}

/// Describes a render (graphics) pipeline.
#[derive(Clone, Debug, PartialEq, Default)]
#[derive(Clone, Debug, PartialEq, Eq, Default, Hash)]
pub struct RenderPipelineDescriptor {
/// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
pub label: Option<Cow<'static, str>>,
Expand Down Expand Up @@ -142,7 +142,7 @@ impl RenderPipelineDescriptor {
}
}

#[derive(Clone, Debug, Eq, PartialEq, Default)]
#[derive(Clone, Debug, Eq, PartialEq, Default, Hash)]
pub struct VertexState {
/// The compiled shader module for this stage.
pub shader: Handle<Shader>,
Expand All @@ -155,7 +155,7 @@ pub struct VertexState {
}

/// Describes the fragment process in a render pipeline.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
#[derive(Clone, Debug, PartialEq, Eq, Default, Hash)]
pub struct FragmentState {
/// The compiled shader module for this stage.
pub shader: Handle<Shader>,
Expand All @@ -174,7 +174,7 @@ impl FragmentState {
}

/// Describes a compute pipeline.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
#[derive(Clone, Debug, PartialEq, Eq, Default, Hash)]
pub struct ComputePipelineDescriptor {
pub label: Option<Cow<'static, str>>,
pub layout: Vec<BindGroupLayoutDescriptor>,
Expand Down
144 changes: 144 additions & 0 deletions crates/bevy_render/src/render_task/bind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
use crate::render_resource::{
BindGroupLayoutEntryBuilder, Buffer, IntoBindGroupLayoutEntryBuilder, IntoBinding, TextureView,
};
use wgpu::{BindingResource, BindingType, BufferBindingType, StorageTextureAccess};

#[derive(Clone)]
pub struct StorageBuffer<'a>(pub &'a Buffer);

#[derive(Clone)]
pub struct StorageBufferWriteable<'a>(pub &'a Buffer);

#[derive(Clone)]
pub struct Texture<'a>(pub &'a TextureView);

#[derive(Clone)]
pub struct StorageTexture<'a>(pub &'a TextureView);

#[derive(Clone)]
pub struct StorageTextureWriteOnly<'a>(pub &'a TextureView);

#[derive(Clone)]
pub struct StorageTextureReadOnly<'a>(pub &'a TextureView);

#[derive(Clone)]
pub struct StorageTextureAtomic<'a>(pub &'a TextureView);

impl<'a> IntoBinding<'a> for StorageBuffer<'a> {
fn into_binding(self) -> BindingResource<'a> {
self.0.as_entire_binding()
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for StorageBuffer<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::Buffer {
ty: BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
}
.into_bind_group_layout_entry_builder()
}
}

impl<'a> IntoBinding<'a> for StorageBufferWriteable<'a> {
fn into_binding(self) -> BindingResource<'a> {
self.0.as_entire_binding()
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for StorageBufferWriteable<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::Buffer {
ty: BufferBindingType::Storage { read_only: false },
has_dynamic_offset: false,
min_binding_size: None,
}
.into_bind_group_layout_entry_builder()
}
}

impl<'a> IntoBinding<'a> for Texture<'a> {
fn into_binding(self) -> BindingResource<'a> {
BindingResource::TextureView(self.0)
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for Texture<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::Texture {
sample_type: todo!(),
view_dimension: todo!(),
multisampled: self.0.texture().sample_count() > 1,
}
.into_bind_group_layout_entry_builder()
}
}

impl<'a> IntoBinding<'a> for StorageTexture<'a> {
fn into_binding(self) -> BindingResource<'a> {
BindingResource::TextureView(self.0)
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for StorageTexture<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::StorageTexture {
access: StorageTextureAccess::ReadWrite,
format: self.0.texture().format(),
view_dimension: todo!(),
}
.into_bind_group_layout_entry_builder()
}
}

impl<'a> IntoBinding<'a> for StorageTextureWriteOnly<'a> {
fn into_binding(self) -> BindingResource<'a> {
BindingResource::TextureView(self.0)
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for StorageTextureWriteOnly<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::StorageTexture {
access: StorageTextureAccess::WriteOnly,
format: self.0.texture().format(),
view_dimension: todo!(),
}
.into_bind_group_layout_entry_builder()
}
}

impl<'a> IntoBinding<'a> for StorageTextureReadOnly<'a> {
fn into_binding(self) -> BindingResource<'a> {
BindingResource::TextureView(self.0)
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for StorageTextureReadOnly<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::StorageTexture {
access: StorageTextureAccess::ReadOnly,
format: self.0.texture().format(),
view_dimension: todo!(),
}
.into_bind_group_layout_entry_builder()
}
}

impl<'a> IntoBinding<'a> for StorageTextureAtomic<'a> {
fn into_binding(self) -> BindingResource<'a> {
BindingResource::TextureView(self.0)
}
}

impl<'a> IntoBindGroupLayoutEntryBuilder for StorageTextureAtomic<'a> {
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
BindingType::StorageTexture {
access: StorageTextureAccess::Atomic,
format: self.0.texture().format(),
view_dimension: todo!(),
}
.into_bind_group_layout_entry_builder()
}
}
Loading
Loading