Skip to content

Commit

Permalink
WebGL2 support (#3039)
Browse files Browse the repository at this point in the history
# Objective

Make possible to use wgpu gles backend on in the browser (wasm32 + WebGL2). 

## Solution

It is built on top of old @cart patch initializing windows before wgpu. Also:
- initializes wgpu with `Backends::GL` and proper `wgpu::Limits` on wasm32
- changes default texture format to `wgpu::TextureFormat::Rgba8UnormSrgb`



Co-authored-by: Mariusz Kryński <mrk@sed.pl>
  • Loading branch information
cart and mrk-its committed Oct 29, 2021
1 parent a2ea927 commit 4ad527d
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 30 deletions.
6 changes: 3 additions & 3 deletions crates/bevy_internal/src/default_plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ impl PluginGroup for PipelinedDefaultPlugins {
group.add(bevy_asset::AssetPlugin::default());
group.add(bevy_scene::ScenePlugin::default());

#[cfg(feature = "bevy_winit")]
group.add(bevy_winit::WinitPlugin::default());

#[cfg(feature = "bevy_render2")]
{
group.add(bevy_render2::RenderPlugin::default());
Expand All @@ -137,8 +140,5 @@ impl PluginGroup for PipelinedDefaultPlugins {
#[cfg(feature = "bevy_gltf2")]
group.add(bevy_gltf2::GltfPlugin::default());
}

#[cfg(feature = "bevy_winit")]
group.add(bevy_winit::WinitPlugin::default());
}
}
49 changes: 36 additions & 13 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ impl Plugin for WinitPlugin {
app.init_resource::<WinitWindows>()
.set_runner(winit_runner)
.add_system_to_stage(CoreStage::PostUpdate, change_window.exclusive_system());
let mut event_loop = EventLoop::new();
handle_initial_window_events(&mut app.world, &mut event_loop);
app.insert_non_send_resource(event_loop);
}
}

Expand Down Expand Up @@ -207,21 +210,22 @@ where
}

pub fn winit_runner(app: App) {
winit_runner_with(app, EventLoop::new());
winit_runner_with(app);
}

#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
pub fn winit_runner_any_thread(app: App) {
winit_runner_with(app, EventLoop::new_any_thread());
}

pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
// #[cfg(any(
// target_os = "linux",
// target_os = "dragonfly",
// target_os = "freebsd",
// target_os = "netbsd",
// target_os = "openbsd"
// ))]
// pub fn winit_runner_any_thread(app: App) {
// winit_runner_with(app, EventLoop::new_any_thread());
// }

pub fn winit_runner_with(mut app: App) {
let mut event_loop = app.world.remove_non_send::<EventLoop<()>>().unwrap();
let mut create_window_event_reader = ManualEventReader::<CreateWindow>::default();
let mut app_exit_event_reader = ManualEventReader::<AppExit>::default();
app.world.insert_non_send(event_loop.create_proxy());
Expand Down Expand Up @@ -525,3 +529,22 @@ fn handle_create_window_events(
});
}
}

fn handle_initial_window_events(world: &mut World, event_loop: &EventLoop<()>) {
let world = world.cell();
let mut winit_windows = world.get_resource_mut::<WinitWindows>().unwrap();
let mut windows = world.get_resource_mut::<Windows>().unwrap();
let mut create_window_events = world.get_resource_mut::<Events<CreateWindow>>().unwrap();
let mut window_created_events = world.get_resource_mut::<Events<WindowCreated>>().unwrap();
for create_window_event in create_window_events.drain() {
let window = winit_windows.create_window(
event_loop,
create_window_event.id,
&create_window_event.descriptor,
);
windows.add(window);
window_created_events.send(WindowCreated {
id: create_window_event.id,
});
}
}
3 changes: 3 additions & 0 deletions pipelined/bevy_render2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ parking_lot = "0.11.0"
regex = "1.5"
crevice = { path = "../../crates/crevice", version = "0.6.0" }

[target.'cfg(target_arch = "wasm32")'.dependencies]
wgpu = { version = "0.11.0", features = ["spirv", "webgl"] }

[features]
png = ["image/png"]
hdr = ["image/hdr"]
Expand Down
41 changes: 33 additions & 8 deletions pipelined/bevy_render2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,40 @@ struct ScratchRenderWorld(World);

impl Plugin for RenderPlugin {
fn build(&self, app: &mut App) {
let (instance, device, queue) =
futures_lite::future::block_on(renderer::initialize_renderer(
wgpu::util::backend_bits_from_env().unwrap_or(Backends::PRIMARY),
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
..Default::default()
let default_backend = if cfg!(not(target_arch = "wasm32")) {
Backends::PRIMARY
} else {
Backends::GL
};
let backends = wgpu::util::backend_bits_from_env().unwrap_or(default_backend);
let instance = wgpu::Instance::new(backends);
let surface = {
let world = app.world.cell();
let windows = world.get_resource_mut::<bevy_window::Windows>().unwrap();
let raw_handle = windows.get_primary().map(|window| unsafe {
let handle = window.raw_window_handle().get_handle();
instance.create_surface(&handle)
});
raw_handle
};
let (device, queue) = futures_lite::future::block_on(renderer::initialize_renderer(
&instance,
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: surface.as_ref(),
..Default::default()
},
&wgpu::DeviceDescriptor {
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
#[cfg(not(target_arch = "wasm32"))]
limits: wgpu::Limits::default(),
#[cfg(target_arch = "wasm32")]
limits: wgpu::Limits {
..wgpu::Limits::downlevel_webgl2_defaults()
},
&wgpu::DeviceDescriptor::default(),
));
..Default::default()
},
));
app.insert_resource(device.clone())
.insert_resource(queue.clone())
.add_asset::<Shader>()
Expand Down
8 changes: 3 additions & 5 deletions pipelined/bevy_render2/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,10 @@ pub type RenderQueue = Arc<Queue>;
pub type RenderInstance = Instance;

pub async fn initialize_renderer(
backends: Backends,
instance: &Instance,
request_adapter_options: &RequestAdapterOptions<'_>,
device_descriptor: &DeviceDescriptor<'_>,
) -> (RenderInstance, RenderDevice, RenderQueue) {
let instance = wgpu::Instance::new(backends);

) -> (RenderDevice, RenderQueue) {
let adapter = instance
.request_adapter(request_adapter_options)
.await
Expand All @@ -72,7 +70,7 @@ pub async fn initialize_renderer(
.unwrap();
let device = Arc::new(device);
let queue = Arc::new(queue);
(instance, RenderDevice::from(device), queue)
(RenderDevice::from(device), queue)
}

pub struct RenderContext {
Expand Down
2 changes: 1 addition & 1 deletion pipelined/bevy_render2/src/texture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub trait BevyDefault {

impl BevyDefault for wgpu::TextureFormat {
fn bevy_default() -> Self {
if cfg!(target_os = "android") {
if cfg!(target_os = "android") || cfg!(target_arch = "wasm32") {
// Bgra8UnormSrgb texture missing on some Android devices
wgpu::TextureFormat::Rgba8UnormSrgb
} else {
Expand Down

0 comments on commit 4ad527d

Please sign in to comment.