mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 11:08:03 +02:00
glthread: add a heuristic to stop locking global mutexes with multiple contexts
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4516 Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8035 Acked-by: Timothy Arceri <tarceri@itsqueeze.com> Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21039>
This commit is contained in:
parent
78c61140f1
commit
3ed141e9d8
4 changed files with 87 additions and 8 deletions
|
|
@ -50,13 +50,70 @@ glthread_unmarshal_batch(void *job, void *gdata, int thread_index)
|
||||||
unsigned pos = 0;
|
unsigned pos = 0;
|
||||||
unsigned used = batch->used;
|
unsigned used = batch->used;
|
||||||
uint64_t *buffer = batch->buffer;
|
uint64_t *buffer = batch->buffer;
|
||||||
|
struct gl_shared_state *shared = ctx->Shared;
|
||||||
|
|
||||||
|
/* Determine if we should lock the global mutexes. */
|
||||||
|
simple_mtx_lock(&shared->Mutex);
|
||||||
|
int64_t current_time = os_time_get_nano();
|
||||||
|
|
||||||
|
/* We can only lock the mutexes after NoLockDuration nanoseconds have
|
||||||
|
* passed since multiple contexts were active.
|
||||||
|
*/
|
||||||
|
bool lock_mutexes = shared->GLThread.LastContextSwitchTime +
|
||||||
|
shared->GLThread.NoLockDuration < current_time;
|
||||||
|
|
||||||
|
/* Check if multiple contexts are active (the last executing context is
|
||||||
|
* different).
|
||||||
|
*/
|
||||||
|
if (ctx != shared->GLThread.LastExecutingCtx) {
|
||||||
|
if (lock_mutexes) {
|
||||||
|
/* If we get here, we've been locking the global mutexes for a while
|
||||||
|
* and now we are switching contexts. */
|
||||||
|
if (shared->GLThread.LastContextSwitchTime +
|
||||||
|
120 * ONE_SECOND_IN_NS < current_time) {
|
||||||
|
/* If it's been more than 2 minutes of only one active context,
|
||||||
|
* indicating that there was no other active context for a long
|
||||||
|
* time, reset the no-lock time to its initial state of only 1
|
||||||
|
* second. This is most likely an infrequent situation of
|
||||||
|
* multi-context loading of game content and shaders.
|
||||||
|
* (this is a heuristic)
|
||||||
|
*/
|
||||||
|
shared->GLThread.NoLockDuration = ONE_SECOND_IN_NS;
|
||||||
|
} else if (shared->GLThread.NoLockDuration < 32 * ONE_SECOND_IN_NS) {
|
||||||
|
/* Double the no-lock duration if we are transitioning from only
|
||||||
|
* one active context to multiple active contexts after a short
|
||||||
|
* time, up to a maximum of 32 seconds, indicating that multiple
|
||||||
|
* contexts are frequently executing. (this is a heuristic)
|
||||||
|
*/
|
||||||
|
shared->GLThread.NoLockDuration *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_mutexes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There are multiple active contexts. Update the last executing context
|
||||||
|
* and the last context switch time. We only start locking global mutexes
|
||||||
|
* after LastContextSwitchTime + NoLockDuration passes, so this
|
||||||
|
* effectively resets the non-locking stopwatch to 0, so that multiple
|
||||||
|
* contexts can execute simultaneously as long as they are not idle.
|
||||||
|
*/
|
||||||
|
shared->GLThread.LastExecutingCtx = ctx;
|
||||||
|
shared->GLThread.LastContextSwitchTime = current_time;
|
||||||
|
}
|
||||||
|
simple_mtx_unlock(&shared->Mutex);
|
||||||
|
|
||||||
|
/* Execute the GL calls. */
|
||||||
_glapi_set_dispatch(ctx->CurrentServerDispatch);
|
_glapi_set_dispatch(ctx->CurrentServerDispatch);
|
||||||
|
|
||||||
_mesa_HashLockMutex(ctx->Shared->BufferObjects);
|
/* Here we lock the mutexes once globally if possible. If not, we just
|
||||||
ctx->BufferObjectsLocked = true;
|
* fallback to the individual API calls doing it.
|
||||||
simple_mtx_lock(&ctx->Shared->TexMutex);
|
*/
|
||||||
ctx->TexturesLocked = true;
|
if (lock_mutexes) {
|
||||||
|
_mesa_HashLockMutex(shared->BufferObjects);
|
||||||
|
ctx->BufferObjectsLocked = true;
|
||||||
|
simple_mtx_lock(&shared->TexMutex);
|
||||||
|
ctx->TexturesLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
while (pos < used) {
|
while (pos < used) {
|
||||||
const struct marshal_cmd_base *cmd =
|
const struct marshal_cmd_base *cmd =
|
||||||
|
|
@ -65,10 +122,12 @@ glthread_unmarshal_batch(void *job, void *gdata, int thread_index)
|
||||||
pos += _mesa_unmarshal_dispatch[cmd->cmd_id](ctx, cmd);
|
pos += _mesa_unmarshal_dispatch[cmd->cmd_id](ctx, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->TexturesLocked = false;
|
if (lock_mutexes) {
|
||||||
simple_mtx_unlock(&ctx->Shared->TexMutex);
|
ctx->TexturesLocked = false;
|
||||||
ctx->BufferObjectsLocked = false;
|
simple_mtx_unlock(&shared->TexMutex);
|
||||||
_mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
|
ctx->BufferObjectsLocked = false;
|
||||||
|
_mesa_HashUnlockMutex(shared->BufferObjects);
|
||||||
|
}
|
||||||
|
|
||||||
assert(pos == used);
|
assert(pos == used);
|
||||||
batch->used = 0;
|
batch->used = 0;
|
||||||
|
|
|
||||||
|
|
@ -2521,6 +2521,22 @@ struct gl_shared_state
|
||||||
struct util_idalloc free_idx;
|
struct util_idalloc free_idx;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
} small_dlist_store;
|
} small_dlist_store;
|
||||||
|
|
||||||
|
/* Global GLThread state. */
|
||||||
|
struct {
|
||||||
|
/* The last context that locked global mutexes. */
|
||||||
|
struct gl_context *LastExecutingCtx;
|
||||||
|
|
||||||
|
/* The last time LastExecutingCtx started executing after a different
|
||||||
|
* context (the time of multiple active contexts).
|
||||||
|
*/
|
||||||
|
int64_t LastContextSwitchTime;
|
||||||
|
|
||||||
|
/* The time for which no context can lock global mutexes since
|
||||||
|
* LastContextSwitchTime.
|
||||||
|
*/
|
||||||
|
int64_t NoLockDuration;
|
||||||
|
} GLThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,8 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
|
||||||
shared->MemoryObjects = _mesa_NewHashTable();
|
shared->MemoryObjects = _mesa_NewHashTable();
|
||||||
shared->SemaphoreObjects = _mesa_NewHashTable();
|
shared->SemaphoreObjects = _mesa_NewHashTable();
|
||||||
|
|
||||||
|
shared->GLThread.NoLockDuration = ONE_SECOND_IN_NS;
|
||||||
|
|
||||||
return shared;
|
return shared;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ONE_SECOND_IN_NS INT64_C(1000000000)
|
||||||
|
|
||||||
/* must be equal to PIPE_TIMEOUT_INFINITE */
|
/* must be equal to PIPE_TIMEOUT_INFINITE */
|
||||||
#define OS_TIMEOUT_INFINITE 0xffffffffffffffffull
|
#define OS_TIMEOUT_INFINITE 0xffffffffffffffffull
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue