Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Make raw_window_handle field in Window and ExtractedWindow an Option. #6114

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 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
352 changes: 179 additions & 173 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,181 +140,187 @@ impl Plugin for RenderPlugin {
.register_type::<Color>();

if let Some(backends) = options.backends {
let windows = app.world.resource_mut::<bevy_window::Windows>();
let instance = wgpu::Instance::new(backends);
let surface = {
let windows = app.world.resource_mut::<bevy_window::Windows>();
let raw_handle = windows.get_primary().map(|window| unsafe {
let handle = window.raw_window_handle().get_handle();
instance.create_surface(&handle)
});
raw_handle
};
let request_adapter_options = wgpu::RequestAdapterOptions {
power_preference: options.power_preference,
compatible_surface: surface.as_ref(),
..Default::default()
};
let (device, queue, adapter_info) = futures_lite::future::block_on(
renderer::initialize_renderer(&instance, &options, &request_adapter_options),
);
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
debug!("Configured wgpu adapter Features: {:#?}", device.features());
app.insert_resource(device.clone())
.insert_resource(queue.clone())
.insert_resource(adapter_info.clone())
.init_resource::<ScratchMainWorld>()
.register_type::<Frustum>()
.register_type::<CubemapFrusta>();

let pipeline_cache = PipelineCache::new(device.clone());
let asset_server = app.world.resource::<AssetServer>().clone();

let mut render_app = App::empty();
let mut extract_stage =
SystemStage::parallel().with_system(PipelineCache::extract_shaders);
// Get the ComponentId for MainWorld. This does technically 'waste' a `WorldId`, but that's probably fine
render_app.init_resource::<MainWorld>();
render_app.world.remove_resource::<MainWorld>();
let main_world_in_render = render_app
.world
.components()
.get_resource_id(TypeId::of::<MainWorld>());
// `Extract` systems must read from the main world. We want to emit an error when that doesn't occur
// Safe to unwrap: Ensured it existed just above
extract_stage.set_must_read_resource(main_world_in_render.unwrap());
// don't apply buffers when the stage finishes running
// extract stage runs on the render world, but buffers are applied
// after access to the main world is removed
// See also https://github.com/bevyengine/bevy/issues/5082
extract_stage.set_apply_buffers(false);
render_app
.add_stage(RenderStage::Extract, extract_stage)
.add_stage(RenderStage::Prepare, SystemStage::parallel())
.add_stage(RenderStage::Queue, SystemStage::parallel())
.add_stage(RenderStage::PhaseSort, SystemStage::parallel())
.add_stage(
RenderStage::Render,
SystemStage::parallel()
.with_system(PipelineCache::process_pipeline_queue_system)
.with_system(render_system.at_end()),
)
.add_stage(RenderStage::Cleanup, SystemStage::parallel())
.init_resource::<RenderGraph>()
.insert_resource(RenderInstance(instance))
.insert_resource(device)
.insert_resource(queue)
.insert_resource(adapter_info)
.insert_resource(pipeline_cache)
.insert_resource(asset_server);

let (sender, receiver) = bevy_time::create_time_channels();
app.insert_resource(receiver);
render_app.insert_resource(sender);

app.add_sub_app(RenderApp, render_app, move |app_world, render_app| {
#[cfg(feature = "trace")]
let _render_span = bevy_utils::tracing::info_span!("renderer subapp").entered();
{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "reserve_and_flush")
.entered();

// reserve all existing app entities for use in render_app
// they can only be spawned using `get_or_spawn()`
let meta_len = app_world.entities().meta_len();
render_app
.world
.entities()
.reserve_entities(meta_len as u32);

// flushing as "invalid" ensures that app world entities aren't added as "empty archetype" entities by default
// these entities cannot be accessed without spawning directly onto them
// this _only_ works as expected because clear_entities() is called at the end of every frame.
unsafe { render_app.world.entities_mut() }.flush_as_invalid();
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "extract").entered();

// extract
extract(app_world, render_app);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "prepare").entered();

// prepare
let prepare = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Prepare)
.unwrap();
prepare.run(&mut render_app.world);
}

{
if let Some(window) = windows.get_primary() {
targrub marked this conversation as resolved.
Show resolved Hide resolved
targrub marked this conversation as resolved.
Show resolved Hide resolved
let surface = {
if let Some(raw_window_handle) = window.raw_window_handle() {
unsafe {
let handle = raw_window_handle.get_handle();
Some(instance.create_surface(&handle))
}
} else {
None
}
};
let request_adapter_options = wgpu::RequestAdapterOptions {
power_preference: options.power_preference,
compatible_surface: surface.as_ref(),
..Default::default()
};
let (device, queue, adapter_info) = futures_lite::future::block_on(
renderer::initialize_renderer(&instance, &options, &request_adapter_options),
);
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
debug!("Configured wgpu adapter Features: {:#?}", device.features());
app.insert_resource(device.clone())
.insert_resource(queue.clone())
.insert_resource(adapter_info.clone())
.init_resource::<ScratchMainWorld>()
.register_type::<Frustum>()
.register_type::<CubemapFrusta>();

let pipeline_cache = PipelineCache::new(device.clone());
let asset_server = app.world.resource::<AssetServer>().clone();

let mut render_app = App::empty();
let mut extract_stage =
SystemStage::parallel().with_system(PipelineCache::extract_shaders);
// Get the ComponentId for MainWorld. This does technically 'waste' a `WorldId`, but that's probably fine
render_app.init_resource::<MainWorld>();
render_app.world.remove_resource::<MainWorld>();
let main_world_in_render = render_app
.world
.components()
.get_resource_id(TypeId::of::<MainWorld>());
// `Extract` systems must read from the main world. We want to emit an error when that doesn't occur
// Safe to unwrap: Ensured it existed just above
extract_stage.set_must_read_resource(main_world_in_render.unwrap());
// don't apply buffers when the stage finishes running
// extract stage runs on the render world, but buffers are applied
// after access to the main world is removed
// See also https://github.com/bevyengine/bevy/issues/5082
extract_stage.set_apply_buffers(false);
render_app
.add_stage(RenderStage::Extract, extract_stage)
.add_stage(RenderStage::Prepare, SystemStage::parallel())
.add_stage(RenderStage::Queue, SystemStage::parallel())
.add_stage(RenderStage::PhaseSort, SystemStage::parallel())
.add_stage(
RenderStage::Render,
SystemStage::parallel()
.with_system(PipelineCache::process_pipeline_queue_system)
.with_system(render_system.at_end()),
)
.add_stage(RenderStage::Cleanup, SystemStage::parallel())
.init_resource::<RenderGraph>()
.insert_resource(RenderInstance(instance))
.insert_resource(device)
.insert_resource(queue)
.insert_resource(adapter_info)
.insert_resource(pipeline_cache)
.insert_resource(asset_server);

let (sender, receiver) = bevy_time::create_time_channels();
app.insert_resource(receiver);
render_app.insert_resource(sender);

app.add_sub_app(RenderApp, render_app, move |app_world, render_app| {
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "queue").entered();

// queue
let queue = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Queue)
.unwrap();
queue.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "sort").entered();

// phase sort
let phase_sort = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::PhaseSort)
.unwrap();
phase_sort.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "render").entered();

// render
let render = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Render)
.unwrap();
render.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "cleanup").entered();

// cleanup
let cleanup = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Cleanup)
.unwrap();
cleanup.run(&mut render_app.world);
}
{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "clear_entities").entered();

render_app.world.clear_entities();
}
});
let _render_span = bevy_utils::tracing::info_span!("renderer subapp").entered();
{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "reserve_and_flush")
.entered();

// reserve all existing app entities for use in render_app
// they can only be spawned using `get_or_spawn()`
let meta_len = app_world.entities().meta_len();
render_app
.world
.entities()
.reserve_entities(meta_len as u32);

// flushing as "invalid" ensures that app world entities aren't added as "empty archetype" entities by default
// these entities cannot be accessed without spawning directly onto them
// this _only_ works as expected because clear_entities() is called at the end of every frame.
unsafe { render_app.world.entities_mut() }.flush_as_invalid();
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "extract").entered();

// extract
extract(app_world, render_app);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "prepare").entered();

// prepare
let prepare = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Prepare)
.unwrap();
prepare.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "queue").entered();

// queue
let queue = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Queue)
.unwrap();
queue.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "sort").entered();

// phase sort
let phase_sort = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::PhaseSort)
.unwrap();
phase_sort.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "render").entered();

// render
let render = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Render)
.unwrap();
render.run(&mut render_app.world);
}

{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "cleanup").entered();

// cleanup
let cleanup = render_app
.schedule
.get_stage_mut::<SystemStage>(RenderStage::Cleanup)
.unwrap();
cleanup.run(&mut render_app.world);
}
{
#[cfg(feature = "trace")]
let _stage_span =
bevy_utils::tracing::info_span!("stage", name = "clear_entities")
.entered();

render_app.world.clear_entities();
}
});
}
}

app.add_plugin(ValidParentCheckPlugin::<ComputedVisibility>::default())
Expand Down
Loading