Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
6 changes: 6 additions & 0 deletions crates/bevy_core_pipeline/src/core_2d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use bevy_render::{
render_phase::{
batch_phase_system, sort_phase_system, BatchedPhaseItem, CachedRenderPipelinePhaseItem,
DrawFunctionId, DrawFunctions, EntityPhaseItem, PhaseItem, RenderPhase,
RenderPhaseSortMode,
},
render_resource::CachedRenderPipelineId,
RenderApp, RenderStage,
Expand Down Expand Up @@ -90,6 +91,11 @@ impl PhaseItem for Transparent2d {
fn draw_function(&self) -> DrawFunctionId {
self.draw_function
}

#[inline]
fn sort_mode() -> RenderPhaseSortMode {
RenderPhaseSortMode::Stable
}
}

impl EntityPhaseItem for Transparent2d {
Expand Down
40 changes: 40 additions & 0 deletions crates/bevy_render/src/render_phase/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ pub trait Draw<P: PhaseItem>: Send + Sync + 'static {
);
}

/// Configures how a render phase is sorted. For more information, see [`PhaseItem::sort_mode`].
pub enum RenderPhaseSortMode {
/// Requires a stable sort. Generally required for proper batching based on external criteria.
/// Specifically when the sorting result is draw order dependent, typically required for
/// transparency that do not use a depth buffer.
Stable,
/// The default: allows unstable sorting. Usually faster than Stable.
Unstable,
/// Unsorted. Omits sorting entirely.
Unsorted,
}

impl Default for RenderPhaseSortMode {
fn default() -> Self {
Self::Unstable
}
}

/// An item which will be drawn to the screen. A phase item should be queued up for rendering
/// during the [`RenderStage::Queue`](crate::RenderStage::Queue) stage.
/// Afterwards it will be sorted and rendered automatically in the
Expand All @@ -42,6 +60,24 @@ pub trait PhaseItem: Send + Sync + 'static {
fn sort_key(&self) -> Self::SortKey;
/// Specifies the [`Draw`] function used to render the item.
fn draw_function(&self) -> DrawFunctionId;

/// Specifies what kind of sort to apply to the phase. Generally if the same type
/// implements [`BatchedPhaseItem`], this should return [`RenderPhaseSortMode::Stable`].
/// In almost all other cases, this should not be altered from the default,
/// [`RenderPhaseSortMode::Unstable`], as this provides the best balance of CPU and GPU
/// performance.
///
/// It's generally only advised to use [`RenderPhaseSortMode::Unsorted`] if and only if
/// the renderer supports a depth prepass, which is by default not supported by the rest
/// of Bevy's first party rendering crates. Even then, this may have a negative impact
/// on GPU-side performance due to overdraw.
///
/// It's advised to always profile for performance changes when changing this to
/// a different value.
#[inline]
fn sort_mode() -> RenderPhaseSortMode {
Default::default()
}
}

// TODO: make this generic?
Expand Down Expand Up @@ -170,6 +206,10 @@ pub trait CachedRenderPipelinePhaseItem: PhaseItem {
///
/// Batching is an optimization that regroups multiple items in the same vertex buffer
/// to render them in a single draw call.
///
/// If this is implemented on a type, the implementation of [`PhaseItem::sort_mode`] should
/// be changed to return [`RenderPhaseSortMode::Stable`], or incorrect/suboptimal batching
/// may result.
pub trait BatchedPhaseItem: EntityPhaseItem {
/// Range in the vertex buffer of this item
fn batch_range(&self) -> &Option<Range<u32>>;
Expand Down
10 changes: 9 additions & 1 deletion crates/bevy_render/src/render_phase/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ impl<I: PhaseItem> RenderPhase<I> {

/// Sorts all of its [`PhaseItems`](PhaseItem).
pub fn sort(&mut self) {
self.items.sort_by_key(|d| d.sort_key());
match I::sort_mode() {
RenderPhaseSortMode::Stable => self.items.sort_by_key(|d| d.sort_key()),
RenderPhaseSortMode::Unstable => self.items.sort_unstable_by_key(|d| d.sort_key()),
RenderPhaseSortMode::Unsorted => {}
}
}
}

Expand Down Expand Up @@ -98,6 +102,10 @@ mod tests {
fn draw_function(&self) -> DrawFunctionId {
unimplemented!();
}

fn sort_mode() -> RenderPhaseSortMode {
RenderPhaseSortMode::Stable
}
}
impl EntityPhaseItem for TestPhaseItem {
fn entity(&self) -> bevy_ecs::entity::Entity {
Expand Down