metal: handle gpu reset
Unfortunately this doesn't seem to work on amdgpu [1]. I've tested that it works on i915. [1] https://gitlab.freedesktop.org/drm/amd/-/issues/1749
This commit is contained in:
parent
4584dee160
commit
d2913449ea
21 changed files with 377 additions and 120 deletions
|
|
@ -3,9 +3,14 @@ use {
|
|||
egl::{
|
||||
display::EglDisplay,
|
||||
sys::{eglDestroyContext, eglMakeCurrent, EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE},
|
||||
PROCS,
|
||||
},
|
||||
ext::GlExt,
|
||||
RenderError,
|
||||
ext::{DisplayExt, GlExt},
|
||||
sys::{
|
||||
GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB,
|
||||
GL_UNKNOWN_CONTEXT_RESET_ARB,
|
||||
},
|
||||
RenderError, ResetStatus,
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
|
@ -31,6 +36,27 @@ impl Drop for EglContext {
|
|||
static mut CURRENT: EGLContext = EGLContext::none();
|
||||
|
||||
impl EglContext {
|
||||
pub fn reset_status(&self) -> Option<ResetStatus> {
|
||||
if !self
|
||||
.dpy
|
||||
.exts
|
||||
.contains(DisplayExt::EXT_CREATE_CONTEXT_ROBUSTNESS)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let status = self.with_current(|| unsafe {
|
||||
let status = match PROCS.glGetGraphicsResetStatusKHR() {
|
||||
0 => return Ok(None),
|
||||
GL_GUILTY_CONTEXT_RESET_ARB => ResetStatus::Guilty,
|
||||
GL_INNOCENT_CONTEXT_RESET_ARB => ResetStatus::Innocent,
|
||||
GL_UNKNOWN_CONTEXT_RESET_ARB => ResetStatus::Unknown,
|
||||
n => ResetStatus::Other(n),
|
||||
};
|
||||
Ok(Some(status))
|
||||
});
|
||||
status.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_current<T, F: FnOnce() -> Result<T, RenderError>>(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ use {
|
|||
PROCS,
|
||||
},
|
||||
ext::{get_display_ext, get_gl_ext, DisplayExt, GlExt},
|
||||
sys::{eglInitialize, EGL_PLATFORM_GBM_KHR},
|
||||
sys::{
|
||||
eglInitialize, EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_EXT, EGL_PLATFORM_GBM_KHR,
|
||||
},
|
||||
RenderError,
|
||||
},
|
||||
video::{dmabuf::DmaBuf, drm::Drm, gbm::GbmDevice, INVALID_MODIFIER},
|
||||
|
|
@ -104,7 +107,17 @@ impl EglDisplay {
|
|||
}
|
||||
|
||||
pub fn create_context(self: &Rc<Self>) -> Result<Rc<EglContext>, RenderError> {
|
||||
let attrib = [EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE];
|
||||
let mut attrib = vec![EGL_CONTEXT_CLIENT_VERSION, 2];
|
||||
if self
|
||||
.exts
|
||||
.contains(DisplayExt::EXT_CREATE_CONTEXT_ROBUSTNESS)
|
||||
{
|
||||
attrib.push(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
|
||||
attrib.push(EGL_LOSE_CONTEXT_ON_RESET_EXT);
|
||||
} else {
|
||||
log::warn!("EGL display does not support gpu reset notifications");
|
||||
}
|
||||
attrib.push(EGL_NONE);
|
||||
unsafe {
|
||||
let ctx = eglCreateContext(
|
||||
self.dpy,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use uapi::c;
|
||||
use {crate::render::sys::GLenum, uapi::c};
|
||||
|
||||
pub type EGLint = i32;
|
||||
pub type EGLenum = c::c_uint;
|
||||
|
|
@ -51,6 +51,12 @@ pub const EGL_BAD_DEVICE_EXT: EGLint = 0x322B;
|
|||
pub const EGL_OPENGL_ES_API: EGLenum = 0x30A0;
|
||||
pub const EGL_PLATFORM_GBM_KHR: EGLint = 0x31D7;
|
||||
pub const EGL_CONTEXT_CLIENT_VERSION: EGLint = 0x3098;
|
||||
pub const EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: EGLint = 0x3138;
|
||||
pub const EGL_LOSE_CONTEXT_ON_RESET_EXT: EGLint = 0x31BF;
|
||||
|
||||
pub const GL_GUILTY_CONTEXT_RESET_ARB: GLenum = 0x8253;
|
||||
pub const GL_INNOCENT_CONTEXT_RESET_ARB: GLenum = 0x8254;
|
||||
pub const GL_UNKNOWN_CONTEXT_RESET_ARB: GLenum = 0x8255;
|
||||
|
||||
pub const EGL_WIDTH: EGLint = 0x3057;
|
||||
pub const EGL_HEIGHT: EGLint = 0x3056;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ bitflags::bitflags! {
|
|||
const MESA_CONFIGLESS_CONTEXT = 1 << 4;
|
||||
const KHR_SURFACELESS_CONTEXT = 1 << 5;
|
||||
const IMG_CONTEXT_PRIORITY = 1 << 6;
|
||||
const EXT_CREATE_CONTEXT_ROBUSTNESS = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +104,10 @@ pub(super) unsafe fn get_display_ext(dpy: EGLDisplay) -> DisplayExt {
|
|||
DisplayExt::KHR_SURFACELESS_CONTEXT,
|
||||
),
|
||||
("EGL_IMG_context_priority", DisplayExt::IMG_CONTEXT_PRIORITY),
|
||||
(
|
||||
"EGL_EXT_create_context_robustness",
|
||||
DisplayExt::EXT_CREATE_CONTEXT_ROBUSTNESS,
|
||||
),
|
||||
];
|
||||
match get_dpy_extensions(dpy) {
|
||||
Some(exts) => get_typed_ext(&exts, DisplayExt::empty(), &map),
|
||||
|
|
|
|||
|
|
@ -66,7 +66,19 @@ impl Debug for RenderContext {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ResetStatus {
|
||||
Guilty,
|
||||
Innocent,
|
||||
Unknown,
|
||||
Other(u32),
|
||||
}
|
||||
|
||||
impl RenderContext {
|
||||
pub fn reset_status(&self) -> Option<ResetStatus> {
|
||||
self.ctx.reset_status()
|
||||
}
|
||||
|
||||
pub fn from_drm_device(drm: &Drm) -> Result<Self, RenderError> {
|
||||
let nodes = drm.get_nodes()?;
|
||||
let node = match nodes
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ impl Renderer<'_> {
|
|||
std::slice::from_ref(&pos.at_point(x, y)),
|
||||
&Color::from_rgba_straight(20, 20, 20, 255),
|
||||
);
|
||||
if let Some(tex) = placeholder.texture() {
|
||||
if let Some(tex) = placeholder.texture.get() {
|
||||
let x = x + (pos.width() - tex.width()) / 2;
|
||||
let y = y + (pos.height() - tex.height()) / 2;
|
||||
self.render_texture(&tex, x, y, &ARGB8888);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue