From: Nicolai Hähnle <nicolai.haeh...@amd.com> The copy shader only depends on the selector. This change avoids creating separate code paths for monolithic vs. non-monolithic geometry shaders. --- src/gallium/drivers/radeonsi/si_pipe.h | 2 +- src/gallium/drivers/radeonsi/si_shader.c | 18 ++++-------------- src/gallium/drivers/radeonsi/si_shader.h | 9 ++++++++- src/gallium/drivers/radeonsi/si_state_shaders.c | 22 ++++++++++++++++++---- 4 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index 0240a3c..e7617bc 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -443,21 +443,21 @@ static inline struct tgsi_shader_info *si_get_vs_info(struct si_context *sctx) return &sctx->tes_shader.cso->info; else if (sctx->vs_shader.cso) return &sctx->vs_shader.cso->info; else return NULL; } static inline struct si_shader* si_get_vs_state(struct si_context *sctx) { if (sctx->gs_shader.current) - return sctx->gs_shader.current->gs_copy_shader; + return sctx->gs_shader.cso->gs_copy_shader; else if (sctx->tes_shader.current) return sctx->tes_shader.current; else return sctx->vs_shader.current; } static inline bool si_vs_exports_prim_id(struct si_shader *shader) { if (shader->selector->type == PIPE_SHADER_VERTEX) return shader->key.vs.epilog.export_prim_id; diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index e755399..38f65f3 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -5944,21 +5944,21 @@ static const char *si_get_shader_name(struct si_shader *shader, else return "Vertex Shader as VS"; case PIPE_SHADER_TESS_CTRL: return "Tessellation Control Shader"; case PIPE_SHADER_TESS_EVAL: if (shader->key.tes.as_es) return "Tessellation Evaluation Shader as ES"; else return "Tessellation Evaluation Shader as VS"; case PIPE_SHADER_GEOMETRY: - if (shader->gs_copy_shader == NULL) + if (shader->is_gs_copy_shader) return "GS Copy Shader as VS"; else return "Geometry Shader"; case PIPE_SHADER_FRAGMENT: return "Pixel Shader"; case PIPE_SHADER_COMPUTE: return "Compute Shader"; default: return "Unknown Shader"; } @@ -6073,21 +6073,21 @@ int si_compile_llvm(struct si_screen *sscreen, static void si_llvm_build_ret(struct si_shader_context *ctx, LLVMValueRef ret) { if (LLVMGetTypeKind(LLVMTypeOf(ret)) == LLVMVoidTypeKind) LLVMBuildRetVoid(ctx->gallivm.builder); else LLVMBuildRet(ctx->gallivm.builder, ret); } /* Generate code for the hardware VS shader stage to go with a geometry shader */ -static struct si_shader * +struct si_shader * si_generate_gs_copy_shader(struct si_screen *sscreen, LLVMTargetMachineRef tm, struct si_shader_selector *gs_selector, struct pipe_debug_callback *debug) { struct si_shader_context ctx; struct si_shader *shader; struct gallivm_state *gallivm = &ctx.gallivm; struct lp_build_tgsi_context *bld_base = &ctx.soa.bld_base; struct lp_build_context *uint = &bld_base->uint_bld; @@ -6096,20 +6096,22 @@ si_generate_gs_copy_shader(struct si_screen *sscreen, LLVMValueRef args[9]; int i, r; outputs = MALLOC(gsinfo->num_outputs * sizeof(outputs[0])); shader = CALLOC_STRUCT(si_shader); if (!shader) return NULL; shader->selector = gs_selector; + shader->is_gs_copy_shader = true; + si_init_shader_ctx(&ctx, sscreen, shader, tm); ctx.type = PIPE_SHADER_VERTEX; ctx.is_gs_copy_shader = true; create_meta_data(&ctx); create_function(&ctx); preload_ring_buffers(&ctx); args[0] = ctx.gsvs_ring[0]; args[1] = lp_build_mul_imm(uint, @@ -7143,27 +7145,20 @@ int si_compile_tgsi_shader(struct si_screen *sscreen, shader->info.num_input_vgprs += 1; } if (G_0286CC_ANCILLARY_ENA(shader->config.spi_ps_input_addr)) shader->info.num_input_vgprs += 1; if (G_0286CC_SAMPLE_COVERAGE_ENA(shader->config.spi_ps_input_addr)) shader->info.num_input_vgprs += 1; if (G_0286CC_POS_FIXED_PT_ENA(shader->config.spi_ps_input_addr)) shader->info.num_input_vgprs += 1; } - if (ctx.type == PIPE_SHADER_GEOMETRY) { - shader->gs_copy_shader = - si_generate_gs_copy_shader(sscreen, tm, shader->selector, debug); - if (!shader->gs_copy_shader) - return -1; - } - return 0; } /** * Create, compile and return a shader part (prolog or epilog). * * \param sscreen screen * \param list list of shader parts of the same category * \param type shader type * \param key shader part key @@ -8091,25 +8086,20 @@ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, if (r) { fprintf(stderr, "LLVM failed to upload shader\n"); return r; } return 0; } void si_shader_destroy(struct si_shader *shader) { - if (shader->gs_copy_shader) { - si_shader_destroy(shader->gs_copy_shader); - FREE(shader->gs_copy_shader); - } - if (shader->scratch_bo) r600_resource_reference(&shader->scratch_bo, NULL); r600_resource_reference(&shader->bo, NULL); if (!shader->is_binary_shared) radeon_shader_binary_clean(&shader->binary); free(shader->shader_log); } diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 6c7a05f..91f9cbf 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -250,20 +250,22 @@ struct si_shader_selector { pipe_mutex mutex; struct si_shader *first_variant; /* immutable after the first variant */ struct si_shader *last_variant; /* mutable */ /* The compiled TGSI shader expecting a prolog and/or epilog (not * uploaded to a buffer). */ struct si_shader *main_shader_part; + struct si_shader *gs_copy_shader; + struct tgsi_token *tokens; struct pipe_stream_output_info so; struct tgsi_shader_info info; /* PIPE_SHADER_[VERTEX|FRAGMENT|...] */ unsigned type; /* GS parameters. */ unsigned esgs_itemsize; unsigned gs_input_verts_per_prim; @@ -437,26 +439,26 @@ struct si_shader_info { ubyte nr_param_exports; }; struct si_shader { struct si_shader_selector *selector; struct si_shader *next_variant; struct si_shader_part *prolog; struct si_shader_part *epilog; - struct si_shader *gs_copy_shader; struct si_pm4_state *pm4; struct r600_resource *bo; struct r600_resource *scratch_bo; union si_shader_key key; bool is_binary_shared; + bool is_gs_copy_shader; /* The following data is all that's needed for binary shaders. */ struct radeon_shader_binary binary; struct si_shader_config config; struct si_shader_info info; /* Shader key + LLVM IR + disassembly + statistics. * Generated for debug contexts only. */ char *shader_log; @@ -464,20 +466,25 @@ struct si_shader { }; struct si_shader_part { struct si_shader_part *next; union si_shader_part_key key; struct radeon_shader_binary binary; struct si_shader_config config; }; /* si_shader.c */ +struct si_shader * +si_generate_gs_copy_shader(struct si_screen *sscreen, + LLVMTargetMachineRef tm, + struct si_shader_selector *gs_selector, + struct pipe_debug_callback *debug); int si_compile_tgsi_shader(struct si_screen *sscreen, LLVMTargetMachineRef tm, struct si_shader *shader, bool is_monolithic, struct pipe_debug_callback *debug); int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, struct si_shader *shader, struct pipe_debug_callback *debug); int si_compile_llvm(struct si_screen *sscreen, struct radeon_shader_binary *binary, diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 537c673..bd217f3 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -825,21 +825,20 @@ static void si_shader_init_pm4_state(struct si_screen *sscreen, si_shader_hs(shader); break; case PIPE_SHADER_TESS_EVAL: if (shader->key.tes.as_es) si_shader_es(sscreen, shader); else si_shader_vs(sscreen, shader, NULL); break; case PIPE_SHADER_GEOMETRY: si_shader_gs(shader); - si_shader_vs(sscreen, shader->gs_copy_shader, shader->selector); break; case PIPE_SHADER_FRAGMENT: si_shader_ps(shader); break; default: assert(0); } } static unsigned si_get_alpha_test_func(struct si_context *sctx) @@ -1225,20 +1224,31 @@ void si_init_shader_selector_async(void *job, int thread_index) if (sel->info.colors_written & (1 << i)) key.ps.epilog.spi_shader_col_format |= V_028710_SPI_SHADER_FP16_ABGR << (i * 4); break; } if (si_shader_select_with_key(sscreen, &state, &key, tm, debug, false, sel->is_debug_context)) fprintf(stderr, "radeonsi: can't create a monolithic shader\n"); } + + /* The GS copy shader is always pre-compiled. */ + if (sel->type == PIPE_SHADER_GEOMETRY) { + sel->gs_copy_shader = si_generate_gs_copy_shader(sscreen, tm, sel, debug); + if (!sel->gs_copy_shader) { + fprintf(stderr, "radeonsi: can't create GS copy shader\n"); + return; + } + + si_shader_vs(sscreen, sel->gs_copy_shader, sel); + } } static void *si_create_shader_selector(struct pipe_context *ctx, const struct pipe_shader_state *state) { struct si_screen *sscreen = (struct si_screen *)ctx->screen; struct si_context *sctx = (struct si_context*)ctx; struct si_shader_selector *sel = CALLOC_STRUCT(si_shader_selector); int i; @@ -1507,22 +1517,24 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader) case PIPE_SHADER_TESS_CTRL: si_pm4_delete_state(sctx, hs, shader->pm4); break; case PIPE_SHADER_TESS_EVAL: if (shader->key.tes.as_es) si_pm4_delete_state(sctx, es, shader->pm4); else si_pm4_delete_state(sctx, vs, shader->pm4); break; case PIPE_SHADER_GEOMETRY: - si_pm4_delete_state(sctx, gs, shader->pm4); - si_pm4_delete_state(sctx, vs, shader->gs_copy_shader->pm4); + if (shader->is_gs_copy_shader) + si_pm4_delete_state(sctx, vs, shader->pm4); + else + si_pm4_delete_state(sctx, gs, shader->pm4); break; case PIPE_SHADER_FRAGMENT: si_pm4_delete_state(sctx, ps, shader->pm4); break; } } si_shader_destroy(shader); free(shader); } @@ -1548,20 +1560,22 @@ static void si_delete_shader_selector(struct pipe_context *ctx, void *state) } while (p) { c = p->next_variant; si_delete_shader(sctx, p); p = c; } if (sel->main_shader_part) si_delete_shader(sctx, sel->main_shader_part); + if (sel->gs_copy_shader) + si_delete_shader(sctx, sel->gs_copy_shader); util_queue_fence_destroy(&sel->ready); pipe_mutex_destroy(sel->mutex); free(sel->tokens); free(sel); } static unsigned si_get_ps_input_cntl(struct si_context *sctx, struct si_shader *vs, unsigned name, unsigned index, unsigned interpolate) @@ -2204,21 +2218,21 @@ bool si_update_shaders(struct si_context *sctx) si_pm4_bind_state(sctx, vs, sctx->vs_shader.current->pm4); si_update_so(sctx, sctx->vs_shader.cso); } /* Update GS. */ if (sctx->gs_shader.cso) { r = si_shader_select(ctx, &sctx->gs_shader); if (r) return false; si_pm4_bind_state(sctx, gs, sctx->gs_shader.current->pm4); - si_pm4_bind_state(sctx, vs, sctx->gs_shader.current->gs_copy_shader->pm4); + si_pm4_bind_state(sctx, vs, sctx->gs_shader.cso->gs_copy_shader->pm4); si_update_so(sctx, sctx->gs_shader.cso); if (!si_update_gs_ring_buffers(sctx)) return false; si_update_gsvs_ring_bindings(sctx); } else { si_pm4_bind_state(sctx, gs, NULL); si_pm4_bind_state(sctx, es, NULL); } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev