#include "gallivm/lp_bld_arit.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_misc.h"
-#include "radeon/radeon_elf_util.h"
#include "util/u_memory.h"
#include "util/u_string.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_dump.h"
+#include "ac_binary.h"
#include "ac_llvm_util.h"
#include "si_shader_internal.h"
#include "si_pipe.h"
input[i] = lp_build_intrinsic(gallivm->builder,
"llvm.SI.vs.load.input", ctx->v4f32, args, 3,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE |
+ LP_FUNC_ATTR_LEGACY);
}
/* Break up the vec4 into individual components */
* Note that every attribute has 4 components.
*/
static LLVMValueRef get_tcs_tes_buffer_address(struct si_shader_context *ctx,
+ LLVMValueRef rel_patch_id,
LLVMValueRef vertex_index,
LLVMValueRef param_index)
{
constant16 = lp_build_const_int32(gallivm, 16);
if (vertex_index) {
- base_addr = LLVMBuildMul(gallivm->builder, get_rel_patch_id(ctx),
+ base_addr = LLVMBuildMul(gallivm->builder, rel_patch_id,
vertices_per_patch, "");
base_addr = LLVMBuildAdd(gallivm->builder, base_addr,
param_stride = total_vertices;
} else {
- base_addr = get_rel_patch_id(ctx);
+ base_addr = rel_patch_id;
param_stride = num_patches;
}
lp_build_const_int32(gallivm, param_index_base),
"");
- return get_tcs_tes_buffer_address(ctx, vertex_index, param_index);
+ return get_tcs_tes_buffer_address(ctx, get_rel_patch_id(ctx),
+ vertex_index, param_index);
}
static LLVMValueRef buffer_load(struct lp_build_tgsi_context *bld_base,
struct si_shader_context *ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
const struct tgsi_full_dst_register *reg = &inst->Dst[0];
+ const struct tgsi_shader_info *sh_info = &ctx->shader->selector->info;
unsigned chan_index;
LLVMValueRef dw_addr, stride;
LLVMValueRef rw_buffers, buffer, base, buf_addr;
LLVMValueRef values[4];
+ bool skip_lds_store;
+ bool is_tess_factor = false;
/* Only handle per-patch and per-vertex outputs here.
* Vectors will be lowered to scalars and this function will be called again.
stride = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 13, 8);
dw_addr = get_tcs_out_current_patch_offset(ctx);
dw_addr = get_dw_address(ctx, reg, NULL, stride, dw_addr);
+ skip_lds_store = !sh_info->reads_pervertex_outputs;
} else {
dw_addr = get_tcs_out_current_patch_data_offset(ctx);
dw_addr = get_dw_address(ctx, reg, NULL, NULL, dw_addr);
+ skip_lds_store = !sh_info->reads_perpatch_outputs;
+
+ if (!reg->Register.Indirect) {
+ int name = sh_info->output_semantic_name[reg->Register.Index];
+
+ /* Always write tess factors into LDS for the TCS epilog. */
+ if (name == TGSI_SEMANTIC_TESSINNER ||
+ name == TGSI_SEMANTIC_TESSOUTER) {
+ skip_lds_store = false;
+ is_tess_factor = true;
+ }
+ }
}
rw_buffers = LLVMGetParam(ctx->main_fn,
if (inst->Instruction.Saturate)
value = ac_emit_clamp(&ctx->ac, value);
- lds_store(bld_base, chan_index, dw_addr, value);
+ /* Skip LDS stores if there is no LDS read of this output. */
+ if (!skip_lds_store)
+ lds_store(bld_base, chan_index, dw_addr, value);
value = LLVMBuildBitCast(gallivm->builder, value, ctx->i32, "");
values[chan_index] = value;
- if (inst->Dst[0].Register.WriteMask != 0xF) {
+ if (inst->Dst[0].Register.WriteMask != 0xF && !is_tess_factor) {
ac_build_tbuffer_store_dwords(&ctx->ac, buffer, value, 1,
buf_addr, base,
4 * chan_index);
}
}
- if (inst->Dst[0].Register.WriteMask == 0xF) {
+ if (inst->Dst[0].Register.WriteMask == 0xF && !is_tess_factor) {
LLVMValueRef value = lp_build_gather_values(bld_base->base.gallivm,
values, 4);
ac_build_tbuffer_store_dwords(&ctx->ac, buffer, value, 4, buf_addr,
value = lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LP_FUNC_ATTR_READONLY);
+ LP_FUNC_ATTR_READONLY |
+ LP_FUNC_ATTR_LEGACY);
if (tgsi_type_is_64bit(type)) {
LLVMValueRef value2;
args[2] = lp_build_const_int32(gallivm, (param * 4 + swizzle + 1) * 256);
value2 = lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LP_FUNC_ATTR_READONLY);
+ LP_FUNC_ATTR_READONLY |
+ LP_FUNC_ATTR_LEGACY);
return si_llvm_emit_fetch_64bit(bld_base, type,
value, value2);
}
LLVMValueRef args[2] = {resource, offset};
return lp_build_intrinsic(builder, "llvm.SI.load.const", ctx->f32, args, 2,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE |
+ LP_FUNC_ATTR_LEGACY);
}
static LLVMValueRef load_sample_position(struct si_shader_context *radeon_bld, LLVMValueRef sample_id)
lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
base = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
- addr = get_tcs_tes_buffer_address(ctx, NULL,
+ addr = get_tcs_tes_buffer_address(ctx, get_rel_patch_id(ctx), NULL,
lp_build_const_int32(gallivm, param));
value = buffer_load(&radeon_bld->bld_base, TGSI_TYPE_FLOAT,
static void si_llvm_init_export_args(struct lp_build_tgsi_context *bld_base,
LLVMValueRef *values,
unsigned target,
- LLVMValueRef *args)
+ struct ac_export_args *args)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- struct lp_build_context *uint = &ctx->bld_base.uint_bld;
struct lp_build_context *base = &bld_base->base;
struct gallivm_state *gallivm = base->gallivm;
LLVMBuilderRef builder = base->gallivm->builder;
bool is_int8, is_int10;
/* Default is 0xf. Adjusted below depending on the format. */
- args[0] = lp_build_const_int32(base->gallivm, 0xf); /* writemask */
+ args->enabled_channels = 0xf; /* writemask */
/* Specify whether the EXEC mask represents the valid mask */
- args[1] = uint->zero;
+ args->valid_mask = 0;
/* Specify whether this is the last export */
- args[2] = uint->zero;
+ args->done = 0;
/* Specify the target we are exporting */
- args[3] = lp_build_const_int32(base->gallivm, target);
+ args->target = target;
if (ctx->type == PIPE_SHADER_FRAGMENT) {
const struct si_shader_key *key = &ctx->shader->key;
is_int10 = (key->part.ps.epilog.color_is_int10 >> cbuf) & 0x1;
}
- args[4] = uint->zero; /* COMPR flag */
- args[5] = base->undef;
- args[6] = base->undef;
- args[7] = base->undef;
- args[8] = base->undef;
+ args->compr = false;
+ args->out[0] = base->undef;
+ args->out[1] = base->undef;
+ args->out[2] = base->undef;
+ args->out[3] = base->undef;
switch (spi_shader_col_format) {
case V_028714_SPI_SHADER_ZERO:
- args[0] = uint->zero; /* writemask */
- args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_NULL);
+ args->enabled_channels = 0; /* writemask */
+ args->target = V_008DFC_SQ_EXP_NULL;
break;
case V_028714_SPI_SHADER_32_R:
- args[0] = uint->one; /* writemask */
- args[5] = values[0];
+ args->enabled_channels = 1; /* writemask */
+ args->out[0] = values[0];
break;
case V_028714_SPI_SHADER_32_GR:
- args[0] = lp_build_const_int32(base->gallivm, 0x3); /* writemask */
- args[5] = values[0];
- args[6] = values[1];
+ args->enabled_channels = 0x3; /* writemask */
+ args->out[0] = values[0];
+ args->out[1] = values[1];
break;
case V_028714_SPI_SHADER_32_AR:
- args[0] = lp_build_const_int32(base->gallivm, 0x9); /* writemask */
- args[5] = values[0];
- args[8] = values[3];
+ args->enabled_channels = 0x9; /* writemask */
+ args->out[0] = values[0];
+ args->out[3] = values[3];
break;
case V_028714_SPI_SHADER_FP16_ABGR:
- args[4] = uint->one; /* COMPR flag */
+ args->compr = 1; /* COMPR flag */
for (chan = 0; chan < 2; chan++) {
LLVMValueRef pack_args[2] = {
packed = lp_build_intrinsic(base->gallivm->builder,
"llvm.SI.packf16",
ctx->i32, pack_args, 2,
- LP_FUNC_ATTR_READNONE);
- args[chan + 5] =
+ LP_FUNC_ATTR_READNONE |
+ LP_FUNC_ATTR_LEGACY);
+ args->out[chan] =
LLVMBuildBitCast(base->gallivm->builder,
packed, ctx->f32, "");
}
ctx->i32, "");
}
- args[4] = uint->one; /* COMPR flag */
- args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->compr = 1; /* COMPR flag */
+ args->out[0] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int16(gallivm, val));
- args[6] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->out[1] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int16(gallivm, val+2));
break;
val[chan] = LLVMBuildFPToSI(builder, val[chan], ctx->i32, "");
}
- args[4] = uint->one; /* COMPR flag */
- args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->compr = 1; /* COMPR flag */
+ args->out[0] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int32_as_int16(gallivm, val));
- args[6] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->out[1] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int32_as_int16(gallivm, val+2));
break;
chan == 3 ? max_alpha : max_rgb);
}
- args[4] = uint->one; /* COMPR flag */
- args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->compr = 1; /* COMPR flag */
+ args->out[0] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int16(gallivm, val));
- args[6] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->out[1] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int16(gallivm, val+2));
break;
}
val[chan], chan == 3 ? min_alpha : min_rgb);
}
- args[4] = uint->one; /* COMPR flag */
- args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->compr = 1; /* COMPR flag */
+ args->out[0] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int32_as_int16(gallivm, val));
- args[6] = bitcast(bld_base, TGSI_TYPE_FLOAT,
+ args->out[1] = bitcast(bld_base, TGSI_TYPE_FLOAT,
si_llvm_pack_two_int32_as_int16(gallivm, val+2));
break;
}
case V_028714_SPI_SHADER_32_ABGR:
- memcpy(&args[5], values, sizeof(values[0]) * 4);
+ memcpy(&args->out[0], values, sizeof(values[0]) * 4);
break;
}
}
lp_build_const_float(gallivm, -1.0f));
lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill",
- ctx->voidt, &arg, 1, 0);
+ ctx->voidt, &arg, 1, LP_FUNC_ATTR_LEGACY);
} else {
lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kilp",
- ctx->voidt, NULL, 0, 0);
+ ctx->voidt, NULL, 0, LP_FUNC_ATTR_LEGACY);
}
}
}
static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context *bld_base,
- LLVMValueRef (*pos)[9], LLVMValueRef *out_elts)
+ struct ac_export_args *pos, LLVMValueRef *out_elts)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
- struct lp_build_context *uint = &ctx->bld_base.uint_bld;
unsigned reg_index;
unsigned chan;
unsigned const_chan;
LLVMValueRef const_resource = ac_build_indexed_load_const(&ctx->ac, ptr, constbuf_index);
for (reg_index = 0; reg_index < 2; reg_index ++) {
- LLVMValueRef *args = pos[2 + reg_index];
+ struct ac_export_args *args = &pos[2 + reg_index];
- args[5] =
- args[6] =
- args[7] =
- args[8] = lp_build_const_float(base->gallivm, 0.0f);
+ args->out[0] =
+ args->out[1] =
+ args->out[2] =
+ args->out[3] = lp_build_const_float(base->gallivm, 0.0f);
/* Compute dot products of position and user clip plane vectors */
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
for (const_chan = 0; const_chan < TGSI_NUM_CHANNELS; const_chan++) {
- args[1] = lp_build_const_int32(base->gallivm,
- ((reg_index * 4 + chan) * 4 +
- const_chan) * 4);
+ LLVMValueRef addr =
+ LLVMConstInt(ctx->i32, ((reg_index * 4 + chan) * 4 +
+ const_chan) * 4, 0);
base_elt = buffer_load_const(ctx, const_resource,
- args[1]);
- args[5 + chan] =
- lp_build_add(base, args[5 + chan],
+ addr);
+ args->out[chan] =
+ lp_build_add(base, args->out[chan],
lp_build_mul(base, base_elt,
out_elts[const_chan]));
}
}
- args[0] = lp_build_const_int32(base->gallivm, 0xf);
- args[1] = uint->zero;
- args[2] = uint->zero;
- args[3] = lp_build_const_int32(base->gallivm,
- V_008DFC_SQ_EXP_POS + 2 + reg_index);
- args[4] = uint->zero;
+ args->enabled_channels = 0xf;
+ args->valid_mask = 0;
+ args->done = 0;
+ args->target = V_008DFC_SQ_EXP_POS + 2 + reg_index;
+ args->compr = 0;
}
}
struct si_shader_context *ctx = si_shader_context(bld_base);
struct si_shader *shader = ctx->shader;
struct lp_build_context *base = &bld_base->base;
- struct lp_build_context *uint = &ctx->bld_base.uint_bld;
- LLVMValueRef args[9];
- LLVMValueRef pos_args[4][9] = { { 0 } };
+ struct ac_export_args args, pos_args[4] = {};
LLVMValueRef psize_value = NULL, edgeflag_value = NULL, layer_value = NULL, viewport_index_value = NULL;
unsigned semantic_name, semantic_index;
unsigned target;
semantic_name);
}
- si_llvm_init_export_args(bld_base, outputs[i].values, target, args);
+ si_llvm_init_export_args(bld_base, outputs[i].values, target, &args);
if (target >= V_008DFC_SQ_EXP_POS &&
target <= (V_008DFC_SQ_EXP_POS + 3)) {
- memcpy(pos_args[target - V_008DFC_SQ_EXP_POS],
- args, sizeof(args));
+ memcpy(&pos_args[target - V_008DFC_SQ_EXP_POS],
+ &args, sizeof(args));
} else {
- lp_build_intrinsic(base->gallivm->builder,
- "llvm.SI.export", ctx->voidt,
- args, 9, 0);
+ ac_emit_export(&ctx->ac, &args);
}
if (semantic_name == TGSI_SEMANTIC_CLIPDIST) {
shader->info.nr_param_exports = param_count;
/* We need to add the position output manually if it's missing. */
- if (!pos_args[0][0]) {
- pos_args[0][0] = lp_build_const_int32(base->gallivm, 0xf); /* writemask */
- pos_args[0][1] = uint->zero; /* EXEC mask */
- pos_args[0][2] = uint->zero; /* last export? */
- pos_args[0][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS);
- pos_args[0][4] = uint->zero; /* COMPR flag */
- pos_args[0][5] = base->zero; /* X */
- pos_args[0][6] = base->zero; /* Y */
- pos_args[0][7] = base->zero; /* Z */
- pos_args[0][8] = base->one; /* W */
+ if (!pos_args[0].out[0]) {
+ pos_args[0].enabled_channels = 0xf; /* writemask */
+ pos_args[0].valid_mask = 0; /* EXEC mask */
+ pos_args[0].done = 0; /* last export? */
+ pos_args[0].target = V_008DFC_SQ_EXP_POS;
+ pos_args[0].compr = 0; /* COMPR flag */
+ pos_args[0].out[0] = base->zero; /* X */
+ pos_args[0].out[1] = base->zero; /* Y */
+ pos_args[0].out[2] = base->zero; /* Z */
+ pos_args[0].out[3] = base->one; /* W */
}
/* Write the misc vector (point size, edgeflag, layer, viewport). */
shader->selector->info.writes_edgeflag ||
shader->selector->info.writes_viewport_index ||
shader->selector->info.writes_layer) {
- pos_args[1][0] = lp_build_const_int32(base->gallivm, /* writemask */
- shader->selector->info.writes_psize |
- (shader->selector->info.writes_edgeflag << 1) |
- (shader->selector->info.writes_layer << 2) |
- (shader->selector->info.writes_viewport_index << 3));
- pos_args[1][1] = uint->zero; /* EXEC mask */
- pos_args[1][2] = uint->zero; /* last export? */
- pos_args[1][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + 1);
- pos_args[1][4] = uint->zero; /* COMPR flag */
- pos_args[1][5] = base->zero; /* X */
- pos_args[1][6] = base->zero; /* Y */
- pos_args[1][7] = base->zero; /* Z */
- pos_args[1][8] = base->zero; /* W */
+ pos_args[1].enabled_channels = shader->selector->info.writes_psize |
+ (shader->selector->info.writes_edgeflag << 1) |
+ (shader->selector->info.writes_layer << 2) |
+ (shader->selector->info.writes_viewport_index << 3);
+ pos_args[1].valid_mask = 0; /* EXEC mask */
+ pos_args[1].done = 0; /* last export? */
+ pos_args[1].target = V_008DFC_SQ_EXP_POS + 1;
+ pos_args[1].compr = 0; /* COMPR flag */
+ pos_args[1].out[0] = base->zero; /* X */
+ pos_args[1].out[1] = base->zero; /* Y */
+ pos_args[1].out[2] = base->zero; /* Z */
+ pos_args[1].out[3] = base->zero; /* W */
if (shader->selector->info.writes_psize)
- pos_args[1][5] = psize_value;
+ pos_args[1].out[0] = psize_value;
if (shader->selector->info.writes_edgeflag) {
/* The output is a float, but the hw expects an integer
bld_base->int_bld.one);
/* The LLVM intrinsic expects a float. */
- pos_args[1][6] = LLVMBuildBitCast(base->gallivm->builder,
+ pos_args[1].out[1] = LLVMBuildBitCast(base->gallivm->builder,
edgeflag_value,
ctx->f32, "");
}
if (shader->selector->info.writes_layer)
- pos_args[1][7] = layer_value;
+ pos_args[1].out[2] = layer_value;
if (shader->selector->info.writes_viewport_index)
- pos_args[1][8] = viewport_index_value;
+ pos_args[1].out[3] = viewport_index_value;
}
for (i = 0; i < 4; i++)
- if (pos_args[i][0])
+ if (pos_args[i].out[0])
shader->info.nr_pos_exports++;
pos_idx = 0;
for (i = 0; i < 4; i++) {
- if (!pos_args[i][0])
+ if (!pos_args[i].out[0])
continue;
/* Specify the target we are exporting */
- pos_args[i][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + pos_idx++);
+ pos_args[i].target = V_008DFC_SQ_EXP_POS + pos_idx++;
if (pos_idx == shader->info.nr_pos_exports)
/* Specify that this is the last export */
- pos_args[i][2] = uint->one;
+ pos_args[i].done = 1;
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- ctx->voidt, pos_args[i], 9, 0);
+ ac_emit_export(&ctx->ac, &pos_args[i]);
}
}
"");
LLVMValueRef buffer_addr = get_tcs_tes_buffer_address(ctx,
+ get_rel_patch_id(ctx),
invocation_id,
lp_build_const_int32(gallivm, i));
struct si_shader *shader = ctx->shader;
unsigned tess_inner_index, tess_outer_index;
LLVMValueRef lds_base, lds_inner, lds_outer, byteoffset, buffer;
- LLVMValueRef out[6], vec0, vec1, rw_buffers, tf_base;
+ LLVMValueRef out[6], vec0, vec1, rw_buffers, tf_base, inner[4], outer[4];
unsigned stride, outer_comps, inner_comps, i;
struct lp_build_if_state if_ctx, inner_if_ctx;
lp_build_const_int32(gallivm,
tess_outer_index * 4), "");
+ for (i = 0; i < 4; i++) {
+ inner[i] = LLVMGetUndef(ctx->i32);
+ outer[i] = LLVMGetUndef(ctx->i32);
+ }
+
if (shader->key.part.tcs.epilog.prim_mode == PIPE_PRIM_LINES) {
/* For isolines, the hardware expects tess factors in the
* reverse order from what GLSL / TGSI specify.
*/
- out[0] = lds_load(bld_base, TGSI_TYPE_SIGNED, 1, lds_outer);
- out[1] = lds_load(bld_base, TGSI_TYPE_SIGNED, 0, lds_outer);
+ outer[0] = out[1] = lds_load(bld_base, TGSI_TYPE_SIGNED, 0, lds_outer);
+ outer[1] = out[0] = lds_load(bld_base, TGSI_TYPE_SIGNED, 1, lds_outer);
} else {
- for (i = 0; i < outer_comps; i++)
- out[i] = lds_load(bld_base, TGSI_TYPE_SIGNED, i, lds_outer);
- for (i = 0; i < inner_comps; i++)
- out[outer_comps+i] = lds_load(bld_base, TGSI_TYPE_SIGNED, i, lds_inner);
+ for (i = 0; i < outer_comps; i++) {
+ outer[i] = out[i] =
+ lds_load(bld_base, TGSI_TYPE_SIGNED, i, lds_outer);
+ }
+ for (i = 0; i < inner_comps; i++) {
+ inner[i] = out[outer_comps+i] =
+ lds_load(bld_base, TGSI_TYPE_SIGNED, i, lds_inner);
+ }
}
/* Convert the outputs to vectors for stores. */
if (vec1)
ac_build_tbuffer_store_dwords(&ctx->ac, buffer, vec1,
stride - 4, byteoffset, tf_base, 20);
+
+ /* Store the tess factors into the offchip buffer if TES reads them. */
+ if (shader->key.part.tcs.epilog.tes_reads_tess_factors) {
+ LLVMValueRef buf, base, inner_vec, outer_vec, tf_outer_offset;
+ LLVMValueRef tf_inner_offset;
+ unsigned param_outer, param_inner;
+
+ buf = ac_build_indexed_load_const(&ctx->ac, rw_buffers,
+ LLVMConstInt(ctx->i32, SI_HS_RING_TESS_OFFCHIP, 0));
+ base = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
+
+ param_outer = si_shader_io_get_unique_index(
+ TGSI_SEMANTIC_TESSOUTER, 0);
+ tf_outer_offset = get_tcs_tes_buffer_address(ctx, rel_patch_id, NULL,
+ LLVMConstInt(ctx->i32, param_outer, 0));
+
+ outer_vec = lp_build_gather_values(gallivm, outer,
+ util_next_power_of_two(outer_comps));
+
+ ac_build_tbuffer_store_dwords(&ctx->ac, buf, outer_vec,
+ outer_comps, tf_outer_offset,
+ base, 0);
+ if (inner_comps) {
+ param_inner = si_shader_io_get_unique_index(
+ TGSI_SEMANTIC_TESSINNER, 0);
+ tf_inner_offset = get_tcs_tes_buffer_address(ctx, rel_patch_id, NULL,
+ LLVMConstInt(ctx->i32, param_inner, 0));
+
+ inner_vec = inner_comps == 1 ? inner[0] :
+ lp_build_gather_values(gallivm, inner, inner_comps);
+ ac_build_tbuffer_store_dwords(&ctx->ac, buf, inner_vec,
+ inner_comps, tf_inner_offset,
+ base, 0);
+ }
+ }
+
lp_build_endif(&if_ctx);
}
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef rel_patch_id, invocation_id, tf_lds_offset;
+ LLVMValueRef offchip_soffset, offchip_layout;
si_copy_tcs_inputs(bld_base);
ret = LLVMBuildInsertValue(builder, ret, rw0, 0, "");
ret = LLVMBuildInsertValue(builder, ret, rw1, 1, "");
- /* Tess factor buffer soffset is after user SGPRs. */
+ /* Tess offchip and factor buffer soffset are after user SGPRs. */
+ offchip_layout = LLVMGetParam(ctx->main_fn,
+ SI_PARAM_TCS_OFFCHIP_LAYOUT);
+ offchip_soffset = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
tf_soffset = LLVMGetParam(ctx->main_fn,
SI_PARAM_TESS_FACTOR_OFFSET);
+ ret = LLVMBuildInsertValue(builder, ret, offchip_layout,
+ SI_SGPR_TCS_OFFCHIP_LAYOUT, "");
+ ret = LLVMBuildInsertValue(builder, ret, offchip_soffset,
+ SI_TCS_NUM_USER_SGPR, "");
ret = LLVMBuildInsertValue(builder, ret, tf_soffset,
SI_TCS_NUM_USER_SGPR + 1, "");
struct si_ps_exports {
unsigned num;
- LLVMValueRef args[10][9];
+ struct ac_export_args args[10];
};
unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
- struct lp_build_context *uint = &bld_base->uint_bld;
- LLVMValueRef args[9];
+ struct ac_export_args args;
unsigned mask = 0;
unsigned format = si_get_spi_shader_z_format(depth != NULL,
stencil != NULL,
assert(depth || stencil || samplemask);
- args[1] = uint->one; /* whether the EXEC mask is valid */
- args[2] = uint->one; /* DONE bit */
+ args.valid_mask = 1; /* whether the EXEC mask is valid */
+ args.done = 1; /* DONE bit */
/* Specify the target we are exporting */
- args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRTZ);
+ args.target = V_008DFC_SQ_EXP_MRTZ;
- args[4] = uint->zero; /* COMP flag */
- args[5] = base->undef; /* R, depth */
- args[6] = base->undef; /* G, stencil test value[0:7], stencil op value[8:15] */
- args[7] = base->undef; /* B, sample mask */
- args[8] = base->undef; /* A, alpha to mask */
+ args.compr = 0; /* COMP flag */
+ args.out[0] = base->undef; /* R, depth */
+ args.out[1] = base->undef; /* G, stencil test value[0:7], stencil op value[8:15] */
+ args.out[2] = base->undef; /* B, sample mask */
+ args.out[3] = base->undef; /* A, alpha to mask */
if (format == V_028710_SPI_SHADER_UINT16_ABGR) {
assert(!depth);
- args[4] = uint->one; /* COMPR flag */
+ args.compr = 1; /* COMPR flag */
if (stencil) {
/* Stencil should be in X[23:16]. */
stencil = bitcast(bld_base, TGSI_TYPE_UNSIGNED, stencil);
stencil = LLVMBuildShl(base->gallivm->builder, stencil,
LLVMConstInt(ctx->i32, 16, 0), "");
- args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT, stencil);
+ args.out[0] = bitcast(bld_base, TGSI_TYPE_FLOAT, stencil);
mask |= 0x3;
}
if (samplemask) {
/* SampleMask should be in Y[15:0]. */
- args[6] = samplemask;
+ args.out[1] = samplemask;
mask |= 0xc;
}
} else {
if (depth) {
- args[5] = depth;
+ args.out[0] = depth;
mask |= 0x1;
}
if (stencil) {
- args[6] = stencil;
+ args.out[1] = stencil;
mask |= 0x2;
}
if (samplemask) {
- args[7] = samplemask;
+ args.out[2] = samplemask;
mask |= 0x4;
}
}
mask |= 0x1;
/* Specify which components to enable */
- args[0] = lp_build_const_int32(base->gallivm, mask);
+ args.enabled_channels = mask;
- memcpy(exp->args[exp->num++], args, sizeof(args));
+ memcpy(&exp->args[exp->num++], &args, sizeof(args));
}
static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
/* If last_cbuf > 0, FS_COLOR0_WRITES_ALL_CBUFS is true. */
if (ctx->shader->key.part.ps.epilog.last_cbuf > 0) {
- LLVMValueRef args[8][9];
+ struct ac_export_args args[8];
int c, last = -1;
/* Get the export arguments, also find out what the last one is. */
for (c = 0; c <= ctx->shader->key.part.ps.epilog.last_cbuf; c++) {
si_llvm_init_export_args(bld_base, color,
- V_008DFC_SQ_EXP_MRT + c, args[c]);
- if (args[c][0] != bld_base->uint_bld.zero)
+ V_008DFC_SQ_EXP_MRT + c, &args[c]);
+ if (args[c].enabled_channels)
last = c;
}
/* Emit all exports. */
for (c = 0; c <= ctx->shader->key.part.ps.epilog.last_cbuf; c++) {
if (is_last && last == c) {
- args[c][1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
- args[c][2] = bld_base->uint_bld.one; /* DONE bit */
- } else if (args[c][0] == bld_base->uint_bld.zero)
+ args[c].valid_mask = 1; /* whether the EXEC mask is valid */
+ args[c].done = 1; /* DONE bit */
+ } else if (!args[c].enabled_channels)
continue; /* unnecessary NULL export */
- memcpy(exp->args[exp->num++], args[c], sizeof(args[c]));
+ memcpy(&exp->args[exp->num++], &args[c], sizeof(args[c]));
}
} else {
- LLVMValueRef args[9];
+ struct ac_export_args args;
/* Export */
si_llvm_init_export_args(bld_base, color, V_008DFC_SQ_EXP_MRT + index,
- args);
+ &args);
if (is_last) {
- args[1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
- args[2] = bld_base->uint_bld.one; /* DONE bit */
- } else if (args[0] == bld_base->uint_bld.zero)
+ args.valid_mask = 1; /* whether the EXEC mask is valid */
+ args.done = 1; /* DONE bit */
+ } else if (!args.enabled_channels)
return; /* unnecessary NULL export */
- memcpy(exp->args[exp->num++], args, sizeof(args));
+ memcpy(&exp->args[exp->num++], &args, sizeof(args));
}
}
struct si_ps_exports *exp)
{
for (unsigned i = 0; i < exp->num; i++)
- lp_build_intrinsic(ctx->gallivm.builder,
- "llvm.SI.export", ctx->voidt,
- exp->args[i], 9, 0);
+ ac_emit_export(&ctx->ac, &exp->args[i]);
}
static void si_export_null(struct lp_build_tgsi_context *bld_base)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
- struct lp_build_context *uint = &bld_base->uint_bld;
- LLVMValueRef args[9];
+ struct ac_export_args args;
- args[0] = lp_build_const_int32(base->gallivm, 0x0); /* enabled channels */
- args[1] = uint->one; /* whether the EXEC mask is valid */
- args[2] = uint->one; /* DONE bit */
- args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_NULL);
- args[4] = uint->zero; /* COMPR flag (0 = 32-bit export) */
- args[5] = base->undef; /* R */
- args[6] = base->undef; /* G */
- args[7] = base->undef; /* B */
- args[8] = base->undef; /* A */
+ args.enabled_channels = 0x0; /* enabled channels */
+ args.valid_mask = 1; /* whether the EXEC mask is valid */
+ args.done = 1; /* DONE bit */
+ args.target = V_008DFC_SQ_EXP_NULL;
+ args.compr = 0; /* COMPR flag (0 = 32-bit export) */
+ args.out[0] = base->undef; /* R */
+ args.out[1] = base->undef; /* G */
+ args.out[2] = base->undef; /* B */
+ args.out[3] = base->undef; /* A */
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- ctx->voidt, args, 9, 0);
+ ac_emit_export(&ctx->ac, &args);
}
/**
return size;
}
-/**
- * Given the i32 or vNi32 \p type, generate the textual name (e.g. for use with
- * intrinsic names).
- */
-static void build_type_name_for_intr(
- LLVMTypeRef type,
- char *buf, unsigned bufsize)
-{
- LLVMTypeRef elem_type = type;
-
- assert(bufsize >= 8);
-
- if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) {
- int ret = snprintf(buf, bufsize, "v%u",
- LLVMGetVectorSize(type));
- if (ret < 0) {
- char *type_name = LLVMPrintTypeToString(type);
- fprintf(stderr, "Error building type name for: %s\n",
- type_name);
- return;
- }
- elem_type = LLVMGetElementType(type);
- buf += ret;
- bufsize -= ret;
- }
- switch (LLVMGetTypeKind(elem_type)) {
- default: break;
- case LLVMIntegerTypeKind:
- snprintf(buf, bufsize, "i%d", LLVMGetIntTypeWidth(elem_type));
- break;
- case LLVMFloatTypeKind:
- snprintf(buf, bufsize, "f32");
- break;
- case LLVMDoubleTypeKind:
- snprintf(buf, bufsize, "f64");
- break;
- }
-}
-
static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data);
if (!image->Register.Indirect) {
const struct tgsi_shader_info *info = bld_base->info;
+ unsigned images_writemask = info->images_store |
+ info->images_atomic;
index = LLVMConstInt(ctx->i32, image->Register.Index, 0);
- if (info->images_writemask & (1 << image->Register.Index) &&
+ if (images_writemask & (1 << image->Register.Index) &&
target != TGSI_TEXTURE_BUFFER)
dcc_off = true;
} else {
{
char coords_type_name[8];
- build_type_name_for_intr(coords_type, coords_type_name,
+ ac_build_type_name_for_intr(coords_type, coords_type_name,
sizeof(coords_type_name));
if (HAVE_LLVM <= 0x0309) {
char data_type_name[8];
char rsrc_type_name[8];
- build_type_name_for_intr(data_type, data_type_name,
+ ac_build_type_name_for_intr(data_type, data_type_name,
sizeof(data_type_name));
- build_type_name_for_intr(rsrc_type, rsrc_type_name,
+ ac_build_type_name_for_intr(rsrc_type, rsrc_type_name,
sizeof(rsrc_type_name));
snprintf(out_name, out_len, "%s.%s.%s.%s", base_name,
data_type_name, coords_type_name, rsrc_type_name);
else
coords = emit_data->args[1];
- build_type_name_for_intr(LLVMTypeOf(coords), coords_type, sizeof(coords_type));
+ ac_build_type_name_for_intr(LLVMTypeOf(coords), coords_type, sizeof(coords_type));
snprintf(intrinsic_name, sizeof(intrinsic_name),
"llvm.amdgcn.image.atomic.%s.%s",
action->intr_name, coords_type);
out = lp_build_intrinsic(
builder, "llvm.SI.getresinfo.i32", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY);
/* Divide the number of layers by 6 to get the number of cubes. */
if (inst->Memory.Texture == TGSI_TEXTURE_CUBE_ARRAY) {
{
struct gallivm_state *gallivm = &ctx->gallivm;
unsigned num_args;
- unsigned is_rect = target == TGSI_TEXTURE_RECT;
+ unsigned is_rect = target == TGSI_TEXTURE_RECT ||
+ target == TGSI_TEXTURE_SHADOWRECT;
/* Pad to power of two vector */
while (count < util_next_power_of_two(count))
emit_data->output[emit_data->chan] = lp_build_intrinsic(
base->gallivm->builder, "llvm.SI.getresinfo.i32",
emit_data->dst_type, emit_data->args, emit_data->arg_count,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY);
/* Divide the number of layers by 6 to get the number of cubes. */
if (target == TGSI_TEXTURE_CUBE_ARRAY ||
emit_data->output[emit_data->chan] =
lp_build_intrinsic(builder, intr_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY);
}
static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
base->gallivm->builder,
"llvm.SI.vs.load.input", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY);
return;
}
}
/* Add the type and suffixes .c, .o if needed. */
- build_type_name_for_intr(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
+ ac_build_type_name_for_intr(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
sprintf(intr_name, "%s%s%s%s.%s",
name, is_shadow ? ".c" : "", infix,
has_offset ? ".o" : "", type);
emit_data->output[emit_data->chan] = lp_build_intrinsic(
base->gallivm->builder, intr_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LP_FUNC_ATTR_READNONE);
+ LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY);
}
static void si_llvm_emit_txqs(
lp_build_const_float(gallivm, -1.0f));
lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill",
- ctx->voidt, &kill, 1, 0);
+ ctx->voidt, &kill, 1, LP_FUNC_ATTR_LEGACY);
} else {
lp_build_if(&if_state, gallivm, can_emit);
}
lp_add_function_attr(ctx->main_fn, i + 1, LP_FUNC_ATTR_INREG);
}
+ LLVMAddTargetDependentFunctionAttr(ctx->main_fn,
+ "no-signed-zeros-fp-math",
+ "true");
+
if (ctx->screen->b.debug_flags & DBG_UNSAFE_MATH) {
/* These were copied from some LLVM test. */
LLVMAddTargetDependentFunctionAttr(ctx->main_fn,
/* The intrinsic kills the thread if arg < 0. */
bit = LLVMBuildSelect(builder, bit, LLVMConstReal(ctx->f32, 0),
LLVMConstReal(ctx->f32, -1), "");
- lp_build_intrinsic(builder, "llvm.AMDGPU.kill", ctx->voidt, &bit, 1, 0);
+ lp_build_intrinsic(builder, "llvm.AMDGPU.kill", ctx->voidt, &bit, 1,
+ LP_FUNC_ATTR_LEGACY);
}
-void si_shader_binary_read_config(struct radeon_shader_binary *binary,
+void si_shader_binary_read_config(struct ac_shader_binary *binary,
struct si_shader_config *conf,
unsigned symbol_offset)
{
unsigned i;
const unsigned char *config =
- radeon_shader_binary_config_start(binary, symbol_offset);
+ ac_shader_binary_config_start(binary, symbol_offset);
bool really_needs_scratch = false;
/* LLVM adds SGPR spills to the scratch size.
* Find out if we really need the scratch buffer.
*/
for (i = 0; i < binary->reloc_count; i++) {
- const struct radeon_shader_reloc *reloc = &binary->relocs[i];
+ const struct ac_shader_reloc *reloc = &binary->relocs[i];
if (!strcmp(scratch_rsrc_dword0_symbol, reloc->name) ||
!strcmp(scratch_rsrc_dword1_symbol, reloc->name)) {
S_008F04_STRIDE(config->scratch_bytes_per_wave / 64);
for (i = 0 ; i < shader->binary.reloc_count; i++) {
- const struct radeon_shader_reloc *reloc =
+ const struct ac_shader_reloc *reloc =
&shader->binary.relocs[i];
if (!strcmp(scratch_rsrc_dword0_symbol, reloc->name)) {
util_memcpy_cpu_to_le32(shader->binary.code + reloc->offset,
int si_shader_binary_upload(struct si_screen *sscreen, struct si_shader *shader)
{
- const struct radeon_shader_binary *prolog =
+ const struct ac_shader_binary *prolog =
shader->prolog ? &shader->prolog->binary : NULL;
- const struct radeon_shader_binary *epilog =
+ const struct ac_shader_binary *epilog =
shader->epilog ? &shader->epilog->binary : NULL;
- const struct radeon_shader_binary *mainb = &shader->binary;
+ const struct ac_shader_binary *mainb = &shader->binary;
unsigned bo_size = si_get_shader_binary_size(shader) +
(!epilog ? mainb->rodata_size : 0);
unsigned char *ptr;
return 0;
}
-static void si_shader_dump_disassembly(const struct radeon_shader_binary *binary,
+static void si_shader_dump_disassembly(const struct ac_shader_binary *binary,
struct pipe_debug_callback *debug,
const char *name, FILE *file)
{
}
int si_compile_llvm(struct si_screen *sscreen,
- struct radeon_shader_binary *binary,
+ struct ac_shader_binary *binary,
struct si_shader_config *conf,
LLVMTargetMachineRef tm,
LLVMModuleRef mod,
outputs[i].values[chan] =
LLVMBuildBitCast(gallivm->builder,
lp_build_intrinsic(gallivm->builder,
- "llvm.SI.buffer.load.dword.i32.i32",
- ctx.i32, args, 9,
- LP_FUNC_ATTR_READONLY),
+ "llvm.SI.buffer.load.dword.i32.i32",
+ ctx.i32, args, 9,
+ LP_FUNC_ATTR_READONLY |
+ LP_FUNC_ATTR_LEGACY),
ctx.f32, "");
}
}
for (i = 0; i < 4; i++) {
LLVMBool loses_info;
- LLVMValueRef p = LLVMGetOperand(inst, 5 + i);
+ LLVMValueRef p = LLVMGetOperand(inst, (HAVE_LLVM >= 0x0500 ? 2 : 5) + i);
/* It's a constant expression. Undef outputs are eliminated too. */
if (LLVMIsUndef(p)) {
unsigned num_args = LLVMCountParams(callee);
/* Check if this is an export instruction. */
- if (num_args != 9 || strcmp(name, "llvm.SI.export"))
+ if ((num_args != 9 && num_args != 8) ||
+ (strcmp(name, "llvm.SI.export") &&
+ strcmp(name, "llvm.amdgcn.exp.")))
continue;
- LLVMValueRef arg = LLVMGetOperand(cur, 3);
+ LLVMValueRef arg = LLVMGetOperand(cur, HAVE_LLVM >= 0x0500 ? 0 : 3);
unsigned target = LLVMConstIntGetZExtValue(arg);
if (target < V_008DFC_SQ_EXP_PARAM)
/* Emit exports. */
if (key->vs_epilog.states.export_prim_id) {
struct lp_build_context *base = &bld_base->base;
- struct lp_build_context *uint = &bld_base->uint_bld;
- LLVMValueRef args[9];
-
- args[0] = lp_build_const_int32(base->gallivm, 0x0); /* enabled channels */
- args[1] = uint->zero; /* whether the EXEC mask is valid */
- args[2] = uint->zero; /* DONE bit */
- args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_PARAM +
- key->vs_epilog.prim_id_param_offset);
- args[4] = uint->zero; /* COMPR flag (0 = 32-bit export) */
- args[5] = LLVMGetParam(ctx->main_fn,
+ struct ac_export_args args;
+
+ args.enabled_channels = 0x1; /* enabled channels */
+ args.valid_mask = 0; /* whether the EXEC mask is valid */
+ args.done = 0; /* DONE bit */
+ args.target = V_008DFC_SQ_EXP_PARAM +
+ key->vs_epilog.prim_id_param_offset;
+ args.compr = 0; /* COMPR flag (0 = 32-bit export) */
+ args.out[0] = LLVMGetParam(ctx->main_fn,
VS_EPILOG_PRIMID_LOC); /* X */
- args[6] = base->undef; /* Y */
- args[7] = base->undef; /* Z */
- args[8] = base->undef; /* W */
+ args.out[1] = base->undef; /* Y */
+ args.out[2] = base->undef; /* Z */
+ args.out[3] = base->undef; /* W */
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- args, 9, 0);
+ ac_emit_export(&ctx->ac, &args);
}
LLVMBuildRetVoid(gallivm->builder);