mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 15:58:05 +02:00
llvmpipe: Implement manual context resets
Make it possible to trigger a emulated GPU reset by creating a file at the path of the `LP_CONTEXT_RESET_FILE` env var. All llvmpipe contexts using the `LOSE_CONTEXT_ON_RESET` strategy that where created before the that file will start returning `PIPE_UNKNOWN_CONTEXT_RESET` in `get_device_reset_status()`, while newer contexts - most notably those created by apps in reaction to the device reset - continue to return `PIPE_NO_RESET`. Note that, because we're dealing with files, rtime is used instead of mtime as the later Usage: ``` LP_CONTEXT_RESET_FILE=~/llvmpipe_reset LIBGL_ALWAYS_SOFTWARE=1 someapp touch ~/llvmpipe_reset ``` Signed-off-by: Robert Mader <robert.mader@collabora.com> Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40681>
This commit is contained in:
parent
c32015da05
commit
e68a0dfb12
3 changed files with 70 additions and 0 deletions
|
|
@ -1356,6 +1356,14 @@ LLVMpipe driver environment variables
|
|||
turns off threading completely. The default value is the number of
|
||||
CPU cores present.
|
||||
|
||||
.. envvar:: LP_CONTEXT_RESET_FILE
|
||||
|
||||
a file path. If set, contexts using the LOSE_CONTEXT_ON_RESET strategy will
|
||||
check it for the presence and modification time of a file and trigger an
|
||||
emulated device reset if they were created before the last modification time.
|
||||
|
||||
Currently not available on Windows.
|
||||
|
||||
VMware SVGA driver environment variables
|
||||
----------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
* Keith Whitwell <keithw@vmware.com>
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_vbuf.h"
|
||||
#include "pipe/p_defines.h"
|
||||
|
|
@ -194,6 +196,45 @@ lp_draw_disk_cache_insert_shader(void *cookie,
|
|||
static enum pipe_reset_status
|
||||
llvmpipe_get_device_reset_status(struct pipe_context *pipe)
|
||||
{
|
||||
#if !DETECT_OS_WINDOWS
|
||||
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
|
||||
struct stat st_reset_file;
|
||||
struct timespec ts_now;
|
||||
int64_t now_ns;
|
||||
|
||||
if (!(llvmpipe->flags & PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET) ||
|
||||
llvmpipe->context_reset_file_path == NULL)
|
||||
return PIPE_NO_RESET;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts_now);
|
||||
now_ns = (int64_t)ts_now.tv_sec * 1000000000LL + ts_now.tv_nsec;
|
||||
|
||||
/*
|
||||
* Only return a *RESET* status for ~0.5 milliseconds. From the spec:
|
||||
*
|
||||
* 5. How should the application react to a reset context event?
|
||||
*
|
||||
* RESOLVED: For this extension, the application is expected to query
|
||||
* the reset status until NO_ERROR is returned. If a reset is encountered,
|
||||
* at least one *RESET* status will be returned. Once NO_ERROR is again
|
||||
* encountered, the application can safely destroy the old context and
|
||||
* create a new one.
|
||||
*/
|
||||
if (llvmpipe->context_reset_time_ns > 0)
|
||||
return now_ns - llvmpipe->context_reset_time_ns < 500000 ?
|
||||
PIPE_UNKNOWN_CONTEXT_RESET : PIPE_NO_RESET;
|
||||
|
||||
if (stat(llvmpipe->context_reset_file_path, &st_reset_file) == 0) {
|
||||
int64_t file_mod_time_ns = (int64_t)st_reset_file.st_mtim.tv_sec *
|
||||
1000000000LL + st_reset_file.st_mtim.tv_nsec;
|
||||
|
||||
if (llvmpipe->context_creation_time_ns < file_mod_time_ns) {
|
||||
llvmpipe->context_reset_time_ns = now_ns;
|
||||
return PIPE_UNKNOWN_CONTEXT_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return PIPE_NO_RESET;
|
||||
}
|
||||
|
||||
|
|
@ -214,6 +255,20 @@ llvmpipe_create_context(struct pipe_screen *screen, void *priv,
|
|||
|
||||
memset(llvmpipe, 0, sizeof *llvmpipe);
|
||||
|
||||
llvmpipe->flags = flags;
|
||||
#if !DETECT_OS_WINDOWS
|
||||
llvmpipe->context_reset_file_path =
|
||||
os_get_option_secure("LP_CONTEXT_RESET_FILE");
|
||||
if (llvmpipe->flags & PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET &&
|
||||
llvmpipe->context_reset_file_path != NULL) {
|
||||
struct timespec ts_now;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts_now);
|
||||
llvmpipe->context_creation_time_ns =
|
||||
(int64_t)ts_now.tv_sec * 1000000000LL + ts_now.tv_nsec;
|
||||
}
|
||||
#endif
|
||||
|
||||
list_inithead(&llvmpipe->fs_variants_list.list);
|
||||
|
||||
list_inithead(&llvmpipe->setup_variants_list.list);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ struct lp_velems_state;
|
|||
struct llvmpipe_context {
|
||||
struct pipe_context pipe; /**< base class */
|
||||
|
||||
/** Context creation flags */
|
||||
unsigned flags;
|
||||
|
||||
struct list_head list;
|
||||
/** Constant state objects */
|
||||
const struct pipe_blend_state *blend;
|
||||
|
|
@ -197,6 +200,10 @@ struct llvmpipe_context {
|
|||
int max_global_buffers;
|
||||
struct pipe_resource **global_buffers;
|
||||
|
||||
/** Used for context reset emulation, see LP_CONTEXT_RESET_FILE */
|
||||
const char *context_reset_file_path;
|
||||
int64_t context_creation_time_ns;
|
||||
int64_t context_reset_time_ns;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue