DEBUG_NAMED_VALUE_END /* must be last */
};
+static void si_init_compiler(struct si_screen *sscreen,
+ struct si_compiler *compiler)
+{
+ enum ac_target_machine_options tm_options =
+ (sscreen->debug_flags & DBG(SI_SCHED) ? AC_TM_SISCHED : 0) |
+ (sscreen->info.chip_class >= GFX9 ? AC_TM_FORCE_ENABLE_XNACK : 0) |
+ (sscreen->info.chip_class < GFX9 ? AC_TM_FORCE_DISABLE_XNACK : 0) |
+ (!sscreen->llvm_has_working_vgpr_indexing ? AC_TM_PROMOTE_ALLOCA_TO_SCRATCH : 0);
+
+ compiler->tm = ac_create_target_machine(sscreen->info.family, tm_options);
+}
+
+static void si_destroy_compiler(struct si_compiler *compiler)
+{
+ if (compiler->tm)
+ LLVMDisposeTargetMachine(compiler->tm);
+}
+
/*
* pipe_context
*/
sctx->ws->fence_reference(&sctx->last_sdma_fence, NULL);
r600_resource_reference(&sctx->eop_bug_scratch, NULL);
- LLVMDisposeTargetMachine(sctx->tm);
+ si_destroy_compiler(&sctx->compiler);
si_saved_cs_reference(&sctx->current_saved_cs, NULL);
u_log_printf(sctx->log, "\nString marker: %*s\n", len, string);
}
-static LLVMTargetMachineRef
-si_create_llvm_target_machine(struct si_screen *sscreen)
-{
- enum ac_target_machine_options tm_options =
- (sscreen->debug_flags & DBG(SI_SCHED) ? AC_TM_SISCHED : 0) |
- (sscreen->info.chip_class >= GFX9 ? AC_TM_FORCE_ENABLE_XNACK : 0) |
- (sscreen->info.chip_class < GFX9 ? AC_TM_FORCE_DISABLE_XNACK : 0) |
- (!sscreen->llvm_has_working_vgpr_indexing ? AC_TM_PROMOTE_ALLOCA_TO_SCRATCH : 0);
-
- return ac_create_target_machine(sscreen->info.family, tm_options);
-}
-
static void si_set_debug_callback(struct pipe_context *ctx,
const struct pipe_debug_callback *cb)
{
sctx->scratch_waves = MAX2(32 * sscreen->info.num_good_compute_units,
max_threads_per_block / 64);
- sctx->tm = si_create_llvm_target_machine(sscreen);
+ si_init_compiler(sscreen, &sctx->compiler);
/* Bindless handles. */
sctx->tex_handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
util_queue_destroy(&sscreen->shader_compiler_queue);
util_queue_destroy(&sscreen->shader_compiler_queue_low_priority);
- for (i = 0; i < ARRAY_SIZE(sscreen->tm); i++)
- if (sscreen->tm[i])
- LLVMDisposeTargetMachine(sscreen->tm[i]);
+ for (i = 0; i < ARRAY_SIZE(sscreen->compiler); i++)
+ si_destroy_compiler(&sscreen->compiler[i]);
- for (i = 0; i < ARRAY_SIZE(sscreen->tm_low_priority); i++)
- if (sscreen->tm_low_priority[i])
- LLVMDisposeTargetMachine(sscreen->tm_low_priority[i]);
+ for (i = 0; i < ARRAY_SIZE(sscreen->compiler_lowp); i++)
+ si_destroy_compiler(&sscreen->compiler_lowp[i]);
/* Free shader parts. */
for (i = 0; i < ARRAY_SIZE(parts); i++) {
*/
num_threads = sysconf(_SC_NPROCESSORS_ONLN);
num_threads = MAX2(1, num_threads - 1);
- num_compiler_threads = MIN2(num_threads, ARRAY_SIZE(sscreen->tm));
+ num_compiler_threads = MIN2(num_threads, ARRAY_SIZE(sscreen->compiler));
num_compiler_threads_lowprio =
- MIN2(num_threads, ARRAY_SIZE(sscreen->tm_low_priority));
+ MIN2(num_threads, ARRAY_SIZE(sscreen->compiler_lowp));
if (!util_queue_init(&sscreen->shader_compiler_queue, "si_shader",
32, num_compiler_threads,
sscreen->debug_flags |= DBG_ALL_SHADERS;
for (i = 0; i < num_compiler_threads; i++)
- sscreen->tm[i] = si_create_llvm_target_machine(sscreen);
+ si_init_compiler(sscreen, &sscreen->compiler[i]);
for (i = 0; i < num_compiler_threads_lowprio; i++)
- sscreen->tm_low_priority[i] = si_create_llvm_target_machine(sscreen);
+ si_init_compiler(sscreen, &sscreen->compiler_lowp[i]);
/* Create the auxiliary context. This must be done last. */
sscreen->aux_context = si_create_context(&sscreen->b, 0);
static void si_init_shader_ctx(struct si_shader_context *ctx,
struct si_screen *sscreen,
- LLVMTargetMachineRef tm);
+ struct si_compiler *compiler);
static void si_llvm_emit_barrier(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
static int si_compile_llvm(struct si_screen *sscreen,
struct ac_shader_binary *binary,
struct si_shader_config *conf,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
LLVMModuleRef mod,
struct pipe_debug_callback *debug,
unsigned processor,
}
if (!si_replace_shader(count, binary)) {
- r = si_llvm_compile(mod, binary, tm, debug);
+ r = si_llvm_compile(mod, binary, compiler, debug);
if (r)
return r;
}
/* Generate code for the hardware VS shader stage to go with a geometry shader */
struct si_shader *
si_generate_gs_copy_shader(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader_selector *gs_selector,
struct pipe_debug_callback *debug)
{
shader->selector = gs_selector;
shader->is_gs_copy_shader = true;
- si_init_shader_ctx(&ctx, sscreen, tm);
+ si_init_shader_ctx(&ctx, sscreen, compiler);
ctx.shader = shader;
ctx.type = PIPE_SHADER_VERTEX;
si_llvm_optimize_module(&ctx);
r = si_compile_llvm(sscreen, &ctx.shader->binary,
- &ctx.shader->config, ctx.tm,
+ &ctx.shader->config, ctx.compiler,
ctx.gallivm.module,
debug, PIPE_SHADER_GEOMETRY,
"GS Copy Shader");
static void si_init_shader_ctx(struct si_shader_context *ctx,
struct si_screen *sscreen,
- LLVMTargetMachineRef tm)
+ struct si_compiler *compiler)
{
struct lp_build_tgsi_context *bld_base;
- si_llvm_context_init(ctx, sscreen, tm);
+ si_llvm_context_init(ctx, sscreen, compiler);
bld_base = &ctx->bld_base;
bld_base->emit_fetch_funcs[TGSI_FILE_CONSTANT] = fetch_constant;
}
int si_compile_tgsi_shader(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader *shader,
bool is_monolithic,
struct pipe_debug_callback *debug)
si_dump_streamout(&sel->so);
}
- si_init_shader_ctx(&ctx, sscreen, tm);
+ si_init_shader_ctx(&ctx, sscreen, compiler);
si_llvm_context_set_tgsi(&ctx, shader);
ctx.separate_prolog = !is_monolithic;
LLVMPointerTypeKind);
/* Compile to bytecode. */
- r = si_compile_llvm(sscreen, &shader->binary, &shader->config, tm,
+ r = si_compile_llvm(sscreen, &shader->binary, &shader->config, compiler,
ctx.gallivm.module, debug, ctx.type, "TGSI shader");
si_llvm_dispose(&ctx);
if (r) {
enum pipe_shader_type type,
bool prolog,
union si_shader_part_key *key,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct pipe_debug_callback *debug,
void (*build)(struct si_shader_context *,
union si_shader_part_key *),
struct si_shader shader = {};
struct si_shader_context ctx;
- si_init_shader_ctx(&ctx, sscreen, tm);
+ si_init_shader_ctx(&ctx, sscreen, compiler);
ctx.shader = &shader;
ctx.type = type;
/* Compile. */
si_llvm_optimize_module(&ctx);
- if (si_compile_llvm(sscreen, &result->binary, &result->config, tm,
+ if (si_compile_llvm(sscreen, &result->binary, &result->config, compiler,
ctx.ac.module, debug, ctx.type, name)) {
FREE(result);
result = NULL;
}
static bool si_get_vs_prolog(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug,
struct si_shader *main_part,
shader->prolog =
si_get_shader_part(sscreen, &sscreen->vs_prologs,
- PIPE_SHADER_VERTEX, true, &prolog_key, tm,
+ PIPE_SHADER_VERTEX, true, &prolog_key, compiler,
debug, si_build_vs_prolog_function,
"Vertex Shader Prolog");
return shader->prolog != NULL;
* Select and compile (or reuse) vertex shader parts (prolog & epilog).
*/
static bool si_shader_select_vs_parts(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
- return si_get_vs_prolog(sscreen, tm, shader, debug, shader,
+ return si_get_vs_prolog(sscreen, compiler, shader, debug, shader,
&shader->key.part.vs.prolog);
}
* Select and compile (or reuse) TCS parts (epilog).
*/
static bool si_shader_select_tcs_parts(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
struct si_shader *ls_main_part =
shader->key.part.tcs.ls->main_shader_part_ls;
- if (!si_get_vs_prolog(sscreen, tm, shader, debug, ls_main_part,
+ if (!si_get_vs_prolog(sscreen, compiler, shader, debug, ls_main_part,
&shader->key.part.tcs.ls_prolog))
return false;
shader->epilog = si_get_shader_part(sscreen, &sscreen->tcs_epilogs,
PIPE_SHADER_TESS_CTRL, false,
- &epilog_key, tm, debug,
+ &epilog_key, compiler, debug,
si_build_tcs_epilog_function,
"Tessellation Control Shader Epilog");
return shader->epilog != NULL;
* Select and compile (or reuse) GS parts (prolog).
*/
static bool si_shader_select_gs_parts(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
shader->key.part.gs.es->main_shader_part_es;
if (shader->key.part.gs.es->type == PIPE_SHADER_VERTEX &&
- !si_get_vs_prolog(sscreen, tm, shader, debug, es_main_part,
+ !si_get_vs_prolog(sscreen, compiler, shader, debug, es_main_part,
&shader->key.part.gs.vs_prolog))
return false;
shader->prolog2 = si_get_shader_part(sscreen, &sscreen->gs_prologs,
PIPE_SHADER_GEOMETRY, true,
- &prolog_key, tm, debug,
+ &prolog_key, compiler, debug,
si_build_gs_prolog_function,
"Geometry Shader Prolog");
return shader->prolog2 != NULL;
* Select and compile (or reuse) pixel shader parts (prolog & epilog).
*/
static bool si_shader_select_ps_parts(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
+ struct si_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
shader->prolog =
si_get_shader_part(sscreen, &sscreen->ps_prologs,
PIPE_SHADER_FRAGMENT, true,
- &prolog_key, tm, debug,
+ &prolog_key, compiler, debug,
si_build_ps_prolog_function,
"Fragment Shader Prolog");
if (!shader->prolog)
shader->epilog =
si_get_shader_part(sscreen, &sscreen->ps_epilogs,
PIPE_SHADER_FRAGMENT, false,
- &epilog_key, tm, debug,
+ &epilog_key, compiler, debug,
si_build_ps_epilog_function,
"Fragment Shader Epilog");
if (!shader->epilog)
}
}
-int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
+int si_shader_create(struct si_screen *sscreen, struct si_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
/* Monolithic shader (compiled as a whole, has many variants,
* may take a long time to compile).
*/
- r = si_compile_tgsi_shader(sscreen, tm, shader, true, debug);
+ r = si_compile_tgsi_shader(sscreen, compiler, shader, true, debug);
if (r)
return r;
} else {
/* Select prologs and/or epilogs. */
switch (sel->type) {
case PIPE_SHADER_VERTEX:
- if (!si_shader_select_vs_parts(sscreen, tm, shader, debug))
+ if (!si_shader_select_vs_parts(sscreen, compiler, shader, debug))
return -1;
break;
case PIPE_SHADER_TESS_CTRL:
- if (!si_shader_select_tcs_parts(sscreen, tm, shader, debug))
+ if (!si_shader_select_tcs_parts(sscreen, compiler, shader, debug))
return -1;
break;
case PIPE_SHADER_TESS_EVAL:
break;
case PIPE_SHADER_GEOMETRY:
- if (!si_shader_select_gs_parts(sscreen, tm, shader, debug))
+ if (!si_shader_select_gs_parts(sscreen, compiler, shader, debug))
return -1;
break;
case PIPE_SHADER_FRAGMENT:
- if (!si_shader_select_ps_parts(sscreen, tm, shader, debug))
+ if (!si_shader_select_ps_parts(sscreen, compiler, shader, debug))
return -1;
/* Make sure we have at least as many VGPRs as there
{
struct si_shader_selector *sel = shader->selector;
struct si_screen *sscreen = sel->screen;
- LLVMTargetMachineRef tm;
+ struct si_compiler *compiler;
struct pipe_debug_callback *debug = &shader->compiler_ctx_state.debug;
int r;
if (thread_index >= 0) {
if (low_priority) {
- assert(thread_index < ARRAY_SIZE(sscreen->tm_low_priority));
- tm = sscreen->tm_low_priority[thread_index];
+ assert(thread_index < ARRAY_SIZE(sscreen->compiler_lowp));
+ compiler = &sscreen->compiler_lowp[thread_index];
} else {
- assert(thread_index < ARRAY_SIZE(sscreen->tm));
- tm = sscreen->tm[thread_index];
+ assert(thread_index < ARRAY_SIZE(sscreen->compiler));
+ compiler = &sscreen->compiler[thread_index];
}
if (!debug->async)
debug = NULL;
} else {
assert(!low_priority);
- tm = shader->compiler_ctx_state.tm;
+ compiler = shader->compiler_ctx_state.compiler;
}
- r = si_shader_create(sscreen, tm, shader, debug);
+ r = si_shader_create(sscreen, compiler, shader, debug);
if (unlikely(r)) {
PRINT_ERR("Failed to build shader variant (type=%u) %d\n",
sel->type, r);
main_part->key.as_es = key->as_es;
main_part->key.as_ls = key->as_ls;
- if (si_compile_tgsi_shader(sscreen, compiler_state->tm,
+ if (si_compile_tgsi_shader(sscreen, compiler_state->compiler,
main_part, false,
&compiler_state->debug) != 0) {
FREE(main_part);
{
struct si_shader_selector *sel = (struct si_shader_selector *)job;
struct si_screen *sscreen = sel->screen;
- LLVMTargetMachineRef tm;
+ struct si_compiler *compiler;
struct pipe_debug_callback *debug = &sel->compiler_ctx_state.debug;
assert(!debug->debug_message || debug->async);
assert(thread_index >= 0);
- assert(thread_index < ARRAY_SIZE(sscreen->tm));
- tm = sscreen->tm[thread_index];
+ assert(thread_index < ARRAY_SIZE(sscreen->compiler));
+ compiler = &sscreen->compiler[thread_index];
/* Compile the main shader part for use with a prolog and/or epilog.
* If this fails, the driver will try to compile a monolithic shader
mtx_unlock(&sscreen->shader_cache_mutex);
/* Compile the shader if it hasn't been loaded from the cache. */
- if (si_compile_tgsi_shader(sscreen, tm, shader, false,
+ if (si_compile_tgsi_shader(sscreen, compiler, shader, false,
debug) != 0) {
FREE(shader);
FREE(ir_binary);
/* 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);
+ sel->gs_copy_shader = si_generate_gs_copy_shader(sscreen, compiler, sel, debug);
if (!sel->gs_copy_shader) {
fprintf(stderr, "radeonsi: can't create GS copy shader\n");
return;
old_ps ? old_ps->key.part.ps.epilog.spi_shader_col_format : 0;
int r;
- compiler_state.tm = sctx->tm;
+ compiler_state.compiler = &sctx->compiler;
compiler_state.debug = sctx->debug;
compiler_state.is_debug_context = sctx->is_debug;