mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 21:50:12 +01:00
st_pbo/compute: use new shader interface to perform async shader creation
this enables compatible drivers to initiate threaded creation of huge compute shaders fully in a thread while falling back to software in order to avoid blocking for several seconds, as slower progress is better than no progress at all--especially in cases where the huge pbo shader may only be used a single time the mechanics are straightforward for thread-enabled drivers: * check hash table for existing shader data * if no shader exists, perform creation of nir shader fully in driver thread and return immediately, enabling software fallback without blocking * once fence for nir shader is signalled, pass the nir back to the driver thread again to run common nir passes and execute normal shader creation * continue to use software fallback until the shader is fully ready Acked-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18198>
This commit is contained in:
parent
b36a741aa4
commit
c79fc40de5
1 changed files with 90 additions and 32 deletions
|
|
@ -40,6 +40,15 @@
|
|||
#include "util/u_sampler.h"
|
||||
#include "util/streaming-load-memcpy.h"
|
||||
|
||||
struct pbo_async_data {
|
||||
struct st_context *st;
|
||||
enum pipe_texture_target target;
|
||||
unsigned num_components;
|
||||
struct util_queue_fence fence;
|
||||
nir_shader *nir;
|
||||
struct pipe_shader_state *cs;
|
||||
};
|
||||
|
||||
#define BGR_FORMAT(NAME) \
|
||||
{{ \
|
||||
[0] = PIPE_FORMAT_##NAME##_SNORM, \
|
||||
|
|
@ -778,6 +787,13 @@ can_copy_direct(const struct gl_pixelstore_attrib *pack)
|
|||
pack->SkipImages);
|
||||
}
|
||||
|
||||
static void
|
||||
create_conversion_shader_async(void *data, void *gdata, int thread_index)
|
||||
{
|
||||
struct pbo_async_data *async = data;
|
||||
async->nir = create_conversion_shader(async->st, async->target, async->num_components);
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
download_texture_compute(struct st_context *st,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
|
|
@ -802,48 +818,80 @@ download_texture_compute(struct st_context *st,
|
|||
|
||||
unsigned num_components = 0;
|
||||
/* Upload constants */
|
||||
{
|
||||
struct pipe_constant_buffer cb;
|
||||
assert(view_target != PIPE_TEXTURE_1D_ARRAY || !zoffset);
|
||||
struct pbo_data pd = {
|
||||
.x = MIN2(xoffset, 65535),
|
||||
.y = view_target == PIPE_TEXTURE_1D_ARRAY ? 0 : MIN2(yoffset, 65535),
|
||||
.width = MIN2(width, 65535),
|
||||
.height = MIN2(height, 65535),
|
||||
.depth = MIN2(depth, 65535),
|
||||
.invert = pack->Invert,
|
||||
.blocksize = util_format_get_blocksize(dst_format) - 1,
|
||||
.alignment = ffs(MAX2(pack->Alignment, 1)) - 1,
|
||||
};
|
||||
num_components = fill_pbo_data(&pd, src_format, dst_format, pack->SwapBytes == 1);
|
||||
struct pipe_constant_buffer cb;
|
||||
assert(view_target != PIPE_TEXTURE_1D_ARRAY || !yoffset);
|
||||
struct pbo_data pd = {
|
||||
.x = MIN2(xoffset, 65535),
|
||||
.y = view_target == PIPE_TEXTURE_1D_ARRAY ? 0 : MIN2(yoffset, 65535),
|
||||
.width = MIN2(width, 65535),
|
||||
.height = MIN2(height, 65535),
|
||||
.depth = MIN2(depth, 65535),
|
||||
.invert = pack->Invert,
|
||||
.blocksize = util_format_get_blocksize(dst_format) - 1,
|
||||
.alignment = ffs(MAX2(pack->Alignment, 1)) - 1,
|
||||
};
|
||||
num_components = fill_pbo_data(&pd, src_format, dst_format, pack->SwapBytes == 1);
|
||||
|
||||
cb.buffer = NULL;
|
||||
cb.user_buffer = &pd;
|
||||
cb.buffer_offset = 0;
|
||||
cb.buffer_size = sizeof(pd);
|
||||
|
||||
pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, false, &cb);
|
||||
}
|
||||
cb.buffer = NULL;
|
||||
cb.user_buffer = &pd;
|
||||
cb.buffer_offset = 0;
|
||||
cb.buffer_size = sizeof(pd);
|
||||
|
||||
uint32_t hash_key = compute_shader_key(view_target, num_components);
|
||||
assert(hash_key != 0);
|
||||
|
||||
struct hash_entry *he = _mesa_hash_table_search(st->pbo.shaders, (void*)(uintptr_t)hash_key);
|
||||
void *cs;
|
||||
if (!he) {
|
||||
nir_shader *nir = create_conversion_shader(st, view_target, num_components);
|
||||
struct pipe_shader_state state = {
|
||||
.type = PIPE_SHADER_IR_NIR,
|
||||
.ir.nir = nir,
|
||||
};
|
||||
void *cs = NULL;
|
||||
if (he) {
|
||||
if (screen->driver_thread_add_job) {
|
||||
struct pbo_async_data *async = he->data;
|
||||
if (!util_queue_fence_is_signalled(&async->fence))
|
||||
return NULL;
|
||||
/* nir is definitely done */
|
||||
if (!async->cs) {
|
||||
/* cs job not yet started */
|
||||
assert(async->nir && !async->cs);
|
||||
struct pipe_compute_state state = {0};
|
||||
state.ir_type = PIPE_SHADER_IR_NIR;
|
||||
state.req_local_mem = async->nir->info.shared_size;
|
||||
state.prog = async->nir;
|
||||
async->nir = NULL;
|
||||
async->cs = pipe->create_compute_state(pipe, &state);
|
||||
}
|
||||
/* cs *may* be done */
|
||||
if (screen->is_parallel_shader_compilation_finished &&
|
||||
!screen->is_parallel_shader_compilation_finished(screen, async->cs, MESA_SHADER_COMPUTE))
|
||||
return NULL;
|
||||
cs = async->cs;
|
||||
}
|
||||
} else {
|
||||
if (screen->driver_thread_add_job) {
|
||||
struct pbo_async_data *async = malloc(sizeof(struct pbo_async_data));
|
||||
async->st = st;
|
||||
async->target = view_target;
|
||||
async->num_components = num_components;
|
||||
async->nir = NULL;
|
||||
async->cs = NULL;
|
||||
util_queue_fence_init(&async->fence);
|
||||
screen->driver_thread_add_job(screen, async, &async->fence, create_conversion_shader_async, NULL, 0);
|
||||
_mesa_hash_table_insert(st->pbo.shaders, (void*)(uintptr_t)hash_key, async);
|
||||
return NULL;
|
||||
} else {
|
||||
nir_shader *nir = create_conversion_shader(st, view_target, num_components);
|
||||
struct pipe_shader_state state = {
|
||||
.type = PIPE_SHADER_IR_NIR,
|
||||
.ir.nir = nir,
|
||||
};
|
||||
|
||||
cs = st_create_nir_shader(st, &state);
|
||||
cs = st_create_nir_shader(st, &state);
|
||||
}
|
||||
he = _mesa_hash_table_insert(st->pbo.shaders, (void*)(uintptr_t)hash_key, cs);
|
||||
}
|
||||
cs = he->data;
|
||||
assert(cs);
|
||||
struct cso_context *cso = st->cso_context;
|
||||
|
||||
pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, false, &cb);
|
||||
|
||||
cso_save_compute_state(cso, CSO_BIT_COMPUTE_SHADER | CSO_BIT_COMPUTE_SAMPLERS);
|
||||
cso_set_compute_shader_handle(cso, cs);
|
||||
|
||||
|
|
@ -1170,9 +1218,19 @@ st_GetTexSubImage_shader(struct gl_context * ctx,
|
|||
void
|
||||
st_pbo_compute_deinit(struct st_context *st)
|
||||
{
|
||||
struct pipe_screen *screen = st->screen;
|
||||
if (!st->pbo.shaders)
|
||||
return;
|
||||
hash_table_foreach(st->pbo.shaders, entry)
|
||||
st->pipe->delete_compute_state(st->pipe, entry->data);
|
||||
hash_table_foreach(st->pbo.shaders, entry) {
|
||||
if (screen->driver_thread_add_job) {
|
||||
struct pbo_async_data *async = entry->data;
|
||||
util_queue_fence_wait(&async->fence);
|
||||
st->pipe->delete_compute_state(st->pipe, async->cs);
|
||||
util_queue_fence_destroy(&async->fence);
|
||||
free(async);
|
||||
} else {
|
||||
st->pipe->delete_compute_state(st->pipe, entry->data);
|
||||
}
|
||||
}
|
||||
_mesa_hash_table_destroy(st->pbo.shaders, NULL);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue