radeonsi: Cache LLVMTargetMachineRef in context instead of in screen
authorMichel Dänzer <michel.daenzer@amd.com>
Thu, 26 Mar 2015 02:32:59 +0000 (11:32 +0900)
committerMichel Dänzer <michel@daenzer.net>
Mon, 30 Mar 2015 06:15:10 +0000 (15:15 +0900)
Fixes a crash in genymotion with several threads compiling shaders
concurrently.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89746

Cc: 10.5 <mesa-stable@lists.freedesktop.org>
Reviewed-by: Tom Stellard <thomas.stellard@amd.com>
src/gallium/drivers/radeonsi/si_compute.c
src/gallium/drivers/radeonsi/si_pipe.c
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index 8609b894108ae80539309294408c6c5dcdb0d701..89bef2e7afddea21577dc1e882bfc1cfa8fbab90 100644 (file)
@@ -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);
                }
        }
index d335bda44f4c916d5085578da197c4f0a404e269..0eada72ad5ae4cd89ea0424a25c4ff056ff32592 100644 (file)
@@ -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;
 }
index 422b873db047da26c5949ab15ccc4b8de6d2d888..f98c7a837448cdbae0696c3fa0db7f43a6940c00 100644 (file)
@@ -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;
index 4dcf7566af08785621662cfe4fc1238aa4347dcd..b4709acc4653c3024281afaaf6fb26fb65dc6539 100644 (file)
@@ -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;
index 5b602ac342801ed985f22801ae95d33a38799117..51055afe36adad21b7e5ecdbaa6835ab646adb18 100644 (file)
@@ -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,
index 382738a21212e0f6a38ecfe23e6141ccb909f108..b0a6fb9fc846fb37daa65745b218370caff4dbb9 100644 (file)
@@ -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);