#include "tgsi/tgsi_strings.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_from_mesa.h"
#include "ac_binary.h"
#include "ac_exp_param.h"
static const char scratch_rsrc_dword1_symbol[] =
"SCRATCH_RSRC_DWORD1";
-struct si_shader_output_values
-{
- LLVMValueRef values[4];
- unsigned semantic_name;
- unsigned semantic_index;
- ubyte vertex_stream[4];
-};
-
static void si_init_shader_ctx(struct si_shader_context *ctx,
struct si_screen *sscreen,
struct ac_llvm_compiler *compiler);
return false;
}
-static bool is_merged_shader(struct si_shader_context *ctx)
+/** Whether the shader runs as a combination of multiple API shaders */
+static bool is_multi_part_shader(struct si_shader_context *ctx)
{
if (ctx->screen->info.chip_class <= GFX8)
return false;
ctx->type == PIPE_SHADER_GEOMETRY;
}
+/** Whether the shader runs on a merged HW stage (LSHS or ESGS) */
+static bool is_merged_shader(struct si_shader_context *ctx)
+{
+ return ctx->shader->key.as_ngg || is_multi_part_shader(ctx);
+}
+
void si_init_function_info(struct si_function_info *fninfo)
{
fninfo->num_params = 0;
si_llvm_load_input_vs(ctx, input_index, out);
}
-static LLVMValueRef get_primitive_id(struct si_shader_context *ctx,
- unsigned swizzle)
+LLVMValueRef si_get_primitive_id(struct si_shader_context *ctx,
+ unsigned swizzle)
{
if (swizzle > 0)
return ctx->i32_0;
}
/**
- * Load from LDS.
+ * Load from LSHS LDS storage.
*
* \param type output value type
* \param swizzle offset (typically 0..3); it can be ~0, which loads a vec4
* \param dw_addr address in dwords
*/
-static LLVMValueRef lds_load(struct lp_build_tgsi_context *bld_base,
+static LLVMValueRef lshs_lds_load(struct lp_build_tgsi_context *bld_base,
LLVMTypeRef type, unsigned swizzle,
LLVMValueRef dw_addr)
{
LLVMValueRef values[TGSI_NUM_CHANNELS];
for (unsigned chan = 0; chan < TGSI_NUM_CHANNELS; chan++)
- values[chan] = lds_load(bld_base, type, chan, dw_addr);
+ values[chan] = lshs_lds_load(bld_base, type, chan, dw_addr);
return ac_build_gather_values(&ctx->ac, values,
TGSI_NUM_CHANNELS);
if (llvm_type_is_64bit(ctx, type)) {
LLVMValueRef lo, hi;
- lo = lds_load(bld_base, ctx->i32, swizzle, dw_addr);
- hi = lds_load(bld_base, ctx->i32, swizzle + 1, dw_addr);
+ lo = lshs_lds_load(bld_base, ctx->i32, swizzle, dw_addr);
+ hi = lshs_lds_load(bld_base, ctx->i32, swizzle + 1, dw_addr);
return si_llvm_emit_fetch_64bit(bld_base, type, lo, hi);
}
}
/**
- * Store to LDS.
+ * Store to LSHS LDS storage.
*
* \param swizzle offset (typically 0..3)
* \param dw_addr address in dwords
* \param value value to store
*/
-static void lds_store(struct si_shader_context *ctx,
+static void lshs_lds_store(struct si_shader_context *ctx,
unsigned dw_offset_imm, LLVMValueRef dw_addr,
LLVMValueRef value)
{
LLVMConstInt(ctx->i32, tf_offset, 0), "");
}
+ uint32_t rsrc3 = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
+ S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
+ S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
+ S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W);
+
+ if (ctx->screen->info.chip_class >= GFX10)
+ rsrc3 |= S_008F0C_FORMAT(V_008F0C_IMG_FORMAT_32_FLOAT) |
+ S_008F0C_OOB_SELECT(3) |
+ S_008F0C_RESOURCE_LEVEL(1);
+ else
+ rsrc3 |= S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
+ S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32);
+
LLVMValueRef desc[4];
desc[0] = addr;
desc[1] = LLVMConstInt(ctx->i32,
S_008F04_BASE_ADDRESS_HI(ctx->screen->info.address32_hi), 0);
desc[2] = LLVMConstInt(ctx->i32, 0xffffffff, 0);
- desc[3] = LLVMConstInt(ctx->i32,
- S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
- S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
- S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
- S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
- S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
- S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32), 0);
+ desc[3] = LLVMConstInt(ctx->i32, rsrc3, false);
return ac_build_gather_values(&ctx->ac, desc, 4);
}
dw_addr = get_tcs_in_current_patch_offset(ctx);
dw_addr = get_dw_address(ctx, NULL, reg, stride, dw_addr);
- return lds_load(bld_base, tgsi2llvmtype(bld_base, type), swizzle, dw_addr);
+ return lshs_lds_load(bld_base, tgsi2llvmtype(bld_base, type), swizzle, dw_addr);
}
static LLVMValueRef si_nir_load_tcs_varyings(struct ac_shader_abi *abi,
offset *= 2;
offset += component;
- value[i + component] = lds_load(bld_base, type, offset, dw_addr);
+ value[i + component] = lshs_lds_load(bld_base, type, offset, dw_addr);
}
return ac_build_varying_gather_values(&ctx->ac, value, num_components, component);
dw_addr = get_dw_address(ctx, NULL, reg, NULL, dw_addr);
}
- return lds_load(bld_base, tgsi2llvmtype(bld_base, type), swizzle, dw_addr);
+ return lshs_lds_load(bld_base, tgsi2llvmtype(bld_base, type), swizzle, dw_addr);
}
static LLVMValueRef fetch_input_tes(
/* Skip LDS stores if there is no LDS read of this output. */
if (!skip_lds_store)
- lds_store(ctx, chan_index, dw_addr, value);
+ lshs_lds_store(ctx, chan_index, dw_addr, value);
value = ac_to_integer(&ctx->ac, value);
values[chan_index] = value;
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, true, false);
+ 4 * chan_index, 1, 0, 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, true, false);
+ base, 0, 1, 0, false);
}
}
/* Skip LDS stores if there is no LDS read of this output. */
if (!skip_lds_store)
- lds_store(ctx, chan, dw_addr, value);
+ lshs_lds_store(ctx, chan, dw_addr, value);
value = ac_to_integer(&ctx->ac, value);
values[chan] = value;
ac_build_buffer_store_dword(&ctx->ac, buffer, value, 1,
addr, base,
4 * buffer_store_offset,
- 1, 0, true, false);
+ 1, 0, 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, true, false);
+ base, 0, 1, 0, false);
}
}
return NULL;
}
+ unsigned offset = param * 4 + swizzle;
vtx_offset = LLVMBuildAdd(ctx->ac.builder, vtx_offset,
- LLVMConstInt(ctx->i32, param * 4, 0), "");
- return lds_load(bld_base, type, swizzle, vtx_offset);
+ LLVMConstInt(ctx->i32, offset, false), "");
+
+ LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->esgs_ring, vtx_offset);
+ LLVMValueRef value = LLVMBuildLoad(ctx->ac.builder, ptr, "");
+ if (llvm_type_is_64bit(ctx, type)) {
+ ptr = LLVMBuildGEP(ctx->ac.builder, ptr,
+ &ctx->ac.i32_1, 1, "");
+ LLVMValueRef values[2] = {
+ value,
+ LLVMBuildLoad(ctx->ac.builder, ptr, "")
+ };
+ value = ac_build_gather_values(&ctx->ac, values, 2);
+ }
+ return LLVMBuildBitCast(ctx->ac.builder, value, type, "");
}
/* GFX6: input load from the ESGS ring in memory. */
unsigned semantic_name = info->input_semantic_name[reg->Register.Index];
if (swizzle != ~0 && semantic_name == TGSI_SEMANTIC_PRIMID)
- return get_primitive_id(ctx, swizzle);
+ return si_get_primitive_id(ctx, swizzle);
if (!reg->Register.Dimension)
return NULL;
}
case TGSI_SEMANTIC_PRIMID:
- value = get_primitive_id(ctx, 0);
+ value = si_get_primitive_id(ctx, 0);
break;
case TGSI_SEMANTIC_GRID_SIZE:
LLVMArrayType(ctx->i8, lds_size),
"compute_lds",
AC_ADDR_SPACE_LDS);
- LLVMSetAlignment(var, 4);
+ LLVMSetAlignment(var, 64 * 1024);
ctx->ac.lds = LLVMBuildBitCast(ctx->ac.builder, var, i8p, "");
}
desc1 = LLVMConstInt(ctx->i32,
S_008F04_BASE_ADDRESS_HI(ctx->screen->info.address32_hi), 0);
+ uint32_t rsrc3 = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
+ S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
+ S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
+ S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W);
+
+ if (ctx->screen->info.chip_class >= GFX10)
+ rsrc3 |= S_008F0C_FORMAT(V_008F0C_IMG_FORMAT_32_FLOAT) |
+ S_008F0C_OOB_SELECT(3) |
+ S_008F0C_RESOURCE_LEVEL(1);
+ else
+ rsrc3 |= S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
+ S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32);
+
LLVMValueRef desc_elems[] = {
desc0,
desc1,
LLVMConstInt(ctx->i32, (sel->info.const_file_max[0] + 1) * 16, 0),
- LLVMConstInt(ctx->i32,
- S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
- S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
- S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
- S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
- S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
- S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32), 0)
+ LLVMConstInt(ctx->i32, rsrc3, false)
};
return ac_build_gather_values(&ctx->ac, desc_elems, 4);
}
}
-static void emit_streamout_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_emit_streamout_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;
vdata, num_comps,
so_write_offsets[buf_idx],
ctx->i32_0,
- stream_out->dst_offset * 4, 1, 1, true, false);
+ stream_out->dst_offset * 4, 1, 1, false);
}
/**
if (stream != so->output[i].stream)
continue;
- emit_streamout_output(ctx, so_buffers, so_write_offset,
- &so->output[i], &outputs[reg]);
+ si_emit_streamout_output(ctx, so_buffers, so_write_offset,
+ &so->output[i], &outputs[reg]);
}
}
lp_build_endif(&if_ctx);
}
}
-/* Generate export instructions for hardware VS shader stage */
-static void si_llvm_export_vs(struct si_shader_context *ctx,
- struct si_shader_output_values *outputs,
- unsigned noutput)
+/* Generate export instructions for hardware VS shader stage or NGG GS stage
+ * (position and parameter data only).
+ */
+void si_llvm_export_vs(struct si_shader_context *ctx,
+ struct si_shader_output_values *outputs,
+ unsigned noutput)
{
struct si_shader *shader = ctx->shader;
struct ac_export_args pos_args[4] = {};
invocation_id,
LLVMConstInt(ctx->i32, i, 0));
- LLVMValueRef value = lds_load(bld_base, ctx->ac.i32, ~0,
- lds_ptr);
+ 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, true, false);
+ buffer_offset, 0, 1, 0, false);
}
}
for (i = 0; i < outer_comps; i++) {
outer[i] = out[i] =
- lds_load(bld_base, ctx->ac.i32, i, lds_outer);
+ lshs_lds_load(bld_base, ctx->ac.i32, i, lds_outer);
}
for (i = 0; i < inner_comps; i++) {
inner[i] = out[outer_comps+i] =
- lds_load(bld_base, ctx->ac.i32, i, lds_inner);
+ lshs_lds_load(bld_base, ctx->ac.i32, i, lds_inner);
}
}
ac_build_buffer_store_dword(&ctx->ac, buffer,
LLVMConstInt(ctx->i32, 0x80000000, 0),
1, ctx->i32_0, tf_base,
- offset, 1, 0, true, false);
+ offset, 1, 0, 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, true, false);
+ offset, 1, 0, false);
offset += 16;
if (vec1)
ac_build_buffer_store_dword(&ctx->ac, buffer, vec1,
stride - 4, byteoffset, tf_base,
- offset, 1, 0, true, false);
+ offset, 1, 0, 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, true, false);
+ base, 0, 1, 0, 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, true, false);
+ base, 0, 1, 0, false);
}
}
/* Pass GS inputs from ES to GS on GFX9. */
static void si_set_es_return_value_for_gs(struct si_shader_context *ctx)
{
+ LLVMBuilderRef builder = ctx->ac.builder;
LLVMValueRef ret = ctx->return_value;
ret = si_insert_input_ptr(ctx, ret, 0, 0);
ret = si_insert_input_ptr(ctx, ret, 1, 1);
- ret = si_insert_input_ret(ctx, ret, ctx->param_gs2vs_offset, 2);
+ if (ctx->shader->key.as_ngg)
+ ret = LLVMBuildInsertValue(builder, ret, ctx->gs_tg_info, 2, "");
+ else
+ ret = si_insert_input_ret(ctx, ret, ctx->param_gs2vs_offset, 2);
ret = si_insert_input_ret(ctx, ret, ctx->param_merged_wave_info, 3);
ret = si_insert_input_ret(ctx, ret, ctx->param_merged_scratch_offset, 5);
if (!(info->output_usagemask[i] & (1 << chan)))
continue;
- lds_store(ctx, chan, dw_addr,
+ lshs_lds_store(ctx, chan, dw_addr,
LLVMBuildLoad(ctx->ac.builder, addrs[4 * i + chan], ""));
}
}
/* GFX9 has the ESGS ring in LDS. */
if (ctx->screen->info.chip_class >= GFX9) {
- lds_store(ctx, param * 4 + chan, lds_base, out_val);
+ LLVMValueRef idx = LLVMConstInt(ctx->i32, param * 4 + chan, false);
+ idx = LLVMBuildAdd(ctx->ac.builder, lds_base, idx, "");
+ ac_build_indexed_store(&ctx->ac, ctx->esgs_ring, idx, out_val);
continue;
}
ctx->esgs_ring,
out_val, 1, NULL, soffset,
(4 * param + chan) * 4,
- 1, 1, true, true);
+ 1, 1, true);
}
}
static void emit_gs_epilogue(struct si_shader_context *ctx)
{
+ if (ctx->shader->key.as_ngg) {
+ gfx10_ngg_gs_emit_epilogue(ctx);
+ return;
+ }
+
ac_build_sendmsg(&ctx->ac, AC_SENDMSG_GS_OP_NOP | AC_SENDMSG_GS_DONE,
si_get_gs_wave_id(ctx));
if (ctx->shader->key.mono.u.vs_export_prim_id) {
outputs[i].semantic_name = TGSI_SEMANTIC_PRIMID;
outputs[i].semantic_index = 0;
- outputs[i].values[0] = ac_to_float(&ctx->ac, get_primitive_id(ctx, 0));
+ outputs[i].values[0] = ac_to_float(&ctx->ac, si_get_primitive_id(ctx, 0));
for (j = 1; j < 4; j++)
outputs[i].values[j] = LLVMConstReal(ctx->f32, 0);
LLVMValueRef *addrs)
{
struct si_shader_context *ctx = si_shader_context_from_abi(abi);
+
+ if (ctx->shader->key.as_ngg) {
+ gfx10_ngg_gs_emit_vertex(ctx, stream, addrs);
+ return;
+ }
+
struct tgsi_shader_info *info = &ctx->shader->selector->info;
struct si_shader *shader = ctx->shader;
struct lp_build_if_state if_state;
ctx->gsvs_ring[stream],
out_val, 1,
voffset, soffset, 0,
- 1, 1, true, true);
+ 1, 1, true);
}
}
{
struct si_shader_context *ctx = si_shader_context_from_abi(abi);
+ if (ctx->shader->key.as_ngg) {
+ LLVMBuildStore(ctx->ac.builder, ctx->ac.i32_0, ctx->gs_curprim_verts[stream]);
+ return;
+ }
+
/* Signal primitive cut */
ac_build_sendmsg(&ctx->ac, AC_SENDMSG_GS_OP_CUT | AC_SENDMSG_GS | (stream << 8),
si_get_gs_wave_id(ctx));
static unsigned si_get_max_workgroup_size(const struct si_shader *shader)
{
switch (shader->selector->type) {
+ case PIPE_SHADER_VERTEX:
+ case PIPE_SHADER_TESS_EVAL:
+ return shader->key.as_ngg ? 128 : 0;
+
case PIPE_SHADER_TESS_CTRL:
/* Return this so that LLVM doesn't remove s_barrier
* instructions on chips where we use s_barrier. */
add_arg_assign(fninfo, ARG_VGPR, ctx->i32, &ctx->abi.vertex_id);
if (shader->key.as_ls) {
ctx->param_rel_auto_id = add_arg(fninfo, ARG_VGPR, ctx->i32);
+ if (ctx->screen->info.chip_class >= GFX10) {
+ add_arg(fninfo, ARG_VGPR, ctx->i32); /* user VGPR */
+ add_arg_assign(fninfo, ARG_VGPR, ctx->i32, &ctx->abi.instance_id);
+ } else {
+ add_arg_assign(fninfo, ARG_VGPR, ctx->i32, &ctx->abi.instance_id);
+ add_arg(fninfo, ARG_VGPR, ctx->i32); /* unused */
+ }
+ } else if (ctx->screen->info.chip_class == GFX10 &&
+ !shader->is_gs_copy_shader) {
+ add_arg(fninfo, ARG_VGPR, ctx->i32); /* user vgpr */
+ add_arg(fninfo, ARG_VGPR, ctx->i32); /* user vgpr */
add_arg_assign(fninfo, ARG_VGPR, ctx->i32, &ctx->abi.instance_id);
} else {
add_arg_assign(fninfo, ARG_VGPR, ctx->i32, &ctx->abi.instance_id);
ctx->param_vs_prim_id = add_arg(fninfo, ARG_VGPR, ctx->i32);
+ add_arg(fninfo, ARG_VGPR, ctx->i32); /* unused */
}
- add_arg(fninfo, ARG_VGPR, ctx->i32); /* unused */
if (!shader->is_gs_copy_shader) {
/* Vertex load indices. */
if (ctx->screen->info.chip_class >= GFX9) {
if (shader->key.as_ls || type == PIPE_SHADER_TESS_CTRL)
type = SI_SHADER_MERGED_VERTEX_TESSCTRL; /* LS or HS */
- else if (shader->key.as_es || type == PIPE_SHADER_GEOMETRY)
+ else if (shader->key.as_es || shader->key.as_ngg || type == PIPE_SHADER_GEOMETRY)
type = SI_SHADER_MERGED_VERTEX_OR_TESSEVAL_GEOMETRY;
}
/* SPI_SHADER_USER_DATA_ADDR_LO/HI_GS */
declare_per_stage_desc_pointers(ctx, &fninfo,
ctx->type == PIPE_SHADER_GEOMETRY);
- ctx->param_gs2vs_offset = add_arg(&fninfo, ARG_SGPR, ctx->i32);
+
+ if (ctx->shader->key.as_ngg)
+ add_arg_assign(&fninfo, ARG_SGPR, ctx->i32, &ctx->gs_tg_info);
+ else
+ ctx->param_gs2vs_offset = add_arg(&fninfo, ARG_SGPR, ctx->i32);
+
ctx->param_merged_wave_info = add_arg(&fninfo, ARG_SGPR, ctx->i32);
ctx->param_tcs_offchip_offset = add_arg(&fninfo, ARG_SGPR, ctx->i32);
ctx->param_merged_scratch_offset = add_arg(&fninfo, ARG_SGPR, ctx->i32);
add_arg(&fninfo, ARG_SGPR, ctx->i32); /* unused (SPI_SHADER_PGM_LO/HI_GS >> 24) */
declare_global_desc_pointers(ctx, &fninfo);
- declare_per_stage_desc_pointers(ctx, &fninfo,
- (ctx->type == PIPE_SHADER_VERTEX ||
- ctx->type == PIPE_SHADER_TESS_EVAL));
+ if (ctx->type != PIPE_SHADER_VERTEX || !vs_blit_property) {
+ declare_per_stage_desc_pointers(ctx, &fninfo,
+ (ctx->type == PIPE_SHADER_VERTEX ||
+ ctx->type == PIPE_SHADER_TESS_EVAL));
+ }
+
if (ctx->type == PIPE_SHADER_VERTEX) {
- declare_vs_specific_input_sgprs(ctx, &fninfo);
+ if (vs_blit_property)
+ declare_vs_blit_inputs(ctx, &fninfo, vs_blit_property);
+ else
+ declare_vs_specific_input_sgprs(ctx, &fninfo);
} else {
ctx->param_vs_state_bits = add_arg(&fninfo, ARG_SGPR, ctx->i32);
ctx->param_tcs_offchip_layout = add_arg(&fninfo, ARG_SGPR, ctx->i32);
declare_tes_input_vgprs(ctx, &fninfo);
}
- if (ctx->type == PIPE_SHADER_VERTEX ||
- ctx->type == PIPE_SHADER_TESS_EVAL) {
+ if (ctx->shader->key.as_es &&
+ (ctx->type == PIPE_SHADER_VERTEX ||
+ ctx->type == PIPE_SHADER_TESS_EVAL)) {
unsigned num_user_sgprs;
if (ctx->type == PIPE_SHADER_VERTEX)
assert(shader->info.num_input_vgprs >= num_prolog_vgprs);
shader->info.num_input_vgprs -= num_prolog_vgprs;
- if (shader->key.as_ls ||
- ctx->type == PIPE_SHADER_TESS_CTRL ||
- /* GFX9 has the ESGS ring buffer in LDS. */
- type == SI_SHADER_MERGED_VERTEX_OR_TESSEVAL_GEOMETRY)
- ac_declare_lds_as_pointer(&ctx->ac);
+ if (shader->key.as_ls || ctx->type == PIPE_SHADER_TESS_CTRL) {
+ if (USE_LDS_SYMBOLS && HAVE_LLVM >= 0x0900) {
+ /* The LSHS size is not known until draw time, so we append it
+ * at the end of whatever LDS use there may be in the rest of
+ * the shader (currently none, unless LLVM decides to do its
+ * own LDS-based lowering).
+ */
+ ctx->ac.lds = LLVMAddGlobalInAddressSpace(
+ ctx->ac.module, LLVMArrayType(ctx->i32, 0),
+ "__lds_end", AC_ADDR_SPACE_LDS);
+ LLVMSetAlignment(ctx->ac.lds, 256);
+ } else {
+ ac_declare_lds_as_pointer(&ctx->ac);
+ }
+ }
}
/**
LLVMValueRef buf_ptr = LLVMGetParam(ctx->main_fn,
ctx->param_rw_buffers);
- if (ctx->screen->info.chip_class <= GFX8 &&
- (ctx->shader->key.as_es || ctx->type == PIPE_SHADER_GEOMETRY)) {
- unsigned ring =
- ctx->type == PIPE_SHADER_GEOMETRY ? SI_GS_RING_ESGS
- : SI_ES_RING_ESGS;
- LLVMValueRef offset = LLVMConstInt(ctx->i32, ring, 0);
+ if (ctx->shader->key.as_es || ctx->type == PIPE_SHADER_GEOMETRY) {
+ if (ctx->screen->info.chip_class <= GFX8) {
+ unsigned ring =
+ ctx->type == PIPE_SHADER_GEOMETRY ? SI_GS_RING_ESGS
+ : SI_ES_RING_ESGS;
+ LLVMValueRef offset = LLVMConstInt(ctx->i32, ring, 0);
- ctx->esgs_ring =
- ac_build_load_to_sgpr(&ctx->ac, buf_ptr, offset);
+ ctx->esgs_ring =
+ ac_build_load_to_sgpr(&ctx->ac, buf_ptr, offset);
+ } else {
+ if (USE_LDS_SYMBOLS && HAVE_LLVM >= 0x0900) {
+ /* Declare the ESGS ring as an explicit LDS symbol.
+ * For monolithic shaders, we declare the ring only once.
+ *
+ * We declare it with 64KB alignment as a hint that the
+ * pointer value will always be 0.
+ */
+ ctx->esgs_ring = LLVMAddGlobalInAddressSpace(
+ ctx->ac.module, LLVMArrayType(ctx->i32, 0),
+ "esgs_ring",
+ AC_ADDR_SPACE_LDS);
+ LLVMSetAlignment(ctx->esgs_ring, 64 * 1024);
+ } else {
+ ac_declare_lds_as_pointer(&ctx->ac);
+ ctx->esgs_ring = ctx->ac.lds;
+ }
+ }
}
if (ctx->shader->is_gs_copy_shader) {
ring = LLVMBuildInsertElement(builder, ring,
LLVMConstInt(ctx->i32, num_records, 0),
LLVMConstInt(ctx->i32, 2, 0), "");
+
+ uint32_t rsrc3 =
+ S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
+ S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
+ S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
+ S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
+ S_008F0C_INDEX_STRIDE(1) | /* index_stride = 16 (elements) */
+ S_008F0C_ADD_TID_ENABLE(1);
+
+ if (ctx->ac.chip_class >= GFX10) {
+ rsrc3 |= S_008F0C_FORMAT(V_008F0C_IMG_FORMAT_32_FLOAT) |
+ S_008F0C_OOB_SELECT(2) |
+ S_008F0C_RESOURCE_LEVEL(1);
+ } else {
+ rsrc3 |= S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
+ S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) |
+ S_008F0C_ELEMENT_SIZE(1); /* element_size = 4 (bytes) */
+ }
+
ring = LLVMBuildInsertElement(builder, ring,
- LLVMConstInt(ctx->i32,
- S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
- S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
- S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
- S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
- S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
- S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) |
- S_008F0C_ELEMENT_SIZE(1) | /* element_size = 4 (bytes) */
- S_008F0C_INDEX_STRIDE(1) | /* index_stride = 16 (elements) */
- S_008F0C_ADD_TID_ENABLE(1),
- 0),
+ LLVMConstInt(ctx->i32, rsrc3, false),
LLVMConstInt(ctx->i32, 3, 0), "");
ctx->gsvs_ring[stream] = ring;
#define DEBUGGER_END_OF_CODE_MARKER 0xbf9f0000 /* invalid instruction */
#define DEBUGGER_NUM_MARKERS 5
-static bool si_shader_binary_open(const struct si_shader *shader,
+static bool si_shader_binary_open(struct si_screen *screen,
+ struct si_shader *shader,
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;
#undef add_part
- return ac_rtld_open(rtld, num_parts, part_elfs, part_sizes);
+ struct ac_rtld_symbol lds_symbols[2];
+ unsigned num_lds_symbols = 0;
+
+ if (sel && screen->info.chip_class >= GFX9 &&
+ sel->type == PIPE_SHADER_GEOMETRY && !shader->is_gs_copy_shader) {
+ /* 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 = shader->gs_info.esgs_ring_size;
+ sym->align = 64 * 1024;
+ }
+
+ if (shader->key.as_ngg && sel->type == PIPE_SHADER_GEOMETRY) {
+ struct ac_rtld_symbol *sym = &lds_symbols[num_lds_symbols++];
+ sym->name = "ngg_emit";
+ sym->size = shader->ngg.ngg_emit_size * 4;
+ sym->align = 4;
+ }
+
+ bool ok = ac_rtld_open(rtld, (struct ac_rtld_open_info){
+ .info = &screen->info,
+ .options = {
+ .halt_at_entry = screen->options.halt_shaders,
+ },
+ .shader_type = tgsi_processor_to_shader_stage(shader_type),
+ .num_parts = num_parts,
+ .elf_ptrs = part_elfs,
+ .elf_sizes = part_sizes,
+ .num_shared_lds_symbols = num_lds_symbols,
+ .shared_lds_symbols = lds_symbols });
+
+ if (rtld->lds_size > 0) {
+ unsigned alloc_granularity = screen->info.chip_class >= GFX7 ? 512 : 256;
+ shader->config.lds_size =
+ align(rtld->lds_size, alloc_granularity) / alloc_granularity;
+ }
+
+ return ok;
}
-static unsigned si_get_shader_binary_size(const struct si_shader *shader)
+static unsigned si_get_shader_binary_size(struct si_screen *screen, struct si_shader *shader)
{
struct ac_rtld_binary rtld;
- si_shader_binary_open(shader, &rtld);
+ si_shader_binary_open(screen, shader, &rtld);
return rtld.rx_size;
}
-
static bool si_get_external_symbol(void *data, const char *name, uint64_t *value)
{
uint64_t *scratch_va = data;
uint64_t scratch_va)
{
struct ac_rtld_binary binary;
- if (!si_shader_binary_open(shader, &binary))
+ if (!si_shader_binary_open(sscreen, shader, &binary))
return false;
si_resource_reference(&shader->bo, NULL);
return ok;
}
-static void si_shader_dump_disassembly(const struct si_shader_binary *binary,
+static void si_shader_dump_disassembly(struct si_screen *screen,
+ const struct si_shader_binary *binary,
struct pipe_debug_callback *debug,
const char *name, FILE *file)
{
struct ac_rtld_binary rtld_binary;
- if (!ac_rtld_open(&rtld_binary, 1, &binary->elf_buffer, &binary->elf_size))
+ if (!ac_rtld_open(&rtld_binary, (struct ac_rtld_open_info){
+ .info = &screen->info,
+ .num_parts = 1,
+ .elf_ptrs = &binary->elf_buffer,
+ .elf_sizes = &binary->elf_size }))
return;
const char *disasm;
if (!ac_rtld_get_section_by_name(&rtld_binary, ".AMDGPU.disasm", &disasm, &nbytes))
goto out;
- fprintf(file, "Shader %s disassembly:\n", name);
- if (nbytes > INT_MAX) {
- fprintf(file, "too long\n");
+ if (nbytes > INT_MAX)
goto out;
- }
-
- fprintf(file, "%*s", (int)nbytes, disasm);
if (debug && debug->debug_message) {
/* Very long debug messages are cut off, so send the
int count = nbytes - line;
const char *nl = memchr(disasm + line, '\n', nbytes - line);
if (nl)
- count = nl - disasm;
+ count = nl - (disasm + line);
if (count) {
pipe_debug_message(debug, SHADER_INFO,
"Shader Disassembly End");
}
+ if (file) {
+ fprintf(file, "Shader %s disassembly:\n", name);
+ fprintf(file, "%*s", (int)nbytes, disasm);
+ }
+
out:
ac_rtld_close(&rtld_binary);
}
shader->info.max_simd_waves = max_simd_waves;
}
-void si_shader_dump_stats_for_shader_db(const struct si_shader *shader,
+void si_shader_dump_stats_for_shader_db(struct si_screen *screen,
+ struct si_shader *shader,
struct pipe_debug_callback *debug)
{
const struct ac_shader_config *conf = &shader->config;
+ if (screen->options.debug_disassembly)
+ si_shader_dump_disassembly(screen, &shader->binary, debug, "main", NULL);
+
pipe_debug_message(debug, SHADER_INFO,
"Shader Stats: SGPRS: %d VGPRS: %d Code Size: %d "
"LDS: %d Scratch: %d Max Waves: %d Spilled SGPRs: %d "
"Spilled VGPRs: %d PrivMem VGPRs: %d",
conf->num_sgprs, conf->num_vgprs,
- si_get_shader_binary_size(shader),
+ si_get_shader_binary_size(screen, shader),
conf->lds_size, conf->scratch_bytes_per_wave,
shader->info.max_simd_waves, conf->spilled_sgprs,
conf->spilled_vgprs, shader->info.private_mem_vgprs);
}
static void si_shader_dump_stats(struct si_screen *sscreen,
- const struct si_shader *shader,
+ struct si_shader *shader,
unsigned processor,
FILE *file,
bool check_debug_option)
conf->num_sgprs, conf->num_vgprs,
conf->spilled_sgprs, conf->spilled_vgprs,
shader->info.private_mem_vgprs,
- si_get_shader_binary_size(shader),
+ si_get_shader_binary_size(sscreen, shader),
conf->lds_size, conf->scratch_bytes_per_wave,
shader->info.max_simd_waves);
}
return "Vertex Shader as LS";
else if (shader->key.opt.vs_as_prim_discard_cs)
return "Vertex Shader as Primitive Discard CS";
+ else if (shader->key.as_ngg)
+ return "Vertex Shader as ESGS";
else
return "Vertex Shader as VS";
case PIPE_SHADER_TESS_CTRL:
case PIPE_SHADER_TESS_EVAL:
if (shader->key.as_es)
return "Tessellation Evaluation Shader as ES";
+ else if (shader->key.as_ngg)
+ return "Tessellation Evaluation Shader as ESGS";
else
return "Tessellation Evaluation Shader as VS";
case PIPE_SHADER_GEOMETRY:
}
}
-void si_shader_dump(struct si_screen *sscreen, const struct si_shader *shader,
+void si_shader_dump(struct si_screen *sscreen, struct si_shader *shader,
struct pipe_debug_callback *debug, unsigned processor,
FILE *file, bool check_debug_option)
{
fprintf(file, "\n%s:\n", si_get_shader_name(shader, processor));
if (shader->prolog)
- si_shader_dump_disassembly(&shader->prolog->binary,
+ si_shader_dump_disassembly(sscreen, &shader->prolog->binary,
debug, "prolog", file);
if (shader->previous_stage)
- si_shader_dump_disassembly(&shader->previous_stage->binary,
+ si_shader_dump_disassembly(sscreen, &shader->previous_stage->binary,
debug, "previous stage", file);
if (shader->prolog2)
- si_shader_dump_disassembly(&shader->prolog2->binary,
+ si_shader_dump_disassembly(sscreen, &shader->prolog2->binary,
debug, "prolog2", file);
- si_shader_dump_disassembly(&shader->binary, debug, "main", file);
+ si_shader_dump_disassembly(sscreen, &shader->binary, debug, "main", file);
if (shader->epilog)
- si_shader_dump_disassembly(&shader->epilog->binary,
+ si_shader_dump_disassembly(sscreen, &shader->epilog->binary,
debug, "epilog", file);
fprintf(file, "\n");
}
}
struct ac_rtld_binary rtld;
- if (!ac_rtld_open(&rtld, 1, &binary->elf_buffer, &binary->elf_size))
+ if (!ac_rtld_open(&rtld, (struct ac_rtld_open_info){
+ .info = &sscreen->info,
+ .num_parts = 1,
+ .elf_ptrs = &binary->elf_buffer,
+ .elf_sizes = &binary->elf_size }))
return -1;
bool ok = ac_rtld_read_config(&rtld, conf);
ctx->abi.emit_outputs = si_llvm_emit_es_epilogue;
else if (shader->key.opt.vs_as_prim_discard_cs)
ctx->abi.emit_outputs = si_llvm_emit_prim_discard_cs_epilogue;
+ else if (shader->key.as_ngg)
+ ctx->abi.emit_outputs = gfx10_emit_ngg_epilogue;
else
ctx->abi.emit_outputs = si_llvm_emit_vs_epilogue;
bld_base->emit_epilogue = si_tgsi_emit_epilogue;
ctx->abi.load_patch_vertices_in = si_load_patch_vertices_in;
if (shader->key.as_es)
ctx->abi.emit_outputs = si_llvm_emit_es_epilogue;
- else
- ctx->abi.emit_outputs = si_llvm_emit_vs_epilogue;
+ else {
+ if (shader->key.as_ngg)
+ ctx->abi.emit_outputs = gfx10_emit_ngg_epilogue;
+ else
+ ctx->abi.emit_outputs = si_llvm_emit_vs_epilogue;
+ }
bld_base->emit_epilogue = si_tgsi_emit_epilogue;
break;
case PIPE_SHADER_GEOMETRY:
create_function(ctx);
preload_ring_buffers(ctx);
+ if (ctx->type == PIPE_SHADER_TESS_CTRL &&
+ sel->tcs_info.tessfactors_are_def_in_all_invocs) {
+ for (unsigned i = 0; i < 6; i++) {
+ ctx->invoc0_tess_factors[i] =
+ ac_build_alloca_undef(&ctx->ac, ctx->i32, "");
+ }
+ }
+
+ if (ctx->type == PIPE_SHADER_GEOMETRY) {
+ for (unsigned i = 0; i < 4; i++) {
+ ctx->gs_next_vertex[i] =
+ ac_build_alloca(&ctx->ac, ctx->i32, "");
+ }
+ if (shader->key.as_ngg) {
+ for (unsigned i = 0; i < 4; ++i) {
+ ctx->gs_curprim_verts[i] =
+ lp_build_alloca(&ctx->gallivm, ctx->ac.i32, "");
+ ctx->gs_generated_prims[i] =
+ lp_build_alloca(&ctx->gallivm, ctx->ac.i32, "");
+ }
+
+ LLVMTypeRef a8i32 = LLVMArrayType(ctx->i32, 8);
+ ctx->gs_ngg_scratch = LLVMAddGlobalInAddressSpace(ctx->ac.module,
+ a8i32, "ngg_scratch", AC_ADDR_SPACE_LDS);
+ LLVMSetInitializer(ctx->gs_ngg_scratch, LLVMGetUndef(a8i32));
+ LLVMSetAlignment(ctx->gs_ngg_scratch, 4);
+
+ ctx->gs_ngg_emit = LLVMAddGlobalInAddressSpace(ctx->ac.module,
+ LLVMArrayType(ctx->i32, 0), "ngg_emit", AC_ADDR_SPACE_LDS);
+ LLVMSetLinkage(ctx->gs_ngg_emit, LLVMExternalLinkage);
+ LLVMSetAlignment(ctx->gs_ngg_emit, 4);
+ }
+ }
+
/* For GFX9 merged shaders:
* - Set EXEC for the first shader. If the prolog is present, set
* EXEC there instead.
*
* For monolithic merged shaders, the first shader is wrapped in an
* if-block together with its prolog in si_build_wrapper_function.
+ *
+ * NGG vertex and tess eval shaders running as the last
+ * vertex/geometry stage handle execution explicitly using
+ * if-statements.
*/
if (ctx->screen->info.chip_class >= GFX9) {
if (!shader->is_monolithic &&
si_init_exec_from_input(ctx,
ctx->param_merged_wave_info, 0);
} else if (ctx->type == PIPE_SHADER_TESS_CTRL ||
- ctx->type == PIPE_SHADER_GEOMETRY) {
- if (!shader->is_monolithic)
+ ctx->type == PIPE_SHADER_GEOMETRY ||
+ shader->key.as_ngg) {
+ LLVMValueRef num_threads;
+ bool nested_barrier;
+
+ if (!shader->is_monolithic ||
+ (ctx->type == PIPE_SHADER_TESS_EVAL &&
+ shader->key.as_ngg))
ac_init_exec_full_mask(&ctx->ac);
- LLVMValueRef num_threads = si_unpack_param(ctx, ctx->param_merged_wave_info, 8, 8);
+ if (ctx->type == PIPE_SHADER_TESS_CTRL ||
+ ctx->type == PIPE_SHADER_GEOMETRY) {
+ if (ctx->type == PIPE_SHADER_GEOMETRY && shader->key.as_ngg) {
+ gfx10_ngg_gs_emit_prologue(ctx);
+ nested_barrier = false;
+ } else {
+ nested_barrier = true;
+ }
+
+ /* Number of patches / primitives */
+ num_threads = si_unpack_param(ctx, ctx->param_merged_wave_info, 8, 8);
+ } else {
+ /* Number of vertices */
+ num_threads = si_unpack_param(ctx, ctx->param_merged_wave_info, 0, 8);
+ nested_barrier = false;
+ }
+
LLVMValueRef ena =
LLVMBuildICmp(ctx->ac.builder, LLVMIntULT,
ac_get_thread_id(&ctx->ac), num_threads, "");
lp_build_if(&ctx->merged_wrap_if_state, &ctx->gallivm, ena);
- /* The barrier must execute for all shaders in a
- * threadgroup.
- *
- * Execute the barrier inside the conditional block,
- * so that empty waves can jump directly to s_endpgm,
- * which will also signal the barrier.
- *
- * If the shader is TCS and the TCS epilog is present
- * and contains a barrier, it will wait there and then
- * reach s_endpgm.
- */
- si_llvm_emit_barrier(NULL, bld_base, NULL);
- }
- }
-
- if (ctx->type == PIPE_SHADER_TESS_CTRL &&
- sel->tcs_info.tessfactors_are_def_in_all_invocs) {
- for (unsigned i = 0; i < 6; i++) {
- ctx->invoc0_tess_factors[i] =
- ac_build_alloca_undef(&ctx->ac, ctx->i32, "");
- }
- }
-
- if (ctx->type == PIPE_SHADER_GEOMETRY) {
- int i;
- for (i = 0; i < 4; i++) {
- ctx->gs_next_vertex[i] =
- ac_build_alloca(&ctx->ac, ctx->i32, "");
+ if (nested_barrier) {
+ /* Execute a barrier before the second shader in
+ * a merged shader.
+ *
+ * Execute the barrier inside the conditional block,
+ * so that empty waves can jump directly to s_endpgm,
+ * which will also signal the barrier.
+ *
+ * This is possible in gfx9, because an empty wave
+ * for the second shader does not participate in
+ * the epilogue. With NGG, empty waves may still
+ * be required to export data (e.g. GS output vertices),
+ * so we cannot let them exit early.
+ *
+ * If the shader is TCS and the TCS epilog is present
+ * and contains a barrier, it will wait there and then
+ * reach s_endpgm.
+ */
+ si_llvm_emit_barrier(NULL, bld_base, NULL);
+ }
}
}
key->vs_prolog.last_input = MAX2(1, info->num_inputs) - 1;
key->vs_prolog.as_ls = shader_out->key.as_ls;
key->vs_prolog.as_es = shader_out->key.as_es;
+ key->vs_prolog.as_ngg = shader_out->key.as_ngg;
if (shader_out->selector->type == PIPE_SHADER_TESS_CTRL) {
key->vs_prolog.as_ls = 1;
} else if (shader_out->selector->type == PIPE_SHADER_GEOMETRY) {
key->vs_prolog.as_es = 1;
key->vs_prolog.num_merged_next_stage_vgprs = 5;
+ } else if (shader_out->key.as_ngg) {
+ key->vs_prolog.num_merged_next_stage_vgprs = 5;
}
/* Enable loading the InstanceID VGPR. */
/* BCOLORs are stored after the last input. */
key->ps_prolog.num_interp_inputs = info->num_inputs;
key->ps_prolog.face_vgpr_index = shader->info.face_vgpr_index;
- shader->config.spi_ps_input_ena |= S_0286CC_FRONT_FACE_ENA(1);
+ if (separate_prolog)
+ shader->config.spi_ps_input_ena |= S_0286CC_FRONT_FACE_ENA(1);
}
for (unsigned i = 0; i < 2; i++) {
switch (location) {
case TGSI_INTERPOLATE_LOC_SAMPLE:
key->ps_prolog.color_interp_vgpr_index[i] = 0;
- shader->config.spi_ps_input_ena |=
- S_0286CC_PERSP_SAMPLE_ENA(1);
+ if (separate_prolog) {
+ shader->config.spi_ps_input_ena |=
+ S_0286CC_PERSP_SAMPLE_ENA(1);
+ }
break;
case TGSI_INTERPOLATE_LOC_CENTER:
key->ps_prolog.color_interp_vgpr_index[i] = 2;
- shader->config.spi_ps_input_ena |=
- S_0286CC_PERSP_CENTER_ENA(1);
+ if (separate_prolog) {
+ shader->config.spi_ps_input_ena |=
+ S_0286CC_PERSP_CENTER_ENA(1);
+ }
break;
case TGSI_INTERPOLATE_LOC_CENTROID:
key->ps_prolog.color_interp_vgpr_index[i] = 4;
- shader->config.spi_ps_input_ena |=
- S_0286CC_PERSP_CENTROID_ENA(1);
+ if (separate_prolog) {
+ shader->config.spi_ps_input_ena |=
+ S_0286CC_PERSP_CENTROID_ENA(1);
+ }
break;
default:
assert(0);
case TGSI_INTERPOLATE_LOC_SAMPLE:
key->ps_prolog.color_interp_vgpr_index[i] =
separate_prolog ? 6 : 9;
- shader->config.spi_ps_input_ena |=
- S_0286CC_LINEAR_SAMPLE_ENA(1);
+ if (separate_prolog) {
+ shader->config.spi_ps_input_ena |=
+ S_0286CC_LINEAR_SAMPLE_ENA(1);
+ }
break;
case TGSI_INTERPOLATE_LOC_CENTER:
key->ps_prolog.color_interp_vgpr_index[i] =
separate_prolog ? 8 : 11;
- shader->config.spi_ps_input_ena |=
- S_0286CC_LINEAR_CENTER_ENA(1);
+ if (separate_prolog) {
+ shader->config.spi_ps_input_ena |=
+ S_0286CC_LINEAR_CENTER_ENA(1);
+ }
break;
case TGSI_INTERPOLATE_LOC_CENTROID:
key->ps_prolog.color_interp_vgpr_index[i] =
separate_prolog ? 10 : 13;
- shader->config.spi_ps_input_ena |=
- S_0286CC_LINEAR_CENTROID_ENA(1);
+ if (separate_prolog) {
+ shader->config.spi_ps_input_ena |=
+ S_0286CC_LINEAR_CENTROID_ENA(1);
+ }
break;
default:
assert(0);
/* Merged shaders are executed conditionally depending
* on the number of enabled threads passed in the input SGPRs. */
- if (is_merged_shader(ctx) && part == 0) {
+ if (is_multi_part_shader(ctx) && part == 0) {
LLVMValueRef ena, count = initial[3];
count = LLVMBuildAnd(builder, count,
out_idx += param_size;
}
- ret = LLVMBuildCall(builder, parts[part], in, num_params, "");
+ ret = ac_build_call(&ctx->ac, parts[part], in, num_params);
- if (is_merged_shader(ctx) &&
+ if (is_multi_part_shader(ctx) &&
part + 1 == next_shader_first_part) {
lp_build_endif(&if_state);
}
si_calculate_max_simd_waves(shader);
- si_shader_dump_stats_for_shader_db(shader, debug);
+ si_shader_dump_stats_for_shader_db(sscreen, shader, debug);
return 0;
}
case PIPE_SHADER_VERTEX:
shader.key.as_ls = key->vs_prolog.as_ls;
shader.key.as_es = key->vs_prolog.as_es;
+ shader.key.as_ngg = key->vs_prolog.as_ngg;
break;
case PIPE_SHADER_TESS_CTRL:
assert(!prolog);
}
unsigned vertex_id_vgpr = first_vs_vgpr;
- unsigned instance_id_vgpr = first_vs_vgpr + (key->vs_prolog.as_ls ? 2 : 1);
+ unsigned instance_id_vgpr =
+ ctx->screen->info.chip_class >= GFX10 ?
+ first_vs_vgpr + 3 :
+ first_vs_vgpr + (key->vs_prolog.as_ls ? 2 : 1);
ctx->abi.vertex_id = input_vgprs[vertex_id_vgpr];
ctx->abi.instance_id = input_vgprs[instance_id_vgpr];
key->vs_prolog.num_input_sgprs + i, "");
}
+ struct lp_build_if_state wrap_if_state;
+ LLVMValueRef original_ret = ret;
+ bool wrapped = false;
+
+ if (key->vs_prolog.is_monolithic && key->vs_prolog.as_ngg) {
+ LLVMValueRef num_threads;
+ LLVMValueRef ena;
+
+ num_threads = si_unpack_param(ctx, 3, 0, 8);
+ ena = LLVMBuildICmp(ctx->ac.builder, LLVMIntULT,
+ ac_get_thread_id(&ctx->ac), num_threads, "");
+ lp_build_if(&wrap_if_state, &ctx->gallivm, ena);
+ wrapped = true;
+ }
+
/* Compute vertex load indices from instance divisors. */
LLVMValueRef instance_divisor_constbuf = NULL;
fninfo.num_params + i, "");
}
+ if (wrapped) {
+ lp_build_endif(&wrap_if_state);
+
+ LLVMValueRef values[2] = {
+ ret,
+ original_ret
+ };
+ LLVMBasicBlockRef bbs[2] = {
+ wrap_if_state.true_block,
+ wrap_if_state.entry_block
+ };
+ ret = ac_build_phi(&ctx->ac, LLVMTypeOf(ret), 2, values, bbs);
+ }
+
si_llvm_build_ret(ctx, ret);
}
/* LS, ES, VS are compiled on demand if the main part hasn't been
* compiled for that stage.
*
+ * GS are compiled on demand if the main part hasn't been compiled
+ * for the chosen NGG-ness.
+ *
* Vertex shaders are compiled on demand when a vertex fetch
* workaround must be applied.
*/
si_calculate_max_simd_waves(shader);
}
+ if (shader->key.as_ngg) {
+ assert(!shader->key.as_es && !shader->key.as_ls);
+ gfx10_ngg_calculate_subgroup_info(shader);
+ } else if (sscreen->info.chip_class >= GFX9 && sel->type == PIPE_SHADER_GEOMETRY) {
+ gfx9_get_gs_info(shader->previous_stage_sel, sel, &shader->gs_info);
+ }
+
si_fix_resource_usage(sscreen, shader);
si_shader_dump(sscreen, shader, debug, sel->info.processor,
stderr, true);