mirror of
https://github.com/bevyengine/bevy.git
synced 2026-05-06 06:06:42 -04:00
71dd9ea7db
# Objective - Recover from rendering errors. - Another step towards render recovery after #22714 #22759 and #16481 ## Solution - Use `wgpu::Device::set_device_lost_callback` and `wgpu::Device::on_uncaptured_error` to listen for errors. - Add a state machine for the renderer - Update it on error - Add a `RenderErrorHandler` to let users specify behavior on error by returning a specific `RenderErrorPolicy` - This lets us for example ignore validation errors, delete responsible entities, or reload the renderer if the device was lost. ## Testing - #22757 with any of ```rs .insert_resource(bevy_render::error_handler::RenderErrorHandler(|_, _, _| { bevy_render::error_handler::RenderErrorPolicy::StopRendering })) ``` ```rs .insert_resource(bevy_render::error_handler::RenderErrorHandler(|_, _, _| { bevy_render::error_handler::RenderErrorPolicy::Recover(default()) })) ``` Note: no release note yet, as recovery does not exactly work well: this PR gets us to the point of being able to care about it, but we currently instantly crash on recover due to gpu resources not existing anymore. We need to build more resilience before publicizing imo. --------- Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
147 lines
4.5 KiB
Rust
147 lines
4.5 KiB
Rust
//! Showcases wireframe rendering for 2d meshes.
|
|
//!
|
|
//! Wireframes currently do not work when using webgl or webgpu.
|
|
//! Supported platforms:
|
|
//! - DX12
|
|
//! - Vulkan
|
|
//! - Metal
|
|
//!
|
|
//! This is a native only feature.
|
|
|
|
use bevy::{
|
|
color::palettes::basic::{GREEN, RED, WHITE},
|
|
prelude::*,
|
|
render::{render_resource::WgpuFeatures, settings::WgpuSettings, RenderPlugin},
|
|
sprite_render::{
|
|
NoWireframe2d, Wireframe2d, Wireframe2dColor, Wireframe2dConfig, Wireframe2dPlugin,
|
|
},
|
|
};
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins((
|
|
DefaultPlugins.set(RenderPlugin {
|
|
render_creation: WgpuSettings {
|
|
// WARN this is a native only feature. It will not work with webgl or webgpu
|
|
features: WgpuFeatures::POLYGON_MODE_LINE,
|
|
..default()
|
|
}
|
|
.into(),
|
|
..default()
|
|
}),
|
|
// You need to add this plugin to enable wireframe rendering
|
|
Wireframe2dPlugin::default(),
|
|
))
|
|
// Wireframes can be configured with this resource. This can be changed at runtime.
|
|
.insert_resource(Wireframe2dConfig {
|
|
// The global wireframe config enables drawing of wireframes on every mesh,
|
|
// except those with `NoWireframe2d`. Meshes with `Wireframe2d` will always have a wireframe,
|
|
// regardless of the global configuration.
|
|
global: true,
|
|
// Controls the default color of all wireframes. Used as the default color for global wireframes.
|
|
// Can be changed per mesh using the `Wireframe2dColor` component.
|
|
default_color: WHITE.into(),
|
|
})
|
|
.add_systems(Startup, setup)
|
|
.add_systems(Update, update_colors)
|
|
.run();
|
|
}
|
|
|
|
/// Set up a simple 3D scene
|
|
fn setup(
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
) {
|
|
// Triangle: Never renders a wireframe
|
|
commands.spawn((
|
|
Mesh2d(meshes.add(Triangle2d::new(
|
|
Vec2::new(0.0, 50.0),
|
|
Vec2::new(-50.0, -50.0),
|
|
Vec2::new(50.0, -50.0),
|
|
))),
|
|
MeshMaterial2d(materials.add(Color::BLACK)),
|
|
Transform::from_xyz(-150.0, 0.0, 0.0),
|
|
NoWireframe2d,
|
|
));
|
|
// Rectangle: Follows global wireframe setting
|
|
commands.spawn((
|
|
Mesh2d(meshes.add(Rectangle::new(100.0, 100.0))),
|
|
MeshMaterial2d(materials.add(Color::BLACK)),
|
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
|
));
|
|
// Circle: Always renders a wireframe
|
|
commands.spawn((
|
|
Mesh2d(meshes.add(Circle::new(50.0))),
|
|
MeshMaterial2d(materials.add(Color::BLACK)),
|
|
Transform::from_xyz(150.0, 0.0, 0.0),
|
|
Wireframe2d,
|
|
// This lets you configure the wireframe color of this entity.
|
|
// If not set, this will use the color in `WireframeConfig`
|
|
Wireframe2dColor {
|
|
color: GREEN.into(),
|
|
},
|
|
));
|
|
|
|
commands.spawn(Camera2d);
|
|
|
|
// Text used to show controls
|
|
commands.spawn((
|
|
Text::default(),
|
|
Node {
|
|
position_type: PositionType::Absolute,
|
|
top: px(12),
|
|
left: px(12),
|
|
..default()
|
|
},
|
|
));
|
|
}
|
|
|
|
/// This system lets you toggle various wireframe settings
|
|
fn update_colors(
|
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
mut config: ResMut<Wireframe2dConfig>,
|
|
mut wireframe_colors: Query<&mut Wireframe2dColor>,
|
|
mut text: Single<&mut Text>,
|
|
) {
|
|
text.0 = format!(
|
|
"Controls
|
|
---------------
|
|
Z - Toggle global
|
|
X - Change global color
|
|
C - Change color of the circle wireframe
|
|
|
|
Wireframe2dConfig
|
|
-------------
|
|
Global: {}
|
|
Color: {:?}",
|
|
config.global,
|
|
config.default_color.to_srgba(),
|
|
);
|
|
|
|
// Toggle showing a wireframe on all meshes
|
|
if keyboard_input.just_pressed(KeyCode::KeyZ) {
|
|
config.global = !config.global;
|
|
}
|
|
|
|
// Toggle the global wireframe color
|
|
if keyboard_input.just_pressed(KeyCode::KeyX) {
|
|
config.default_color = if config.default_color == WHITE.into() {
|
|
RED.into()
|
|
} else {
|
|
WHITE.into()
|
|
};
|
|
}
|
|
|
|
// Toggle the color of a wireframe using `Wireframe2dColor` and not the global color
|
|
if keyboard_input.just_pressed(KeyCode::KeyC) {
|
|
for mut color in &mut wireframe_colors {
|
|
color.color = if color.color == GREEN.into() {
|
|
RED.into()
|
|
} else {
|
|
GREEN.into()
|
|
};
|
|
}
|
|
}
|
|
}
|