-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Refactor the gles choose config, add gl library path in gl options #8794
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
base: trunk
Are you sure you want to change the base?
Conversation
|
Thanks for this! Is there a related issue, preferably with logs of these failures on the devices you mentioned? Also, just a side note, we are switching away from manually using EGL/WGL into using glutin, so unless this is also a problem there, expect this to be fixed as a side-effect at some point. I don't however know on what timeframe the switch to glutin will happen. |
|
@inner-daemons You can take a look at my other pr(#8809). It roughly initializes the OpenGL environment using glutin. This should be helpful for porting to glutin. Moreover, glutin also has this issue. The error message for this problem is that the address obtained from eglGetProcAddress for glGetString is null. |
|
@ZengGengSen You haven't yet provided any logs about this supposed error. Until you do so this PR won't be considered for merging. Please file an issue with logs and steps to reproduce. I'd also be very surprised if your glutin PR is merged though I haven't taken a close look yet. I know orher maintainers were planning to tackle this themselves. |
|
@inner-daemons I want to wait for the results from glutin before addressing the pointer fetching issue (either by merging my pr, or if the dev team has a better idea). A new pull request will be created at that time to address the issue with the pointers. The solutions to some of the issues in my glutin's pr are not very good. There are some parts that are not particularly elegant. This situation is related to the conflict between the architecture of wgpu and that of glutin. If we want to use the code in this pr, it might require certain modifications to the structure of wgpu. This aspect is likely to require research by other developers who have a better understanding of this area. Hope this can be of some help to the development team |
|
@ZengGengSen Neither PR will be discussed at all until you can provide logs of the errors. Paraphrasing in text doesn't count. |
|
Also, can I ask you. For what tasks (if any) are you using LLMs or AI like ChatGPT? Are these errors discovered by such a tool? Is the code written by such a tool? Are you using one for translating? |
|
At the beginning, I was using it on my embedded Linux. so I wrote code. fn run_with_fbdev() -> Result<(), Box<dyn std::error::Error>> {
use std::{ffi, ptr, sync::Arc};
use glutin_egl_sys::egl;
use raw_window_handle as rwh;
#[derive(Debug)]
struct Window {
display: rwh::RawDisplayHandle,
window: rwh::RawWindowHandle,
}
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
impl rwh::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh::DisplayHandle<'_>, rwh::HandleError> {
Ok(unsafe { rwh::DisplayHandle::borrow_raw(self.display) })
}
}
impl rwh::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh::WindowHandle<'_>, rwh::HandleError> {
Ok(unsafe { rwh::WindowHandle::borrow_raw(self.window) })
}
}
let raw_display = rwh::GbmDisplayHandle::new(unsafe {
ptr::NonNull::new_unchecked(egl::DEFAULT_DISPLAY as *mut ffi::c_void)
})
.into();
let raw_window =
rwh::GbmWindowHandle::new(unsafe { ptr::NonNull::new_unchecked(ptr::null_mut()) }).into();
let window = Arc::new(Window {
display: raw_display,
window: raw_window,
});
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::GL,
display: Some(Box::new(window.clone())),
backend_options: wgpu::BackendOptions {
gl: wgpu::GlBackendOptions {
..Default::default()
},
..Default::default()
},
..Default::default()
});
let surface = instance
.create_surface(window)
.expect("Cannot create surface");
let renderer =
pollster::block_on(renderer::WGPURenderer::new(&instance, &surface, 720, 720)).unwrap();
loop {
renderer.render(&surface).unwrap();
// std::thread::sleep(std::time::Duration::from_millis(16));
}
Ok(())
}The Result is > adb shell /fbgpu
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] Client extensions: []
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] No (or unknown) windowing system (Some(Gbm(GbmDisplayHandle { gbm_device: 0x0 })), None) and EGL_MESA_platform_surfaceless not available. Using default platform
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] Display vendor "Imagination Technologies", version (1, 4)
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] Display extensions: [
"EGL_KHR_image",
"EGL_KHR_image_base",
"EGL_KHR_gl_texture_2D_image",
"EGL_KHR_gl_texture_cubemap_image",
"EGL_KHR_gl_texture_3D_image",
"EGL_KHR_gl_renderbuffer_image",
"EGL_IMG_cl_image",
"EGL_KHR_fence_sync",
"EGL_KHR_wait_sync",
"EGL_EXT_create_context_robustness",
"EGL_IMG_image_plane_attribs",
"EGL_EXT_swap_buffers_with_damage",
"EGL_KHR_swap_buffers_with_damage",
"EGL_KHR_partial_update",
"EGL_EXT_buffer_age",
"EGL_EXT_image_dma_buf_import",
"EGL_EXT_image_dma_buf_import_modifiers",
"EGL_EXT_yuv_surface",
"EGL_IMG_context_priority",
"EGL_KHR_create_context",
"EGL_KHR_surfaceless_context",
"EGL_KHR_no_config_context",
"EGL_KHR_gl_colorspace",
"EGL_EXT_image_gl_colorspace",
]
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] EGL surface: +srgb khr
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] Trying native-render
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] No config found!
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] Trying presentation
[1970-03-03T01:23:46Z INFO wgpu_hal::gles::egl] EGL says it can present to the window but not natively
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] EGL context: +robust access EXT
[1970-03-03T01:23:46Z DEBUG wgpu_hal::gles::egl] EGL context: +surfaceless
[1970-03-03T01:23:46Z DEBUG wgpu_core::instance] Instance::new: created Gl backend
[1970-03-03T01:23:46Z DEBUG wgpu_core::instance] Instance::create_surface: failed to create surface for Gl: InstanceError { message: "unsupported window: (Gbm(GbmWindowHandle { gbm_surface: 0x0 }), Gbm(GbmDisplayHandle { gbm_device: 0x0 }))", source: None }
thread 'main' (8200) panicked at src/main.rs:142:10:
Cannot create surface: CreateSurfaceError { inner: Hal(FailedToCreateSurfaceForAnyBackend({Gl: InstanceError { message: "unsupported window: (Gbm(GbmWindowHandle { gbm_surface: 0x0 }), Gbm(GbmDisplayHandle { gbm_device: 0x0 }))", source: None }})) }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace |
|
So I Directly add gbm support in the code diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs
index 606d1b2d4..c565d0cfb 100644
--- a/wgpu-hal/src/gles/egl.rs
+++ b/wgpu-hal/src/gles/egl.rs
@@ -814,6 +814,14 @@ impl crate::Instance for Instance {
.map_err(instance_err("failed to get Angle display"))?;
(display, WindowKind::AngleX11)
}
+ (Some(Rdh::Gbm(display)), _) => {
+ log::debug!("Using GBM platform");
+ let display = unsafe { egl.get_display(display.gbm_device.as_ptr() as *mut _) }
+ .ok_or_else(|| {
+ crate::InstanceError::new("Failed to get default display".into())
+ })?;
+ (display, WindowKind::Unknown)
+ }
(Some(Rdh::Xcb(_xcb_display_handle)), Some(_egl)) => todo!("xcb"),
x if client_ext_str.contains("EGL_MESA_platform_surfaceless") => {
log::debug!(
@@ -937,6 +945,7 @@ impl crate::Instance for Instance {
(Rwh::Wayland(_), _) => {}
#[cfg(Emscripten)]
(Rwh::Web(_), _) => {}
+ (Rwh::Gbm(_), _) => {}
other => {
return Err(crate::InstanceError::new(format!(
"unsupported window: {other:?}"
@@ -1261,6 +1270,9 @@ impl crate::Surface for Surface {
};
window_ptr
}
+ (WindowKind::Unknown, Rwh::Gbm(handle)) => {
+ handle.gbm_surface.as_ptr() as *mut ffi::c_void
+ }
_ => {
log::warn!(
"Initialized platform {:?} doesn't work with window {:?}",The Result is > adb shell RUST_LOG=debug /fbgpu
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] Client extensions: []
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] No (or unknown) windowing system (Some(Gbm(GbmDisplayHandle { gbm_device: 0x0 })), None) and EGL_MESA_platform_surfaceless not available. Using default platform
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] Display vendor "Imagination Technologies", version (1, 4)
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] Display extensions: [
"EGL_KHR_image",
"EGL_KHR_image_base",
"EGL_KHR_gl_texture_2D_image",
"EGL_KHR_gl_texture_cubemap_image",
"EGL_KHR_gl_texture_3D_image",
"EGL_KHR_gl_renderbuffer_image",
"EGL_IMG_cl_image",
"EGL_KHR_fence_sync",
"EGL_KHR_wait_sync",
"EGL_EXT_create_context_robustness",
"EGL_IMG_image_plane_attribs",
"EGL_EXT_swap_buffers_with_damage",
"EGL_KHR_swap_buffers_with_damage",
"EGL_KHR_partial_update",
"EGL_EXT_buffer_age",
"EGL_EXT_image_dma_buf_import",
"EGL_EXT_image_dma_buf_import_modifiers",
"EGL_EXT_yuv_surface",
"EGL_IMG_context_priority",
"EGL_KHR_create_context",
"EGL_KHR_surfaceless_context",
"EGL_KHR_no_config_context",
"EGL_KHR_gl_colorspace",
"EGL_EXT_image_gl_colorspace",
]
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] EGL surface: +srgb khr
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] Trying native-render
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] No config found!
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] Trying presentation
[1970-03-03T01:31:00Z INFO wgpu_hal::gles::egl] EGL says it can present to the window but not natively
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] EGL context: +robust access EXT
[1970-03-03T01:31:00Z DEBUG wgpu_hal::gles::egl] EGL context: +surfaceless
[1970-03-03T01:31:00Z DEBUG wgpu_core::instance] Instance::new: created Gl backend
thread 'main' (8255) panicked at /home/ubuntu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/glow-0.16.0/src/gl46.rs:4515:5:
called glGetString but it was not loaded.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace |
|
Add an external interface for the gl library, allowing users to provide the path of the gl library for direct reading. diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs
index 606d1b2d4..ee5055b0e 100644
--- a/wgpu-hal/src/gles/egl.rs
+++ b/wgpu-hal/src/gles/egl.rs
@@ -680,6 +680,8 @@ pub struct Instance {
flags: wgt::InstanceFlags,
options: wgt::GlBackendOptions,
inner: Mutex<Inner>,
+ #[cfg(not(Emscripten))]
+ gl_library: Option<Arc<libloading::Library>>,
}
impl Instance {
@@ -885,6 +887,15 @@ impl crate::Instance for Instance {
flags: desc.flags,
options: desc.backend_options.gl.clone(),
inner: Mutex::new(inner),
+ #[cfg(not(Emscripten))]
+ gl_library: desc
+ .backend_options
+ .gl
+ .gl_library
+ .as_ref()
+ .map_or(None, |path| {
+ unsafe { libloading::Library::new(path) }.map(Arc::new).ok()
+ }),
})
}
@@ -964,14 +975,43 @@ impl crate::Instance for Instance {
let inner = self.inner.lock();
inner.egl.make_current();
- let mut gl = unsafe {
- glow::Context::from_loader_function(|name| {
+ let mut gl = {
+ let egl_load_func = |name: &str| {
inner
.egl
.instance
.get_proc_address(name)
.map_or(ptr::null(), |p| p as *const _)
- })
+ };
+
+ #[cfg(not(Emscripten))]
+ {
+ if let Some(ref library) = self.gl_library {
+ unsafe {
+ glow::Context::from_loader_function(|name| {
+ let symbol_name = std::ffi::CString::new(name).unwrap();
+ let ptr = match library
+ .get::<*const ffi::c_void>(symbol_name.as_bytes_with_nul())
+ {
+ Ok(symbol) => *symbol,
+ Err(_) => ptr::null(),
+ };
+ if ptr.is_null() {
+ egl_load_func(name)
+ } else {
+ ptr
+ }
+ })
+ }
+ } else {
+ unsafe { glow::Context::from_loader_function(egl_load_func) }
+ }
+ }
+
+ #[cfg(Emscripten)]
+ {
+ unsafe { glow::Context::from_loader_function(egl_load_func) }
+ }
};
// In contrast to OpenGL ES, OpenGL requires explicitly enabling sRGB conversions,
diff --git a/wgpu-types/src/backend.rs b/wgpu-types/src/backend.rs
index 5c6fa2980..20d7399ab 100644
--- a/wgpu-types/src/backend.rs
+++ b/wgpu-types/src/backend.rs
@@ -252,6 +252,8 @@ pub struct GlBackendOptions {
pub gles_minor_version: Gles3MinorVersion,
/// Behavior of OpenGL fences. Affects how `on_completed_work_done` and `device.poll` behave.
pub fence_behavior: GlFenceBehavior,
+ /// The GL library path to load, if any.
+ pub gl_library: Option<String>,
}
impl GlBackendOptions {
@@ -264,6 +266,7 @@ impl GlBackendOptions {
Self {
gles_minor_version,
fence_behavior: GlFenceBehavior::Normal,
+ gl_library: None,
}
}
@@ -277,6 +280,7 @@ impl GlBackendOptions {
Self {
gles_minor_version,
fence_behavior: short_circuit_fences,
+ gl_library: None,
}
}
}
diff --git a/wgpu-types/src/surface.rs b/wgpu-types/src/surface.rs
index 316135323..fc01a1801 100644
--- a/wgpu-types/src/surface.rs
+++ b/wgpu-types/src/surface.rs
@@ -105,7 +105,7 @@ pub enum PresentMode {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum CompositeAlphaMode {
- /// Chooses either `Opaque` or `Inherit` automatically, depending on the
+ /// Chooses either `Opaque` or `Inherit` automatically,depending on the
/// `alpha_mode` that the current surface can support.
#[default]
Auto = 0,
diff --git a/src/main.rs b/src/main.rs
index 6212408..af10d5e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -129,6 +129,7 @@ fn run_with_fbdev() -> Result<(), Box<dyn std::error::Error>> {
// window: Some(Box::new(window.clone())),
backend_options: wgpu::BackendOptions {
gl: wgpu::GlBackendOptions {
+ gl_library: Some("libGLESv2.so.2".to_string()),
..Default::default()
},
..Default::default()I found that the problem lies in the "choose_config" function. let (config, supports_native_window) = choose_config(&egl, display, srgb_kind)?;It return the > adb shell /fdgpu
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] Client extensions: []
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] No (or unknown) windowing system (Some(Gbm(GbmDisplayHandle { gbm_device: 0x0 })), None) and EGL_MESA_platform_surfaceless not available. Using default platform
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] Display vendor "Imagination Technologies", version (1, 4)
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] Display extensions: [
"EGL_KHR_image",
"EGL_KHR_image_base",
"EGL_KHR_gl_texture_2D_image",
"EGL_KHR_gl_texture_cubemap_image",
"EGL_KHR_gl_texture_3D_image",
"EGL_KHR_gl_renderbuffer_image",
"EGL_IMG_cl_image",
"EGL_KHR_fence_sync",
"EGL_KHR_wait_sync",
"EGL_EXT_create_context_robustness",
"EGL_IMG_image_plane_attribs",
"EGL_EXT_swap_buffers_with_damage",
"EGL_KHR_swap_buffers_with_damage",
"EGL_KHR_partial_update",
"EGL_EXT_buffer_age",
"EGL_EXT_image_dma_buf_import",
"EGL_EXT_image_dma_buf_import_modifiers",
"EGL_EXT_yuv_surface",
"EGL_IMG_context_priority",
"EGL_KHR_create_context",
"EGL_KHR_surfaceless_context",
"EGL_KHR_no_config_context",
"EGL_KHR_gl_colorspace",
"EGL_EXT_image_gl_colorspace",
]
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] EGL surface: +srgb khr
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] Trying native-render
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] No config found!
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] Trying presentation
[1970-03-03T01:43:44Z INFO wgpu_hal::gles::egl] EGL says it can present to the window but not natively
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] EGL context: +robust access EXT
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::egl] EGL context: +surfaceless
[1970-03-03T01:43:44Z DEBUG wgpu_core::instance] Instance::new: created Gl backend
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::adapter] Vendor: Imagination Technologies
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::adapter] Renderer: PowerVR Rogue GE8300
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::adapter] Version: OpenGL ES 3.2 build 1.19@6345021
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::adapter] SL version: OpenGL ES GLSL ES 3.20 build 1.19@6345021
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::adapter] Supported GL Extensions: {
"GL_EXT_texture_format_BGRA8888",
"GL_OES_rgb8_rgba8",
"GL_OES_sample_variables",
"GL_OES_texture_half_float",
"GL_OES_texture_npot",
"GL_EXT_shader_framebuffer_fetch",
"GL_EXT_sRGB_write_control",
"GL_EXT_compressed_ETC1_RGB8_sub_texture",
"GL_EXT_memory_object_fd",
"GL_EXT_polygon_offset_clamp",
"GL_ANDROID_extension_pack_es31a",
"GL_EXT_tessellation_shader",
"GL_EXT_texture_buffer",
"GL_IMG_shader_binary",
"GL_EXT_texture_rg",
"GL_EXT_geometry_shader",
"GL_KHR_blend_equation_advanced",
"GL_EXT_robustness",
"GL_OES_depth_texture",
"GL_EXT_occlusion_query_boolean",
"GL_EXT_color_buffer_half_float",
"GL_EXT_conservative_depth",
"GL_APPLE_texture_format_BGRA8888",
"GL_EXT_draw_buffers_indexed",
"GL_EXT_separate_shader_objects",
"GL_EXT_shader_io_blocks",
"GL_EXT_tessellation_point_size",
"GL_EXT_draw_elements_base_vertex",
"GL_EXT_memory_object",
"GL_IMG_multisampled_render_to_texture",
"GL_IMG_texture_compression_pvrtc2",
"GL_KHR_texture_compression_astc_ldr",
"GL_EXT_texture_sRGB_R8",
"GL_EXT_shader_pixel_local_storage2",
"GL_OES_compressed_ETC1_RGB8_texture",
"GL_EXT_pvrtc_sRGB",
"GL_OES_EGL_image",
"GL_EXT_float_blend",
"GL_IMG_program_binary",
"GL_OES_draw_elements_base_vertex",
"GL_IMG_framebuffer_downsample",
"GL_EXT_EGL_image_array",
"GL_EXT_discard_framebuffer",
"GL_OES_get_program_binary",
"GL_IMG_texture_compression_pvrtc",
"GL_OES_sample_shading",
"GL_OES_shader_image_atomic",
"GL_IMG_texture_npot",
"GL_OES_shader_io_blocks",
"GL_EXT_buffer_storage",
"GL_OES_texture_3D",
"GL_OES_texture_buffer",
"GL_OES_texture_cube_map_array",
"GL_OES_texture_border_clamp",
"GL_EXT_texture_format_sRGB_override",
"GL_EXT_texture_sRGB_decode",
"GL_EXT_texture_border_clamp",
"GL_EXT_multisampled_render_to_texture",
"GL_EXT_gpu_shader5",
"GL_EXT_read_format_bgra",
"GL_EXT_shader_group_vote",
"GL_EXT_shader_implicit_conversions",
"GL_EXT_YUV_target",
"GL_EXT_texture_sRGB_RG8",
"GL_OES_geometry_point_size",
"GL_EXT_texture_cube_map_array",
"GL_OES_geometry_shader",
"GL_OES_surfaceless_context",
"GL_OES_tessellation_point_size",
"GL_OES_tessellation_shader",
"GL_OES_texture_float",
"GL_EXT_color_buffer_float",
"GL_OES_texture_stencil8",
"GL_EXT_sparse_texture",
"GL_EXT_sRGB",
"GL_EXT_shader_texture_lod",
"GL_EXT_shadow_samplers",
"GL_EXT_copy_image",
"GL_OES_required_internalformat",
"GL_OES_vertex_array_object",
"GL_EXT_clear_texture",
"GL_EXT_draw_buffers",
"GL_EXT_multisampled_render_to_texture2",
"GL_EXT_clip_control",
"GL_EXT_shader_non_constant_global_initializers",
"GL_OES_depth_texture_cube_map",
"GL_OES_depth24",
"GL_OES_mapbuffer",
"GL_EXT_multi_draw_arrays",
"GL_OES_fragment_precision_high",
"GL_OES_packed_depth_stencil",
"GL_EXT_unpack_subimage",
"GL_OES_standard_derivatives",
"GL_OES_vertex_half_float",
"GL_KHR_blend_equation_advanced_coherent",
"GL_EXT_shader_pixel_local_storage",
"GL_IMG_read_format",
"GL_OES_element_index_uint",
"GL_EXT_texture_shadow_lod",
"GL_EXT_geometry_point_size",
"GL_EXT_texture_type_2_10_10_10_REV",
"GL_OES_texture_storage_multisample_2d_array",
"GL_OES_draw_buffers_indexed",
"GL_IMG_texture_format_BGRA8888",
"GL_OES_shader_multisample_interpolation",
"GL_EXT_blend_minmax",
"GL_EXT_primitive_bounding_box",
"GL_KHR_debug",
"GL_KHR_robustness",
"GL_OES_EGL_sync",
"GL_OES_gpu_shader5",
}
[1970-03-03T01:43:44Z DEBUG wgpu_core::instance] Found 1 compatible adapters. Sorted by preference:
[1970-03-03T01:43:44Z DEBUG wgpu_core::instance] * AdapterInfo { name: "PowerVR Rogue GE8300", vendor: 0, device: 0, device_type: Other, device_pci_bus_id: "", driver: "", driver_info: "OpenGL ES 3.2 build 1.19@6345021", backend: Gl, subgroup_min_size: 4, subgroup_max_size: 128, transient_saves_memory: false }
[1970-03-03T01:43:44Z DEBUG wgpu_core::instance] Request adapter result AdapterInfo { name: "PowerVR Rogue GE8300", vendor: 0, device: 0, device_type: Other, device_pci_bus_id: "", driver: "", driver_info: "OpenGL ES 3.2 build 1.19@6345021", backend: Gl, subgroup_min_size: 4, subgroup_max_size: 128, transient_saves_memory: false }
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::device] Naga generated shader:
#version 320 es
precision highp float;
precision highp int;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
struct OffsetPc {
uint inner;
};
layout(std430, binding = 0) buffer type_1_block_0Compute { uint _group_0_binding_0_cs[6]; };
layout(std430, binding = 1) readonly buffer type_2_block_1Compute { uint _group_1_binding_0_cs[]; };
uniform OffsetPc _immediates_binding_cs;
void main() {
bool local = false;
bool local_1 = false;
uint _e3 = _immediates_binding_cs.inner;
uint _e5 = _group_1_binding_0_cs[_e3];
uint _e9 = _immediates_binding_cs.inner;
uint _e13 = _group_1_binding_0_cs[(_e9 + 1u)];
uint _e17 = _immediates_binding_cs.inner;
uint _e21 = _group_1_binding_0_cs[(_e17 + 2u)];
uvec3 src_1 = uvec3(_e5, _e13, _e21);
if (!((src_1.x > 65535u))) {
local = (src_1.y > 65535u);
} else {
local = true;
}
bool _e32 = local;
if (!(_e32)) {
local_1 = (src_1.z > 65535u);
} else {
local_1 = true;
}
bool _e39 = local_1;
if (_e39) {
_group_0_binding_0_cs = uint[6](0u, 0u, 0u, 0u, 0u, 0u);
return;
} else {
_group_0_binding_0_cs = uint[6](src_1.x, src_1.y, src_1.z, src_1.x, src_1.y, src_1.z);
return;
}
}
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::device] Compiled shader NativeShader(2)
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::device] Linked program NativeProgram(1)
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::device] Naga generated shader:
#version 320 es
precision highp float;
precision highp int;
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
struct MetadataEntry {
uint src_offset;
uint dst_offset;
uint vertex_or_index_limit;
uint instance_limit;
};
struct MetadataRange {
uint start;
uint count;
};
const bool supports_indirect_first_instance = false;
const bool write_d3d12_special_constants = false;
uniform MetadataRange _immediates_binding_cs;
layout(std430, binding = 0) readonly buffer type_2_block_0Compute { MetadataEntry _group_0_binding_0_cs[]; };
layout(std430, binding = 1) readonly buffer type_3_block_1Compute { uint _group_1_binding_0_cs[]; };
layout(std430, binding = 2) buffer type_3_block_2Compute { uint _group_2_binding_0_cs[]; };
bool is_bit_set(uint data, uint index) {
return (((data >> index) & 1u) == 1u);
}
void main() {
uvec3 global_invocation_id = gl_GlobalInvocationID;
bool failed = false;
bool local = false;
bool local_1 = false;
uint _e4 = _immediates_binding_cs.count;
if ((global_invocation_id.x >= _e4)) {
return;
}
uint _e9 = _immediates_binding_cs.start;
MetadataEntry metadata_1 = _group_0_binding_0_cs[(_e9 + global_invocation_id.x)];
bool _e18 = is_bit_set(metadata_1.src_offset, 31u);
uint src_base_offset = ((metadata_1.src_offset << 2u) >> 2u);
uint dst_base_offset = ((metadata_1.dst_offset << 2u) >> 2u);
uint first_vertex_or_index = _group_1_binding_0_cs[(src_base_offset + 2u)];
uint vertex_or_index_count = _group_1_binding_0_cs[(src_base_offset + 0u)];
{
bool _e41 = is_bit_set(metadata_1.dst_offset, 30u);
bool sub_overflows = (metadata_1.vertex_or_index_limit < first_vertex_or_index);
if (sub_overflows) {
local = !(_e41);
} else {
local = false;
}
bool _e48 = local;
bool _e49 = failed;
failed = (_e49 || _e48);
uint vertex_or_index_limit = (metadata_1.vertex_or_index_limit - first_vertex_or_index);
bool _e54 = failed;
failed = (_e54 || (vertex_or_index_limit < vertex_or_index_count));
}
uint first_instance = _group_1_binding_0_cs[((src_base_offset + 3u) + uint(_e18))];
uint instance_count = _group_1_binding_0_cs[(src_base_offset + 1u)];
{
bool _e70 = is_bit_set(metadata_1.dst_offset, 31u);
bool sub_overflows_1 = (metadata_1.instance_limit < first_instance);
if (sub_overflows_1) {
local_1 = !(_e70);
} else {
local_1 = false;
}
bool _e77 = local_1;
bool _e78 = failed;
failed = (_e78 || _e77);
uint instance_limit = (metadata_1.instance_limit - first_instance);
bool _e83 = failed;
failed = (_e83 || (instance_limit < instance_count));
}
if (true) {
bool _e90 = failed;
failed = (_e90 || (first_instance != 0u));
}
bool _e97 = failed;
if (_e97) {
if (write_d3d12_special_constants) {
_group_2_binding_0_cs[(dst_base_offset + 0u)] = 0u;
_group_2_binding_0_cs[(dst_base_offset + 1u)] = 0u;
_group_2_binding_0_cs[(dst_base_offset + 2u)] = 0u;
}
_group_2_binding_0_cs[((dst_base_offset + 0u) + 0u)] = 0u;
_group_2_binding_0_cs[((dst_base_offset + 0u) + 1u)] = 0u;
_group_2_binding_0_cs[((dst_base_offset + 0u) + 2u)] = 0u;
_group_2_binding_0_cs[((dst_base_offset + 0u) + 3u)] = 0u;
if (_e18) {
_group_2_binding_0_cs[((dst_base_offset + 0u) + 4u)] = 0u;
return;
} else {
return;
}
} else {
if (write_d3d12_special_constants) {
uint _e155 = _group_1_binding_0_cs[((src_base_offset + 2u) + uint(_e18))];
_group_2_binding_0_cs[(dst_base_offset + 0u)] = _e155;
uint _e166 = _group_1_binding_0_cs[((src_base_offset + 3u) + uint(_e18))];
_group_2_binding_0_cs[(dst_base_offset + 1u)] = _e166;
_group_2_binding_0_cs[(dst_base_offset + 2u)] = 0u;
}
uint _e181 = _group_1_binding_0_cs[(src_base_offset + 0u)];
_group_2_binding_0_cs[((dst_base_offset + 0u) + 0u)] = _e181;
uint _e191 = _group_1_binding_0_cs[(src_base_offset + 1u)];
_group_2_binding_0_cs[((dst_base_offset + 0u) + 1u)] = _e191;
uint _e201 = _group_1_binding_0_cs[(src_base_offset + 2u)];
_group_2_binding_0_cs[((dst_base_offset + 0u) + 2u)] = _e201;
uint _e211 = _group_1_binding_0_cs[(src_base_offset + 3u)];
_group_2_binding_0_cs[((dst_base_offset + 0u) + 3u)] = _e211;
if (_e18) {
uint _e221 = _group_1_binding_0_cs[(src_base_offset + 4u)];
_group_2_binding_0_cs[((dst_base_offset + 0u) + 4u)] = _e221;
return;
} else {
return;
}
}
}
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::device] Compiled shader NativeShader(4)
[1970-03-03T01:43:44Z DEBUG wgpu_hal::gles::device] Linked program NativeProgram(3)
thread 'main' (8374) panicked at src/renderer.rs:51:33:
index out of bounds: the len is 0 but the index is 0
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace |
|
Finally, after modifying the "choose_config" part, it was possible to run it. diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs
index d7546d619..975a3939e 100644
--- a/wgpu-hal/src/gles/egl.rs
+++ b/wgpu-hal/src/gles/egl.rs
@@ -88,82 +88,217 @@ enum SrgbFrameBufferKind {
Khr,
}
+struct EglConfig {
+ red_size: khronos_egl::Int,
+ green_size: khronos_egl::Int,
+ blue_size: khronos_egl::Int,
+ alpha_size: khronos_egl::Int,
+ depth_size: khronos_egl::Int,
+ buffer_size: khronos_egl::Int,
+ stencil_size: khronos_egl::Int,
+ multi_sample_buffers: khronos_egl::Int,
+ multi_sample_samples: khronos_egl::Int,
+ floating_point: bool,
+ offscreen: bool,
+ profile: khronos_egl::Int,
+ surface_type: khronos_egl::Int,
+ native_renderable: bool,
+}
+
+impl Default for EglConfig {
+ fn default() -> Self {
+ Self {
+ red_size: 8,
+ green_size: 8,
+ blue_size: 8,
+ alpha_size: 8,
+ depth_size: 16,
+ buffer_size: 0,
+ stencil_size: 0,
+ multi_sample_buffers: 0,
+ multi_sample_samples: 0,
+ floating_point: false,
+ offscreen: false,
+ profile: khronos_egl::OPENGL_BIT,
+ surface_type: 0,
+ native_renderable: false,
+ }
+ }
+}
+
/// Choose GLES framebuffer configuration.
-fn choose_config(
+fn choose_config_inner(
egl: &EglInstance,
display: khronos_egl::Display,
- srgb_kind: SrgbFrameBufferKind,
+ egl_config: &EglConfig,
+ set_config_caveat_none: bool,
) -> Result<(khronos_egl::Config, bool), crate::InstanceError> {
- //TODO: EGL_SLOW_CONFIG
- let tiers = [
- (
- "off-screen",
- &[
- khronos_egl::SURFACE_TYPE,
- khronos_egl::PBUFFER_BIT,
- khronos_egl::RENDERABLE_TYPE,
- khronos_egl::OPENGL_ES2_BIT,
- ][..],
- ),
- (
- "presentation",
- &[khronos_egl::SURFACE_TYPE, khronos_egl::WINDOW_BIT][..],
- ),
- #[cfg(not(target_os = "android"))]
- (
- "native-render",
- &[khronos_egl::NATIVE_RENDERABLE, khronos_egl::TRUE as _][..],
- ),
- ];
-
- let mut attributes = Vec::with_capacity(9);
- for tier_max in (0..tiers.len()).rev() {
- let name = tiers[tier_max].0;
- log::debug!("\tTrying {name}");
-
- attributes.clear();
- for &(_, tier_attr) in tiers[..=tier_max].iter() {
- attributes.extend_from_slice(tier_attr);
- }
- // make sure the Alpha is enough to support sRGB
- match srgb_kind {
- SrgbFrameBufferKind::None => {}
- _ => {
- attributes.push(khronos_egl::ALPHA_SIZE);
- attributes.push(8);
- }
- }
+ let mut attributes = Vec::with_capacity(32);
+
+ attributes.push(khronos_egl::RED_SIZE);
+ attributes.push(egl_config.red_size);
+ attributes.push(khronos_egl::GREEN_SIZE);
+ attributes.push(egl_config.green_size);
+ attributes.push(khronos_egl::BLUE_SIZE);
+ attributes.push(egl_config.blue_size);
+
+ if set_config_caveat_none {
+ attributes.push(khronos_egl::CONFIG_CAVEAT);
attributes.push(khronos_egl::NONE);
+ }
- match egl.choose_first_config(display, &attributes) {
- Ok(Some(config)) => {
- if tier_max == 1 {
- //Note: this has been confirmed to malfunction on Intel+NV laptops,
- // but also on Angle.
- log::info!("EGL says it can present to the window but not natively",);
- }
- // Android emulator can't natively present either.
- let tier_threshold =
- if cfg!(target_os = "android") || cfg!(windows) || cfg!(target_env = "ohos") {
- 1
- } else {
- 2
- };
- return Ok((config, tier_max >= tier_threshold));
- }
- Ok(None) => {
- log::debug!("No config found!");
- }
- Err(e) => {
- log::error!("error in choose_first_config: {e:?}");
+ if egl_config.alpha_size > 0 {
+ attributes.push(khronos_egl::ALPHA_SIZE);
+ attributes.push(egl_config.alpha_size);
+ }
+
+ if egl_config.depth_size > 0 {
+ attributes.push(khronos_egl::DEPTH_SIZE);
+ attributes.push(egl_config.depth_size);
+ }
+
+ if egl_config.stencil_size > 0 {
+ attributes.push(khronos_egl::STENCIL_SIZE);
+ attributes.push(egl_config.stencil_size);
+ }
+
+ if egl_config.buffer_size > 0 {
+ attributes.push(khronos_egl::BUFFER_SIZE);
+ attributes.push(egl_config.buffer_size);
+ }
+
+ if egl_config.multi_sample_buffers > 0 {
+ attributes.push(khronos_egl::SAMPLE_BUFFERS);
+ attributes.push(egl_config.multi_sample_buffers);
+ }
+
+ if egl_config.multi_sample_samples > 0 {
+ attributes.push(khronos_egl::SAMPLES);
+ attributes.push(egl_config.multi_sample_samples);
+ }
+
+ if egl_config.floating_point {
+ // TODO: EGL_EXT_pixel_format_float Support?
+ // attributes.push(khronos_egl::COLOR_COMPNENT_TYPE_EXT);
+ // attributes.push(khronos_egl::COLOR_COMPONENT_TYPE_FLOAT_EXT);
+ }
+
+ if egl_config.offscreen {
+ attributes.push(khronos_egl::SURFACE_TYPE);
+ attributes.push(khronos_egl::PBUFFER_BIT);
+ }
+
+ attributes.push(khronos_egl::RENDERABLE_TYPE);
+ attributes.push(egl_config.profile);
+
+ if egl_config.surface_type != 0 {
+ attributes.push(khronos_egl::SURFACE_TYPE);
+ attributes.push(egl_config.surface_type);
+ }
+
+ if egl_config.native_renderable {
+ attributes.push(khronos_egl::NATIVE_RENDERABLE);
+ attributes.push(khronos_egl::TRUE as _);
+ }
+
+ attributes.push(khronos_egl::NONE);
+
+ let mut configs = Vec::with_capacity(128);
+ egl.choose_config(display, &attributes, &mut configs)
+ .map_err(|e| {
+ crate::InstanceError::with_source(String::from("error in eglChooseConfig"), e)
+ })?;
+
+ if configs.is_empty() {
+ return Err(crate::InstanceError::new(String::from(
+ "no matching EGL framebuffer configuration found",
+ )));
+ }
+
+ // eglChooseConfig returns a number of configurations that match or exceed the requested attribs.
+ // From those, we select the one that matches our requirements more closely via a makeshift algorithm
+ let mut best_bitdiff = None;
+ let mut best_config = None;
+ for config in configs.iter() {
+ let mut bitdiff = 0;
+
+ let red_size = egl
+ .get_config_attrib(display, *config, khronos_egl::RED_SIZE)
+ .unwrap_or(0);
+ let green_size = egl
+ .get_config_attrib(display, *config, khronos_egl::GREEN_SIZE)
+ .unwrap_or(0);
+ let blue_size = egl
+ .get_config_attrib(display, *config, khronos_egl::BLUE_SIZE)
+ .unwrap_or(0);
+ let alpha_size = egl
+ .get_config_attrib(display, *config, khronos_egl::ALPHA_SIZE)
+ .unwrap_or(0);
+
+ bitdiff += (red_size - egl_config.red_size).abs();
+ bitdiff += (green_size - egl_config.green_size).abs();
+ bitdiff += (blue_size - egl_config.blue_size).abs();
+ bitdiff += (alpha_size - egl_config.alpha_size).abs();
+
+ if let Some(diff) = best_bitdiff {
+ if bitdiff < diff {
+ best_bitdiff = Some(bitdiff);
+ best_config = Some(*config);
}
+ } else {
+ best_bitdiff = Some(bitdiff);
+ best_config = Some(*config);
}
}
- // TODO: include diagnostic details that are currently logged
- Err(crate::InstanceError::new(String::from(
- "unable to find an acceptable EGL framebuffer configuration",
- )))
+ if let Some(config) = best_config {
+ let surface_type = egl
+ .get_config_attrib(display, config, khronos_egl::SURFACE_TYPE)
+ .unwrap_or(0);
+
+ let support_window_bit = (surface_type & khronos_egl::WINDOW_BIT) != 0;
+
+ let supports_native_window =
+ if cfg!(target_os = "android") || cfg!(windows) || cfg!(target_env = "ohos") {
+ support_window_bit
+ } else {
+ let native_renderable = egl
+ .get_config_attrib(display, config, khronos_egl::NATIVE_RENDERABLE)
+ .unwrap_or(0);
+ let supports_native_renderable = native_renderable == khronos_egl::TRUE as i32;
+ support_window_bit && supports_native_renderable
+ };
+
+ Ok((config, supports_native_window))
+ } else {
+ Err(crate::InstanceError::new(String::from(
+ "no matching EGL framebuffer configuration found",
+ )))
+ }
+}
+
+fn choose_config(
+ egl: &EglInstance,
+ display: khronos_egl::Display,
+ egl_config: &EglConfig,
+) -> Result<(khronos_egl::Config, bool), crate::InstanceError> {
+ // Try with EGL_CONFIG_CAVEAT set to EGL_NONE, to avoid any EGL_SLOW_CONFIG or EGL_NON_CONFORMANT_CONFIG
+ match choose_config_inner(egl, display, egl_config, true) {
+ Ok(result) => return Ok(result),
+ Err(e) => {
+ log::info!(
+ "Failed to choose EGL config with CONFIG_CAVEAT=NONE, retrying without it: {e}"
+ );
+ }
+ }
+
+ match choose_config_inner(egl, display, egl_config, false) {
+ Ok(result) => Ok(result),
+ Err(e) => {
+ log::info!("Failed to choose EGL config without CONFIG_CAVEAT=NONE: {e}");
+ Err(e)
+ }
+ }
}
#[derive(Clone, Debug)]
@@ -441,8 +576,6 @@ impl Inner {
}
}
- let (config, supports_native_window) = choose_config(&egl, display, srgb_kind)?;
-
let supports_opengl = if version >= (1, 4) {
let client_apis = egl
.query_string(Some(display), khronos_egl::CLIENT_APIS)
@@ -454,6 +587,27 @@ impl Inner {
} else {
false
};
+
+ let profile = if supports_opengl {
+ khronos_egl::OPENGL_BIT
+ } else {
+ // TODO: Add OpenGL ES 3.x bit when supported
+ // if display_extensions.contains("EGL_KHR_create_context") {
+ // khronos_egl::OPENGL_ES3_BIT
+ // }
+ khronos_egl::OPENGL_ES2_BIT
+ };
+
+ let egl_config = EglConfig {
+ profile,
+ alpha_size: match srgb_kind {
+ SrgbFrameBufferKind::None => 0,
+ _ => 8,
+ },
+ ..Default::default()
+ };
+ let (config, supports_native_window) = choose_config(&egl, display, &egl_config)?;
+
egl.bind_api(if supports_opengl {
khronos_egl::OPENGL_API
} else { |
The tools I use most frequently are Gemini and Copilot. Copilot is directly integrated into the IDE, while Gemini is used to help me analyze the output of some log issues. |
Connections
Description
In some embedded Linux systems, the EGL+GLES libraries cannot have their addresses obtained through eglGetProcAddress; instead, the symbol table of the library must be directly accessed (for instance, PowerVR Rogue GE8300, and some Mali GPUs).
Testing
Explain how this change is tested.
Squash or Rebase?
Squash
Checklist
cargo fmt.taplo format.cargo clippy --tests. If applicable, add:--target wasm32-unknown-unknowncargo xtask testto run tests.