Added better handing for graphics bind failures
This commit is contained in:
@@ -538,15 +538,28 @@ namespace cuda {
|
||||
} else if (descriptor.sequence > sequence) {
|
||||
sequence = descriptor.sequence;
|
||||
|
||||
rgb = egl::rgb_t {};
|
||||
|
||||
auto rgb_opt = egl::import_source(display.get(), descriptor.sd);
|
||||
|
||||
if (!rgb_opt) {
|
||||
return -1;
|
||||
}
|
||||
// The plane's current format/modifier can't be imported (e.g. a game switched to a
|
||||
// 10bpc swapchain in exclusive fullscreen that this driver won't bind to a GL texture).
|
||||
// Encode a blank frame instead of dropping the client, and only log once per failure
|
||||
// streak to avoid flooding the log every frame.
|
||||
if (!import_failed_last_frame) {
|
||||
BOOST_LOG(warning) << "Skipping frame(s): plane format (fourcc: "sv << util::hex(descriptor.sd.fourcc).to_string_view()
|
||||
<< ") failed to import; will resume automatically if the format changes back"sv;
|
||||
import_failed_last_frame = true;
|
||||
}
|
||||
|
||||
rgb = std::move(*rgb_opt);
|
||||
rgb = egl::create_blank(img);
|
||||
} else {
|
||||
if (import_failed_last_frame) {
|
||||
BOOST_LOG(info) << "Resumed capture after plane format import failure"sv;
|
||||
import_failed_last_frame = false;
|
||||
}
|
||||
|
||||
rgb = std::move(*rgb_opt);
|
||||
}
|
||||
}
|
||||
|
||||
auto fmt_desc = av_pix_fmt_desc_get(sw_format);
|
||||
@@ -640,6 +653,8 @@ namespace cuda {
|
||||
int offset_y; ///< Vertical offset in physical pixels.
|
||||
|
||||
bool is_yuv444; ///< Whether the CUDA converter outputs YUV 4:4:4.
|
||||
|
||||
bool import_failed_last_frame = false; ///< Whether the previous frame's plane import failed, to avoid log spam.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -655,10 +655,23 @@ namespace egl {
|
||||
gl::ctx.BindTexture(GL_TEXTURE_2D, rgb->tex[0]);
|
||||
if (!gl::egl_image_target_texture_2d()) {
|
||||
BOOST_LOG(error) << "glEGLImageTargetTexture2DOES is not available; cannot import RGB DMA-BUF"sv;
|
||||
gl::ctx.BindTexture(GL_TEXTURE_2D, 0);
|
||||
return std::nullopt;
|
||||
}
|
||||
gl::egl_image_target_texture_2d()(GL_TEXTURE_2D, rgb->xrgb8);
|
||||
|
||||
// Some drivers accept an EGLImage of a given DRM format/modifier from eglCreateImage()
|
||||
// but then reject binding it to a GL texture, e.g. Mesa/RADV rejecting a 10bpc format
|
||||
// like DRM_FORMAT_XBGR2101010. When that happens, the texture is left with stale or
|
||||
// incomplete contents, so this must be treated as an import failure rather than
|
||||
// silently streaming whatever ends up in the texture.
|
||||
if (auto err = gl::ctx.GetError(); err != GL_NO_ERROR) {
|
||||
BOOST_LOG(error) << "Failed to bind EGLImage (DRM fourcc: "sv << util::hex(xrgb.fourcc).to_string_view()
|
||||
<< ") to GL texture: "sv << util::hex(err).to_string_view();
|
||||
gl::ctx.BindTexture(GL_TEXTURE_2D, 0);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
gl::ctx.BindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
gl_drain_errors;
|
||||
|
||||
@@ -1668,7 +1668,21 @@ namespace platf {
|
||||
auto rgb_opt = egl::import_source(display.get(), sd);
|
||||
|
||||
if (!rgb_opt) {
|
||||
return capture_e::error;
|
||||
// The plane's current format/modifier can't be imported (e.g. a game switched to a
|
||||
// 10bpc swapchain in exclusive fullscreen that this driver won't bind to a GL texture).
|
||||
// Skip this frame rather than tearing down the whole capture thread for every client,
|
||||
// and only log once per failure streak to avoid flooding the log every frame.
|
||||
if (!import_failed_last_frame) {
|
||||
BOOST_LOG(warning) << "Skipping frame(s): plane format (fourcc: "sv << util::hex(sd.fourcc).to_string_view()
|
||||
<< ") failed to import; will resume automatically if the format changes back"sv;
|
||||
import_failed_last_frame = true;
|
||||
}
|
||||
return capture_e::timeout;
|
||||
}
|
||||
|
||||
if (import_failed_last_frame) {
|
||||
BOOST_LOG(info) << "Resumed capture after plane format import failure"sv;
|
||||
import_failed_last_frame = false;
|
||||
}
|
||||
|
||||
auto &rgb = *rgb_opt;
|
||||
@@ -1726,6 +1740,7 @@ namespace platf {
|
||||
gbm::gbm_t gbm; ///< GBM device used for buffer allocation.
|
||||
egl::display_t display; ///< EGL display created from the GBM device.
|
||||
egl::ctx_t ctx; ///< EGL context used to copy KMS frames into RAM.
|
||||
bool import_failed_last_frame = false; ///< Whether the previous frame's plane import failed, to avoid log spam.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -558,15 +558,28 @@ namespace va {
|
||||
} else if (descriptor.sequence > sequence) {
|
||||
sequence = descriptor.sequence;
|
||||
|
||||
rgb = egl::rgb_t {};
|
||||
|
||||
auto rgb_opt = egl::import_source(display.get(), descriptor.sd);
|
||||
|
||||
if (!rgb_opt) {
|
||||
return -1;
|
||||
}
|
||||
// The plane's current format/modifier can't be imported (e.g. a game switched to a
|
||||
// 10bpc swapchain in exclusive fullscreen that this driver won't bind to a GL texture).
|
||||
// Encode a blank frame instead of dropping the client, and only log once per failure
|
||||
// streak to avoid flooding the log every frame.
|
||||
if (!import_failed_last_frame) {
|
||||
BOOST_LOG(warning) << "Skipping frame(s): plane format (fourcc: "sv << util::hex(descriptor.sd.fourcc).to_string_view()
|
||||
<< ") failed to import; will resume automatically if the format changes back"sv;
|
||||
import_failed_last_frame = true;
|
||||
}
|
||||
|
||||
rgb = std::move(*rgb_opt);
|
||||
rgb = egl::create_blank(img);
|
||||
} else {
|
||||
if (import_failed_last_frame) {
|
||||
BOOST_LOG(info) << "Resumed capture after plane format import failure"sv;
|
||||
import_failed_last_frame = false;
|
||||
}
|
||||
|
||||
rgb = std::move(*rgb_opt);
|
||||
}
|
||||
}
|
||||
|
||||
sws.load_vram(descriptor, offset_x, offset_y, rgb->tex[0], false);
|
||||
@@ -603,6 +616,8 @@ namespace va {
|
||||
|
||||
int offset_x; ///< Horizontal offset in physical pixels.
|
||||
int offset_y; ///< Vertical offset in physical pixels.
|
||||
|
||||
bool import_failed_last_frame = false; ///< Whether the previous frame's plane import failed, to avoid log spam.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user