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:
@@ -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])
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user