diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 53c589f2e8b..3937c7bbb3b 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -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; diff --git a/src/gallium/drivers/radeonsi/si_shader_internal.h b/src/gallium/drivers/radeonsi/si_shader_internal.h index ede39887c29..4f7a6b80ab3 100644 --- a/src/gallium/drivers/radeonsi/si_shader_internal.h +++ b/src/gallium/drivers/radeonsi/si_shader_internal.h @@ -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); diff --git a/src/gallium/drivers/radeonsi/si_shader_llvm_gs.c b/src/gallium/drivers/radeonsi/si_shader_llvm_gs.c index d682725bd0d..36c07d21a7e 100644 --- a/src/gallium/drivers/radeonsi/si_shader_llvm_gs.c +++ b/src/gallium/drivers/radeonsi/si_shader_llvm_gs.c @@ -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; diff --git a/src/gallium/drivers/radeonsi/si_shader_llvm_vs.c b/src/gallium/drivers/radeonsi/si_shader_llvm_vs.c index 1aadd00b360..1679f6863eb 100644 --- a/src/gallium/drivers/radeonsi/si_shader_llvm_vs.c +++ b/src/gallium/drivers/radeonsi/si_shader_llvm_vs.c @@ -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]) {