Skip to content

[hal][egl] Fix robust context creation failing on some devices #7952

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

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Changes from all 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
132 changes: 93 additions & 39 deletions wgpu-hal/src/gles/egl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,6 @@ impl Inner {
})
.unwrap();

let needs_robustness = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This boolean perplexed me; Not mutable, unconditionaly set to true and then checked later on. I think this might be leftover debug code

let mut khr_context_flags = 0;
let supports_khr_context = display_extensions.contains("EGL_KHR_create_context");

Expand Down Expand Up @@ -617,53 +616,108 @@ impl Inner {
log::debug!("\tEGL context: -debug");
}
}
if needs_robustness {
//Note: the core version can fail if robustness is not supported
// (regardless of whether the extension is supported!).
// In fact, Angle does precisely that awful behavior, so we don't try it there.
if version >= (1, 5) && !display_extensions.contains("EGL_ANGLE_") {
log::debug!("\tEGL context: +robust access");
context_attributes.push(khronos_egl::CONTEXT_OPENGL_ROBUST_ACCESS);
context_attributes.push(khronos_egl::TRUE as _);
} else if display_extensions.contains("EGL_EXT_create_context_robustness") {
log::debug!("\tEGL context: +robust access EXT");
context_attributes.push(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
context_attributes.push(khronos_egl::TRUE as _);
} else {
//Note: we aren't trying `EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR`
// because it's for desktop GL only, not GLES.
log::warn!("\tEGL context: -robust access");
}
}

if khr_context_flags != 0 {
context_attributes.push(EGL_CONTEXT_FLAGS_KHR);
context_attributes.push(khr_context_flags);
}
context_attributes.push(khronos_egl::NONE);

gl_context_attributes.extend(&context_attributes);
gles_context_attributes.extend(&context_attributes);

let context = if supports_opengl {
egl.create_context(display, config, None, &gl_context_attributes)
.or_else(|_| {
egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
let context = {
enum Robustness {
Core,
Ext,
}

let mut robustness = if version >= (1, 5) {
Some(Robustness::Core)
} else if display_extensions.contains("EGL_EXT_create_context_robustness") {
Some(Robustness::Ext)
} else {
None
};

loop {
let robustness_attributes = match robustness {
Some(Robustness::Core) => {
vec![
khronos_egl::CONTEXT_OPENGL_ROBUST_ACCESS,
khronos_egl::TRUE as _,
khronos_egl::NONE,
]
}
Some(Robustness::Ext) => {
vec![
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT,
khronos_egl::TRUE as _,
khronos_egl::NONE,
]
}
None => vec![khronos_egl::NONE],
};

let mut gl_context_attributes = gl_context_attributes.clone();
gl_context_attributes.extend(&robustness_attributes);

let mut gles_context_attributes = gles_context_attributes.clone();
gles_context_attributes.extend(&robustness_attributes);

let result = if supports_opengl {
egl.create_context(display, config, None, &gl_context_attributes)
.or_else(|_| {
egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
egl.create_context(display, config, None, &gles_context_attributes)
})
} else {
egl.create_context(display, config, None, &gles_context_attributes)
})
.map_err(|e| {
crate::InstanceError::with_source(
String::from("unable to create OpenGL or GLES 3.x context"),
e,
)
})
} else {
egl.create_context(display, config, None, &gles_context_attributes)
.map_err(|e| {
crate::InstanceError::with_source(
String::from("unable to create GLES 3.x context"),
e,
)
})
};

match (result, robustness) {
// We have a context at the requested robustness level
(Ok(_), robustness) => {
match robustness {
Some(Robustness::Core) => {
log::debug!("\tEGL context: +robust access");
}
Some(Robustness::Ext) => {
log::debug!("\tEGL context: +robust access EXT");
}
None => {
log::debug!("\tEGL context: -robust access");
}
}

break result;
}

// BadAttribute could mean that context creation is not supported at the requested robustness level
// We try the next robustness level.
(Err(khronos_egl::Error::BadAttribute), Some(r)) => {
// Trying EXT robustness if Core robustness is not working
// and EXT robustness is supported.
robustness = if matches!(r, Robustness::Core)
&& display_extensions.contains("EGL_EXT_create_context_robustness")
{
Some(Robustness::Ext)
} else {
None
};

continue;
}

// Any other error, or depleted robustness levels, we give up.
_ => break result,
}
}
.map_err(|e| {
crate::InstanceError::with_source(
String::from("unable to create OpenGL or GLES 3.x context"),
e,
)
})
}?;

// Testing if context can be binded without surface
Expand Down