radeonsi: remove llvm gs copy shader generate

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19489>
This commit is contained in:
Qiang Yu
2022-12-04 13:38:53 +08:00
committed by Marge Bot
parent e007c7fa6f
commit 6219374c4e
4 changed files with 0 additions and 356 deletions
-7
View File
@@ -993,13 +993,6 @@ bool si_get_external_symbol(enum amd_gfx_level gfx_level, void *data, const char
void si_nir_scan_shader(struct si_screen *sscreen, const struct nir_shader *nir,
struct si_shader_info *info);
/* si_shader_llvm_gs.c */
struct si_shader *si_generate_gs_copy_shader(struct si_screen *sscreen,
struct ac_llvm_compiler *compiler,
struct si_shader_selector *gs_selector,
const struct pipe_stream_output_info *so,
struct util_debug_callback *debug);
/* si_shader_nir.c */
extern const nir_lower_subgroups_options si_nir_subgroups_options;
@@ -118,7 +118,6 @@ struct si_shader_context {
struct ac_llvm_context ac;
struct si_shader *shader;
struct si_screen *screen;
struct pipe_stream_output_info so;
gl_shader_stage stage;
@@ -259,12 +258,6 @@ void si_llvm_init_ps_callbacks(struct si_shader_context *ctx);
/* si_shader_llvm_vs.c */
void si_llvm_clipvertex_to_clipdist(struct si_shader_context *ctx,
struct ac_export_args clipdist[2], LLVMValueRef clipvertex[4]);
void si_llvm_streamout_store_output(struct si_shader_context *ctx, LLVMValueRef const *so_buffers,
LLVMValueRef const *so_write_offsets,
struct pipe_stream_output *stream_out,
struct si_shader_output_values *shader_out);
void si_llvm_emit_streamout(struct si_shader_context *ctx, struct si_shader_output_values *outputs,
unsigned noutput, unsigned stream);
void si_llvm_build_vs_exports(struct si_shader_context *ctx,
struct si_shader_output_values *outputs, unsigned noutput);
void si_llvm_build_vs_prolog(struct si_shader_context *ctx, union si_shader_part_key *key);
@@ -339,234 +339,6 @@ void si_preload_gs_rings(struct si_shader_context *ctx)
}
}
/**
* Vertex color clamping.
*
* This uses a state constant loaded in a user data SGPR and
* an IF statement is added that clamps all colors if the constant
* is true.
*/
static void si_vertex_color_clamping(struct si_shader_context *ctx,
struct si_shader_output_values *outputs, unsigned noutput)
{
LLVMValueRef addr[SI_MAX_VS_OUTPUTS][4];
bool has_colors = false;
/* Store original colors to alloca variables. */
for (unsigned i = 0; i < noutput; i++) {
if (outputs[i].semantic != VARYING_SLOT_COL0 &&
outputs[i].semantic != VARYING_SLOT_COL1 &&
outputs[i].semantic != VARYING_SLOT_BFC0 &&
outputs[i].semantic != VARYING_SLOT_BFC1)
continue;
for (unsigned j = 0; j < 4; j++)
addr[i][j] = ac_build_alloca_init(&ctx->ac, outputs[i].values[j], "");
has_colors = true;
}
if (!has_colors)
return;
/* The state is in the first bit of the user SGPR. */
LLVMValueRef cond = GET_FIELD(ctx, VS_STATE_CLAMP_VERTEX_COLOR);
cond = LLVMBuildTrunc(ctx->ac.builder, cond, ctx->ac.i1, "");
ac_build_ifcc(&ctx->ac, cond, 6502);
/* Store clamped colors to alloca variables within the conditional block. */
for (unsigned i = 0; i < noutput; i++) {
if (outputs[i].semantic != VARYING_SLOT_COL0 &&
outputs[i].semantic != VARYING_SLOT_COL1 &&
outputs[i].semantic != VARYING_SLOT_BFC0 &&
outputs[i].semantic != VARYING_SLOT_BFC1)
continue;
for (unsigned j = 0; j < 4; j++) {
LLVMBuildStore(ctx->ac.builder, ac_build_clamp(&ctx->ac, outputs[i].values[j]),
addr[i][j]);
}
}
ac_build_endif(&ctx->ac, 6502);
/* Load clamped colors */
for (unsigned i = 0; i < noutput; i++) {
if (outputs[i].semantic != VARYING_SLOT_COL0 &&
outputs[i].semantic != VARYING_SLOT_COL1 &&
outputs[i].semantic != VARYING_SLOT_BFC0 &&
outputs[i].semantic != VARYING_SLOT_BFC1)
continue;
for (unsigned j = 0; j < 4; j++) {
outputs[i].values[j] = LLVMBuildLoad2(ctx->ac.builder, ctx->ac.f32, addr[i][j], "");
}
}
}
/* 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,
struct ac_llvm_compiler *compiler,
struct si_shader_selector *gs_selector,
const struct pipe_stream_output_info *so,
struct util_debug_callback *debug)
{
struct si_shader_context ctx;
struct si_shader *shader;
LLVMBuilderRef builder;
struct si_shader_output_values outputs[SI_MAX_VS_OUTPUTS];
struct si_shader_info *gsinfo = &gs_selector->info;
int i;
shader = CALLOC_STRUCT(si_shader);
if (!shader)
return NULL;
/* We can leave the fence as permanently signaled because the GS copy
* shader only becomes visible globally after it has been compiled. */
util_queue_fence_init(&shader->ready);
shader->selector = gs_selector;
shader->is_gs_copy_shader = true;
shader->wave_size = si_determine_wave_size(sscreen, shader);
STATIC_ASSERT(sizeof(shader->info.vs_output_param_offset[0]) == 1);
memset(shader->info.vs_output_param_offset, AC_EXP_PARAM_DEFAULT_VAL_0000,
sizeof(shader->info.vs_output_param_offset));
for (unsigned i = 0; i < gsinfo->num_outputs; i++) {
unsigned semantic = gsinfo->output_semantic[i];
/* Skip if no channel writes to stream 0. */
if (!nir_slot_is_varying(semantic) ||
(gsinfo->output_streams[i] & 0x03 &&
gsinfo->output_streams[i] & 0x0c &&
gsinfo->output_streams[i] & 0x30 &&
gsinfo->output_streams[i] & 0xc0))
continue;
shader->info.vs_output_param_offset[semantic] = shader->info.nr_param_exports++;
shader->info.vs_output_param_mask |= BITFIELD64_BIT(i);
}
si_llvm_context_init(&ctx, sscreen, compiler, shader->wave_size, false, false);
ctx.shader = shader;
ctx.stage = MESA_SHADER_VERTEX;
ctx.so = *so;
struct si_shader_args args;
si_init_shader_args(shader, &args);
ctx.args = &args;
builder = ctx.ac.builder;
/* Build the main function. */
si_llvm_create_main_func(&ctx);
ctx.gsvs_ring[0] =
ac_build_load_to_sgpr(&ctx.ac,
ac_get_ptr_arg(&ctx.ac, &ctx.args->ac, ctx.args->internal_bindings), LLVMConstInt(ctx.ac.i32, SI_RING_GSVS, 0));
LLVMValueRef voffset =
LLVMBuildMul(ctx.ac.builder, ctx.abi.vertex_id, LLVMConstInt(ctx.ac.i32, 4, 0), "");
/* Fetch the vertex stream ID.*/
LLVMValueRef stream_id;
if (!sscreen->use_ngg_streamout && ctx.so.num_outputs)
stream_id = si_unpack_param(&ctx, ctx.args->ac.streamout_config, 24, 2);
else
stream_id = ctx.ac.i32_0;
/* Fill in output information. */
for (i = 0; i < gsinfo->num_outputs; ++i) {
outputs[i].semantic = gsinfo->output_semantic[i];
outputs[i].vertex_streams = gsinfo->output_streams[i];
}
LLVMBasicBlockRef end_bb;
LLVMValueRef switch_inst;
end_bb = LLVMAppendBasicBlockInContext(ctx.ac.context, ctx.main_fn.value, "end");
switch_inst = LLVMBuildSwitch(builder, stream_id, end_bb, 4);
for (int stream = 0; stream < 4; stream++) {
LLVMBasicBlockRef bb;
unsigned offset;
if (!gsinfo->num_stream_output_components[stream])
continue;
if (stream > 0 && !ctx.so.num_outputs)
continue;
bb = LLVMInsertBasicBlockInContext(ctx.ac.context, end_bb, "out");
LLVMAddCase(switch_inst, LLVMConstInt(ctx.ac.i32, stream, 0), bb);
LLVMPositionBuilderAtEnd(builder, bb);
/* Fetch vertex data from GSVS ring */
offset = 0;
for (i = 0; i < gsinfo->num_outputs; ++i) {
for (unsigned chan = 0; chan < 4; chan++) {
if (!(gsinfo->output_usagemask[i] & (1 << chan)) ||
((outputs[i].vertex_streams >> (chan * 2)) & 0x3) != stream) {
outputs[i].values[chan] = LLVMGetUndef(ctx.ac.f32);
continue;
}
LLVMValueRef soffset =
LLVMConstInt(ctx.ac.i32, offset * gs_selector->info.base.gs.vertices_out * 16 * 4, 0);
offset++;
outputs[i].values[chan] =
ac_build_buffer_load(&ctx.ac, ctx.gsvs_ring[0], 1, ctx.ac.i32_0, voffset, soffset,
ctx.ac.f32, ac_glc | ac_slc, true, false);
}
}
/* Streamout and exports. */
if (!sscreen->use_ngg_streamout && ctx.so.num_outputs) {
si_llvm_emit_streamout(&ctx, outputs, gsinfo->num_outputs, stream);
}
if (stream == 0) {
si_vertex_color_clamping(&ctx, outputs, gsinfo->num_outputs);
si_llvm_build_vs_exports(&ctx, outputs, gsinfo->num_outputs);
}
LLVMBuildBr(builder, end_bb);
}
LLVMPositionBuilderAtEnd(builder, end_bb);
LLVMBuildRetVoid(ctx.ac.builder);
ctx.stage = MESA_SHADER_GEOMETRY; /* override for shader dumping */
si_llvm_optimize_module(&ctx);
bool ok = false;
if (si_compile_llvm(sscreen, &ctx.shader->binary, &ctx.shader->config, ctx.compiler, &ctx.ac,
debug, MESA_SHADER_GEOMETRY, "GS Copy Shader", false)) {
assert(!ctx.shader->config.scratch_bytes_per_wave);
if (!ctx.shader->config.scratch_bytes_per_wave)
ok = si_shader_binary_upload(sscreen, ctx.shader, 0);
if (si_can_dump_shader(sscreen, MESA_SHADER_GEOMETRY))
fprintf(stderr, "GS Copy Shader:\n");
si_shader_dump(sscreen, ctx.shader, debug, stderr, true);
}
si_llvm_dispose(&ctx);
if (!ok) {
FREE(shader);
shader = NULL;
} else {
si_fix_resource_usage(sscreen, shader);
}
return shader;
}
void si_llvm_init_gs_callbacks(struct si_shader_context *ctx)
{
ctx->abi.emit_vertex_with_counter = si_llvm_emit_vertex;
@@ -330,120 +330,6 @@ static LLVMValueRef si_load_vs_input(struct ac_shader_abi *abi, unsigned driver_
return ac_build_varying_gather_values(&ctx->ac, values, num_components, component);
}
void si_llvm_streamout_store_output(struct si_shader_context *ctx, LLVMValueRef const *so_buffers,
LLVMValueRef const *so_write_offsets,
struct pipe_stream_output *stream_out,
struct si_shader_output_values *shader_out)
{
unsigned buf_idx = stream_out->output_buffer;
unsigned start = stream_out->start_component;
unsigned num_comps = stream_out->num_components;
LLVMValueRef out[4];
assert(num_comps && num_comps <= 4);
if (!num_comps || num_comps > 4)
return;
/* Load the output as int. */
for (int j = 0; j < num_comps; j++) {
assert(stream_out->stream == ((shader_out->vertex_streams >> ((start + j) * 2)) & 0x3));
out[j] = ac_to_integer(&ctx->ac, shader_out->values[start + j]);
}
/* Pack the output. */
LLVMValueRef vdata = NULL;
switch (num_comps) {
case 1: /* as i32 */
vdata = out[0];
break;
case 2: /* as v2i32 */
case 3: /* as v3i32 */
case 4: /* as v4i32 */
vdata = ac_build_gather_values(&ctx->ac, out, num_comps);
break;
}
ac_build_buffer_store_dword(&ctx->ac, so_buffers[buf_idx], vdata, NULL,
LLVMBuildAdd(ctx->ac.builder, so_write_offsets[buf_idx],
LLVMConstInt(ctx->ac.i32, stream_out->dst_offset * 4, 0), ""),
ctx->ac.i32_0, ac_glc | ac_slc);
}
/**
* Write streamout data to buffers for vertex stream @p stream (different
* vertex streams can occur for GS copy shaders).
*/
void si_llvm_emit_streamout(struct si_shader_context *ctx, struct si_shader_output_values *outputs,
unsigned noutput, unsigned stream)
{
struct pipe_stream_output_info *so = &ctx->so;
LLVMBuilderRef builder = ctx->ac.builder;
int i;
/* Get bits [22:16], i.e. (so_param >> 16) & 127; */
LLVMValueRef so_vtx_count = si_unpack_param(ctx, ctx->args->ac.streamout_config, 16, 7);
LLVMValueRef tid = ac_get_thread_id(&ctx->ac);
/* can_emit = tid < so_vtx_count; */
LLVMValueRef can_emit = LLVMBuildICmp(builder, LLVMIntULT, tid, so_vtx_count, "");
/* Emit the streamout code conditionally. This actually avoids
* out-of-bounds buffer access. The hw tells us via the SGPR
* (so_vtx_count) which threads are allowed to emit streamout data. */
ac_build_ifcc(&ctx->ac, can_emit, 6501);
{
/* The buffer offset is computed as follows:
* ByteOffset = streamout_offset[buffer_id]*4 +
* (streamout_write_index + thread_id)*stride[buffer_id] +
* attrib_offset
*/
LLVMValueRef so_write_index = ac_get_arg(&ctx->ac, ctx->args->ac.streamout_write_index);
/* Compute (streamout_write_index + thread_id). */
so_write_index = LLVMBuildAdd(builder, so_write_index, tid, "");
/* Load the descriptor and compute the write offset for each
* enabled buffer. */
LLVMValueRef so_write_offset[4] = {};
LLVMValueRef so_buffers[4];
struct ac_llvm_pointer arg = ac_get_ptr_arg(&ctx->ac, &ctx->args->ac, ctx->args->internal_bindings);
for (i = 0; i < 4; i++) {
if (!so->stride[i])
continue;
LLVMValueRef offset = LLVMConstInt(ctx->ac.i32, SI_VS_STREAMOUT_BUF0 + i, 0);
so_buffers[i] = ac_build_load_to_sgpr(&ctx->ac, arg, offset);
LLVMValueRef so_offset = ac_get_arg(&ctx->ac, ctx->args->ac.streamout_offset[i]);
so_offset = LLVMBuildMul(builder, so_offset, LLVMConstInt(ctx->ac.i32, 4, 0), "");
so_write_offset[i] = ac_build_imad(
&ctx->ac, so_write_index, LLVMConstInt(ctx->ac.i32, so->stride[i] * 4, 0), so_offset);
}
/* Write streamout data. */
for (i = 0; i < so->num_outputs; i++) {
unsigned reg = so->output[i].register_index;
if (reg >= noutput)
continue;
if (stream != so->output[i].stream)
continue;
si_llvm_streamout_store_output(ctx, so_buffers, so_write_offset, &so->output[i],
&outputs[reg]);
}
}
ac_build_endif(&ctx->ac, 6501);
}
void si_llvm_clipvertex_to_clipdist(struct si_shader_context *ctx,
struct ac_export_args clipdist[2], LLVMValueRef clipvertex[4])
{