Skip to content

Commit

Permalink
Android Fix Attempt
Browse files Browse the repository at this point in the history
  • Loading branch information
ManevilleF committed Mar 1, 2022
1 parent 3f6068d commit fd898a3
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ jobs:
- name: Install Cargo APK
run: cargo install --force cargo-apk
- name: Build APK
run: cargo apk build --example android
run: cd examples/android && cargo apk build

markdownlint:
runs-on: ubuntu-latest
Expand Down
19 changes: 2 additions & 17 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repository = "https://github.com/bevyengine/bevy"

[workspace]
exclude = ["benches", "crates/bevy_ecs_compile_fail_tests"]
members = ["crates/*", "examples/ios", "tools/ci", "errors"]
members = ["crates/*", "examples/ios", "tools/ci", "errors", "examples/android"]

[features]
default = [
Expand Down Expand Up @@ -536,19 +536,4 @@ path = "examples/window/transparent_window.rs"

[[example]]
name = "window_settings"
path = "examples/window/window_settings.rs"

# Android
[[example]]
crate-type = ["cdylib"]
name = "android"
path = "examples/android/android.rs"

[package.metadata.android]
apk_label = "Bevy Example"
assets = "assets"
res = "assets/android-res"
icon = "@mipmap/ic_launcher"
build_targets = ["aarch64-linux-android", "armv7-linux-androideabi"]
min_sdk_version = 16
target_sdk_version = 29
path = "examples/window/window_settings.rs"
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::ops::Range;
use bevy_app::{App, Plugin};
use bevy_core::FloatOrd;
use bevy_ecs::prelude::*;
use bevy_render::texture::DEFAULT_DEPTH_FORMAT;
use bevy_render::{
camera::{ActiveCameras, CameraPlugin, RenderTarget},
color::Color,
Expand Down Expand Up @@ -414,8 +415,7 @@ pub fn prepare_core_views_system(
mip_level_count: 1,
sample_count: msaa.samples,
dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24
* bit depth for better performance */
format: DEFAULT_DEPTH_FORMAT,
usage: TextureUsages::RENDER_ATTACHMENT,
},
);
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub const MAX_POINT_LIGHT_SHADOW_MAPS: usize = 10;
pub const MAX_DIRECTIONAL_LIGHTS: usize = 1;
pub const POINT_SHADOW_LAYERS: u32 = (6 * MAX_POINT_LIGHT_SHADOW_MAPS) as u32;
pub const DIRECTIONAL_SHADOW_LAYERS: u32 = MAX_DIRECTIONAL_LIGHTS as u32;
pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float;
pub const SHADOW_FORMAT: TextureFormat = DEFAULT_DEPTH_FORMAT;

pub struct ShadowPipeline {
pub view_layout: BindGroupLayout,
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use bevy_ecs::{
};
use bevy_math::{Mat4, Size};
use bevy_reflect::TypeUuid;
use bevy_render::texture::DEFAULT_DEPTH_FORMAT;
use bevy_render::{
mesh::{GpuBufferInfo, Mesh, MeshVertexBufferLayout},
render_asset::RenderAssets,
Expand Down Expand Up @@ -477,7 +478,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
strip_index_format: None,
},
depth_stencil: Some(DepthStencilState {
format: TextureFormat::Depth32Float,
format: DEFAULT_DEPTH_FORMAT,
depth_write_enabled,
depth_compare: CompareFunction::Greater,
stencil: StencilState {
Expand Down
28 changes: 10 additions & 18 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub mod prelude {
};
}

use bevy_utils::tracing::debug;
use bevy_utils::tracing::{debug, info};
pub use once_cell;

use crate::{
Expand Down Expand Up @@ -122,25 +122,16 @@ impl Plugin for RenderPlugin {

if let Some(backends) = options.backends {
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),
let (device, adapter, queue, adapter_info) = futures_lite::future::block_on(
renderer::initialize_renderer(app, &instance, backends, &options),
);
debug!("Configured wgpu adapter Limits: {:#?}", &adapter.limits());
debug!(
"Configured wgpu adapter Features: {:#?}",
&adapter.features()
);
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
debug!("Configured wgpu adapter Features: {:#?}", device.features());
app.insert_resource(device.clone())
.insert_resource(adapter.clone())
.insert_resource(queue.clone())
.insert_resource(adapter_info.clone())
.init_resource::<ScratchRenderWorld>()
Expand Down Expand Up @@ -169,6 +160,7 @@ impl Plugin for RenderPlugin {
.add_stage(RenderStage::Cleanup, SystemStage::parallel())
.insert_resource(instance)
.insert_resource(device)
.insert_resource(adapter)
.insert_resource(queue)
.insert_resource(adapter_info)
.insert_resource(render_pipeline_cache)
Expand Down
101 changes: 89 additions & 12 deletions crates/bevy_render/src/renderer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
mod graph_runner;
mod render_device;

use bevy_utils::tracing::{info, info_span};
use bevy_utils::tracing::info_span;
pub use graph_runner::*;
pub use render_device::*;

use crate::{
info,
render_graph::RenderGraph,
settings::{WgpuSettings, WgpuSettingsPriority},
view::{ExtractedWindows, ViewTarget},
};
use bevy_ecs::prelude::*;
use std::sync::Arc;
use wgpu::{AdapterInfo, CommandEncoder, Instance, Queue, RequestAdapterOptions};
use wgpu::{Adapter, AdapterInfo, CommandEncoder, Instance, Queue};

/// Updates the [`RenderGraph`] with all of its nodes and then runs it to render the entire frame.
pub fn render_system(world: &mut World) {
Expand Down Expand Up @@ -57,24 +58,95 @@ pub fn render_system(world: &mut World) {
/// This queue is used to enqueue tasks for the GPU to execute asynchronously.
pub type RenderQueue = Arc<Queue>;

pub type RenderAdapter = Arc<Adapter>;

/// The GPU instance is used to initialize the [`RenderQueue`] and [`RenderDevice`],
/// aswell as to create [`WindowSurfaces`](crate::view::window::WindowSurfaces).
pub type RenderInstance = Instance;

/// Initializes the renderer by retrieving and preparing the GPU instance, device and queue
/// for the specified backend.
pub async fn initialize_renderer(
instance: &Instance,
#[cfg_attr(not(target_arch = "wasm32"), allow(unused))] app: &mut bevy_app::App,
instance: &wgpu::Instance,
#[cfg_attr(target_arch = "wasm32", allow(unused))] backends: wgpu::Backends,
options: &WgpuSettings,
request_adapter_options: &RequestAdapterOptions<'_>,
) -> (RenderDevice, RenderQueue, AdapterInfo) {
let adapter = instance
.request_adapter(request_adapter_options)
.await
.expect("Unable to find a GPU! Make sure you have installed required drivers!");
) -> (RenderDevice, RenderAdapter, RenderQueue, AdapterInfo) {
let adapter = {
#[cfg(not(target_arch = "wasm32"))]
{
use crate::texture::{BevyDefault as _, DEFAULT_DEPTH_FORMAT};
let mut adapters: Vec<wgpu::Adapter> = instance.enumerate_adapters(backends).collect();
let (mut integrated, mut discrete, mut virt, mut cpu, mut other) =
(None, None, None, None, None);

let adapter_info = adapter.get_info();
info!("{:?}", adapter_info);
for (i, adapter) in adapters.iter().enumerate() {
let default_texture_format_features =
adapter.get_texture_format_features(wgpu::TextureFormat::bevy_default());
let default_depth_format_features =
adapter.get_texture_format_features(DEFAULT_DEPTH_FORMAT);
if default_texture_format_features
.allowed_usages
.contains(wgpu::TextureUsages::RENDER_ATTACHMENT)
&& default_depth_format_features
.allowed_usages
.contains(wgpu::TextureUsages::RENDER_ATTACHMENT)
{
let info = adapter.get_info();
match info.device_type {
wgpu::DeviceType::IntegratedGpu => {
integrated = integrated.or(Some(i));
}
wgpu::DeviceType::DiscreteGpu => {
discrete = discrete.or(Some(i));
}
wgpu::DeviceType::VirtualGpu => {
virt = virt.or(Some(i));
}
wgpu::DeviceType::Cpu => {
cpu = cpu.or(Some(i));
}
wgpu::DeviceType::Other => {
other = other.or(Some(i));
}
}
}
}

let preferred_gpu_index = match options.power_preference {
wgpu::PowerPreference::LowPower => {
integrated.or(other).or(discrete).or(virt).or(cpu)
}
wgpu::PowerPreference::HighPerformance => {
discrete.or(other).or(integrated).or(virt).or(cpu)
}
}
.expect("Unable to find a GPU! Make sure you have installed required drivers!");

adapters.swap_remove(preferred_gpu_index)
}

#[cfg(target_arch = "wasm32")]
{
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
};
instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: options.power_preference,
compatible_surface: surface.as_ref(),
..Default::default()
})
.await
.expect("Unable to find a GPU! Make sure you have installed required drivers!")
}
};

#[cfg(feature = "wgpu_trace")]
let trace_path = {
Expand All @@ -89,6 +161,10 @@ pub async fn initialize_renderer(
// Maybe get features and limits based on what is supported by the adapter/backend
let mut features = wgpu::Features::empty();
let mut limits = options.limits.clone();

let adapter_info = adapter.get_info();
info!("{:?}", adapter_info);

if matches!(options.priority, WgpuSettingsPriority::Functionality) {
features = adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES;
if adapter_info.device_type == wgpu::DeviceType::DiscreteGpu {
Expand Down Expand Up @@ -212,8 +288,9 @@ pub async fn initialize_renderer(
.await
.unwrap();
let device = Arc::new(device);
let adapter = Arc::new(adapter);
let queue = Arc::new(queue);
(RenderDevice::from(device), queue, adapter_info)
(RenderDevice::from(device), adapter, queue, adapter_info)
}

/// The context with all information required to interact with the GPU.
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_render/src/texture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ impl Plugin for ImagePlugin {
}
}

// PERF: vulkan docs recommend using 24 bit depth for better performance
pub const DEFAULT_DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;

pub trait BevyDefault {
fn bevy_default() -> Self;
}
Expand Down
8 changes: 7 additions & 1 deletion crates/bevy_render/src/view/window.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::renderer::RenderAdapter;
use crate::{
render_resource::TextureView,
renderer::{RenderDevice, RenderInstance},
Expand Down Expand Up @@ -120,6 +121,7 @@ pub fn prepare_windows(
_marker: NonSend<NonSendMarker>,
mut windows: ResMut<ExtractedWindows>,
mut window_surfaces: ResMut<WindowSurfaces>,
render_adapter: Res<RenderAdapter>,
render_device: Res<RenderDevice>,
render_instance: Res<RenderInstance>,
) {
Expand All @@ -133,8 +135,12 @@ pub fn prepare_windows(
render_instance.create_surface(&window.handle.get_handle())
});

let surface_format = surface
.get_preferred_format(&render_adapter)
.unwrap_or_else(TextureFormat::bevy_default);

let swap_chain_descriptor = wgpu::SurfaceConfiguration {
format: TextureFormat::bevy_default(),
format: surface_format,
width: window.physical_width,
height: window.physical_height,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
Expand Down
13 changes: 8 additions & 5 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ impl Plugin for WinitPlugin {
.set_runner(winit_runner)
.add_system_to_stage(CoreStage::PostUpdate, change_window.exclusive_system());
let event_loop = EventLoop::new();
// TODO: Required for WebGL. Currently breaks only android initialization. Should be a part of init system
#[cfg(not(target_os = "android"))]
handle_initial_window_events(&mut app.world, &event_loop);
app.insert_non_send_resource(event_loop);
}
Expand Down Expand Up @@ -499,12 +501,12 @@ pub fn winit_runner_with(mut app: App) {
active = true;
}
event::Event::MainEventsCleared => {
handle_create_window_events(
&mut app.world,
event_loop,
&mut create_window_event_reader,
);
if active {
handle_create_window_events(
&mut app.world,
event_loop,
&mut create_window_event_reader,
);
app.update();
}
}
Expand Down Expand Up @@ -541,6 +543,7 @@ fn handle_create_window_events(
}
}

#[cfg(not(target_os = "android"))]
fn handle_initial_window_events(world: &mut World, event_loop: &EventLoop<()>) {
let world = world.cell();
let mut winit_windows = world.get_non_send_mut::<WinitWindows>().unwrap();
Expand Down
9 changes: 3 additions & 6 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ When using `NDK (Side by side)`, the environment variable `ANDROID_NDK_ROOT` mus
To run on a device setup for Android development, run:

```sh
cargo apk run --example android
cd examples/android
cargo apk run
```

:warning: At this time Bevy does not work in Android Emulator.
Expand All @@ -308,18 +309,14 @@ Bevy by default targets Android API level 29 in its examples which is the <!-- m
[Play Store's minimum API to upload or update apps](https://developer.android.com/distribute/best-practices/develop/target-sdk). <!-- markdown-link-check-enable -->
Users of older phones may want to use an older API when testing.

To use a different API, the following fields must be updated in Cargo.toml:
To use a different API, the following fields must be updated in [Cargo.toml](./android/Cargo.toml):

```toml
[package.metadata.android]
target_sdk_version = >>API<<
min_sdk_version = >>API or less<<
```

Example | File | Description
--- | --- | ---
`android` | [`android/android.rs`](./android/android.rs) | The `3d/3d_scene.rs` example for Android

## iOS

### Setup
Expand Down
Loading

0 comments on commit fd898a3

Please sign in to comment.