mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 22:10:10 +01:00
llvmpipe: Use two LLVMContexts per OpenGL context instead of a global one.
This is one step to make llvmpipe thread safe as mandated by the OpenGL standard. Using the global LLVMContext is obviously a problem for that kind of use pattern. The patch introduces two LLVMContext instances that are private to an OpenGL context and used for all compiles. One is put into struct draw_llvm and the other one into struct llvmpipe_context. Reviewed-by: Jose Fonseca <jfonseca@vmware.com> Signed-off-by: Mathias Froehlich <Mathias.Froehlich@web.de>
This commit is contained in:
parent
98d00d6640
commit
83c62597fc
13 changed files with 40 additions and 31 deletions
|
|
@ -493,6 +493,10 @@ draw_llvm_create(struct draw_context *draw)
|
||||||
|
|
||||||
llvm->draw = draw;
|
llvm->draw = draw;
|
||||||
|
|
||||||
|
llvm->context = LLVMContextCreate();
|
||||||
|
if (!llvm->context)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
llvm->nr_variants = 0;
|
llvm->nr_variants = 0;
|
||||||
make_empty_list(&llvm->vs_variants_list);
|
make_empty_list(&llvm->vs_variants_list);
|
||||||
|
|
||||||
|
|
@ -500,6 +504,10 @@ draw_llvm_create(struct draw_context *draw)
|
||||||
make_empty_list(&llvm->gs_variants_list);
|
make_empty_list(&llvm->gs_variants_list);
|
||||||
|
|
||||||
return llvm;
|
return llvm;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
draw_llvm_destroy(llvm);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -509,6 +517,9 @@ draw_llvm_create(struct draw_context *draw)
|
||||||
void
|
void
|
||||||
draw_llvm_destroy(struct draw_llvm *llvm)
|
draw_llvm_destroy(struct draw_llvm *llvm)
|
||||||
{
|
{
|
||||||
|
LLVMContextDispose(llvm->context);
|
||||||
|
llvm->context = NULL;
|
||||||
|
|
||||||
/* XXX free other draw_llvm data? */
|
/* XXX free other draw_llvm data? */
|
||||||
FREE(llvm);
|
FREE(llvm);
|
||||||
}
|
}
|
||||||
|
|
@ -540,7 +551,7 @@ draw_llvm_create_variant(struct draw_llvm *llvm,
|
||||||
util_snprintf(module_name, sizeof(module_name), "draw_llvm_vs_variant%u",
|
util_snprintf(module_name, sizeof(module_name), "draw_llvm_vs_variant%u",
|
||||||
variant->shader->variants_cached);
|
variant->shader->variants_cached);
|
||||||
|
|
||||||
variant->gallivm = gallivm_create(module_name);
|
variant->gallivm = gallivm_create(module_name, llvm->context);
|
||||||
|
|
||||||
create_jit_types(variant);
|
create_jit_types(variant);
|
||||||
|
|
||||||
|
|
@ -2195,7 +2206,7 @@ draw_gs_llvm_create_variant(struct draw_llvm *llvm,
|
||||||
util_snprintf(module_name, sizeof(module_name), "draw_llvm_gs_variant%u",
|
util_snprintf(module_name, sizeof(module_name), "draw_llvm_gs_variant%u",
|
||||||
variant->shader->variants_cached);
|
variant->shader->variants_cached);
|
||||||
|
|
||||||
variant->gallivm = gallivm_create(module_name);
|
variant->gallivm = gallivm_create(module_name, llvm->context);
|
||||||
|
|
||||||
create_gs_jit_types(variant);
|
create_gs_jit_types(variant);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -461,6 +461,8 @@ struct llvm_geometry_shader {
|
||||||
struct draw_llvm {
|
struct draw_llvm {
|
||||||
struct draw_context *draw;
|
struct draw_context *draw;
|
||||||
|
|
||||||
|
LLVMContextRef context;
|
||||||
|
|
||||||
struct draw_jit_context jit_context;
|
struct draw_jit_context jit_context;
|
||||||
struct draw_gs_jit_context gs_jit_context;
|
struct draw_gs_jit_context gs_jit_context;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,17 +78,6 @@
|
||||||
void LLVMLinkInMCJIT();
|
void LLVMLinkInMCJIT();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* LLVM has several global caches which pointing/derived from objects
|
|
||||||
* owned by the context, so if we freeing contexts causes
|
|
||||||
* memory leaks and false cache hits when these objects are destroyed.
|
|
||||||
*
|
|
||||||
* TODO: For thread safety on multi-threaded OpenGL we should use one LLVM
|
|
||||||
* context per thread, and put them in a pool when threads are destroyed.
|
|
||||||
*/
|
|
||||||
#define USE_GLOBAL_CONTEXT 1
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
unsigned gallivm_debug = 0;
|
unsigned gallivm_debug = 0;
|
||||||
|
|
||||||
|
|
@ -209,8 +198,7 @@ gallivm_free_ir(struct gallivm_state *gallivm)
|
||||||
if (gallivm->builder)
|
if (gallivm->builder)
|
||||||
LLVMDisposeBuilder(gallivm->builder);
|
LLVMDisposeBuilder(gallivm->builder);
|
||||||
|
|
||||||
if (!USE_GLOBAL_CONTEXT && gallivm->context)
|
/* The LLVMContext should be owned by the parent of gallivm. */
|
||||||
LLVMContextDispose(gallivm->context);
|
|
||||||
|
|
||||||
gallivm->engine = NULL;
|
gallivm->engine = NULL;
|
||||||
gallivm->target = NULL;
|
gallivm->target = NULL;
|
||||||
|
|
@ -301,7 +289,8 @@ fail:
|
||||||
* \return TRUE for success, FALSE for failure
|
* \return TRUE for success, FALSE for failure
|
||||||
*/
|
*/
|
||||||
static boolean
|
static boolean
|
||||||
init_gallivm_state(struct gallivm_state *gallivm, const char *name)
|
init_gallivm_state(struct gallivm_state *gallivm, const char *name,
|
||||||
|
LLVMContextRef context)
|
||||||
{
|
{
|
||||||
assert(!gallivm->context);
|
assert(!gallivm->context);
|
||||||
assert(!gallivm->module);
|
assert(!gallivm->module);
|
||||||
|
|
@ -309,11 +298,8 @@ init_gallivm_state(struct gallivm_state *gallivm, const char *name)
|
||||||
if (!lp_build_init())
|
if (!lp_build_init())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (USE_GLOBAL_CONTEXT) {
|
gallivm->context = context;
|
||||||
gallivm->context = LLVMGetGlobalContext();
|
|
||||||
} else {
|
|
||||||
gallivm->context = LLVMContextCreate();
|
|
||||||
}
|
|
||||||
if (!gallivm->context)
|
if (!gallivm->context)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
@ -495,13 +481,13 @@ lp_build_init(void)
|
||||||
* Create a new gallivm_state object.
|
* Create a new gallivm_state object.
|
||||||
*/
|
*/
|
||||||
struct gallivm_state *
|
struct gallivm_state *
|
||||||
gallivm_create(const char *name)
|
gallivm_create(const char *name, LLVMContextRef context)
|
||||||
{
|
{
|
||||||
struct gallivm_state *gallivm;
|
struct gallivm_state *gallivm;
|
||||||
|
|
||||||
gallivm = CALLOC_STRUCT(gallivm_state);
|
gallivm = CALLOC_STRUCT(gallivm_state);
|
||||||
if (gallivm) {
|
if (gallivm) {
|
||||||
if (!init_gallivm_state(gallivm, name)) {
|
if (!init_gallivm_state(gallivm, name, context)) {
|
||||||
FREE(gallivm);
|
FREE(gallivm);
|
||||||
gallivm = NULL;
|
gallivm = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ lp_build_init(void);
|
||||||
|
|
||||||
|
|
||||||
struct gallivm_state *
|
struct gallivm_state *
|
||||||
gallivm_create(const char *name);
|
gallivm_create(const char *name, LLVMContextRef context);
|
||||||
|
|
||||||
void
|
void
|
||||||
gallivm_destroy(struct gallivm_state *gallivm);
|
gallivm_destroy(struct gallivm_state *gallivm);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
|
||||||
|
|
||||||
lp_delete_setup_variants(llvmpipe);
|
lp_delete_setup_variants(llvmpipe);
|
||||||
|
|
||||||
|
LLVMContextDispose(llvmpipe->context);
|
||||||
|
llvmpipe->context = NULL;
|
||||||
|
|
||||||
align_free( llvmpipe );
|
align_free( llvmpipe );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,6 +164,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
|
||||||
llvmpipe_init_context_resource_funcs( &llvmpipe->pipe );
|
llvmpipe_init_context_resource_funcs( &llvmpipe->pipe );
|
||||||
llvmpipe_init_surface_functions(llvmpipe);
|
llvmpipe_init_surface_functions(llvmpipe);
|
||||||
|
|
||||||
|
llvmpipe->context = LLVMContextCreate();
|
||||||
|
if (!llvmpipe->context)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create drawing context and plug our rendering stage into it.
|
* Create drawing context and plug our rendering stage into it.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,9 @@ struct llvmpipe_context {
|
||||||
struct pipe_query *render_cond_query;
|
struct pipe_query *render_cond_query;
|
||||||
uint render_cond_mode;
|
uint render_cond_mode;
|
||||||
boolean render_cond_cond;
|
boolean render_cond_cond;
|
||||||
|
|
||||||
|
/** The LLVMContext to use for LLVM related work */
|
||||||
|
LLVMContextRef context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2565,7 +2565,7 @@ generate_variant(struct llvmpipe_context *lp,
|
||||||
util_snprintf(module_name, sizeof(module_name), "fs%u_variant%u",
|
util_snprintf(module_name, sizeof(module_name), "fs%u_variant%u",
|
||||||
shader->no, shader->variants_created);
|
shader->no, shader->variants_created);
|
||||||
|
|
||||||
variant->gallivm = gallivm_create(module_name);
|
variant->gallivm = gallivm_create(module_name, lp->context);
|
||||||
if (!variant->gallivm) {
|
if (!variant->gallivm) {
|
||||||
FREE(variant);
|
FREE(variant);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -731,7 +731,7 @@ generate_setup_variant(struct lp_setup_variant_key *key,
|
||||||
util_snprintf(func_name, sizeof(func_name), "setup_variant_%u",
|
util_snprintf(func_name, sizeof(func_name), "setup_variant_%u",
|
||||||
variant->no);
|
variant->no);
|
||||||
|
|
||||||
variant->gallivm = gallivm = gallivm_create(func_name);
|
variant->gallivm = gallivm = gallivm_create(func_name, lp->context);
|
||||||
if (!variant->gallivm) {
|
if (!variant->gallivm) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -354,7 +354,7 @@ test_unary(unsigned verbose, FILE *fp, const struct unary_test_t *test)
|
||||||
in[i] = 1.0;
|
in[i] = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gallivm = gallivm_create("test_module");
|
gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
|
||||||
|
|
||||||
test_func = build_unary_test_func(gallivm, test);
|
test_func = build_unary_test_func(gallivm, test);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -450,7 +450,7 @@ test_one(unsigned verbose,
|
||||||
if(verbose >= 1)
|
if(verbose >= 1)
|
||||||
dump_blend_type(stdout, blend, type);
|
dump_blend_type(stdout, blend, type);
|
||||||
|
|
||||||
gallivm = gallivm_create("test_module");
|
gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
|
||||||
|
|
||||||
func = add_blend_test(gallivm, blend, type);
|
func = add_blend_test(gallivm, blend, type);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ test_one(unsigned verbose,
|
||||||
|
|
||||||
eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type));
|
eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type));
|
||||||
|
|
||||||
gallivm = gallivm_create("test_module");
|
gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
|
||||||
|
|
||||||
func = add_conv_test(gallivm, src_type, num_srcs, dst_type, num_dsts);
|
func = add_conv_test(gallivm, src_type, num_srcs, dst_type, num_dsts);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ test_format_float(unsigned verbose, FILE *fp,
|
||||||
boolean success = TRUE;
|
boolean success = TRUE;
|
||||||
unsigned i, j, k, l;
|
unsigned i, j, k, l;
|
||||||
|
|
||||||
gallivm = gallivm_create("test_module_float");
|
gallivm = gallivm_create("test_module_float", LLVMGetGlobalContext());
|
||||||
|
|
||||||
fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_float32_vec4_type());
|
fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_float32_vec4_type());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ test_printf(unsigned verbose, FILE *fp,
|
||||||
test_printf_t test_printf_func;
|
test_printf_t test_printf_func;
|
||||||
boolean success = TRUE;
|
boolean success = TRUE;
|
||||||
|
|
||||||
gallivm = gallivm_create("test_module");
|
gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
|
||||||
|
|
||||||
test = add_printf_test(gallivm);
|
test = add_printf_test(gallivm);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue