From d64adc3a79e419062432cfa8d1cbc437676a3fbd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michel=20D=C3=A4nzer?= Date: Thu, 26 Mar 2015 11:32:59 +0900 Subject: [PATCH] radeonsi: Cache LLVMTargetMachineRef in context instead of in screen Fixes a crash in genymotion with several threads compiling shaders concurrently. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89746 Cc: 10.5 Reviewed-by: Tom Stellard --- src/gallium/drivers/radeonsi/si_compute.c | 3 +- src/gallium/drivers/radeonsi/si_pipe.c | 43 ++++++++++--------- src/gallium/drivers/radeonsi/si_pipe.h | 3 +- src/gallium/drivers/radeonsi/si_shader.c | 13 +++--- src/gallium/drivers/radeonsi/si_shader.h | 5 ++- .../drivers/radeonsi/si_state_shaders.c | 4 +- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_compute.c b/src/gallium/drivers/radeonsi/si_compute.c index 8609b894108..89bef2e7afd 100644 --- a/src/gallium/drivers/radeonsi/si_compute.c +++ b/src/gallium/drivers/radeonsi/si_compute.c @@ -130,7 +130,8 @@ static void *si_create_compute_state( for (i = 0; i < program->num_kernels; i++) { LLVMModuleRef mod = radeon_llvm_get_kernel_module(program->llvm_ctx, i, code, header->num_bytes); - si_compile_llvm(sctx->screen, &program->kernels[i], mod); + si_compile_llvm(sctx->screen, &program->kernels[i], sctx->tm, + mod); LLVMDisposeModule(mod); } } diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index d335bda44f4..0eada72ad5a 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -69,6 +69,11 @@ static void si_destroy_context(struct pipe_context *context) si_pm4_cleanup(sctx); r600_common_context_cleanup(&sctx->b); + +#if HAVE_LLVM >= 0x0306 + LLVMDisposeTargetMachine(sctx->tm); +#endif + FREE(sctx); } @@ -77,6 +82,12 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, void * struct si_context *sctx = CALLOC_STRUCT(si_context); struct si_screen* sscreen = (struct si_screen *)screen; struct radeon_winsys *ws = sscreen->b.ws; + LLVMTargetRef r600_target; +#if HAVE_LLVM >= 0x0306 + const char *triple = "amdgcn--"; +#else + const char *triple = "r600--"; +#endif int shader, i; if (sctx == NULL) @@ -170,6 +181,17 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, void * */ sctx->scratch_waves = 32 * sscreen->b.info.max_compute_units; +#if HAVE_LLVM >= 0x0306 + /* Initialize LLVM TargetMachine */ + r600_target = radeon_llvm_get_r600_target(triple); + sctx->tm = LLVMCreateTargetMachine(r600_target, triple, + r600_get_llvm_processor_name(sscreen->b.family), + "+DumpCode,+vgpr-spilling", + LLVMCodeGenLevelDefault, + LLVMRelocDefault, + LLVMCodeModelDefault); +#endif + return &sctx->b.b; fail: si_destroy_context(&sctx->b.b); @@ -445,12 +467,6 @@ static void si_destroy_screen(struct pipe_screen* pscreen) if (!sscreen->b.ws->unref(sscreen->b.ws)) return; -#if HAVE_LLVM >= 0x0306 - // r600_destroy_common_screen() frees sscreen, so we need to make - // sure to dispose the TargetMachine before we call it. - LLVMDisposeTargetMachine(sscreen->tm); -#endif - r600_destroy_common_screen(&sscreen->b); } @@ -508,12 +524,7 @@ static bool si_initialize_pipe_config(struct si_screen *sscreen) struct pipe_screen *radeonsi_screen_create(struct radeon_winsys *ws) { struct si_screen *sscreen = CALLOC_STRUCT(si_screen); - LLVMTargetRef r600_target; -#if HAVE_LLVM >= 0x0306 - const char *triple = "amdgcn--"; -#else - const char *triple = "r600--"; -#endif + if (sscreen == NULL) { return NULL; } @@ -541,13 +552,5 @@ struct pipe_screen *radeonsi_screen_create(struct radeon_winsys *ws) /* Create the auxiliary context. This must be done last. */ sscreen->b.aux_context = sscreen->b.b.context_create(&sscreen->b.b, NULL); -#if HAVE_LLVM >= 0x0306 - /* Initialize LLVM TargetMachine */ - r600_target = radeon_llvm_get_r600_target(triple); - sscreen->tm = LLVMCreateTargetMachine(r600_target, triple, - r600_get_llvm_processor_name(sscreen->b.family), - "+DumpCode,+vgpr-spilling", LLVMCodeGenLevelDefault, LLVMRelocDefault, - LLVMCodeModelDefault); -#endif return &sscreen->b.b; } diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index 422b873db04..f98c7a83744 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -85,7 +85,6 @@ struct si_compute; struct si_screen { struct r600_common_screen b; - LLVMTargetMachineRef tm; }; struct si_sampler_view { @@ -203,6 +202,8 @@ struct si_context { struct pipe_resource *esgs_ring; struct pipe_resource *gsvs_ring; + LLVMTargetMachineRef tm; + /* SI state handling */ union si_state queued; union si_state emitted; diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 4dcf7566af0..b4709acc465 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -72,6 +72,7 @@ struct si_shader_context int param_streamout_offset[4]; int param_vertex_id; int param_instance_id; + LLVMTargetMachineRef tm; LLVMValueRef const_md; LLVMValueRef const_resource[SI_NUM_CONST_BUFFERS]; LLVMValueRef ddxy_lds; @@ -2697,13 +2698,13 @@ int si_shader_binary_read(struct si_screen *sscreen, } int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, - LLVMModuleRef mod) + LLVMTargetMachineRef tm, LLVMModuleRef mod) { int r = 0; bool dump = r600_can_dump_shader(&sscreen->b, shader->selector ? shader->selector->tokens : NULL); r = radeon_llvm_compile(mod, &shader->binary, - r600_get_llvm_processor_name(sscreen->b.family), dump, sscreen->tm); + r600_get_llvm_processor_name(sscreen->b.family), dump, tm); if (r) { return r; @@ -2791,7 +2792,7 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, fprintf(stderr, "Copy Vertex Shader for Geometry Shader:\n\n"); r = si_compile_llvm(sscreen, si_shader_ctx->shader, - bld_base->base.gallivm->module); + si_shader_ctx->tm, bld_base->base.gallivm->module); radeon_llvm_dispose(&si_shader_ctx->radeon_bld); @@ -2836,7 +2837,8 @@ static void si_dump_key(unsigned shader, union si_shader_key *key) } } -int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) +int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, + struct si_shader *shader) { struct si_shader_selector *sel = shader->selector; struct tgsi_token *tokens = sel->tokens; @@ -2909,6 +2911,7 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) si_shader_ctx.shader = shader; si_shader_ctx.type = tgsi_get_processor_type(tokens); si_shader_ctx.screen = sscreen; + si_shader_ctx.tm = tm; switch (si_shader_ctx.type) { case TGSI_PROCESSOR_VERTEX: @@ -2964,7 +2967,7 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) radeon_llvm_finalize_module(&si_shader_ctx.radeon_bld); mod = bld_base->base.gallivm->module; - r = si_compile_llvm(sscreen, shader, mod); + r = si_compile_llvm(sscreen, shader, tm, mod); if (r) { fprintf(stderr, "LLVM failed to compile shader\n"); goto out; diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 5b602ac3428..51055afe36a 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -183,9 +183,10 @@ static inline struct si_shader* si_get_vs_state(struct si_context *sctx) } /* radeonsi_shader.c */ -int si_shader_create(struct si_screen *sscreen, struct si_shader *shader); +int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, + struct si_shader *shader); int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, - LLVMModuleRef mod); + LLVMTargetMachineRef tm, LLVMModuleRef mod); void si_shader_destroy(struct pipe_context *ctx, struct si_shader *shader); unsigned si_shader_io_get_unique_index(unsigned semantic_name, unsigned index); int si_shader_binary_read(struct si_screen *sscreen, struct si_shader *shader, diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 382738a2121..b0a6fb9fc84 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -405,6 +405,7 @@ static INLINE void si_shader_selector_key(struct pipe_context *ctx, static int si_shader_select(struct pipe_context *ctx, struct si_shader_selector *sel) { + struct si_context *sctx = (struct si_context *)ctx; union si_shader_key key; struct si_shader * shader = NULL; int r; @@ -444,7 +445,8 @@ static int si_shader_select(struct pipe_context *ctx, shader->next_variant = sel->current; sel->current = shader; - r = si_shader_create((struct si_screen*)ctx->screen, shader); + r = si_shader_create((struct si_screen*)ctx->screen, sctx->tm, + shader); if (unlikely(r)) { R600_ERR("Failed to build shader variant (type=%u) %d\n", sel->type, r); -- 2.30.2