struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data);
-static void si_dump_shader_key(unsigned processor, const struct si_shader *shader,
- FILE *f);
+static void si_dump_shader_key(const struct si_shader *shader, FILE *f);
static void si_build_vs_prolog_function(struct si_shader_context *ctx,
union si_shader_part_key *key);
assert(!"invalid generic index");
return 0;
- case TGSI_SEMANTIC_PSIZE:
- return SI_MAX_IO_GENERIC + 1;
- case TGSI_SEMANTIC_CLIPDIST:
- assert(index <= 1);
- return SI_MAX_IO_GENERIC + 2 + index;
case TGSI_SEMANTIC_FOG:
- return SI_MAX_IO_GENERIC + 4;
- case TGSI_SEMANTIC_LAYER:
- return SI_MAX_IO_GENERIC + 5;
- case TGSI_SEMANTIC_VIEWPORT_INDEX:
- return SI_MAX_IO_GENERIC + 6;
- case TGSI_SEMANTIC_PRIMID:
- return SI_MAX_IO_GENERIC + 7;
+ return SI_MAX_IO_GENERIC + 1;
case TGSI_SEMANTIC_COLOR:
assert(index < 2);
- return SI_MAX_IO_GENERIC + 8 + index;
+ return SI_MAX_IO_GENERIC + 2 + index;
case TGSI_SEMANTIC_BCOLOR:
assert(index < 2);
/* If it's a varying, COLOR and BCOLOR alias. */
if (is_varying)
- return SI_MAX_IO_GENERIC + 8 + index;
+ return SI_MAX_IO_GENERIC + 2 + index;
else
- return SI_MAX_IO_GENERIC + 10 + index;
+ return SI_MAX_IO_GENERIC + 4 + index;
case TGSI_SEMANTIC_TEXCOORD:
assert(index < 8);
- STATIC_ASSERT(SI_MAX_IO_GENERIC + 12 + 8 <= 63);
- return SI_MAX_IO_GENERIC + 12 + index;
+ return SI_MAX_IO_GENERIC + 6 + index;
+
+ /* These are rarely used between LS and HS or ES and GS. */
+ case TGSI_SEMANTIC_CLIPDIST:
+ assert(index < 2);
+ return SI_MAX_IO_GENERIC + 6 + 8 + index;
case TGSI_SEMANTIC_CLIPVERTEX:
- return 63;
+ return SI_MAX_IO_GENERIC + 6 + 8 + 2;
+ case TGSI_SEMANTIC_PSIZE:
+ return SI_MAX_IO_GENERIC + 6 + 8 + 3;
+
+ /* These can't be written by LS, HS, and ES. */
+ case TGSI_SEMANTIC_LAYER:
+ return SI_MAX_IO_GENERIC + 6 + 8 + 4;
+ case TGSI_SEMANTIC_VIEWPORT_INDEX:
+ return SI_MAX_IO_GENERIC + 6 + 8 + 5;
+ case TGSI_SEMANTIC_PRIMID:
+ STATIC_ASSERT(SI_MAX_IO_GENERIC + 6 + 8 + 6 <= 63);
+ return SI_MAX_IO_GENERIC + 6 + 8 + 6;
default:
fprintf(stderr, "invalid semantic name = %u\n", semantic_name);
assert(!"invalid semantic name");
tmp = ac_build_opencoded_load_format(
&ctx->ac, fix_fetch.u.log_size, fix_fetch.u.num_channels_m1 + 1,
fix_fetch.u.format, fix_fetch.u.reverse, !opencode,
- t_list, vertex_index, ctx->ac.i32_0, ctx->ac.i32_0,
- false, false, true);
+ t_list, vertex_index, ctx->ac.i32_0, ctx->ac.i32_0, 0, true);
for (unsigned i = 0; i < 4; ++i)
out[i] = LLVMBuildExtractElement(ctx->ac.builder, tmp, LLVMConstInt(ctx->i32, i, false), "");
return;
for (unsigned i = 0; i < num_fetches; ++i) {
LLVMValueRef voffset = LLVMConstInt(ctx->i32, fetch_stride * i, 0);
fetches[i] = ac_build_buffer_load_format(&ctx->ac, t_list, vertex_index, voffset,
- channels_per_fetch, false, true);
+ channels_per_fetch, 0, true);
}
if (num_fetches == 1 && channels_per_fetch > 1) {
if (swizzle == ~0) {
value = ac_build_buffer_load(&ctx->ac, buffer, 4, NULL, base, offset,
- 0, 1, 0, can_speculate, false);
+ 0, ac_glc, can_speculate, false);
return LLVMBuildBitCast(ctx->ac.builder, value, vec_type, "");
}
if (!llvm_type_is_64bit(ctx, type)) {
value = ac_build_buffer_load(&ctx->ac, buffer, 4, NULL, base, offset,
- 0, 1, 0, can_speculate, false);
+ 0, ac_glc, can_speculate, false);
value = LLVMBuildBitCast(ctx->ac.builder, value, vec_type, "");
return LLVMBuildExtractElement(ctx->ac.builder, value,
}
value = ac_build_buffer_load(&ctx->ac, buffer, 1, NULL, base, offset,
- swizzle * 4, 1, 0, can_speculate, false);
+ swizzle * 4, ac_glc, can_speculate, false);
value2 = ac_build_buffer_load(&ctx->ac, buffer, 1, NULL, base, offset,
- swizzle * 4 + 4, 1, 0, can_speculate, false);
+ swizzle * 4 + 4, ac_glc, can_speculate, false);
return si_llvm_emit_fetch_64bit(bld_base, type, value, value2);
}
if (reg->Register.WriteMask != 0xF && !is_tess_factor) {
ac_build_buffer_store_dword(&ctx->ac, buffer, value, 1,
buf_addr, base,
- 4 * chan_index, 1, 0, false);
+ 4 * chan_index, ac_glc, false);
}
/* Write tess factors into VGPRs for the epilog. */
LLVMValueRef value = ac_build_gather_values(&ctx->ac,
values, 4);
ac_build_buffer_store_dword(&ctx->ac, buffer, value, 4, buf_addr,
- base, 0, 1, 0, false);
+ base, 0, ac_glc, false);
}
}
ac_build_buffer_store_dword(&ctx->ac, buffer, value, 1,
addr, base,
4 * buffer_store_offset,
- 1, 0, false);
+ ac_glc, false);
}
/* Write tess factors into VGPRs for the epilog. */
LLVMValueRef value = ac_build_gather_values(&ctx->ac,
values, 4);
ac_build_buffer_store_dword(&ctx->ac, buffer, value, 4, addr,
- base, 0, 1, 0, false);
+ base, 0, ac_glc, false);
}
}
soffset = LLVMConstInt(ctx->i32, (param * 4 + swizzle) * 256, 0);
value = ac_build_buffer_load(&ctx->ac, ctx->esgs_ring, 1, ctx->i32_0,
- vtx_offset, soffset, 0, 1, 0, true, false);
+ vtx_offset, soffset, 0, ac_glc, true, false);
if (llvm_type_is_64bit(ctx, type)) {
LLVMValueRef value2;
soffset = LLVMConstInt(ctx->i32, (param * 4 + swizzle + 1) * 256, 0);
value2 = ac_build_buffer_load(&ctx->ac, ctx->esgs_ring, 1,
ctx->i32_0, vtx_offset, soffset,
- 0, 1, 0, true, false);
+ 0, ac_glc, true, false);
return si_llvm_emit_fetch_64bit(bld_base, type, value, value2);
}
return LLVMBuildBitCast(ctx->ac.builder, value, type, "");
LLVMValueRef offset)
{
return ac_build_buffer_load(&ctx->ac, resource, 1, NULL, offset, NULL,
- 0, 0, 0, true, true);
+ 0, 0, true, true);
}
static LLVMValueRef load_sample_position(struct ac_shader_abi *abi, LLVMValueRef sample_id)
vdata, num_comps,
so_write_offsets[buf_idx],
ctx->i32_0,
- stream_out->dst_offset * 4, 1, 1, false);
+ stream_out->dst_offset * 4, ac_glc | ac_slc, false);
}
/**
/* Write the misc vector (point size, edgeflag, layer, viewport). */
if (shader->selector->info.writes_psize ||
- shader->selector->info.writes_edgeflag ||
+ shader->selector->pos_writes_edgeflag ||
shader->selector->info.writes_viewport_index ||
shader->selector->info.writes_layer) {
pos_args[1].enabled_channels = shader->selector->info.writes_psize |
- (shader->selector->info.writes_edgeflag << 1) |
+ (shader->selector->pos_writes_edgeflag << 1) |
(shader->selector->info.writes_layer << 2);
pos_args[1].valid_mask = 0; /* EXEC mask */
if (shader->selector->info.writes_psize)
pos_args[1].out[0] = psize_value;
- if (shader->selector->info.writes_edgeflag) {
+ if (shader->selector->pos_writes_edgeflag) {
/* The output is a float, but the hw expects an integer
* with the first bit containing the edge flag. */
edgeflag_value = LLVMBuildFPToUI(ctx->ac.builder,
LLVMValueRef value = lshs_lds_load(bld_base, ctx->ac.i32, ~0, lds_ptr);
ac_build_buffer_store_dword(&ctx->ac, buffer, value, 4, buffer_addr,
- buffer_offset, 0, 1, 0, false);
+ buffer_offset, 0, ac_glc, false);
}
}
ac_build_buffer_store_dword(&ctx->ac, buffer,
LLVMConstInt(ctx->i32, 0x80000000, 0),
1, ctx->i32_0, tf_base,
- offset, 1, 0, false);
+ offset, ac_glc, false);
offset += 4;
}
/* Store the tessellation factors. */
ac_build_buffer_store_dword(&ctx->ac, buffer, vec0,
MIN2(stride, 4), byteoffset, tf_base,
- offset, 1, 0, false);
+ offset, ac_glc, false);
offset += 16;
if (vec1)
ac_build_buffer_store_dword(&ctx->ac, buffer, vec1,
stride - 4, byteoffset, tf_base,
- offset, 1, 0, false);
+ offset, ac_glc, false);
/* Store the tess factors into the offchip buffer if TES reads them. */
if (shader->key.part.tcs.epilog.tes_reads_tess_factors) {
ac_build_buffer_store_dword(&ctx->ac, buf, outer_vec,
outer_comps, tf_outer_offset,
- base, 0, 1, 0, false);
+ base, 0, ac_glc, false);
if (inner_comps) {
param_inner = si_shader_io_get_unique_index_patch(
TGSI_SEMANTIC_TESSINNER, 0);
ac_build_gather_values(&ctx->ac, inner, inner_comps);
ac_build_buffer_store_dword(&ctx->ac, buf, inner_vec,
inner_comps, tf_inner_offset,
- base, 0, 1, 0, false);
+ base, 0, ac_glc, false);
}
}
ctx->esgs_ring,
out_val, 1, NULL, soffset,
(4 * param + chan) * 4,
- 1, 1, true);
+ ac_glc | ac_slc, true);
}
}
ctx->gsvs_ring[stream],
out_val, 1,
voffset, soffset, 0,
- 1, 1, true);
+ ac_glc | ac_slc, true);
}
}
case PIPE_SHADER_TESS_CTRL:
/* Return this so that LLVM doesn't remove s_barrier
* instructions on chips where we use s_barrier. */
- return shader->selector->screen->info.chip_class >= GFX7 ? 128 : 64;
+ return shader->selector->screen->info.chip_class >= GFX7 ? 128 : 0;
case PIPE_SHADER_GEOMETRY:
- return shader->selector->screen->info.chip_class >= GFX9 ? 128 : 64;
+ return shader->selector->screen->info.chip_class >= GFX9 ? 128 : 0;
case PIPE_SHADER_COMPUTE:
break; /* see below */
struct ac_rtld_binary *rtld)
{
const struct si_shader_selector *sel = shader->selector;
- enum pipe_shader_type shader_type = sel ? sel->type : PIPE_SHADER_COMPUTE;
const char *part_elfs[5];
size_t part_sizes[5];
unsigned num_parts = 0;
struct ac_rtld_symbol lds_symbols[2];
unsigned num_lds_symbols = 0;
- unsigned esgs_ring_size = 0;
- if (sel && screen->info.chip_class >= GFX9 &&
- sel->type == PIPE_SHADER_GEOMETRY && !shader->is_gs_copy_shader) {
- esgs_ring_size = shader->gs_info.esgs_ring_size;
- }
-
- if (sel && shader->key.as_ngg) {
- if (sel->so.num_outputs) {
- unsigned esgs_vertex_bytes = 4 * (4 * sel->info.num_outputs + 1);
- esgs_ring_size = MAX2(esgs_ring_size,
- shader->ngg.max_out_verts * esgs_vertex_bytes);
- }
-
- /* GS stores Primitive IDs into LDS at the address corresponding
- * to the ES thread of the provoking vertex. All ES threads
- * load and export PrimitiveID for their thread.
- */
- if (sel->type == PIPE_SHADER_VERTEX &&
- shader->key.mono.u.vs_export_prim_id)
- esgs_ring_size = MAX2(esgs_ring_size, shader->ngg.max_out_verts * 4);
- }
-
- if (esgs_ring_size) {
+ if (sel && screen->info.chip_class >= GFX9 && !shader->is_gs_copy_shader &&
+ (sel->type == PIPE_SHADER_GEOMETRY || shader->key.as_ngg)) {
/* We add this symbol even on LLVM <= 8 to ensure that
* shader->config.lds_size is set correctly below.
*/
struct ac_rtld_symbol *sym = &lds_symbols[num_lds_symbols++];
sym->name = "esgs_ring";
- sym->size = esgs_ring_size;
+ sym->size = shader->gs_info.esgs_ring_size;
sym->align = 64 * 1024;
}
.options = {
.halt_at_entry = screen->options.halt_shaders,
},
- .shader_type = tgsi_processor_to_shader_stage(shader_type),
+ .shader_type = tgsi_processor_to_shader_stage(sel->type),
.num_parts = num_parts,
.elf_ptrs = part_elfs,
.elf_sizes = part_sizes,
static void si_shader_dump_disassembly(struct si_screen *screen,
const struct si_shader_binary *binary,
+ enum pipe_shader_type shader_type,
struct pipe_debug_callback *debug,
const char *name, FILE *file)
{
if (!ac_rtld_open(&rtld_binary, (struct ac_rtld_open_info){
.info = &screen->info,
+ .shader_type = tgsi_processor_to_shader_stage(shader_type),
.num_parts = 1,
.elf_ptrs = &binary->elf_buffer,
.elf_sizes = &binary->elf_size }))
DIV_ROUND_UP(max_workgroup_size, 64);
}
break;
+ default:;
}
/* Compute the per-SIMD wave counts. */
const struct ac_shader_config *conf = &shader->config;
if (screen->options.debug_disassembly)
- si_shader_dump_disassembly(screen, &shader->binary, debug, "main", NULL);
+ si_shader_dump_disassembly(screen, &shader->binary,
+ shader->selector->type,
+ debug, "main", NULL);
pipe_debug_message(debug, SHADER_INFO,
"Shader Stats: SGPRS: %d VGPRS: %d Code Size: %d "
static void si_shader_dump_stats(struct si_screen *sscreen,
struct si_shader *shader,
- unsigned processor,
FILE *file,
bool check_debug_option)
{
const struct ac_shader_config *conf = &shader->config;
if (!check_debug_option ||
- si_can_dump_shader(sscreen, processor)) {
- if (processor == PIPE_SHADER_FRAGMENT) {
+ si_can_dump_shader(sscreen, shader->selector->type)) {
+ if (shader->selector->type == PIPE_SHADER_FRAGMENT) {
fprintf(file, "*** SHADER CONFIG ***\n"
"SPI_PS_INPUT_ADDR = 0x%04x\n"
"SPI_PS_INPUT_ENA = 0x%04x\n",
}
}
-const char *si_get_shader_name(const struct si_shader *shader, unsigned processor)
+const char *si_get_shader_name(const struct si_shader *shader)
{
- switch (processor) {
+ switch (shader->selector->type) {
case PIPE_SHADER_VERTEX:
if (shader->key.as_es)
return "Vertex Shader as ES";
}
void si_shader_dump(struct si_screen *sscreen, struct si_shader *shader,
- struct pipe_debug_callback *debug, unsigned processor,
+ struct pipe_debug_callback *debug,
FILE *file, bool check_debug_option)
{
+ enum pipe_shader_type shader_type = shader->selector->type;
+
if (!check_debug_option ||
- si_can_dump_shader(sscreen, processor))
- si_dump_shader_key(processor, shader, file);
+ si_can_dump_shader(sscreen, shader_type))
+ si_dump_shader_key(shader, file);
if (!check_debug_option && shader->binary.llvm_ir_string) {
if (shader->previous_stage &&
shader->previous_stage->binary.llvm_ir_string) {
fprintf(file, "\n%s - previous stage - LLVM IR:\n\n",
- si_get_shader_name(shader, processor));
+ si_get_shader_name(shader));
fprintf(file, "%s\n", shader->previous_stage->binary.llvm_ir_string);
}
fprintf(file, "\n%s - main shader part - LLVM IR:\n\n",
- si_get_shader_name(shader, processor));
+ si_get_shader_name(shader));
fprintf(file, "%s\n", shader->binary.llvm_ir_string);
}
if (!check_debug_option ||
- (si_can_dump_shader(sscreen, processor) &&
+ (si_can_dump_shader(sscreen, shader_type) &&
!(sscreen->debug_flags & DBG(NO_ASM)))) {
- fprintf(file, "\n%s:\n", si_get_shader_name(shader, processor));
+ fprintf(file, "\n%s:\n", si_get_shader_name(shader));
if (shader->prolog)
si_shader_dump_disassembly(sscreen, &shader->prolog->binary,
- debug, "prolog", file);
+ shader_type, debug, "prolog", file);
if (shader->previous_stage)
si_shader_dump_disassembly(sscreen, &shader->previous_stage->binary,
- debug, "previous stage", file);
+ shader_type, debug, "previous stage", file);
if (shader->prolog2)
si_shader_dump_disassembly(sscreen, &shader->prolog2->binary,
- debug, "prolog2", file);
+ shader_type, debug, "prolog2", file);
- si_shader_dump_disassembly(sscreen, &shader->binary, debug, "main", file);
+ si_shader_dump_disassembly(sscreen, &shader->binary, shader_type, debug, "main", file);
if (shader->epilog)
si_shader_dump_disassembly(sscreen, &shader->epilog->binary,
- debug, "epilog", file);
+ shader_type, debug, "epilog", file);
fprintf(file, "\n");
}
- si_shader_dump_stats(sscreen, shader, processor, file,
- check_debug_option);
+ si_shader_dump_stats(sscreen, shader, file, check_debug_option);
}
static int si_compile_llvm(struct si_screen *sscreen,
struct ac_llvm_compiler *compiler,
LLVMModuleRef mod,
struct pipe_debug_callback *debug,
- unsigned processor,
+ enum pipe_shader_type shader_type,
const char *name,
bool less_optimized)
{
unsigned count = p_atomic_inc_return(&sscreen->num_compilations);
- if (si_can_dump_shader(sscreen, processor)) {
+ if (si_can_dump_shader(sscreen, shader_type)) {
fprintf(stderr, "radeonsi: Compiling shader %d\n", count);
if (!(sscreen->debug_flags & (DBG(NO_IR) | DBG(PREOPT_IR)))) {
struct ac_rtld_binary rtld;
if (!ac_rtld_open(&rtld, (struct ac_rtld_open_info){
.info = &sscreen->info,
+ .shader_type = tgsi_processor_to_shader_stage(shader_type),
.num_parts = 1,
.elf_ptrs = &binary->elf_buffer,
.elf_sizes = &binary->elf_size }))
ac_build_buffer_load(&ctx.ac,
ctx.gsvs_ring[0], 1,
ctx.i32_0, voffset,
- soffset, 0, 1, 1,
+ soffset, 0, ac_glc | ac_slc,
true, false);
}
}
"GS Copy Shader", false) == 0) {
if (si_can_dump_shader(sscreen, PIPE_SHADER_GEOMETRY))
fprintf(stderr, "GS Copy Shader:\n");
- si_shader_dump(sscreen, ctx.shader, debug,
- PIPE_SHADER_GEOMETRY, stderr, true);
+ si_shader_dump(sscreen, ctx.shader, debug, stderr, true);
if (!ctx.shader->config.scratch_bytes_per_wave)
ok = si_shader_binary_upload(sscreen, ctx.shader, 0);
fprintf(f, "}\n");
}
-static void si_dump_shader_key(unsigned processor, const struct si_shader *shader,
- FILE *f)
+static void si_dump_shader_key(const struct si_shader *shader, FILE *f)
{
const struct si_shader_key *key = &shader->key;
+ enum pipe_shader_type shader_type = shader->selector->type;
fprintf(f, "SHADER KEY\n");
- switch (processor) {
+ switch (shader_type) {
case PIPE_SHADER_VERTEX:
si_dump_shader_key_vs(key, &key->part.vs.prolog,
"part.vs.prolog", f);
assert(0);
}
- if ((processor == PIPE_SHADER_GEOMETRY ||
- processor == PIPE_SHADER_TESS_EVAL ||
- processor == PIPE_SHADER_VERTEX) &&
+ if ((shader_type == PIPE_SHADER_GEOMETRY ||
+ shader_type == PIPE_SHADER_TESS_EVAL ||
+ shader_type == PIPE_SHADER_VERTEX) &&
!key->as_es && !key->as_ls) {
fprintf(f, " opt.kill_outputs = 0x%"PRIx64"\n", key->opt.kill_outputs);
fprintf(f, " opt.clip_disable = %u\n", key->opt.clip_disable);
/* Dump TGSI code before doing TGSI->LLVM conversion in case the
* conversion fails. */
- if (si_can_dump_shader(sscreen, sel->info.processor) &&
+ if (si_can_dump_shader(sscreen, sel->type) &&
!(sscreen->debug_flags & DBG(NO_TGSI))) {
if (sel->tokens)
tgsi_dump(sel->tokens, 0);
memset(&gs_prolog_key, 0, sizeof(gs_prolog_key));
gs_prolog_key.gs_prolog.states = shader->key.part.gs.prolog;
gs_prolog_key.gs_prolog.is_monolithic = true;
+ gs_prolog_key.gs_prolog.as_ngg = shader->key.as_ngg;
si_build_gs_prolog_function(&ctx, &gs_prolog_key);
gs_prolog = ctx.main_fn;
/* Compile to bytecode. */
r = si_compile_llvm(sscreen, &shader->binary, &shader->config, compiler,
ctx.ac.module, debug, ctx.type,
- si_get_shader_name(shader, ctx.type),
+ si_get_shader_name(shader),
si_should_optimize_less(compiler, shader->selector));
si_llvm_dispose(&ctx);
if (r) {
result->key = *key;
struct si_shader shader = {};
- struct si_shader_context ctx;
-
- si_init_shader_ctx(&ctx, sscreen, compiler);
- ctx.shader = &shader;
- ctx.type = type;
switch (type) {
case PIPE_SHADER_VERTEX:
break;
case PIPE_SHADER_GEOMETRY:
assert(prolog);
+ shader.key.as_ngg = key->gs_prolog.as_ngg;
break;
case PIPE_SHADER_FRAGMENT:
if (prolog)
unreachable("bad shader part");
}
+ struct si_shader_context ctx;
+ si_init_shader_ctx(&ctx, sscreen, compiler);
+ ctx.shader = &shader;
+ ctx.type = type;
+
build(&ctx, key);
/* Compile. */
/* Create the function. */
si_create_function(ctx, "tcs_epilog", NULL, 0, &fninfo,
- ctx->screen->info.chip_class >= GFX7 ? 128 : 64);
+ ctx->screen->info.chip_class >= GFX7 ? 128 : 0);
ac_declare_lds_as_pointer(&ctx->ac);
func = ctx->main_fn;
union si_shader_part_key prolog_key;
memset(&prolog_key, 0, sizeof(prolog_key));
prolog_key.gs_prolog.states = shader->key.part.gs.prolog;
+ prolog_key.gs_prolog.as_ngg = shader->key.as_ngg;
shader->prolog2 = si_get_shader_part(sscreen, &sscreen->gs_prologs,
PIPE_SHADER_GEOMETRY, true,
shader->config.num_vgprs = MAX2(shader->config.num_vgprs,
shader->info.num_input_vgprs);
break;
+ default:;
}
/* Update SGPR and VGPR counts. */
}
si_fix_resource_usage(sscreen, shader);
- si_shader_dump(sscreen, shader, debug, sel->info.processor,
- stderr, true);
+ si_shader_dump(sscreen, shader, debug, stderr, true);
/* Upload. */
if (!si_shader_binary_upload(sscreen, shader, 0)) {