#include "gallivm/lp_bld_intr.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_arit.h"
-#include "gallivm/lp_bld_bitarit.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_misc.h"
-#include "radeon/r600_cs.h"
-#include "radeon/radeon_llvm.h"
#include "radeon/radeon_elf_util.h"
-#include "radeon/radeon_llvm_emit.h"
#include "util/u_memory.h"
#include "util/u_string.h"
-#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_dump.h"
+#include "ac_llvm_util.h"
+#include "si_shader_internal.h"
#include "si_pipe.h"
-#include "si_shader.h"
#include "sid.h"
-#include <errno.h>
static const char *scratch_rsrc_dword0_symbol =
"SCRATCH_RSRC_DWORD0";
unsigned sid;
};
-struct si_shader_context
-{
- struct radeon_llvm_context radeon_bld;
- struct si_shader *shader;
- struct si_screen *screen;
-
- unsigned type; /* PIPE_SHADER_* specifies the type of shader. */
- bool is_gs_copy_shader;
-
- /* Whether to generate the optimized shader variant compiled as a whole
- * (without a prolog and epilog)
- */
- bool is_monolithic;
-
- int param_streamout_config;
- int param_streamout_write_index;
- int param_streamout_offset[4];
- int param_vertex_id;
- int param_rel_auto_id;
- int param_vs_prim_id;
- int param_instance_id;
- int param_vertex_index0;
- int param_tes_u;
- int param_tes_v;
- int param_tes_rel_patch_id;
- int param_tes_patch_id;
- int param_es2gs_offset;
- int param_oc_lds;
-
- /* Sets a bit if the dynamic HS control word was 0x80000000. The bit is
- * 0x800000 for VS, 0x1 for ES.
- */
- int param_tess_offchip;
-
- LLVMTargetMachineRef tm;
-
- unsigned invariant_load_md_kind;
- unsigned range_md_kind;
- unsigned uniform_md_kind;
- LLVMValueRef empty_md;
-
- LLVMValueRef const_buffers[SI_NUM_CONST_BUFFERS];
- LLVMValueRef lds;
- LLVMValueRef *constants[SI_NUM_CONST_BUFFERS];
- LLVMValueRef shader_buffers[SI_NUM_SHADER_BUFFERS];
- LLVMValueRef sampler_views[SI_NUM_SAMPLERS];
- LLVMValueRef sampler_states[SI_NUM_SAMPLERS];
- LLVMValueRef fmasks[SI_NUM_SAMPLERS];
- LLVMValueRef images[SI_NUM_IMAGES];
- LLVMValueRef so_buffers[4];
- LLVMValueRef esgs_ring;
- LLVMValueRef gsvs_ring[4];
- LLVMValueRef gs_next_vertex[4];
- LLVMValueRef return_value;
-
- LLVMTypeRef voidt;
- LLVMTypeRef i1;
- LLVMTypeRef i8;
- LLVMTypeRef i32;
- LLVMTypeRef i64;
- LLVMTypeRef i128;
- LLVMTypeRef f32;
- LLVMTypeRef v16i8;
- LLVMTypeRef v2i32;
- LLVMTypeRef v4i32;
- LLVMTypeRef v4f32;
- LLVMTypeRef v8i32;
-
- LLVMValueRef shared_memory;
-};
-
-static struct si_shader_context *si_shader_context(
- struct lp_build_tgsi_context *bld_base)
-{
- return (struct si_shader_context *)bld_base;
-}
-
static void si_init_shader_ctx(struct si_shader_context *ctx,
struct si_screen *sscreen,
struct si_shader *shader,
static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
FILE *f);
+static void si_build_vs_prolog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key);
+static void si_build_vs_epilog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key);
+static void si_build_ps_prolog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key);
+static void si_build_ps_epilog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key);
+
/* Ideally pass the sample mask input to the PS epilog as v13, which
* is its usual location, so that the shader doesn't have to add v_mov.
*/
*/
#define VS_EPILOG_PRIMID_LOC 2
-#define PERSPECTIVE_BASE 0
-#define LINEAR_BASE 9
-
-#define SAMPLE_OFFSET 0
-#define CENTER_OFFSET 2
-#define CENTROID_OFSET 4
-
-#define USE_SGPR_MAX_SUFFIX_LEN 5
-#define CONST_ADDR_SPACE 2
-#define LOCAL_ADDR_SPACE 3
-#define USER_SGPR_ADDR_SPACE 8
-
+enum {
+ CONST_ADDR_SPACE = 2,
+ LOCAL_ADDR_SPACE = 3,
+};
#define SENDMSG_GS 2
#define SENDMSG_GS_DONE 3
unsigned param, unsigned rshift,
unsigned bitwidth)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- LLVMValueRef value = LLVMGetParam(ctx->radeon_bld.main_fn,
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ LLVMValueRef value = LLVMGetParam(ctx->main_fn,
param);
if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMFloatTypeKind)
- value = bitcast(&ctx->radeon_bld.soa.bld_base,
+ value = bitcast(&ctx->soa.bld_base,
TGSI_TYPE_UNSIGNED, value);
if (rshift)
return unpack_param(ctx, SI_PARAM_REL_IDS, 0, 8);
case PIPE_SHADER_TESS_EVAL:
- return LLVMGetParam(ctx->radeon_bld.main_fn,
+ return LLVMGetParam(ctx->main_fn,
ctx->param_tes_rel_patch_id);
default:
static LLVMValueRef
get_tcs_out_patch0_offset(struct si_shader_context *ctx)
{
- return lp_build_mul_imm(&ctx->radeon_bld.soa.bld_base.uint_bld,
+ return lp_build_mul_imm(&ctx->soa.bld_base.uint_bld,
unpack_param(ctx,
SI_PARAM_TCS_OUT_OFFSETS,
0, 16),
static LLVMValueRef
get_tcs_out_patch0_patch_data_offset(struct si_shader_context *ctx)
{
- return lp_build_mul_imm(&ctx->radeon_bld.soa.bld_base.uint_bld,
+ return lp_build_mul_imm(&ctx->soa.bld_base.uint_bld,
unpack_param(ctx,
SI_PARAM_TCS_OUT_OFFSETS,
16, 16),
static LLVMValueRef
get_tcs_in_current_patch_offset(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMValueRef patch_stride = get_tcs_in_patch_stride(ctx);
LLVMValueRef rel_patch_id = get_rel_patch_id(ctx);
static LLVMValueRef
get_tcs_out_current_patch_offset(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMValueRef patch0_offset = get_tcs_out_patch0_offset(ctx);
LLVMValueRef patch_stride = get_tcs_out_patch_stride(ctx);
LLVMValueRef rel_patch_id = get_rel_patch_id(ctx);
static LLVMValueRef
get_tcs_out_current_patch_data_offset(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMValueRef patch0_patch_data_offset =
get_tcs_out_patch0_patch_data_offset(ctx);
LLVMValueRef patch_stride = get_tcs_out_patch_stride(ctx);
"");
}
+static LLVMValueRef build_gep0(struct si_shader_context *ctx,
+ LLVMValueRef base_ptr, LLVMValueRef index)
+{
+ LLVMValueRef indices[2] = {
+ LLVMConstInt(ctx->i32, 0, 0),
+ index,
+ };
+ return LLVMBuildGEP(ctx->gallivm.builder, base_ptr,
+ indices, 2, "");
+}
+
static void build_indexed_store(struct si_shader_context *ctx,
LLVMValueRef base_ptr, LLVMValueRef index,
LLVMValueRef value)
{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef indices[2], pointer;
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = index;
-
- pointer = LLVMBuildGEP(gallivm->builder, base_ptr, indices, 2, "");
- LLVMBuildStore(gallivm->builder, value, pointer);
+ LLVMBuildStore(gallivm->builder, value,
+ build_gep0(ctx, base_ptr, index));
}
/**
LLVMValueRef base_ptr, LLVMValueRef index,
bool uniform)
{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef indices[2], pointer;
-
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = index;
+ LLVMValueRef pointer;
- pointer = LLVMBuildGEP(gallivm->builder, base_ptr, indices, 2, "");
+ pointer = build_gep0(ctx, base_ptr, index);
if (uniform)
LLVMSetMetadata(pointer, ctx->uniform_md_kind, ctx->empty_md);
return LLVMBuildLoad(gallivm->builder, pointer, "");
}
static LLVMValueRef get_instance_index_for_fetch(
- struct radeon_llvm_context *radeon_bld,
+ struct si_shader_context *radeon_bld,
unsigned param_start_instance, unsigned divisor)
{
struct si_shader_context *ctx =
}
static void declare_input_vs(
- struct radeon_llvm_context *radeon_bld,
+ struct si_shader_context *radeon_bld,
unsigned input_index,
- const struct tgsi_full_declaration *decl)
+ const struct tgsi_full_declaration *decl,
+ LLVMValueRef out[4])
{
struct lp_build_context *base = &radeon_bld->soa.bld_base.base;
struct gallivm_state *gallivm = base->gallivm;
LLVMValueRef input;
/* Load the T list */
- t_list_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_VERTEX_BUFFERS);
+ t_list_ptr = LLVMGetParam(ctx->main_fn, SI_PARAM_VERTEX_BUFFERS);
t_offset = lp_build_const_int32(gallivm, input_index);
/* Build the attribute offset */
attribute_offset = lp_build_const_int32(gallivm, 0);
- if (!ctx->is_monolithic) {
+ if (!ctx->no_prolog) {
buffer_index = LLVMGetParam(radeon_bld->main_fn,
ctx->param_vertex_index0 +
input_index);
} else if (divisor) {
/* Build index from instance ID, start instance and divisor */
ctx->shader->info.uses_instanceid = true;
- buffer_index = get_instance_index_for_fetch(&ctx->radeon_bld,
+ buffer_index = get_instance_index_for_fetch(ctx,
SI_PARAM_START_INSTANCE,
divisor);
} else {
/* Load the buffer index for vertices. */
- LLVMValueRef vertex_id = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef vertex_id = LLVMGetParam(ctx->main_fn,
ctx->param_vertex_id);
LLVMValueRef base_vertex = LLVMGetParam(radeon_bld->main_fn,
SI_PARAM_BASE_VERTEX);
/* Break up the vec4 into individual components */
for (chan = 0; chan < 4; chan++) {
LLVMValueRef llvm_chan = lp_build_const_int32(gallivm, chan);
- /* XXX: Use a helper function for this. There is one in
- * tgsi_llvm.c. */
- ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, chan)] =
- LLVMBuildExtractElement(gallivm->builder,
- input, llvm_chan, "");
+ out[chan] = LLVMBuildExtractElement(gallivm->builder,
+ input, llvm_chan, "");
}
}
switch (ctx->type) {
case PIPE_SHADER_VERTEX:
- return LLVMGetParam(ctx->radeon_bld.main_fn,
+ return LLVMGetParam(ctx->main_fn,
ctx->param_vs_prim_id);
case PIPE_SHADER_TESS_CTRL:
- return LLVMGetParam(ctx->radeon_bld.main_fn,
+ return LLVMGetParam(ctx->main_fn,
SI_PARAM_PATCH_ID);
case PIPE_SHADER_TESS_EVAL:
- return LLVMGetParam(ctx->radeon_bld.main_fn,
+ return LLVMGetParam(ctx->main_fn,
ctx->param_tes_patch_id);
case PIPE_SHADER_GEOMETRY:
- return LLVMGetParam(ctx->radeon_bld.main_fn,
+ return LLVMGetParam(ctx->main_fn,
SI_PARAM_PRIMITIVE_ID);
default:
assert(0);
const struct tgsi_ind_register *ind,
int rel_index)
{
- struct gallivm_state *gallivm = ctx->radeon_bld.soa.bld_base.base.gallivm;
+ struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
LLVMValueRef result;
- result = ctx->radeon_bld.soa.addr[ind->Index][ind->Swizzle];
+ result = ctx->soa.addr[ind->Index][ind->Swizzle];
result = LLVMBuildLoad(gallivm->builder, result, "");
result = LLVMBuildAdd(gallivm->builder, result,
lp_build_const_int32(gallivm, rel_index), "");
if (HAVE_LLVM <= 0x0308)
return LLVMGetUndef(ctx->i32);
- return radeon_llvm_bound_index(&ctx->radeon_bld, result, num);
+ return si_llvm_bound_index(ctx, result, num);
}
LLVMValueRef vertex_dw_stride,
LLVMValueRef base_addr)
{
- struct gallivm_state *gallivm = ctx->radeon_bld.soa.bld_base.base.gallivm;
+ struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
struct tgsi_shader_info *info = &ctx->shader->selector->info;
ubyte *name, *index, *array_first;
int first, param;
LLVMValueRef vertex_index,
LLVMValueRef param_index)
{
- struct gallivm_state *gallivm = ctx->radeon_bld.soa.bld_base.base.gallivm;
+ struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
LLVMValueRef base_addr, vertices_per_patch, num_patches, total_vertices;
LLVMValueRef param_stride, constant16;
const struct tgsi_full_dst_register *dst,
const struct tgsi_full_src_register *src)
{
- struct gallivm_state *gallivm = ctx->radeon_bld.soa.bld_base.base.gallivm;
+ struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
struct tgsi_shader_info *info = &ctx->shader->selector->info;
ubyte *name, *index, *array_first;
struct tgsi_full_src_register reg;
unsigned slc,
unsigned tfe)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMValueRef args[] = {
rsrc,
vdata,
unsigned glc,
unsigned slc)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
unsigned func = CLAMP(num_channels, 1, 3) - 1;
if (HAVE_LLVM >= 0x309) {
value2 = build_buffer_load(ctx, buffer, 1, NULL, base, offset,
swizzle * 4 + 4, 1, 0);
- return radeon_llvm_emit_fetch_64bit(bld_base, type, value, value2);
+ return si_llvm_emit_fetch_64bit(bld_base, type, value, value2);
}
/**
if (tgsi_type_is_64bit(type)) {
LLVMValueRef value2;
dw_addr = lp_build_add(&bld_base->uint_bld, dw_addr,
- lp_build_const_int32(gallivm, swizzle + 1));
+ lp_build_const_int32(gallivm, 1));
value2 = build_indexed_load(ctx, ctx->lds, dw_addr, false);
- return radeon_llvm_emit_fetch_64bit(bld_base, type, value, value2);
+ return si_llvm_emit_fetch_64bit(bld_base, type, value, value2);
}
return LLVMBuildBitCast(gallivm->builder, value,
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMValueRef rw_buffers, buffer, base, addr;
- rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ rw_buffers = LLVMGetParam(ctx->main_fn,
SI_PARAM_RW_BUFFERS);
buffer = build_indexed_load_const(ctx, rw_buffers,
lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
- base = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ base = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
addr = get_tcs_tes_buffer_address_from_reg(ctx, NULL, reg);
return buffer_load(bld_base, type, swizzle, buffer, base, addr);
*/
if (reg->Register.File != TGSI_FILE_OUTPUT ||
(dst[0] && LLVMGetTypeKind(LLVMTypeOf(dst[0])) == LLVMVectorTypeKind)) {
- radeon_llvm_emit_store(bld_base, inst, info, dst);
+ si_llvm_emit_store(bld_base, inst, info, dst);
return;
}
dw_addr = get_dw_address(ctx, reg, NULL, NULL, dw_addr);
}
- rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ rw_buffers = LLVMGetParam(ctx->main_fn,
SI_PARAM_RW_BUFFERS);
buffer = build_indexed_load_const(ctx, rw_buffers,
lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
- base = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ base = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
buf_addr = get_tcs_tes_buffer_address_from_reg(ctx, reg, NULL);
LLVMValueRef value = dst[chan_index];
if (inst->Instruction.Saturate)
- value = radeon_llvm_saturate(bld_base, value);
+ value = si_llvm_saturate(bld_base, value);
lds_store(bld_base, chan_index, dw_addr, value);
struct lp_build_context *base = &bld_base->base;
struct si_shader_context *ctx = si_shader_context(bld_base);
struct si_shader *shader = ctx->shader;
- struct lp_build_context *uint = &ctx->radeon_bld.soa.bld_base.uint_bld;
+ struct lp_build_context *uint = &ctx->soa.bld_base.uint_bld;
struct gallivm_state *gallivm = base->gallivm;
LLVMValueRef vtx_offset;
LLVMValueRef args[9];
vtx_offset_param += SI_PARAM_VTX2_OFFSET - 2;
}
vtx_offset = lp_build_mul_imm(uint,
- LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMGetParam(ctx->main_fn,
vtx_offset_param),
4);
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
LLVMReadOnlyAttribute);
- return radeon_llvm_emit_fetch_64bit(bld_base, type,
- value, value2);
+ return si_llvm_emit_fetch_64bit(bld_base, type,
+ value, value2);
}
return LLVMBuildBitCast(gallivm->builder,
value,
static unsigned select_interp_param(struct si_shader_context *ctx,
unsigned param)
{
- if (!ctx->is_monolithic)
+ if (!ctx->no_prolog)
return param;
if (ctx->shader->key.ps.prolog.force_persp_sample_interp) {
LLVMValueRef face,
LLVMValueRef result[4])
{
- struct lp_build_context *base = &ctx->radeon_bld.soa.bld_base.base;
- struct lp_build_context *uint = &ctx->radeon_bld.soa.bld_base.uint_bld;
+ struct lp_build_context *base = &ctx->soa.bld_base.base;
+ struct lp_build_context *uint = &ctx->soa.bld_base.uint_bld;
struct gallivm_state *gallivm = base->gallivm;
const char *intr_name;
LLVMValueRef attr_number;
static LLVMValueRef get_interp_param(struct si_shader_context *ctx,
int interp_param_idx)
{
- LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
- LLVMValueRef main_fn = ctx->radeon_bld.main_fn;
+ LLVMBuilderRef builder = ctx->gallivm.builder;
+ LLVMValueRef main_fn = ctx->main_fn;
LLVMValueRef param = NULL;
/* Handle PRIM_MASK[31] (bc_optimize). */
- if (ctx->is_monolithic &&
+ if (ctx->no_prolog &&
((ctx->shader->key.ps.prolog.bc_optimize_for_persp &&
interp_param_idx == SI_PARAM_PERSP_CENTROID) ||
(ctx->shader->key.ps.prolog.bc_optimize_for_linear &&
}
static void declare_input_fs(
- struct radeon_llvm_context *radeon_bld,
+ struct si_shader_context *radeon_bld,
unsigned input_index,
- const struct tgsi_full_declaration *decl)
+ const struct tgsi_full_declaration *decl,
+ LLVMValueRef out[4])
{
struct lp_build_context *base = &radeon_bld->soa.bld_base.base;
struct si_shader_context *ctx =
int interp_param_idx;
/* Get colors from input VGPRs (set by the prolog). */
- if (!ctx->is_monolithic &&
+ if (!ctx->no_prolog &&
decl->Semantic.Name == TGSI_SEMANTIC_COLOR) {
unsigned i = decl->Semantic.Index;
unsigned colors_read = shader->selector->info.colors_read;
unsigned offset = SI_PARAM_POS_FIXED_PT + 1 +
(i ? util_bitcount(colors_read & 0xf) : 0);
- radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
- mask & 0x1 ? LLVMGetParam(main_fn, offset++) : base->undef;
- radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
- mask & 0x2 ? LLVMGetParam(main_fn, offset++) : base->undef;
- radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
- mask & 0x4 ? LLVMGetParam(main_fn, offset++) : base->undef;
- radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
- mask & 0x8 ? LLVMGetParam(main_fn, offset++) : base->undef;
+ out[0] = mask & 0x1 ? LLVMGetParam(main_fn, offset++) : base->undef;
+ out[1] = mask & 0x2 ? LLVMGetParam(main_fn, offset++) : base->undef;
+ out[2] = mask & 0x4 ? LLVMGetParam(main_fn, offset++) : base->undef;
+ out[3] = mask & 0x8 ? LLVMGetParam(main_fn, offset++) : base->undef;
return;
}
shader->selector->info.colors_read, interp_param,
LLVMGetParam(main_fn, SI_PARAM_PRIM_MASK),
LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE),
- &radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)]);
+ &out[0]);
}
-static LLVMValueRef get_sample_id(struct radeon_llvm_context *radeon_bld)
+static LLVMValueRef get_sample_id(struct si_shader_context *radeon_bld)
{
return unpack_param(si_shader_context(&radeon_bld->soa.bld_base),
SI_PARAM_ANCILLARY, 8, 4);
static LLVMValueRef get_thread_id(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMValueRef tid;
if (HAVE_LLVM < 0x0308) {
LLVMValueRef resource,
LLVMValueRef offset)
{
- LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
+ LLVMBuilderRef builder = ctx->gallivm.builder;
LLVMValueRef args[2] = {resource, offset};
return lp_build_intrinsic(builder, "llvm.SI.load.const", ctx->f32, args, 2,
LLVMReadNoneAttribute);
}
-static LLVMValueRef load_sample_position(struct radeon_llvm_context *radeon_bld, LLVMValueRef sample_id)
+static LLVMValueRef load_sample_position(struct si_shader_context *radeon_bld, LLVMValueRef sample_id)
{
struct si_shader_context *ctx =
si_shader_context(&radeon_bld->soa.bld_base);
struct lp_build_context *uint_bld = &radeon_bld->soa.bld_base.uint_bld;
struct gallivm_state *gallivm = &radeon_bld->gallivm;
LLVMBuilderRef builder = gallivm->builder;
- LLVMValueRef desc = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_RW_BUFFERS);
+ LLVMValueRef desc = LLVMGetParam(ctx->main_fn, SI_PARAM_RW_BUFFERS);
LLVMValueRef buf_index = lp_build_const_int32(gallivm, SI_PS_CONST_SAMPLE_POSITIONS);
LLVMValueRef resource = build_indexed_load_const(ctx, desc, buf_index);
}
static void declare_system_value(
- struct radeon_llvm_context *radeon_bld,
+ struct si_shader_context *radeon_bld,
unsigned index,
const struct tgsi_full_declaration *decl)
{
LLVMValueRef rw_buffers, buffer, base, addr;
int param = si_shader_io_get_unique_index(decl->Semantic.Name, 0);
- rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ rw_buffers = LLVMGetParam(ctx->main_fn,
SI_PARAM_RW_BUFFERS);
buffer = build_indexed_load_const(ctx, rw_buffers,
lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
- base = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ base = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
addr = get_tcs_tes_buffer_address(ctx, NULL,
lp_build_const_int32(gallivm, param));
int i, offset;
slot = lp_build_const_int32(gallivm, SI_HS_CONST_DEFAULT_TESS_LEVELS);
- buf = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_RW_BUFFERS);
+ buf = LLVMGetParam(ctx->main_fn, SI_PARAM_RW_BUFFERS);
buf = build_indexed_load_const(ctx, buf, slot);
offset = decl->Semantic.Name == TGSI_SEMANTIC_DEFAULT_TESSINNER_SI ? 4 : 0;
LLVMValueRef values[3];
unsigned i;
unsigned *properties = ctx->shader->selector->info.properties;
- unsigned sizes[3] = {
- properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH],
- properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT],
- properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH]
- };
- for (i = 0; i < 3; ++i)
- values[i] = lp_build_const_int32(gallivm, sizes[i]);
+ if (properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] != 0) {
+ unsigned sizes[3] = {
+ properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH],
+ properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT],
+ properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH]
+ };
+
+ for (i = 0; i < 3; ++i)
+ values[i] = lp_build_const_int32(gallivm, sizes[i]);
- value = lp_build_gather_values(gallivm, values, 3);
+ value = lp_build_gather_values(gallivm, values, 3);
+ } else {
+ value = LLVMGetParam(radeon_bld->main_fn, SI_PARAM_BLOCK_SIZE);
+ }
break;
}
radeon_bld->system_values[index] = value;
}
-static void declare_compute_memory(struct radeon_llvm_context *radeon_bld,
+static void declare_compute_memory(struct si_shader_context *radeon_bld,
const struct tgsi_full_declaration *decl)
{
struct si_shader_context *ctx =
ctx->shared_memory = LLVMBuildBitCast(gallivm->builder, var, i8p, "");
}
+static LLVMValueRef load_const_buffer_desc(struct si_shader_context *ctx, int i)
+{
+ LLVMValueRef list_ptr = LLVMGetParam(ctx->main_fn,
+ SI_PARAM_CONST_BUFFERS);
+
+ return build_indexed_load_const(ctx, list_ptr,
+ LLVMConstInt(ctx->i32, i, 0));
+}
+
static LLVMValueRef fetch_constant(
struct lp_build_tgsi_context *bld_base,
const struct tgsi_full_src_register *reg,
buf = reg->Register.Dimension ? reg->Dimension.Index : 0;
idx = reg->Register.Index * 4 + swizzle;
- if (!reg->Register.Indirect && !reg->Dimension.Indirect) {
- if (!tgsi_type_is_64bit(type))
- return bitcast(bld_base, type, ctx->constants[buf][idx]);
- else {
- return radeon_llvm_emit_fetch_64bit(bld_base, type,
- ctx->constants[buf][idx],
- ctx->constants[buf][idx + 1]);
- }
- }
-
if (reg->Register.Dimension && reg->Dimension.Indirect) {
- LLVMValueRef ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_CONST_BUFFERS);
+ LLVMValueRef ptr = LLVMGetParam(ctx->main_fn, SI_PARAM_CONST_BUFFERS);
LLVMValueRef index;
index = get_bounded_indirect_index(ctx, ®->DimIndirect,
reg->Dimension.Index,
SI_NUM_CONST_BUFFERS);
bufp = build_indexed_load_const(ctx, ptr, index);
} else
- bufp = ctx->const_buffers[buf];
-
- addr = ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle];
- addr = LLVMBuildLoad(base->gallivm->builder, addr, "load addr reg");
- addr = lp_build_mul_imm(&bld_base->uint_bld, addr, 16);
- addr = lp_build_add(&bld_base->uint_bld, addr,
- lp_build_const_int32(base->gallivm, idx * 4));
+ bufp = load_const_buffer_desc(ctx, buf);
+
+ if (reg->Register.Indirect) {
+ addr = ctx->soa.addr[ireg->Index][ireg->Swizzle];
+ addr = LLVMBuildLoad(base->gallivm->builder, addr, "load addr reg");
+ addr = lp_build_mul_imm(&bld_base->uint_bld, addr, 16);
+ addr = lp_build_add(&bld_base->uint_bld, addr,
+ lp_build_const_int32(base->gallivm, idx * 4));
+ } else {
+ addr = LLVMConstInt(ctx->i32, idx * 4, 0);
+ }
result = buffer_load_const(ctx, bufp, addr);
result = bitcast(bld_base, type, result);
else {
LLVMValueRef addr2, result2;
- addr2 = ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle + 1];
- addr2 = LLVMBuildLoad(base->gallivm->builder, addr2, "load addr reg2");
- addr2 = lp_build_mul_imm(&bld_base->uint_bld, addr2, 16);
- addr2 = lp_build_add(&bld_base->uint_bld, addr2,
- lp_build_const_int32(base->gallivm, idx * 4));
- result2 = buffer_load_const(ctx, ctx->const_buffers[buf],
- addr2);
+ addr2 = lp_build_add(&bld_base->uint_bld, addr,
+ LLVMConstInt(ctx->i32, 4, 0));
+ result2 = buffer_load_const(ctx, bufp, addr2);
- result = radeon_llvm_emit_fetch_64bit(bld_base, type,
- result, result2);
+ result = si_llvm_emit_fetch_64bit(bld_base, type,
+ result, result2);
}
return result;
}
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *uint =
- &ctx->radeon_bld.soa.bld_base.uint_bld;
+ &ctx->soa.bld_base.uint_bld;
struct lp_build_context *base = &bld_base->base;
struct gallivm_state *gallivm = base->gallivm;
LLVMBuilderRef builder = base->gallivm->builder;
case V_028714_SPI_SHADER_UNORM16_ABGR:
for (chan = 0; chan < 4; chan++) {
- val[chan] = radeon_llvm_saturate(bld_base, values[chan]);
+ val[chan] = si_llvm_saturate(bld_base, values[chan]);
val[chan] = LLVMBuildFMul(builder, val[chan],
lp_build_const_float(gallivm, 65535), "");
val[chan] = LLVMBuildFAdd(builder, val[chan],
struct gallivm_state *gallivm = bld_base->base.gallivm;
if (ctx->shader->key.ps.epilog.alpha_func != PIPE_FUNC_NEVER) {
- LLVMValueRef alpha_ref = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef alpha_ref = LLVMGetParam(ctx->main_fn,
SI_PARAM_ALPHA_REF);
LLVMValueRef alpha_pass =
LLVMValueRef coverage;
/* alpha = alpha * popcount(coverage) / SI_NUM_SMOOTH_AA_SAMPLES */
- coverage = LLVMGetParam(ctx->radeon_bld.main_fn,
+ coverage = LLVMGetParam(ctx->main_fn,
samplemask_param);
coverage = bitcast(bld_base, TGSI_TYPE_SIGNED, coverage);
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
- struct lp_build_context *uint = &ctx->radeon_bld.soa.bld_base.uint_bld;
+ struct lp_build_context *uint = &ctx->soa.bld_base.uint_bld;
unsigned reg_index;
unsigned chan;
unsigned const_chan;
LLVMValueRef base_elt;
- LLVMValueRef ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_RW_BUFFERS);
+ LLVMValueRef ptr = LLVMGetParam(ctx->main_fn, SI_PARAM_RW_BUFFERS);
LLVMValueRef constbuf_index = lp_build_const_int32(base->gallivm,
SI_VS_CONST_CLIP_PLANES);
LLVMValueRef const_resource = build_indexed_load_const(ctx, ptr, constbuf_index);
unsigned noutput)
{
struct pipe_stream_output_info *so = &ctx->shader->selector->so;
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
int i, j;
struct lp_build_if_state if_ctx;
+ LLVMValueRef so_buffers[4];
+ LLVMValueRef buf_ptr = LLVMGetParam(ctx->main_fn,
+ SI_PARAM_RW_BUFFERS);
+
+ /* Load the descriptors. */
+ for (i = 0; i < 4; ++i) {
+ if (ctx->shader->selector->so.stride[i]) {
+ LLVMValueRef offset = lp_build_const_int32(gallivm,
+ SI_VS_STREAMOUT_BUF0 + i);
+
+ so_buffers[i] = build_indexed_load_const(ctx, buf_ptr, offset);
+ }
+ }
/* Get bits [22:16], i.e. (so_param >> 16) & 127; */
LLVMValueRef so_vtx_count =
*/
LLVMValueRef so_write_index =
- LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMGetParam(ctx->main_fn,
ctx->param_streamout_write_index);
/* Compute (streamout_write_index + thread_id). */
if (!so->stride[i])
continue;
- LLVMValueRef so_offset = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef so_offset = LLVMGetParam(ctx->main_fn,
ctx->param_streamout_offset[i]);
so_offset = LLVMBuildMul(builder, so_offset, LLVMConstInt(ctx->i32, 4, 0), "");
lp_build_const_int32(gallivm, stream), "");
lp_build_if(&if_ctx_stream, gallivm, can_emit_stream);
- build_tbuffer_store_dwords(ctx, ctx->so_buffers[buf_idx],
+ build_tbuffer_store_dwords(ctx, so_buffers[buf_idx],
vdata, num_comps,
so_write_offset[buf_idx],
LLVMConstInt(ctx->i32, 0, 0),
struct si_shader *shader = ctx->shader;
struct lp_build_context *base = &bld_base->base;
struct lp_build_context *uint =
- &ctx->radeon_bld.soa.bld_base.uint_bld;
+ &ctx->soa.bld_base.uint_bld;
LLVMValueRef args[9];
LLVMValueRef pos_args[4][9] = { { 0 } };
LLVMValueRef psize_value = NULL, edgeflag_value = NULL, layer_value = NULL, viewport_index_value = NULL;
invocation_id = unpack_param(ctx, SI_PARAM_REL_IDS, 8, 5);
- rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_RW_BUFFERS);
+ rw_buffers = LLVMGetParam(ctx->main_fn, SI_PARAM_RW_BUFFERS);
buffer = build_indexed_load_const(ctx, rw_buffers,
lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
- buffer_offset = LLVMGetParam(ctx->radeon_bld.main_fn, ctx->param_oc_lds);
+ buffer_offset = LLVMGetParam(ctx->main_fn, ctx->param_oc_lds);
lds_vertex_stride = unpack_param(ctx, SI_PARAM_TCS_IN_LAYOUT, 13, 8);
lds_vertex_offset = LLVMBuildMul(gallivm->builder, invocation_id,
vec1 = lp_build_gather_values(gallivm, out+4, stride - 4);
/* Get the buffer. */
- rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ rw_buffers = LLVMGetParam(ctx->main_fn,
SI_PARAM_RW_BUFFERS);
buffer = build_indexed_load_const(ctx, rw_buffers,
lp_build_const_int32(gallivm, SI_HS_RING_TESS_FACTOR));
/* Get the offset. */
- tf_base = LLVMGetParam(ctx->radeon_bld.main_fn,
+ tf_base = LLVMGetParam(ctx->main_fn,
SI_PARAM_TESS_FACTOR_OFFSET);
byteoffset = LLVMBuildMul(gallivm->builder, rel_patch_id,
lp_build_const_int32(gallivm, 4 * stride), "");
invocation_id = unpack_param(ctx, SI_PARAM_REL_IDS, 8, 5);
tf_lds_offset = get_tcs_out_current_patch_data_offset(ctx);
- if (!ctx->is_monolithic) {
+ if (!ctx->no_epilog) {
/* Return epilog parameters from this function. */
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
LLVMValueRef ret = ctx->return_value;
unsigned vgpr;
/* RW_BUFFERS pointer */
- rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ rw_buffers = LLVMGetParam(ctx->main_fn,
SI_PARAM_RW_BUFFERS);
rw_buffers = LLVMBuildPtrToInt(builder, rw_buffers, ctx->i64, "");
rw_buffers = LLVMBuildBitCast(builder, rw_buffers, ctx->v2i32, "");
ret = LLVMBuildInsertValue(builder, ret, rw1, 1, "");
/* Tess factor buffer soffset is after user SGPRs. */
- tf_soffset = LLVMGetParam(ctx->radeon_bld.main_fn,
+ tf_soffset = LLVMGetParam(ctx->main_fn,
SI_PARAM_TESS_FACTOR_OFFSET);
ret = LLVMBuildInsertValue(builder, ret, tf_soffset,
SI_TCS_NUM_USER_SGPR + 1, "");
struct tgsi_shader_info *info = &shader->selector->info;
struct gallivm_state *gallivm = bld_base->base.gallivm;
unsigned i, chan;
- LLVMValueRef vertex_id = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef vertex_id = LLVMGetParam(ctx->main_fn,
ctx->param_rel_auto_id);
LLVMValueRef vertex_dw_stride =
unpack_param(ctx, SI_PARAM_LS_OUT_LAYOUT, 13, 8);
/* Write outputs to LDS. The next shader (TCS aka HS) will read
* its inputs from it. */
for (i = 0; i < info->num_outputs; i++) {
- LLVMValueRef *out_ptr = ctx->radeon_bld.soa.outputs[i];
+ LLVMValueRef *out_ptr = ctx->soa.outputs[i];
unsigned name = info->output_semantic_name[i];
unsigned index = info->output_semantic_index[i];
int param = si_shader_io_get_unique_index(name, index);
struct gallivm_state *gallivm = bld_base->base.gallivm;
struct si_shader *es = ctx->shader;
struct tgsi_shader_info *info = &es->selector->info;
- LLVMValueRef soffset = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef soffset = LLVMGetParam(ctx->main_fn,
ctx->param_es2gs_offset);
unsigned chan;
int i;
for (i = 0; i < info->num_outputs; i++) {
LLVMValueRef *out_ptr =
- ctx->radeon_bld.soa.outputs[i];
+ ctx->soa.outputs[i];
int param_index;
if (info->output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX ||
LLVMValueRef args[2];
args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_NOP | SENDMSG_GS_DONE);
- args[1] = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_GS_WAVE_ID);
+ args[1] = LLVMGetParam(ctx->main_fn, SI_PARAM_GS_WAVE_ID);
lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg",
ctx->voidt, args, 2, 0);
}
/* We've found a color. */
if (!cond) {
/* The state is in the first bit of the user SGPR. */
- cond = LLVMGetParam(ctx->radeon_bld.main_fn,
+ cond = LLVMGetParam(ctx->main_fn,
SI_PARAM_VS_STATE_BITS);
cond = LLVMBuildTrunc(gallivm->builder, cond,
ctx->i1, "");
}
for (j = 0; j < 4; j++) {
- addr = ctx->radeon_bld.soa.outputs[i][j];
+ addr = ctx->soa.outputs[i][j];
val = LLVMBuildLoad(gallivm->builder, addr, "");
- val = radeon_llvm_saturate(bld_base, val);
+ val = si_llvm_saturate(bld_base, val);
LLVMBuildStore(gallivm->builder, val, addr);
}
}
for (j = 0; j < 4; j++)
outputs[i].values[j] =
LLVMBuildLoad(gallivm->builder,
- ctx->radeon_bld.soa.outputs[i][j],
+ ctx->soa.outputs[i][j],
"");
}
- if (ctx->is_monolithic) {
+ if (ctx->no_epilog) {
/* Export PrimitiveID when PS needs it. */
if (si_vs_exports_prim_id(ctx->shader)) {
outputs[i].name = TGSI_SEMANTIC_PRIMID;
LLVMValueRef args[10][9];
};
+unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
+ bool writes_samplemask)
+{
+ if (writes_z) {
+ /* Z needs 32 bits. */
+ if (writes_samplemask)
+ return V_028710_SPI_SHADER_32_ABGR;
+ else if (writes_stencil)
+ return V_028710_SPI_SHADER_32_GR;
+ else
+ return V_028710_SPI_SHADER_32_R;
+ } else if (writes_stencil || writes_samplemask) {
+ /* Both stencil and sample mask need only 16 bits. */
+ return V_028710_SPI_SHADER_UINT16_ABGR;
+ } else {
+ return V_028710_SPI_SHADER_ZERO;
+ }
+}
+
static void si_export_mrt_z(struct lp_build_tgsi_context *bld_base,
LLVMValueRef depth, LLVMValueRef stencil,
LLVMValueRef samplemask, struct si_ps_exports *exp)
struct lp_build_context *uint = &bld_base->uint_bld;
LLVMValueRef args[9];
unsigned mask = 0;
+ unsigned format = si_get_spi_shader_z_format(depth != NULL,
+ stencil != NULL,
+ samplemask != NULL);
assert(depth || stencil || samplemask);
args[7] = base->undef; /* B, sample mask */
args[8] = base->undef; /* A, alpha to mask */
- if (depth) {
- args[5] = depth;
- mask |= 0x1;
- }
-
- if (stencil) {
- args[6] = stencil;
- mask |= 0x2;
- }
+ if (format == V_028710_SPI_SHADER_UINT16_ABGR) {
+ assert(!depth);
+ args[4] = uint->one; /* COMPR flag */
- if (samplemask) {
- args[7] = samplemask;
- mask |= 0x4;
+ 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);
+ mask |= 0x3;
+ }
+ if (samplemask) {
+ /* SampleMask should be in Y[15:0]. */
+ args[6] = samplemask;
+ mask |= 0xc;
+ }
+ } else {
+ if (depth) {
+ args[5] = depth;
+ mask |= 0x1;
+ }
+ if (stencil) {
+ args[6] = stencil;
+ mask |= 0x2;
+ }
+ if (samplemask) {
+ args[7] = samplemask;
+ mask |= 0x4;
+ }
}
/* SI (except OLAND) has a bug that it only looks
/* Clamp color */
if (ctx->shader->key.ps.epilog.clamp_color)
for (i = 0; i < 4; i++)
- color[i] = radeon_llvm_saturate(bld_base, color[i]);
+ color[i] = si_llvm_saturate(bld_base, color[i]);
/* Alpha to one */
if (ctx->shader->key.ps.epilog.alpha_to_one)
struct si_ps_exports *exp)
{
for (unsigned i = 0; i < exp->num; i++)
- lp_build_intrinsic(ctx->radeon_bld.gallivm.builder,
+ lp_build_intrinsic(ctx->gallivm.builder,
"llvm.SI.export", ctx->voidt,
exp->args[i], 9, 0);
}
switch (semantic_name) {
case TGSI_SEMANTIC_POSITION:
depth = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][2], "");
+ ctx->soa.outputs[i][2], "");
break;
case TGSI_SEMANTIC_STENCIL:
stencil = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][1], "");
+ ctx->soa.outputs[i][1], "");
break;
case TGSI_SEMANTIC_SAMPLEMASK:
samplemask = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][0], "");
+ ctx->soa.outputs[i][0], "");
break;
case TGSI_SEMANTIC_COLOR:
for (j = 0; j < 4; j++)
color[j] = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][j], "");
+ ctx->soa.outputs[i][j], "");
si_export_mrt_color(bld_base, color, semantic_index,
SI_PARAM_SAMPLE_COVERAGE,
case TGSI_SEMANTIC_COLOR:
assert(semantic_index < 8);
for (j = 0; j < 4; j++) {
- LLVMValueRef ptr = ctx->radeon_bld.soa.outputs[i][j];
+ LLVMValueRef ptr = ctx->soa.outputs[i][j];
LLVMValueRef result = LLVMBuildLoad(builder, ptr, "");
color[semantic_index][j] = result;
}
break;
case TGSI_SEMANTIC_POSITION:
depth = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][2], "");
+ ctx->soa.outputs[i][2], "");
break;
case TGSI_SEMANTIC_STENCIL:
stencil = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][1], "");
+ ctx->soa.outputs[i][1], "");
break;
case TGSI_SEMANTIC_SAMPLEMASK:
samplemask = LLVMBuildLoad(builder,
- ctx->radeon_bld.soa.outputs[i][0], "");
+ ctx->soa.outputs[i][0], "");
break;
default:
fprintf(stderr, "Warning: SI unhandled fs output type:%d\n",
/* Set SGPRs. */
ret = LLVMBuildInsertValue(builder, ret,
bitcast(bld_base, TGSI_TYPE_SIGNED,
- LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMGetParam(ctx->main_fn,
SI_PARAM_ALPHA_REF)),
SI_SGPR_ALPHA_REF, "");
if (vgpr < first_vgpr + PS_EPILOG_SAMPLEMASK_MIN_LOC)
vgpr = first_vgpr + PS_EPILOG_SAMPLEMASK_MIN_LOC;
ret = LLVMBuildInsertValue(builder, ret,
- LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMGetParam(ctx->main_fn,
SI_PARAM_SAMPLE_COVERAGE), vgpr++, "");
ctx->return_value = ret;
* Given the i32 or vNi32 \p type, generate the textual name (e.g. for use with
* intrinsic names).
*/
-static void build_int_type_name(
+static void build_type_name_for_intr(
LLVMTypeRef type,
char *buf, unsigned bufsize)
{
- assert(bufsize >= 6);
+ LLVMTypeRef elem_type = type;
- if (LLVMGetTypeKind(type) == LLVMVectorTypeKind)
- snprintf(buf, bufsize, "v%ui32",
- LLVMGetVectorSize(type));
- else
- strcpy(buf, "i32");
+ 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,
*/
static void emit_optimization_barrier(struct si_shader_context *ctx)
{
- LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
+ LLVMBuilderRef builder = ctx->gallivm.builder;
LLVMTypeRef ftype = LLVMFunctionType(ctx->voidt, NULL, 0, false);
LLVMValueRef inlineasm = LLVMConstInlineAsm(ftype, "", "", true, false);
LLVMBuildCall(builder, inlineasm, NULL, 0, "");
static void emit_waitcnt(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef args[1] = {
lp_build_const_int32(gallivm, 0xf70)
shader_buffer_fetch_rsrc(struct si_shader_context *ctx,
const struct tgsi_full_src_register *reg)
{
- LLVMValueRef ind_index;
- LLVMValueRef rsrc_ptr;
+ LLVMValueRef index;
+ LLVMValueRef rsrc_ptr = LLVMGetParam(ctx->main_fn,
+ SI_PARAM_SHADER_BUFFERS);
if (!reg->Register.Indirect)
- return ctx->shader_buffers[reg->Register.Index];
-
- ind_index = get_bounded_indirect_index(ctx, ®->Indirect,
- reg->Register.Index,
- SI_NUM_SHADER_BUFFERS);
+ index = LLVMConstInt(ctx->i32, reg->Register.Index, 0);
+ else
+ index = get_bounded_indirect_index(ctx, ®->Indirect,
+ reg->Register.Index,
+ SI_NUM_SHADER_BUFFERS);
- rsrc_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_SHADER_BUFFERS);
- return build_indexed_load_const(ctx, rsrc_ptr, ind_index);
+ return build_indexed_load_const(ctx, rsrc_ptr, index);
}
static bool tgsi_is_array_sampler(unsigned target)
if (ctx->screen->b.chip_class <= CIK) {
return rsrc;
} else {
- LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
+ LLVMBuilderRef builder = ctx->gallivm.builder;
LLVMValueRef i32_6 = LLVMConstInt(ctx->i32, 6, 0);
LLVMValueRef i32_C = LLVMConstInt(ctx->i32, C_008F28_COMPRESSION_EN, 0);
LLVMValueRef tmp;
LLVMValueRef *rsrc)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMValueRef rsrc_ptr = LLVMGetParam(ctx->main_fn,
+ SI_PARAM_IMAGES);
+ LLVMValueRef index, tmp;
assert(image->Register.File == TGSI_FILE_IMAGE);
if (!image->Register.Indirect) {
- /* Fast path: use preloaded resources */
- *rsrc = ctx->images[image->Register.Index];
- } else {
- /* Indexing and manual load */
- LLVMValueRef ind_index;
- LLVMValueRef rsrc_ptr;
- LLVMValueRef tmp;
+ const struct tgsi_shader_info *info = bld_base->info;
+ index = LLVMConstInt(ctx->i32, image->Register.Index, 0);
+
+ if (info->images_writemask & (1 << image->Register.Index) &&
+ !(info->images_buffers & (1 << image->Register.Index)))
+ dcc_off = true;
+ } else {
/* From the GL_ARB_shader_image_load_store extension spec:
*
* If a shader performs an image load, store, or atomic
* array, the results of the operation are undefined but may
* not lead to termination.
*/
- ind_index = get_bounded_indirect_index(ctx, &image->Indirect,
- image->Register.Index,
- SI_NUM_IMAGES);
-
- rsrc_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_IMAGES);
- tmp = build_indexed_load_const(ctx, rsrc_ptr, ind_index);
- if (dcc_off)
- tmp = force_dcc_off(ctx, tmp);
- *rsrc = tmp;
+ index = get_bounded_indirect_index(ctx, &image->Indirect,
+ image->Register.Index,
+ SI_NUM_IMAGES);
}
+
+ tmp = build_indexed_load_const(ctx, rsrc_ptr, index);
+ if (dcc_off)
+ tmp = force_dcc_off(ctx, tmp);
+ *rsrc = tmp;
}
static LLVMValueRef image_fetch_coords(
const struct tgsi_full_instruction *inst = emit_data->inst;
LLVMValueRef i1false = LLVMConstInt(ctx->i1, 0, 0);
LLVMValueRef i1true = LLVMConstInt(ctx->i1, 1, 0);
-
- emit_data->args[emit_data->arg_count++] = i1false; /* r128 */
- emit_data->args[emit_data->arg_count++] =
- tgsi_is_array_image(target) ? i1true : i1false; /* da */
- if (!atomic) {
- emit_data->args[emit_data->arg_count++] =
- inst->Memory.Qualifier & (TGSI_MEMORY_COHERENT | TGSI_MEMORY_VOLATILE) ?
- i1true : i1false; /* glc */
+ LLVMValueRef r128 = i1false;
+ LLVMValueRef da = tgsi_is_array_image(target) ? i1true : i1false;
+ LLVMValueRef glc =
+ inst->Memory.Qualifier & (TGSI_MEMORY_COHERENT | TGSI_MEMORY_VOLATILE) ?
+ i1true : i1false;
+ LLVMValueRef slc = i1false;
+ LLVMValueRef lwe = i1false;
+
+ if (atomic || (HAVE_LLVM <= 0x0309)) {
+ emit_data->args[emit_data->arg_count++] = r128;
+ emit_data->args[emit_data->arg_count++] = da;
+ if (!atomic) {
+ emit_data->args[emit_data->arg_count++] = glc;
+ }
+ emit_data->args[emit_data->arg_count++] = slc;
+ return;
}
- emit_data->args[emit_data->arg_count++] = i1false; /* slc */
+
+ /* HAVE_LLVM >= 0x0400 */
+ emit_data->args[emit_data->arg_count++] = glc;
+ emit_data->args[emit_data->arg_count++] = slc;
+ emit_data->args[emit_data->arg_count++] = lwe;
+ emit_data->args[emit_data->arg_count++] = da;
}
/**
struct si_shader_context *ctx,
LLVMValueRef rsrc)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
LLVMTypeRef v2i128 = LLVMVectorType(ctx->i128, 2);
rsrc = LLVMBuildBitCast(gallivm->builder, rsrc, v2i128, "");
struct lp_build_emit_data *emit_data)
{
const struct tgsi_full_instruction *inst = emit_data->inst;
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
uint writemask = inst->Dst[0].Register.WriteMask;
uint count = util_last_bit(writemask);
const struct tgsi_full_instruction *inst,
LLVMTypeRef type, int arg)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef offset, ptr;
int addr_space;
- offset = lp_build_emit_fetch(&ctx->radeon_bld.soa.bld_base, inst, arg, 0);
+ offset = lp_build_emit_fetch(&ctx->soa.bld_base, inst, arg, 0);
offset = LLVMBuildBitCast(builder, offset, ctx->i32, "");
ptr = ctx->shared_memory;
struct lp_build_emit_data *emit_data)
{
const struct tgsi_full_instruction *inst = emit_data->inst;
- struct lp_build_context *base = &ctx->radeon_bld.soa.bld_base.base;
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct lp_build_context *base = &ctx->soa.bld_base.base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
unsigned writemask = inst->Dst[0].Register.WriteMask;
LLVMValueRef channels[4], ptr, derived_ptr, index;
emit_data->output[emit_data->chan] = lp_build_gather_values(gallivm, channels, 4);
}
+static void get_image_intr_name(const char *base_name,
+ LLVMTypeRef data_type,
+ LLVMTypeRef coords_type,
+ LLVMTypeRef rsrc_type,
+ char *out_name, unsigned out_len)
+{
+ char coords_type_name[8];
+
+ build_type_name_for_intr(coords_type, coords_type_name,
+ sizeof(coords_type_name));
+
+ if (HAVE_LLVM <= 0x0309) {
+ snprintf(out_name, out_len, "%s.%s", base_name, coords_type_name);
+ } else {
+ char data_type_name[8];
+ char rsrc_type_name[8];
+
+ build_type_name_for_intr(data_type, data_type_name,
+ sizeof(data_type_name));
+ 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);
+ }
+}
+
static void load_emit(
const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = gallivm->builder;
const struct tgsi_full_instruction * inst = emit_data->inst;
- char intrinsic_name[32];
- char coords_type[8];
+ char intrinsic_name[64];
if (inst->Src[0].Register.File == TGSI_FILE_MEMORY) {
load_emit_memory(ctx, emit_data);
emit_data->args, emit_data->arg_count,
LLVMReadOnlyAttribute);
} else {
- build_int_type_name(LLVMTypeOf(emit_data->args[0]),
- coords_type, sizeof(coords_type));
-
- snprintf(intrinsic_name, sizeof(intrinsic_name),
- "llvm.amdgcn.image.load.%s", coords_type);
+ get_image_intr_name("llvm.amdgcn.image.load",
+ emit_data->dst_type, /* vdata */
+ LLVMTypeOf(emit_data->args[0]), /* coords */
+ LLVMTypeOf(emit_data->args[1]), /* rsrc */
+ intrinsic_name, sizeof(intrinsic_name));
emit_data->output[emit_data->chan] =
lp_build_intrinsic(
struct lp_build_emit_data *emit_data)
{
const struct tgsi_full_instruction *inst = emit_data->inst;
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
- struct lp_build_context *uint_bld = &ctx->radeon_bld.soa.bld_base.uint_bld;
+ struct lp_build_context *uint_bld = &ctx->soa.bld_base.uint_bld;
LLVMValueRef base_data = emit_data->args[0];
LLVMValueRef base_offset = emit_data->args[3];
unsigned writemask = inst->Dst[0].Register.WriteMask;
struct lp_build_emit_data *emit_data)
{
const struct tgsi_full_instruction *inst = emit_data->inst;
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- struct lp_build_context *base = &ctx->radeon_bld.soa.bld_base.base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_context *base = &ctx->soa.bld_base.base;
LLVMBuilderRef builder = gallivm->builder;
unsigned writemask = inst->Dst[0].Register.WriteMask;
LLVMValueRef ptr, derived_ptr, data, index;
if (!(writemask & (1 << chan))) {
continue;
}
- data = lp_build_emit_fetch(&ctx->radeon_bld.soa.bld_base, inst, 1, chan);
+ data = lp_build_emit_fetch(&ctx->soa.bld_base, inst, 1, chan);
index = lp_build_const_int32(gallivm, chan);
derived_ptr = LLVMBuildGEP(builder, ptr, &index, 1, "");
LLVMBuildStore(builder, data, derived_ptr);
LLVMBuilderRef builder = gallivm->builder;
const struct tgsi_full_instruction * inst = emit_data->inst;
unsigned target = inst->Memory.Texture;
- char intrinsic_name[32];
- char coords_type[8];
+ char intrinsic_name[64];
if (inst->Dst[0].Register.File == TGSI_FILE_MEMORY) {
store_emit_memory(ctx, emit_data);
emit_data->dst_type, emit_data->args,
emit_data->arg_count, 0);
} else {
- build_int_type_name(LLVMTypeOf(emit_data->args[1]),
- coords_type, sizeof(coords_type));
- snprintf(intrinsic_name, sizeof(intrinsic_name),
- "llvm.amdgcn.image.store.%s", coords_type);
+ get_image_intr_name("llvm.amdgcn.image.store",
+ LLVMTypeOf(emit_data->args[0]), /* vdata */
+ LLVMTypeOf(emit_data->args[1]), /* coords */
+ LLVMTypeOf(emit_data->args[2]), /* rsrc */
+ intrinsic_name, sizeof(intrinsic_name));
emit_data->output[emit_data->chan] =
lp_build_intrinsic(
static void atomic_emit_memory(struct si_shader_context *ctx,
struct lp_build_emit_data *emit_data) {
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
const struct tgsi_full_instruction * inst = emit_data->inst;
LLVMValueRef ptr, result, arg;
ptr = get_memory_ptr(ctx, inst, ctx->i32, 1);
- arg = lp_build_emit_fetch(&ctx->radeon_bld.soa.bld_base, inst, 2, 0);
+ arg = lp_build_emit_fetch(&ctx->soa.bld_base, inst, 2, 0);
arg = LLVMBuildBitCast(builder, arg, ctx->i32, "");
if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMCAS) {
LLVMValueRef new_data;
- new_data = lp_build_emit_fetch(&ctx->radeon_bld.soa.bld_base,
+ new_data = lp_build_emit_fetch(&ctx->soa.bld_base,
inst, 3, 0);
new_data = LLVMBuildBitCast(builder, new_data, ctx->i32, "");
snprintf(intrinsic_name, sizeof(intrinsic_name),
"llvm.amdgcn.buffer.atomic.%s", action->intr_name);
} else {
+ LLVMValueRef coords;
char coords_type[8];
- build_int_type_name(LLVMTypeOf(emit_data->args[1]),
- coords_type, sizeof(coords_type));
+ if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMCAS)
+ coords = emit_data->args[2];
+ else
+ coords = emit_data->args[1];
+
+ 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);
const struct tgsi_full_instruction *inst = emit_data->inst;
const struct tgsi_full_src_register *reg = &inst->Src[0];
- emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4);
+ emit_data->dst_type = ctx->v4i32;
if (reg->Register.File == TGSI_FILE_BUFFER) {
emit_data->args[0] = shader_buffer_fetch_rsrc(ctx, reg);
LLVMValueRef imm6 = lp_build_const_int32(gallivm, 6);
LLVMValueRef z = LLVMBuildExtractElement(builder, out, imm2, "");
- z = LLVMBuildBitCast(builder, z, bld_base->uint_bld.elem_type, "");
z = LLVMBuildSDiv(builder, z, imm6, "");
- z = LLVMBuildBitCast(builder, z, bld_base->base.elem_type, "");
out = LLVMBuildInsertElement(builder, out, z, imm2, "");
}
}
LLVMValueRef *param, unsigned count,
unsigned dmask)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
unsigned num_args;
unsigned is_rect = target == TGSI_TEXTURE_RECT;
/**
* Load an image view, fmask view. or sampler state descriptor.
*/
-static LLVMValueRef get_sampler_desc_custom(struct si_shader_context *ctx,
- LLVMValueRef list, LLVMValueRef index,
- enum desc_type type)
+static LLVMValueRef load_sampler_desc_custom(struct si_shader_context *ctx,
+ LLVMValueRef list, LLVMValueRef index,
+ enum desc_type type)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMBuilderRef builder = gallivm->builder;
switch (type) {
return build_indexed_load_const(ctx, list, index);
}
-static LLVMValueRef get_sampler_desc(struct si_shader_context *ctx,
+static LLVMValueRef load_sampler_desc(struct si_shader_context *ctx,
LLVMValueRef index, enum desc_type type)
{
- LLVMValueRef list = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef list = LLVMGetParam(ctx->main_fn,
SI_PARAM_SAMPLERS);
- return get_sampler_desc_custom(ctx, list, index, type);
+ return load_sampler_desc_custom(ctx, list, index, type);
}
/* Disable anisotropic filtering if BASE_LEVEL == LAST_LEVEL.
static LLVMValueRef sici_fix_sampler_aniso(struct si_shader_context *ctx,
LLVMValueRef res, LLVMValueRef samp)
{
- LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
+ LLVMBuilderRef builder = ctx->gallivm.builder;
LLVMValueRef img7, samp0;
if (ctx->screen->b.chip_class >= VI)
unsigned target = inst->Texture.Texture;
unsigned sampler_src;
unsigned sampler_index;
+ LLVMValueRef index;
sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
if (emit_data->inst->Src[sampler_src].Register.Indirect) {
const struct tgsi_full_src_register *reg = &emit_data->inst->Src[sampler_src];
- LLVMValueRef ind_index;
- ind_index = get_bounded_indirect_index(ctx,
- ®->Indirect,
- reg->Register.Index,
- SI_NUM_SAMPLERS);
+ index = get_bounded_indirect_index(ctx,
+ ®->Indirect,
+ reg->Register.Index,
+ SI_NUM_SAMPLERS);
+ } else {
+ index = LLVMConstInt(ctx->i32, sampler_index, 0);
+ }
- *res_ptr = get_sampler_desc(ctx, ind_index, DESC_IMAGE);
+ *res_ptr = load_sampler_desc(ctx, index, DESC_IMAGE);
- if (target == TGSI_TEXTURE_2D_MSAA ||
- target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
- if (samp_ptr)
- *samp_ptr = NULL;
- if (fmask_ptr)
- *fmask_ptr = get_sampler_desc(ctx, ind_index, DESC_FMASK);
- } else {
- if (samp_ptr) {
- *samp_ptr = get_sampler_desc(ctx, ind_index, DESC_SAMPLER);
- *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
- }
- if (fmask_ptr)
- *fmask_ptr = NULL;
- }
- } else {
- *res_ptr = ctx->sampler_views[sampler_index];
+ if (target == TGSI_TEXTURE_2D_MSAA ||
+ target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
if (samp_ptr)
- *samp_ptr = ctx->sampler_states[sampler_index];
+ *samp_ptr = NULL;
+ if (fmask_ptr)
+ *fmask_ptr = load_sampler_desc(ctx, index, DESC_FMASK);
+ } else {
+ if (samp_ptr) {
+ *samp_ptr = load_sampler_desc(ctx, index, DESC_SAMPLER);
+ *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
+ }
if (fmask_ptr)
- *fmask_ptr = ctx->fmasks[sampler_index];
+ *fmask_ptr = NULL;
}
}
/* Pack depth comparison value */
if (tgsi_is_shadow_target(target) && opcode != TGSI_OPCODE_LODQ) {
+ LLVMValueRef z;
+
if (target == TGSI_TEXTURE_SHADOWCUBE_ARRAY) {
- address[count++] = lp_build_emit_fetch(bld_base, inst, 1, TGSI_CHAN_X);
+ z = lp_build_emit_fetch(bld_base, inst, 1, TGSI_CHAN_X);
} else {
assert(ref_pos >= 0);
- address[count++] = coords[ref_pos];
+ z = coords[ref_pos];
}
+
+ /* TC-compatible HTILE promotes Z16 and Z24 to Z32_FLOAT,
+ * so the depth comparison value isn't clamped for Z16 and
+ * Z24 anymore. Do it manually here.
+ *
+ * It's unnecessary if the original texture format was
+ * Z32_FLOAT, but we don't know that here.
+ */
+ if (ctx->screen->b.chip_class == VI)
+ z = si_llvm_saturate(bld_base, z);
+
+ address[count++] = z;
}
/* Pack user derivatives */
target == TGSI_TEXTURE_CUBE_ARRAY ||
target == TGSI_TEXTURE_SHADOWCUBE ||
target == TGSI_TEXTURE_SHADOWCUBE_ARRAY)
- radeon_llvm_emit_prepare_cube_coords(bld_base, emit_data, coords, derivs);
+ si_prepare_cube_coords(bld_base, emit_data, coords, derivs);
if (opcode == TGSI_OPCODE_TXD)
for (int i = 0; i < num_deriv_channels * 2; i++)
samp_ptr, address, count, dmask);
}
+/* Gather4 should follow the same rules as bilinear filtering, but the hardware
+ * incorrectly forces nearest filtering if the texture format is integer.
+ * The only effect it has on Gather4, which always returns 4 texels for
+ * bilinear filtering, is that the final coordinates are off by 0.5 of
+ * the texel size.
+ *
+ * The workaround is to subtract 0.5 from the unnormalized coordinates,
+ * or (0.5 / size) from the normalized coordinates.
+ */
+static void si_lower_gather4_integer(struct si_shader_context *ctx,
+ struct lp_build_emit_data *emit_data,
+ const char *intr_name,
+ unsigned coord_vgpr_index)
+{
+ LLVMBuilderRef builder = ctx->gallivm.builder;
+ LLVMValueRef coord = emit_data->args[0];
+ LLVMValueRef half_texel[2];
+ int c;
+
+ if (emit_data->inst->Texture.Texture == TGSI_TEXTURE_RECT ||
+ emit_data->inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT) {
+ half_texel[0] = half_texel[1] = LLVMConstReal(ctx->f32, -0.5);
+ } else {
+ struct tgsi_full_instruction txq_inst = {};
+ struct lp_build_emit_data txq_emit_data = {};
+
+ /* Query the texture size. */
+ txq_inst.Texture.Texture = emit_data->inst->Texture.Texture;
+ txq_emit_data.inst = &txq_inst;
+ txq_emit_data.dst_type = ctx->v4i32;
+ set_tex_fetch_args(ctx, &txq_emit_data, TGSI_OPCODE_TXQ,
+ txq_inst.Texture.Texture,
+ emit_data->args[1], NULL,
+ &ctx->soa.bld_base.uint_bld.zero,
+ 1, 0xf);
+ txq_emit(NULL, &ctx->soa.bld_base, &txq_emit_data);
+
+ /* Compute -0.5 / size. */
+ for (c = 0; c < 2; c++) {
+ half_texel[c] =
+ LLVMBuildExtractElement(builder, txq_emit_data.output[0],
+ LLVMConstInt(ctx->i32, c, 0), "");
+ half_texel[c] = LLVMBuildUIToFP(builder, half_texel[c], ctx->f32, "");
+ half_texel[c] =
+ lp_build_emit_llvm_unary(&ctx->soa.bld_base,
+ TGSI_OPCODE_RCP, half_texel[c]);
+ half_texel[c] = LLVMBuildFMul(builder, half_texel[c],
+ LLVMConstReal(ctx->f32, -0.5), "");
+ }
+ }
+
+ for (c = 0; c < 2; c++) {
+ LLVMValueRef tmp;
+ LLVMValueRef index = LLVMConstInt(ctx->i32, coord_vgpr_index + c, 0);
+
+ tmp = LLVMBuildExtractElement(builder, coord, index, "");
+ tmp = LLVMBuildBitCast(builder, tmp, ctx->f32, "");
+ tmp = LLVMBuildFAdd(builder, tmp, half_texel[c], "");
+ tmp = LLVMBuildBitCast(builder, tmp, ctx->i32, "");
+ coord = LLVMBuildInsertElement(builder, coord, tmp, index, "");
+ }
+
+ emit_data->args[0] = coord;
+ emit_data->output[emit_data->chan] =
+ lp_build_intrinsic(builder, intr_name, emit_data->dst_type,
+ emit_data->args, emit_data->arg_count,
+ LLVMReadNoneAttribute);
+}
+
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)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
- unsigned opcode = emit_data->inst->Instruction.Opcode;
- unsigned target = emit_data->inst->Texture.Texture;
+ const struct tgsi_full_instruction *inst = emit_data->inst;
+ unsigned opcode = inst->Instruction.Opcode;
+ unsigned target = inst->Texture.Texture;
char intr_name[127];
- bool has_offset = emit_data->inst->Texture.NumOffsets > 0;
+ bool has_offset = inst->Texture.NumOffsets > 0;
bool is_shadow = tgsi_is_shadow_target(target);
char type[64];
const char *name = "llvm.SI.image.sample";
}
/* Add the type and suffixes .c, .o if needed. */
- build_int_type_name(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
+ 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);
+ /* The hardware needs special lowering for Gather4 with integer formats. */
+ if (opcode == TGSI_OPCODE_TG4) {
+ struct tgsi_shader_info *info = &ctx->shader->selector->info;
+ /* This will also work with non-constant indexing because of how
+ * glsl_to_tgsi works and we intent to preserve that behavior.
+ */
+ const unsigned src_idx = 2;
+ unsigned sampler = inst->Src[src_idx].Register.Index;
+
+ assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER);
+
+ if (info->sampler_type[sampler] == TGSI_RETURN_TYPE_SINT ||
+ info->sampler_type[sampler] == TGSI_RETURN_TYPE_UINT) {
+ /* Texture coordinates start after:
+ * {offset, bias, z-compare, derivatives}
+ * Only the offset and z-compare can occur here.
+ */
+ si_lower_gather4_integer(ctx, emit_data, intr_name,
+ (int)has_offset + (int)is_shadow);
+ return;
+ }
+ }
+
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,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
- const struct tgsi_full_instruction *inst = emit_data->inst;
- unsigned opcode = inst->Instruction.Opcode;
- LLVMValueRef indices[2];
- LLVMValueRef store_ptr, load_ptr0, load_ptr1;
- LLVMValueRef tl, trbl, result[4];
- LLVMValueRef tl_tid, trbl_tid;
- unsigned swizzle[4];
- unsigned c;
+ unsigned opcode = emit_data->info->opcode;
+ LLVMValueRef thread_id, tl, trbl, tl_tid, trbl_tid, val, args[2];
int idx;
unsigned mask;
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = get_thread_id(ctx);
- store_ptr = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
+ thread_id = get_thread_id(ctx);
if (opcode == TGSI_OPCODE_DDX_FINE)
mask = TID_MASK_LEFT;
else
mask = TID_MASK_TOP_LEFT;
- tl_tid = LLVMBuildAnd(gallivm->builder, indices[1],
+ tl_tid = LLVMBuildAnd(gallivm->builder, thread_id,
lp_build_const_int32(gallivm, mask), "");
- indices[1] = tl_tid;
- load_ptr0 = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
/* for DDX we want to next X pixel, DDY next Y pixel. */
idx = (opcode == TGSI_OPCODE_DDX || opcode == TGSI_OPCODE_DDX_FINE) ? 1 : 2;
- trbl_tid = LLVMBuildAdd(gallivm->builder, indices[1],
+ trbl_tid = LLVMBuildAdd(gallivm->builder, tl_tid,
lp_build_const_int32(gallivm, idx), "");
- indices[1] = trbl_tid;
- load_ptr1 = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- for (c = 0; c < 4; ++c) {
- unsigned i;
- LLVMValueRef val;
- LLVMValueRef args[2];
-
- swizzle[c] = tgsi_util_get_full_src_register_swizzle(&inst->Src[0], c);
- for (i = 0; i < c; ++i) {
- if (swizzle[i] == swizzle[c]) {
- result[c] = result[i];
- break;
- }
- }
- if (i != c)
- continue;
-
- val = LLVMBuildBitCast(gallivm->builder,
- lp_build_emit_fetch(bld_base, inst, 0, c),
- ctx->i32, "");
- if ((HAVE_LLVM >= 0x0309) && ctx->screen->b.family >= CHIP_TONGA) {
+ val = LLVMBuildBitCast(gallivm->builder, emit_data->args[0], ctx->i32, "");
- args[0] = LLVMBuildMul(gallivm->builder, tl_tid,
- lp_build_const_int32(gallivm, 4), "");
- args[1] = val;
- tl = lp_build_intrinsic(gallivm->builder,
+ if (ctx->screen->has_ds_bpermute) {
+ args[0] = LLVMBuildMul(gallivm->builder, tl_tid,
+ lp_build_const_int32(gallivm, 4), "");
+ args[1] = val;
+ tl = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.ds.bpermute", ctx->i32,
args, 2, LLVMReadNoneAttribute);
- args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
- lp_build_const_int32(gallivm, 4), "");
- trbl = lp_build_intrinsic(gallivm->builder,
- "llvm.amdgcn.ds.bpermute", ctx->i32,
- args, 2, LLVMReadNoneAttribute);
- } else {
- LLVMBuildStore(gallivm->builder, val, store_ptr);
- tl = LLVMBuildLoad(gallivm->builder, load_ptr0, "");
- trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
- }
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
- trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
- result[c] = LLVMBuildFSub(gallivm->builder, trbl, tl, "");
+ args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
+ lp_build_const_int32(gallivm, 4), "");
+ trbl = lp_build_intrinsic(gallivm->builder,
+ "llvm.amdgcn.ds.bpermute", ctx->i32,
+ args, 2, LLVMReadNoneAttribute);
+ } else {
+ LLVMValueRef store_ptr, load_ptr0, load_ptr1;
+
+ store_ptr = build_gep0(ctx, ctx->lds, thread_id);
+ load_ptr0 = build_gep0(ctx, ctx->lds, tl_tid);
+ load_ptr1 = build_gep0(ctx, ctx->lds, trbl_tid);
+
+ LLVMBuildStore(gallivm->builder, val, store_ptr);
+ tl = LLVMBuildLoad(gallivm->builder, load_ptr0, "");
+ trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
}
- emit_data->output[0] = lp_build_gather_values(gallivm, result, 4);
+ tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
+ trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
+
+ emit_data->output[emit_data->chan] =
+ LLVMBuildFSub(gallivm->builder, trbl, tl, "");
}
/*
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef indices[2];
- LLVMValueRef store_ptr, load_ptr_x, load_ptr_y, load_ptr_ddx, load_ptr_ddy, temp, temp2;
- LLVMValueRef tl, tr, bl, result[4];
- unsigned c;
-
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = get_thread_id(ctx);
- store_ptr = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- temp = LLVMBuildAnd(gallivm->builder, indices[1],
- lp_build_const_int32(gallivm, TID_MASK_LEFT), "");
-
- temp2 = LLVMBuildAnd(gallivm->builder, indices[1],
- lp_build_const_int32(gallivm, TID_MASK_TOP), "");
-
- indices[1] = temp;
- load_ptr_x = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- indices[1] = temp2;
- load_ptr_y = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- indices[1] = LLVMBuildAdd(gallivm->builder, temp,
- lp_build_const_int32(gallivm, 1), "");
- load_ptr_ddx = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- indices[1] = LLVMBuildAdd(gallivm->builder, temp2,
- lp_build_const_int32(gallivm, 2), "");
- load_ptr_ddy = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- for (c = 0; c < 2; ++c) {
- LLVMValueRef store_val;
- LLVMValueRef c_ll = lp_build_const_int32(gallivm, c);
-
- store_val = LLVMBuildExtractElement(gallivm->builder,
- interp_ij, c_ll, "");
- LLVMBuildStore(gallivm->builder,
- store_val,
- store_ptr);
-
- tl = LLVMBuildLoad(gallivm->builder, load_ptr_x, "");
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
- tr = LLVMBuildLoad(gallivm->builder, load_ptr_ddx, "");
- tr = LLVMBuildBitCast(gallivm->builder, tr, ctx->f32, "");
-
- result[c] = LLVMBuildFSub(gallivm->builder, tr, tl, "");
-
- tl = LLVMBuildLoad(gallivm->builder, load_ptr_y, "");
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
- bl = LLVMBuildLoad(gallivm->builder, load_ptr_ddy, "");
- bl = LLVMBuildBitCast(gallivm->builder, bl, ctx->f32, "");
+ LLVMValueRef result[4], a;
+ unsigned i;
- result[c + 2] = LLVMBuildFSub(gallivm->builder, bl, tl, "");
+ for (i = 0; i < 2; i++) {
+ a = LLVMBuildExtractElement(gallivm->builder, interp_ij,
+ LLVMConstInt(ctx->i32, i, 0), "");
+ result[i] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_DDX, a);
+ result[2+i] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_DDY, a);
}
return lp_build_gather_values(gallivm, result, 4);
emit_data->inst, 1, TGSI_CHAN_X);
sample_id = LLVMBuildBitCast(gallivm->builder, sample_id,
ctx->i32, "");
- sample_position = load_sample_position(&ctx->radeon_bld, sample_id);
+ sample_position = load_sample_position(ctx, sample_id);
emit_data->args[0] = LLVMBuildExtractElement(gallivm->builder,
sample_position,
int chan;
int i;
LLVMValueRef attr_number;
- LLVMValueRef params = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_PRIM_MASK);
+ LLVMValueRef params = LLVMGetParam(ctx->main_fn, SI_PARAM_PRIM_MASK);
int interp_param_idx;
unsigned interp = shader->selector->info.input_interpolate[input_index];
unsigned location;
}
intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant";
- for (chan = 0; chan < 2; chan++) {
+ for (chan = 0; chan < 4; chan++) {
LLVMValueRef args[4];
LLVMValueRef llvm_chan;
unsigned schan;
struct si_shader *shader = ctx->shader;
struct tgsi_shader_info *info = &shader->selector->info;
struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef soffset = LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMValueRef soffset = LLVMGetParam(ctx->main_fn,
SI_PARAM_GS2VS_OFFSET);
LLVMValueRef gs_next_vertex;
LLVMValueRef can_emit, kill;
for (i = 0; i < info->num_outputs; i++) {
LLVMValueRef *out_ptr =
- ctx->radeon_bld.soa.outputs[i];
+ ctx->soa.outputs[i];
for (chan = 0; chan < 4; chan++) {
LLVMValueRef out_val = LLVMBuildLoad(gallivm->builder, out_ptr[chan], "");
/* Signal vertex emission */
args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_EMIT | SENDMSG_GS | (stream << 8));
- args[1] = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_GS_WAVE_ID);
+ args[1] = LLVMGetParam(ctx->main_fn, SI_PARAM_GS_WAVE_ID);
lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg",
ctx->voidt, args, 2, 0);
}
/* Signal primitive cut */
stream = si_llvm_get_stream(bld_base, emit_data);
args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_CUT | SENDMSG_GS | (stream << 8));
- args[1] = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_GS_WAVE_ID);
+ args[1] = LLVMGetParam(ctx->main_fn, SI_PARAM_GS_WAVE_ID);
lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg",
ctx->voidt, args, 2, 0);
}
};
static void si_create_function(struct si_shader_context *ctx,
+ const char *name,
LLVMTypeRef *returns, unsigned num_returns,
LLVMTypeRef *params, unsigned num_params,
int last_sgpr)
{
int i;
- radeon_llvm_create_func(&ctx->radeon_bld, returns, num_returns,
- params, num_params);
- radeon_llvm_shader_type(ctx->radeon_bld.main_fn, ctx->type);
- ctx->return_value = LLVMGetUndef(ctx->radeon_bld.return_type);
+ si_llvm_create_func(ctx, name, returns, num_returns,
+ params, num_params);
+ si_llvm_shader_type(ctx->main_fn, ctx->type);
+ ctx->return_value = LLVMGetUndef(ctx->return_type);
for (i = 0; i <= last_sgpr; ++i) {
- LLVMValueRef P = LLVMGetParam(ctx->radeon_bld.main_fn, i);
+ LLVMValueRef P = LLVMGetParam(ctx->main_fn, i);
/* The combination of:
* - ByVal
if (ctx->screen->b.debug_flags & DBG_UNSAFE_MATH) {
/* These were copied from some LLVM test. */
- LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ LLVMAddTargetDependentFunctionAttr(ctx->main_fn,
"less-precise-fpmad",
"true");
- LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ LLVMAddTargetDependentFunctionAttr(ctx->main_fn,
"no-infs-fp-math",
"true");
- LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ LLVMAddTargetDependentFunctionAttr(ctx->main_fn,
"no-nans-fp-math",
"true");
- LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ LLVMAddTargetDependentFunctionAttr(ctx->main_fn,
"unsafe-fp-math",
"true");
}
static void create_meta_data(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = ctx->radeon_bld.soa.bld_base.base.gallivm;
+ struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
ctx->invariant_load_md_kind = LLVMGetMDKindIDInContext(gallivm->context,
"invariant.load", 14);
static void declare_tess_lds(struct si_shader_context *ctx)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
struct lp_build_context *uint = &bld_base->uint_bld;
unsigned lds_size = ctx->screen->b.chip_class >= CIK ? 65536 : 32768;
static void create_function(struct si_shader_context *ctx)
{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
struct gallivm_state *gallivm = bld_base->base.gallivm;
struct si_shader *shader = ctx->shader;
LLVMTypeRef params[SI_NUM_PARAMS + SI_NUM_VERTEX_BUFFERS], v3i32;
LLVMTypeRef returns[16+32*4];
unsigned i, last_sgpr, num_params, num_return_sgprs;
unsigned num_returns = 0;
+ unsigned num_prolog_vgprs = 0;
v3i32 = LLVMVectorType(ctx->i32, 3);
params[ctx->param_vs_prim_id = num_params++] = ctx->i32;
params[ctx->param_instance_id = num_params++] = ctx->i32;
- if (!ctx->is_monolithic &&
+ if (!ctx->no_prolog &&
!ctx->is_gs_copy_shader) {
/* Vertex load indices. */
ctx->param_vertex_index0 = num_params;
for (i = 0; i < shader->selector->info.num_inputs; i++)
params[num_params++] = ctx->i32;
+ num_prolog_vgprs += shader->selector->info.num_inputs;
+ }
+
+ if (!ctx->no_epilog &&
+ !ctx->is_gs_copy_shader) {
/* PrimitiveID output. */
if (!shader->key.vs.as_es && !shader->key.vs.as_ls)
for (i = 0; i <= VS_EPILOG_PRIMID_LOC; i++)
params[SI_PARAM_REL_IDS] = ctx->i32;
num_params = SI_PARAM_REL_IDS+1;
- if (!ctx->is_monolithic) {
+ if (!ctx->no_epilog) {
/* SI_PARAM_TCS_OC_LDS and PARAM_TESS_FACTOR_OFFSET are
* placed after the user SGPRs.
*/
params[ctx->param_tes_patch_id = num_params++] = ctx->i32;
/* PrimitiveID output. */
- if (!ctx->is_monolithic && !shader->key.tes.as_es)
+ if (!ctx->no_epilog && !shader->key.tes.as_es)
for (i = 0; i <= VS_EPILOG_PRIMID_LOC; i++)
returns[num_returns++] = ctx->f32;
break;
params[SI_PARAM_POS_Z_FLOAT] = ctx->f32;
params[SI_PARAM_POS_W_FLOAT] = ctx->f32;
params[SI_PARAM_FRONT_FACE] = ctx->i32;
+ shader->info.face_vgpr_index = 20;
params[SI_PARAM_ANCILLARY] = ctx->i32;
params[SI_PARAM_SAMPLE_COVERAGE] = ctx->f32;
params[SI_PARAM_POS_FIXED_PT] = ctx->i32;
num_params = SI_PARAM_POS_FIXED_PT+1;
- if (!ctx->is_monolithic) {
+ if (!ctx->no_prolog) {
/* Color inputs from the prolog. */
if (shader->selector->info.colors_read) {
unsigned num_color_elements =
assert(num_params + num_color_elements <= ARRAY_SIZE(params));
for (i = 0; i < num_color_elements; i++)
params[num_params++] = ctx->f32;
+
+ num_prolog_vgprs += num_color_elements;
}
+ }
+ if (!ctx->no_epilog) {
/* Outputs for the epilog. */
num_return_sgprs = SI_SGPR_ALPHA_REF + 1;
num_returns =
case PIPE_SHADER_COMPUTE:
params[SI_PARAM_GRID_SIZE] = v3i32;
+ params[SI_PARAM_BLOCK_SIZE] = v3i32;
params[SI_PARAM_BLOCK_ID] = v3i32;
last_sgpr = SI_PARAM_BLOCK_ID;
assert(num_params <= ARRAY_SIZE(params));
- si_create_function(ctx, returns, num_returns, params,
+ si_create_function(ctx, "main", returns, num_returns, params,
num_params, last_sgpr);
/* Reserve register locations for VGPR inputs the PS prolog may need. */
if (ctx->type == PIPE_SHADER_FRAGMENT &&
- !ctx->is_monolithic) {
- radeon_llvm_add_attribute(ctx->radeon_bld.main_fn,
- "InitialPSInputAddr",
- S_0286D0_PERSP_SAMPLE_ENA(1) |
- S_0286D0_PERSP_CENTER_ENA(1) |
- S_0286D0_PERSP_CENTROID_ENA(1) |
- S_0286D0_LINEAR_SAMPLE_ENA(1) |
- S_0286D0_LINEAR_CENTER_ENA(1) |
- S_0286D0_LINEAR_CENTROID_ENA(1) |
- S_0286D0_FRONT_FACE_ENA(1) |
- S_0286D0_POS_FIXED_PT_ENA(1));
+ ctx->separate_prolog) {
+ si_llvm_add_attribute(ctx->main_fn,
+ "InitialPSInputAddr",
+ S_0286D0_PERSP_SAMPLE_ENA(1) |
+ S_0286D0_PERSP_CENTER_ENA(1) |
+ S_0286D0_PERSP_CENTROID_ENA(1) |
+ S_0286D0_LINEAR_SAMPLE_ENA(1) |
+ S_0286D0_LINEAR_CENTER_ENA(1) |
+ S_0286D0_LINEAR_CENTROID_ENA(1) |
+ S_0286D0_FRONT_FACE_ENA(1) |
+ S_0286D0_POS_FIXED_PT_ENA(1));
} else if (ctx->type == PIPE_SHADER_COMPUTE) {
const unsigned *properties = shader->selector->info.properties;
unsigned max_work_group_size =
properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH];
- assert(max_work_group_size);
+ if (!max_work_group_size) {
+ /* This is a variable group size compute shader,
+ * compile it for the maximum possible group size.
+ */
+ max_work_group_size = SI_MAX_VARIABLE_THREADS_PER_BLOCK;
+ }
- radeon_llvm_add_attribute(ctx->radeon_bld.main_fn,
- "amdgpu-max-work-group-size",
- max_work_group_size);
+ si_llvm_add_attribute(ctx->main_fn,
+ "amdgpu-max-work-group-size",
+ max_work_group_size);
}
shader->info.num_input_sgprs = 0;
for (i = 0; i <= last_sgpr; ++i)
shader->info.num_input_sgprs += llvm_get_type_size(params[i]) / 4;
- /* Unused fragment shader inputs are eliminated by the compiler,
- * so we don't know yet how many there will be.
- */
- if (ctx->type != PIPE_SHADER_FRAGMENT)
- for (; i < num_params; ++i)
- shader->info.num_input_vgprs += llvm_get_type_size(params[i]) / 4;
+ for (; i < num_params; ++i)
+ shader->info.num_input_vgprs += llvm_get_type_size(params[i]) / 4;
+
+ assert(shader->info.num_input_vgprs >= num_prolog_vgprs);
+ shader->info.num_input_vgprs -= num_prolog_vgprs;
- if (bld_base->info &&
+ if (!ctx->screen->has_ds_bpermute &&
+ bld_base->info &&
(bld_base->info->opcode_count[TGSI_OPCODE_DDX] > 0 ||
bld_base->info->opcode_count[TGSI_OPCODE_DDY] > 0 ||
bld_base->info->opcode_count[TGSI_OPCODE_DDX_FINE] > 0 ||
declare_tess_lds(ctx);
}
-static void preload_constants(struct si_shader_context *ctx)
+/**
+ * Load ESGS and GSVS ring buffer resource descriptors and save the variables
+ * for later use.
+ */
+static void preload_ring_buffers(struct si_shader_context *ctx)
{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- const struct tgsi_shader_info *info = bld_base->info;
- unsigned buf;
- LLVMValueRef ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_CONST_BUFFERS);
-
- for (buf = 0; buf < SI_NUM_CONST_BUFFERS; buf++) {
- unsigned i, num_const = info->const_file_max[buf] + 1;
-
- if (num_const == 0)
- continue;
+ struct gallivm_state *gallivm =
+ ctx->soa.bld_base.base.gallivm;
- /* Allocate space for the constant values */
- ctx->constants[buf] = CALLOC(num_const * 4, sizeof(LLVMValueRef));
+ LLVMValueRef buf_ptr = LLVMGetParam(ctx->main_fn,
+ SI_PARAM_RW_BUFFERS);
- /* Load the resource descriptor */
- ctx->const_buffers[buf] =
- build_indexed_load_const(ctx, ptr, lp_build_const_int32(gallivm, buf));
+ if ((ctx->type == PIPE_SHADER_VERTEX &&
+ ctx->shader->key.vs.as_es) ||
+ (ctx->type == PIPE_SHADER_TESS_EVAL &&
+ ctx->shader->key.tes.as_es) ||
+ ctx->type == PIPE_SHADER_GEOMETRY) {
+ unsigned ring =
+ ctx->type == PIPE_SHADER_GEOMETRY ? SI_GS_RING_ESGS
+ : SI_ES_RING_ESGS;
+ LLVMValueRef offset = lp_build_const_int32(gallivm, ring);
- /* Load the constants, we rely on the code sinking to do the rest */
- for (i = 0; i < num_const * 4; ++i) {
- ctx->constants[buf][i] =
- buffer_load_const(ctx,
- ctx->const_buffers[buf],
- lp_build_const_int32(gallivm, i * 4));
- }
+ ctx->esgs_ring =
+ build_indexed_load_const(ctx, buf_ptr, offset);
}
-}
-static void preload_shader_buffers(struct si_shader_context *ctx)
-{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- LLVMValueRef ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_SHADER_BUFFERS);
- int buf, maxbuf;
+ if (ctx->is_gs_copy_shader) {
+ LLVMValueRef offset = lp_build_const_int32(gallivm, SI_VS_RING_GSVS);
- maxbuf = MIN2(ctx->shader->selector->info.file_max[TGSI_FILE_BUFFER],
- SI_NUM_SHADER_BUFFERS - 1);
- for (buf = 0; buf <= maxbuf; ++buf) {
- ctx->shader_buffers[buf] =
- build_indexed_load_const(
- ctx, ptr, lp_build_const_int32(gallivm, buf));
+ ctx->gsvs_ring[0] =
+ build_indexed_load_const(ctx, buf_ptr, offset);
}
-}
-
-static void preload_samplers(struct si_shader_context *ctx)
-{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- const struct tgsi_shader_info *info = bld_base->info;
- unsigned i, num_samplers = info->file_max[TGSI_FILE_SAMPLER] + 1;
- LLVMValueRef offset;
-
- if (num_samplers == 0)
- return;
+ if (ctx->type == PIPE_SHADER_GEOMETRY) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ LLVMValueRef offset = lp_build_const_int32(gallivm, SI_GS_RING_GSVS0 + i);
- /* Load the resources and samplers, we rely on the code sinking to do the rest */
- for (i = 0; i < num_samplers; ++i) {
- /* Resource */
- offset = lp_build_const_int32(gallivm, i);
- ctx->sampler_views[i] =
- get_sampler_desc(ctx, offset, DESC_IMAGE);
-
- /* FMASK resource */
- if (info->is_msaa_sampler[i])
- ctx->fmasks[i] =
- get_sampler_desc(ctx, offset, DESC_FMASK);
- else {
- ctx->sampler_states[i] =
- get_sampler_desc(ctx, offset, DESC_SAMPLER);
- ctx->sampler_states[i] =
- sici_fix_sampler_aniso(ctx, ctx->sampler_views[i],
- ctx->sampler_states[i]);
+ ctx->gsvs_ring[i] =
+ build_indexed_load_const(ctx, buf_ptr, offset);
}
}
}
-static void preload_images(struct si_shader_context *ctx)
+static void si_llvm_emit_polygon_stipple(struct si_shader_context *ctx,
+ LLVMValueRef param_rw_buffers,
+ unsigned param_pos_fixed_pt)
{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
- struct tgsi_shader_info *info = &ctx->shader->selector->info;
+ struct lp_build_tgsi_context *bld_base =
+ &ctx->soa.bld_base;
struct gallivm_state *gallivm = bld_base->base.gallivm;
- unsigned num_images = bld_base->info->file_max[TGSI_FILE_IMAGE] + 1;
- LLVMValueRef res_ptr;
- unsigned i;
-
- if (num_images == 0)
- return;
-
- res_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_IMAGES);
-
- for (i = 0; i < num_images; ++i) {
- /* Rely on LLVM to shrink the load for buffer resources. */
- LLVMValueRef rsrc =
- build_indexed_load_const(ctx, res_ptr,
- lp_build_const_int32(gallivm, i));
-
- if (info->images_writemask & (1 << i) &&
- !(info->images_buffers & (1 << i)))
- rsrc = force_dcc_off(ctx, rsrc);
-
- ctx->images[i] = rsrc;
- }
-}
-
-static void preload_streamout_buffers(struct si_shader_context *ctx)
-{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- unsigned i;
-
- /* Streamout can only be used if the shader is compiled as VS. */
- if (!ctx->shader->selector->so.num_outputs ||
- (ctx->type == PIPE_SHADER_VERTEX &&
- (ctx->shader->key.vs.as_es ||
- ctx->shader->key.vs.as_ls)) ||
- (ctx->type == PIPE_SHADER_TESS_EVAL &&
- ctx->shader->key.tes.as_es))
- return;
-
- LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
- SI_PARAM_RW_BUFFERS);
-
- /* Load the resources, we rely on the code sinking to do the rest */
- for (i = 0; i < 4; ++i) {
- if (ctx->shader->selector->so.stride[i]) {
- LLVMValueRef offset = lp_build_const_int32(gallivm,
- SI_VS_STREAMOUT_BUF0 + i);
-
- ctx->so_buffers[i] = build_indexed_load_const(ctx, buf_ptr, offset);
- }
- }
-}
-
-/**
- * Load ESGS and GSVS ring buffer resource descriptors and save the variables
- * for later use.
- */
-static void preload_ring_buffers(struct si_shader_context *ctx)
-{
- struct gallivm_state *gallivm =
- ctx->radeon_bld.soa.bld_base.base.gallivm;
-
- LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
- SI_PARAM_RW_BUFFERS);
-
- if ((ctx->type == PIPE_SHADER_VERTEX &&
- ctx->shader->key.vs.as_es) ||
- (ctx->type == PIPE_SHADER_TESS_EVAL &&
- ctx->shader->key.tes.as_es) ||
- ctx->type == PIPE_SHADER_GEOMETRY) {
- unsigned ring =
- ctx->type == PIPE_SHADER_GEOMETRY ? SI_GS_RING_ESGS
- : SI_ES_RING_ESGS;
- LLVMValueRef offset = lp_build_const_int32(gallivm, ring);
-
- ctx->esgs_ring =
- build_indexed_load_const(ctx, buf_ptr, offset);
- }
-
- if (ctx->is_gs_copy_shader) {
- LLVMValueRef offset = lp_build_const_int32(gallivm, SI_VS_RING_GSVS);
-
- ctx->gsvs_ring[0] =
- build_indexed_load_const(ctx, buf_ptr, offset);
- }
- if (ctx->type == PIPE_SHADER_GEOMETRY) {
- int i;
- for (i = 0; i < 4; i++) {
- LLVMValueRef offset = lp_build_const_int32(gallivm, SI_GS_RING_GSVS0 + i);
-
- ctx->gsvs_ring[i] =
- build_indexed_load_const(ctx, buf_ptr, offset);
- }
- }
-}
-
-static void si_llvm_emit_polygon_stipple(struct si_shader_context *ctx,
- LLVMValueRef param_rw_buffers,
- unsigned param_pos_fixed_pt)
-{
- struct lp_build_tgsi_context *bld_base =
- &ctx->radeon_bld.soa.bld_base;
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMBuilderRef builder = gallivm->builder;
- LLVMValueRef slot, desc, offset, row, bit, address[2];
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef slot, desc, offset, row, bit, address[2];
/* Use the fixed-point gl_FragCoord input.
* Since the stipple pattern is 32x32 and it repeats, just get 5 bits
assert(!epilog || !epilog->rodata_size);
r600_resource_reference(&shader->bo, NULL);
- shader->bo = si_resource_create_custom(&sscreen->b.b,
- PIPE_USAGE_IMMUTABLE,
- bo_size);
+ shader->bo = (struct r600_resource*)
+ pipe_buffer_create(&sscreen->b.b, 0,
+ PIPE_USAGE_IMMUTABLE, bo_size);
if (!shader->bo)
return -ENOMEM;
}
if (!si_replace_shader(count, binary)) {
- r = radeon_llvm_compile(mod, binary, tm, debug);
+ r = si_llvm_compile(mod, binary, tm, debug);
if (r)
return r;
}
static void si_llvm_build_ret(struct si_shader_context *ctx, LLVMValueRef ret)
{
if (LLVMGetTypeKind(LLVMTypeOf(ret)) == LLVMVoidTypeKind)
- LLVMBuildRetVoid(ctx->radeon_bld.gallivm.builder);
+ LLVMBuildRetVoid(ctx->gallivm.builder);
else
- LLVMBuildRet(ctx->radeon_bld.gallivm.builder, ret);
+ LLVMBuildRet(ctx->gallivm.builder, ret);
}
/* Generate code for the hardware VS shader stage to go with a geometry shader */
struct si_shader *gs,
struct pipe_debug_callback *debug)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
struct lp_build_context *uint = &bld_base->uint_bld;
struct si_shader_output_values *outputs;
struct tgsi_shader_info *gsinfo = &gs->selector->info;
create_meta_data(ctx);
create_function(ctx);
- preload_streamout_buffers(ctx);
preload_ring_buffers(ctx);
args[0] = ctx->gsvs_ring[0];
args[1] = lp_build_mul_imm(uint,
- LLVMGetParam(ctx->radeon_bld.main_fn,
+ LLVMGetParam(ctx->main_fn,
ctx->param_vertex_id),
4);
args[3] = uint->zero;
r600_can_dump_shader(&sscreen->b, PIPE_SHADER_GEOMETRY))
LLVMDumpModule(bld_base->base.gallivm->module);
- radeon_llvm_finalize_module(&ctx->radeon_bld);
+ si_llvm_finalize_module(ctx,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_GEOMETRY));
r = si_compile_llvm(sscreen, &ctx->shader->binary,
&ctx->shader->config, ctx->tm,
r = si_shader_binary_upload(sscreen, ctx->shader);
}
- radeon_llvm_dispose(&ctx->radeon_bld);
+ si_llvm_dispose(ctx);
FREE(outputs);
return r;
struct lp_build_tgsi_action tmpl = {};
memset(ctx, 0, sizeof(*ctx));
- radeon_llvm_context_init(
- &ctx->radeon_bld, "amdgcn--",
+ si_llvm_context_init(
+ ctx, "amdgcn--",
(shader && shader->selector) ? &shader->selector->info : NULL,
(shader && shader->selector) ? shader->selector->tokens : NULL);
+ si_shader_context_init_alu(&ctx->soa.bld_base);
ctx->tm = tm;
ctx->screen = sscreen;
if (shader && shader->selector)
ctx->type = -1;
ctx->shader = shader;
- ctx->voidt = LLVMVoidTypeInContext(ctx->radeon_bld.gallivm.context);
- ctx->i1 = LLVMInt1TypeInContext(ctx->radeon_bld.gallivm.context);
- ctx->i8 = LLVMInt8TypeInContext(ctx->radeon_bld.gallivm.context);
- ctx->i32 = LLVMInt32TypeInContext(ctx->radeon_bld.gallivm.context);
- ctx->i64 = LLVMInt64TypeInContext(ctx->radeon_bld.gallivm.context);
- ctx->i128 = LLVMIntTypeInContext(ctx->radeon_bld.gallivm.context, 128);
- ctx->f32 = LLVMFloatTypeInContext(ctx->radeon_bld.gallivm.context);
+ ctx->voidt = LLVMVoidTypeInContext(ctx->gallivm.context);
+ ctx->i1 = LLVMInt1TypeInContext(ctx->gallivm.context);
+ ctx->i8 = LLVMInt8TypeInContext(ctx->gallivm.context);
+ ctx->i32 = LLVMInt32TypeInContext(ctx->gallivm.context);
+ ctx->i64 = LLVMInt64TypeInContext(ctx->gallivm.context);
+ ctx->i128 = LLVMIntTypeInContext(ctx->gallivm.context, 128);
+ ctx->f32 = LLVMFloatTypeInContext(ctx->gallivm.context);
ctx->v16i8 = LLVMVectorType(ctx->i8, 16);
ctx->v2i32 = LLVMVectorType(ctx->i32, 2);
ctx->v4i32 = LLVMVectorType(ctx->i32, 4);
ctx->v4f32 = LLVMVectorType(ctx->f32, 4);
ctx->v8i32 = LLVMVectorType(ctx->i32, 8);
- bld_base = &ctx->radeon_bld.soa.bld_base;
+ bld_base = &ctx->soa.bld_base;
bld_base->emit_fetch_funcs[TGSI_FILE_CONSTANT] = fetch_constant;
bld_base->op_actions[TGSI_OPCODE_INTERP_CENTROID] = interp_action;
bld_base->op_actions[TGSI_OPCODE_EMIT].emit = si_llvm_emit_vertex;
bld_base->op_actions[TGSI_OPCODE_ENDPRIM].emit = si_llvm_emit_primitive;
bld_base->op_actions[TGSI_OPCODE_BARRIER].emit = si_llvm_emit_barrier;
-
- bld_base->op_actions[TGSI_OPCODE_MAX].emit = build_tgsi_intrinsic_nomem;
- bld_base->op_actions[TGSI_OPCODE_MAX].intr_name = "llvm.maxnum.f32";
- bld_base->op_actions[TGSI_OPCODE_MIN].emit = build_tgsi_intrinsic_nomem;
- bld_base->op_actions[TGSI_OPCODE_MIN].intr_name = "llvm.minnum.f32";
}
-int si_compile_tgsi_shader(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
- struct si_shader *shader,
- bool is_monolithic,
- struct pipe_debug_callback *debug)
+/* Return true if the PARAM export has been eliminated. */
+static bool si_eliminate_const_output(struct si_shader_context *ctx,
+ LLVMValueRef inst, unsigned offset)
{
- struct si_shader_selector *sel = shader->selector;
- struct si_shader_context ctx;
- struct lp_build_tgsi_context *bld_base;
- LLVMModuleRef mod;
- int r = 0;
+ struct si_shader *shader = ctx->shader;
+ unsigned num_outputs = shader->selector->info.num_outputs;
+ unsigned i, default_val; /* SPI_PS_INPUT_CNTL_i.DEFAULT_VAL */
+ bool is_zero[4] = {}, is_one[4] = {};
- /* Dump TGSI code before doing TGSI->LLVM conversion in case the
- * conversion fails. */
- if (r600_can_dump_shader(&sscreen->b, sel->info.processor) &&
- !(sscreen->b.debug_flags & DBG_NO_TGSI)) {
- tgsi_dump(sel->tokens, 0);
- si_dump_streamout(&sel->so);
+ for (i = 0; i < 4; i++) {
+ LLVMBool loses_info;
+ LLVMValueRef p = LLVMGetOperand(inst, 5 + i);
+
+ /* It's a constant expression. Undef outputs are eliminated too. */
+ if (LLVMIsUndef(p)) {
+ is_zero[i] = true;
+ is_one[i] = true;
+ } else if (LLVMIsAConstantFP(p)) {
+ double a = LLVMConstRealGetDouble(p, &loses_info);
+
+ if (a == 0)
+ is_zero[i] = true;
+ else if (a == 1)
+ is_one[i] = true;
+ else
+ return false; /* other constant */
+ } else
+ return false;
}
- si_init_shader_ctx(&ctx, sscreen, shader, tm);
- ctx.is_monolithic = is_monolithic;
+ /* Only certain combinations of 0 and 1 can be eliminated. */
+ if (is_zero[0] && is_zero[1] && is_zero[2])
+ default_val = is_zero[3] ? 0 : 1;
+ else if (is_one[0] && is_one[1] && is_one[2])
+ default_val = is_zero[3] ? 2 : 3;
+ else
+ return false;
- shader->info.uses_instanceid = sel->info.uses_instanceid;
+ /* The PARAM export can be represented as DEFAULT_VAL. Kill it. */
+ LLVMInstructionEraseFromParent(inst);
+
+ /* Change OFFSET to DEFAULT_VAL. */
+ for (i = 0; i < num_outputs; i++) {
+ if (shader->info.vs_output_param_offset[i] == offset) {
+ shader->info.vs_output_param_offset[i] =
+ EXP_PARAM_DEFAULT_VAL_0000 + default_val;
+ break;
+ }
+ }
+ return true;
+}
+
+struct si_vs_exports {
+ unsigned num;
+ unsigned offset[SI_MAX_VS_OUTPUTS];
+ LLVMValueRef inst[SI_MAX_VS_OUTPUTS];
+};
+
+static void si_eliminate_const_vs_outputs(struct si_shader_context *ctx)
+{
+ struct si_shader *shader = ctx->shader;
+ struct tgsi_shader_info *info = &shader->selector->info;
+ LLVMBasicBlockRef bb;
+ struct si_vs_exports exports;
+ bool removed_any = false;
+
+ exports.num = 0;
+
+ if ((ctx->type == PIPE_SHADER_VERTEX &&
+ (shader->key.vs.as_es || shader->key.vs.as_ls)) ||
+ (ctx->type == PIPE_SHADER_TESS_EVAL && shader->key.tes.as_es))
+ return;
+
+ /* Process all LLVM instructions. */
+ bb = LLVMGetFirstBasicBlock(ctx->main_fn);
+ while (bb) {
+ LLVMValueRef inst = LLVMGetFirstInstruction(bb);
+
+ while (inst) {
+ LLVMValueRef cur = inst;
+ inst = LLVMGetNextInstruction(inst);
+
+ if (LLVMGetInstructionOpcode(cur) != LLVMCall)
+ continue;
+
+ LLVMValueRef callee = lp_get_called_value(cur);
+
+ if (!lp_is_function(callee))
+ continue;
+
+ const char *name = LLVMGetValueName(callee);
+ unsigned num_args = LLVMCountParams(callee);
+
+ /* Check if this is an export instruction. */
+ if (num_args != 9 || strcmp(name, "llvm.SI.export"))
+ continue;
+
+ LLVMValueRef arg = LLVMGetOperand(cur, 3);
+ unsigned target = LLVMConstIntGetZExtValue(arg);
+
+ if (target < V_008DFC_SQ_EXP_PARAM)
+ continue;
+
+ target -= V_008DFC_SQ_EXP_PARAM;
+
+ /* Eliminate constant value PARAM exports. */
+ if (si_eliminate_const_output(ctx, cur, target)) {
+ removed_any = true;
+ } else {
+ exports.offset[exports.num] = target;
+ exports.inst[exports.num] = cur;
+ exports.num++;
+ }
+ }
+ bb = LLVMGetNextBasicBlock(bb);
+ }
+
+ /* Remove holes in export memory due to removed PARAM exports.
+ * This is done by renumbering all PARAM exports.
+ */
+ if (removed_any) {
+ ubyte current_offset[SI_MAX_VS_OUTPUTS];
+ unsigned new_count = 0;
+ unsigned out, i;
+
+ /* Make a copy of the offsets. We need the old version while
+ * we are modifying some of them. */
+ assert(sizeof(current_offset) ==
+ sizeof(shader->info.vs_output_param_offset));
+ memcpy(current_offset, shader->info.vs_output_param_offset,
+ sizeof(current_offset));
+
+ for (i = 0; i < exports.num; i++) {
+ unsigned offset = exports.offset[i];
+
+ for (out = 0; out < info->num_outputs; out++) {
+ if (current_offset[out] != offset)
+ continue;
+
+ LLVMSetOperand(exports.inst[i], 3,
+ LLVMConstInt(ctx->i32,
+ V_008DFC_SQ_EXP_PARAM + new_count, 0));
+ shader->info.vs_output_param_offset[out] = new_count;
+ new_count++;
+ break;
+ }
+ }
+ shader->info.nr_param_exports = new_count;
+ }
+}
- bld_base = &ctx.radeon_bld.soa.bld_base;
- ctx.radeon_bld.load_system_value = declare_system_value;
+static bool si_compile_tgsi_main(struct si_shader_context *ctx,
+ struct si_shader *shader)
+{
+ struct si_shader_selector *sel = shader->selector;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
- switch (ctx.type) {
+ switch (ctx->type) {
case PIPE_SHADER_VERTEX:
- ctx.radeon_bld.load_input = declare_input_vs;
+ ctx->load_input = declare_input_vs;
if (shader->key.vs.as_ls)
bld_base->emit_epilogue = si_llvm_emit_ls_epilogue;
else if (shader->key.vs.as_es)
bld_base->emit_epilogue = si_llvm_emit_gs_epilogue;
break;
case PIPE_SHADER_FRAGMENT:
- ctx.radeon_bld.load_input = declare_input_fs;
- if (is_monolithic)
+ ctx->load_input = declare_input_fs;
+ if (ctx->no_epilog)
bld_base->emit_epilogue = si_llvm_emit_fs_epilogue;
else
bld_base->emit_epilogue = si_llvm_return_fs_outputs;
break;
case PIPE_SHADER_COMPUTE:
- ctx.radeon_bld.declare_memory_region = declare_compute_memory;
+ ctx->declare_memory_region = declare_compute_memory;
break;
default:
assert(!"Unsupported shader type");
- return -1;
+ return false;
}
- create_meta_data(&ctx);
- create_function(&ctx);
- preload_constants(&ctx);
- preload_shader_buffers(&ctx);
- preload_samplers(&ctx);
- preload_images(&ctx);
- preload_streamout_buffers(&ctx);
- preload_ring_buffers(&ctx);
+ create_meta_data(ctx);
+ create_function(ctx);
+ preload_ring_buffers(ctx);
- if (ctx.is_monolithic && sel->type == PIPE_SHADER_FRAGMENT &&
+ if (ctx->no_prolog && sel->type == PIPE_SHADER_FRAGMENT &&
shader->key.ps.prolog.poly_stipple) {
- LLVMValueRef list = LLVMGetParam(ctx.radeon_bld.main_fn,
+ LLVMValueRef list = LLVMGetParam(ctx->main_fn,
SI_PARAM_RW_BUFFERS);
- si_llvm_emit_polygon_stipple(&ctx, list,
+ si_llvm_emit_polygon_stipple(ctx, list,
SI_PARAM_POS_FIXED_PT);
}
- if (ctx.type == PIPE_SHADER_GEOMETRY) {
+ if (ctx->type == PIPE_SHADER_GEOMETRY) {
int i;
for (i = 0; i < 4; i++) {
- ctx.gs_next_vertex[i] =
+ ctx->gs_next_vertex[i] =
lp_build_alloca(bld_base->base.gallivm,
- ctx.i32, "");
+ ctx->i32, "");
}
}
if (!lp_build_tgsi_llvm(bld_base, sel->tokens)) {
fprintf(stderr, "Failed to translate shader from TGSI to LLVM\n");
- goto out;
+ return false;
}
- si_llvm_build_ret(&ctx, ctx.return_value);
- mod = bld_base->base.gallivm->module;
+ si_llvm_build_ret(ctx, ctx->return_value);
+ return true;
+}
- /* Dump LLVM IR before any optimization passes */
- if (sscreen->b.debug_flags & DBG_PREOPT_IR &&
- r600_can_dump_shader(&sscreen->b, ctx.type))
- LLVMDumpModule(mod);
+/**
+ * Compute the VS prolog key, which contains all the information needed to
+ * build the VS prolog function, and set shader->info bits where needed.
+ */
+static void si_get_vs_prolog_key(struct si_shader *shader,
+ union si_shader_part_key *key)
+{
+ struct tgsi_shader_info *info = &shader->selector->info;
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ memset(key, 0, sizeof(*key));
+ key->vs_prolog.states = shader->key.vs.prolog;
+ key->vs_prolog.num_input_sgprs = shader->info.num_input_sgprs;
+ key->vs_prolog.last_input = MAX2(1, info->num_inputs) - 1;
- r = si_compile_llvm(sscreen, &shader->binary, &shader->config, tm,
- mod, debug, ctx.type, "TGSI shader");
- if (r) {
- fprintf(stderr, "LLVM failed to compile shader\n");
- goto out;
- }
+ /* Set the instanceID flag. */
+ for (unsigned i = 0; i < info->num_inputs; i++)
+ if (key->vs_prolog.states.instance_divisors[i])
+ shader->info.uses_instanceid = true;
+}
- radeon_llvm_dispose(&ctx.radeon_bld);
+/**
+ * Compute the VS epilog key, which contains all the information needed to
+ * build the VS epilog function, and set the PrimitiveID output offset.
+ */
+static void si_get_vs_epilog_key(struct si_shader *shader,
+ struct si_vs_epilog_bits *states,
+ union si_shader_part_key *key)
+{
+ memset(key, 0, sizeof(*key));
+ key->vs_epilog.states = *states;
- /* Validate SGPR and VGPR usage for compute to detect compiler bugs.
- * LLVM 3.9svn has this bug.
- */
- if (sel->type == PIPE_SHADER_COMPUTE) {
- unsigned *props = sel->info.properties;
- unsigned wave_size = 64;
- unsigned max_vgprs = 256;
- unsigned max_sgprs = sscreen->b.chip_class >= VI ? 800 : 512;
- unsigned max_sgprs_per_wave = 128;
- unsigned min_waves_per_cu =
- DIV_ROUND_UP(props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] *
- props[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
- props[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH],
- wave_size);
- unsigned min_waves_per_simd = DIV_ROUND_UP(min_waves_per_cu, 4);
+ /* Set up the PrimitiveID output. */
+ if (shader->key.vs.epilog.export_prim_id) {
+ unsigned index = shader->selector->info.num_outputs;
+ unsigned offset = shader->info.nr_param_exports++;
- max_vgprs = max_vgprs / min_waves_per_simd;
- max_sgprs = MIN2(max_sgprs / min_waves_per_simd, max_sgprs_per_wave);
+ key->vs_epilog.prim_id_param_offset = offset;
+ assert(index < ARRAY_SIZE(shader->info.vs_output_param_offset));
+ shader->info.vs_output_param_offset[index] = offset;
+ }
+}
- if (shader->config.num_sgprs > max_sgprs ||
- shader->config.num_vgprs > max_vgprs) {
- fprintf(stderr, "LLVM failed to compile a shader correctly: "
- "SGPR:VGPR usage is %u:%u, but the hw limit is %u:%u\n",
- shader->config.num_sgprs, shader->config.num_vgprs,
- max_sgprs, max_vgprs);
+/**
+ * Compute the PS prolog key, which contains all the information needed to
+ * build the PS prolog function, and set related bits in shader->config.
+ */
+static void si_get_ps_prolog_key(struct si_shader *shader,
+ union si_shader_part_key *key,
+ bool separate_prolog)
+{
+ struct tgsi_shader_info *info = &shader->selector->info;
- /* Just terminate the process, because dependent
- * shaders can hang due to bad input data, but use
- * the env var to allow shader-db to work.
- */
- if (!debug_get_bool_option("SI_PASS_BAD_SHADERS", false))
- abort();
+ memset(key, 0, sizeof(*key));
+ key->ps_prolog.states = shader->key.ps.prolog;
+ key->ps_prolog.colors_read = info->colors_read;
+ key->ps_prolog.num_input_sgprs = shader->info.num_input_sgprs;
+ key->ps_prolog.num_input_vgprs = shader->info.num_input_vgprs;
+ key->ps_prolog.wqm = info->uses_derivatives &&
+ (key->ps_prolog.colors_read ||
+ key->ps_prolog.states.force_persp_sample_interp ||
+ key->ps_prolog.states.force_linear_sample_interp ||
+ key->ps_prolog.states.force_persp_center_interp ||
+ key->ps_prolog.states.force_linear_center_interp ||
+ key->ps_prolog.states.bc_optimize_for_persp ||
+ key->ps_prolog.states.bc_optimize_for_linear);
+
+ if (info->colors_read) {
+ unsigned *color = shader->selector->color_attr_index;
+
+ if (shader->key.ps.prolog.color_two_side) {
+ /* 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);
}
- }
- /* Add the scratch offset to input SGPRs. */
- if (shader->config.scratch_bytes_per_wave)
- shader->info.num_input_sgprs += 1; /* scratch byte offset */
+ for (unsigned i = 0; i < 2; i++) {
+ unsigned interp = info->input_interpolate[color[i]];
+ unsigned location = info->input_interpolate_loc[color[i]];
- /* Calculate the number of fragment input VGPRs. */
- if (ctx.type == PIPE_SHADER_FRAGMENT) {
- shader->info.num_input_vgprs = 0;
- shader->info.face_vgpr_index = -1;
+ if (!(info->colors_read & (0xf << i*4)))
+ continue;
- if (G_0286CC_PERSP_SAMPLE_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 2;
- if (G_0286CC_PERSP_CENTER_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 2;
- if (G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 2;
- if (G_0286CC_PERSP_PULL_MODEL_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 3;
- if (G_0286CC_LINEAR_SAMPLE_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 2;
- if (G_0286CC_LINEAR_CENTER_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 2;
- if (G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 2;
- if (G_0286CC_LINE_STIPPLE_TEX_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 1;
- if (G_0286CC_POS_X_FLOAT_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 1;
- if (G_0286CC_POS_Y_FLOAT_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 1;
- if (G_0286CC_POS_Z_FLOAT_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 1;
- if (G_0286CC_POS_W_FLOAT_ENA(shader->config.spi_ps_input_addr))
- shader->info.num_input_vgprs += 1;
- if (G_0286CC_FRONT_FACE_ENA(shader->config.spi_ps_input_addr)) {
- shader->info.face_vgpr_index = shader->info.num_input_vgprs;
- shader->info.num_input_vgprs += 1;
- }
- if (G_0286CC_ANCILLARY_ENA(shader->config.spi_ps_input_addr))
+ key->ps_prolog.color_attr_index[i] = color[i];
+
+ if (shader->key.ps.prolog.flatshade_colors &&
+ interp == TGSI_INTERPOLATE_COLOR)
+ interp = TGSI_INTERPOLATE_CONSTANT;
+
+ switch (interp) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ key->ps_prolog.color_interp_vgpr_index[i] = -1;
+ break;
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ case TGSI_INTERPOLATE_COLOR:
+ /* Force the interpolation location for colors here. */
+ if (shader->key.ps.prolog.force_persp_sample_interp)
+ location = TGSI_INTERPOLATE_LOC_SAMPLE;
+ if (shader->key.ps.prolog.force_persp_center_interp)
+ location = TGSI_INTERPOLATE_LOC_CENTER;
+
+ 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);
+ 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);
+ 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);
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ case TGSI_INTERPOLATE_LINEAR:
+ /* Force the interpolation location for colors here. */
+ if (shader->key.ps.prolog.force_linear_sample_interp)
+ location = TGSI_INTERPOLATE_LOC_SAMPLE;
+ if (shader->key.ps.prolog.force_linear_center_interp)
+ location = TGSI_INTERPOLATE_LOC_CENTER;
+
+ /* The VGPR assignment for non-monolithic shaders
+ * works because InitialPSInputAddr is set on the
+ * main shader and PERSP_PULL_MODEL is never used.
+ */
+ switch (location) {
+ 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);
+ 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);
+ 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);
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+}
+
+/**
+ * Check whether a PS prolog is required based on the key.
+ */
+static bool si_need_ps_prolog(const union si_shader_part_key *key)
+{
+ return key->ps_prolog.colors_read ||
+ key->ps_prolog.states.force_persp_sample_interp ||
+ key->ps_prolog.states.force_linear_sample_interp ||
+ key->ps_prolog.states.force_persp_center_interp ||
+ key->ps_prolog.states.force_linear_center_interp ||
+ key->ps_prolog.states.bc_optimize_for_persp ||
+ key->ps_prolog.states.bc_optimize_for_linear ||
+ key->ps_prolog.states.poly_stipple;
+}
+
+/**
+ * Compute the PS epilog key, which contains all the information needed to
+ * build the PS epilog function.
+ */
+static void si_get_ps_epilog_key(struct si_shader *shader,
+ union si_shader_part_key *key)
+{
+ struct tgsi_shader_info *info = &shader->selector->info;
+ memset(key, 0, sizeof(*key));
+ key->ps_epilog.colors_written = info->colors_written;
+ key->ps_epilog.writes_z = info->writes_z;
+ key->ps_epilog.writes_stencil = info->writes_stencil;
+ key->ps_epilog.writes_samplemask = info->writes_samplemask;
+ key->ps_epilog.states = shader->key.ps.epilog;
+}
+
+/**
+ * Given a list of shader part functions, build a wrapper function that
+ * runs them in sequence to form a monolithic shader.
+ */
+static void si_build_wrapper_function(struct si_shader_context *ctx,
+ LLVMValueRef *parts,
+ unsigned num_parts,
+ unsigned main_part)
+{
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ LLVMBuilderRef builder = ctx->gallivm.builder;
+ /* PS epilog has one arg per color component */
+ LLVMTypeRef param_types[48];
+ LLVMValueRef out[48];
+ LLVMTypeRef function_type;
+ unsigned num_params;
+ unsigned num_out_sgpr, num_out;
+ unsigned num_sgprs, num_vgprs;
+ unsigned last_sgpr_param;
+ unsigned gprs;
+
+ for (unsigned i = 0; i < num_parts; ++i) {
+ LLVMAddFunctionAttr(parts[i], LLVMAlwaysInlineAttribute);
+ LLVMSetLinkage(parts[i], LLVMPrivateLinkage);
+ }
+
+ /* The parameters of the wrapper function correspond to those of the
+ * first part in terms of SGPRs and VGPRs, but we use the types of the
+ * main part to get the right types. This is relevant for the
+ * dereferenceable attribute on descriptor table pointers.
+ */
+ num_sgprs = 0;
+ num_vgprs = 0;
+
+ function_type = LLVMGetElementType(LLVMTypeOf(parts[0]));
+ num_params = LLVMCountParamTypes(function_type);
+
+ for (unsigned i = 0; i < num_params; ++i) {
+ LLVMValueRef param = LLVMGetParam(parts[0], i);
+
+ if (ac_is_sgpr_param(param)) {
+ assert(num_vgprs == 0);
+ num_sgprs += llvm_get_type_size(LLVMTypeOf(param)) / 4;
+ } else {
+ num_vgprs += llvm_get_type_size(LLVMTypeOf(param)) / 4;
+ }
+ }
+ assert(num_vgprs + num_sgprs <= ARRAY_SIZE(param_types));
+
+ num_params = 0;
+ last_sgpr_param = 0;
+ gprs = 0;
+ while (gprs < num_sgprs + num_vgprs) {
+ LLVMValueRef param = LLVMGetParam(parts[main_part], num_params);
+ unsigned size;
+
+ param_types[num_params] = LLVMTypeOf(param);
+ if (gprs < num_sgprs)
+ last_sgpr_param = num_params;
+ size = llvm_get_type_size(param_types[num_params]) / 4;
+ num_params++;
+
+ assert(ac_is_sgpr_param(param) == (gprs < num_sgprs));
+ assert(gprs + size <= num_sgprs + num_vgprs &&
+ (gprs >= num_sgprs || gprs + size <= num_sgprs));
+
+ gprs += size;
+ }
+
+ si_create_function(ctx, "wrapper", NULL, 0, param_types, num_params, last_sgpr_param);
+
+ /* Record the arguments of the function as if they were an output of
+ * a previous part.
+ */
+ num_out = 0;
+ num_out_sgpr = 0;
+
+ for (unsigned i = 0; i < num_params; ++i) {
+ LLVMValueRef param = LLVMGetParam(ctx->main_fn, i);
+ LLVMTypeRef param_type = LLVMTypeOf(param);
+ LLVMTypeRef out_type = i <= last_sgpr_param ? ctx->i32 : ctx->f32;
+ unsigned size = llvm_get_type_size(param_type) / 4;
+
+ if (size == 1) {
+ if (param_type != out_type)
+ param = LLVMBuildBitCast(builder, param, out_type, "");
+ out[num_out++] = param;
+ } else {
+ LLVMTypeRef vector_type = LLVMVectorType(out_type, size);
+
+ if (LLVMGetTypeKind(param_type) == LLVMPointerTypeKind) {
+ param = LLVMBuildPtrToInt(builder, param, ctx->i64, "");
+ param_type = ctx->i64;
+ }
+
+ if (param_type != vector_type)
+ param = LLVMBuildBitCast(builder, param, vector_type, "");
+
+ for (unsigned j = 0; j < size; ++j)
+ out[num_out++] = LLVMBuildExtractElement(
+ builder, param, LLVMConstInt(ctx->i32, j, 0), "");
+ }
+
+ if (i <= last_sgpr_param)
+ num_out_sgpr = num_out;
+ }
+
+ /* Now chain the parts. */
+ for (unsigned part = 0; part < num_parts; ++part) {
+ LLVMValueRef in[48];
+ LLVMValueRef ret;
+ LLVMTypeRef ret_type;
+ unsigned out_idx = 0;
+
+ num_params = LLVMCountParams(parts[part]);
+ assert(num_params <= ARRAY_SIZE(param_types));
+
+ /* Derive arguments for the next part from outputs of the
+ * previous one.
+ */
+ for (unsigned param_idx = 0; param_idx < num_params; ++param_idx) {
+ LLVMValueRef param;
+ LLVMTypeRef param_type;
+ bool is_sgpr;
+ unsigned param_size;
+ LLVMValueRef arg = NULL;
+
+ param = LLVMGetParam(parts[part], param_idx);
+ param_type = LLVMTypeOf(param);
+ param_size = llvm_get_type_size(param_type) / 4;
+ is_sgpr = ac_is_sgpr_param(param);
+
+ if (is_sgpr) {
+ LLVMRemoveAttribute(param, LLVMByValAttribute);
+ LLVMAddAttribute(param, LLVMInRegAttribute);
+ }
+
+ assert(out_idx + param_size <= (is_sgpr ? num_out_sgpr : num_out));
+ assert(is_sgpr || out_idx >= num_out_sgpr);
+
+ if (param_size == 1)
+ arg = out[out_idx];
+ else
+ arg = lp_build_gather_values(gallivm, &out[out_idx], param_size);
+
+ if (LLVMTypeOf(arg) != param_type) {
+ if (LLVMGetTypeKind(param_type) == LLVMPointerTypeKind) {
+ arg = LLVMBuildBitCast(builder, arg, ctx->i64, "");
+ arg = LLVMBuildIntToPtr(builder, arg, param_type, "");
+ } else {
+ arg = LLVMBuildBitCast(builder, arg, param_type, "");
+ }
+ }
+
+ in[param_idx] = arg;
+ out_idx += param_size;
+ }
+
+ ret = LLVMBuildCall(builder, parts[part], in, num_params, "");
+ ret_type = LLVMTypeOf(ret);
+
+ /* Extract the returned GPRs. */
+ num_out = 0;
+ num_out_sgpr = 0;
+
+ if (LLVMGetTypeKind(ret_type) != LLVMVoidTypeKind) {
+ assert(LLVMGetTypeKind(ret_type) == LLVMStructTypeKind);
+
+ unsigned ret_size = LLVMCountStructElementTypes(ret_type);
+
+ for (unsigned i = 0; i < ret_size; ++i) {
+ LLVMValueRef val =
+ LLVMBuildExtractValue(builder, ret, i, "");
+
+ out[num_out++] = val;
+
+ if (LLVMTypeOf(val) == ctx->i32) {
+ assert(num_out_sgpr + 1 == num_out);
+ num_out_sgpr = num_out;
+ }
+ }
+ }
+ }
+
+ LLVMBuildRetVoid(builder);
+}
+
+int si_compile_tgsi_shader(struct si_screen *sscreen,
+ LLVMTargetMachineRef tm,
+ struct si_shader *shader,
+ bool is_monolithic,
+ struct pipe_debug_callback *debug)
+{
+ struct si_shader_selector *sel = shader->selector;
+ struct si_shader_context ctx;
+ struct lp_build_tgsi_context *bld_base;
+ LLVMModuleRef mod;
+ int r = -1;
+
+ /* Dump TGSI code before doing TGSI->LLVM conversion in case the
+ * conversion fails. */
+ if (r600_can_dump_shader(&sscreen->b, sel->info.processor) &&
+ !(sscreen->b.debug_flags & DBG_NO_TGSI)) {
+ tgsi_dump(sel->tokens, 0);
+ si_dump_streamout(&sel->so);
+ }
+
+ si_init_shader_ctx(&ctx, sscreen, shader, tm);
+ ctx.no_prolog = is_monolithic;
+ ctx.no_epilog = is_monolithic;
+ ctx.separate_prolog = !is_monolithic;
+
+ if (ctx.type == PIPE_SHADER_VERTEX ||
+ ctx.type == PIPE_SHADER_FRAGMENT) {
+ ctx.no_prolog = false;
+ ctx.no_epilog = false;
+ }
+
+ memset(shader->info.vs_output_param_offset, 0xff,
+ sizeof(shader->info.vs_output_param_offset));
+
+ shader->info.uses_instanceid = sel->info.uses_instanceid;
+
+ bld_base = &ctx.soa.bld_base;
+ ctx.load_system_value = declare_system_value;
+
+ if (!si_compile_tgsi_main(&ctx, shader)) {
+ si_llvm_dispose(&ctx);
+ return -1;
+ }
+
+ if (is_monolithic && ctx.type == PIPE_SHADER_VERTEX) {
+ LLVMValueRef parts[3];
+ bool need_prolog;
+ bool need_epilog;
+
+ need_prolog = sel->info.num_inputs;
+ need_epilog = !shader->key.vs.as_es && !shader->key.vs.as_ls;
+
+ parts[need_prolog ? 1 : 0] = ctx.main_fn;
+
+ if (need_prolog) {
+ union si_shader_part_key prolog_key;
+ si_get_vs_prolog_key(shader, &prolog_key);
+ si_build_vs_prolog_function(&ctx, &prolog_key);
+ parts[0] = ctx.main_fn;
+ }
+
+ if (need_epilog) {
+ union si_shader_part_key epilog_key;
+ si_get_vs_epilog_key(shader, &shader->key.vs.epilog, &epilog_key);
+ si_build_vs_epilog_function(&ctx, &epilog_key);
+ parts[need_prolog ? 2 : 1] = ctx.main_fn;
+ }
+
+ si_build_wrapper_function(&ctx, parts, 1 + need_prolog + need_epilog,
+ need_prolog ? 1 : 0);
+ } else if (is_monolithic && ctx.type == PIPE_SHADER_FRAGMENT) {
+ LLVMValueRef parts[3];
+ union si_shader_part_key prolog_key;
+ union si_shader_part_key epilog_key;
+ bool need_prolog;
+
+ si_get_ps_prolog_key(shader, &prolog_key, false);
+ need_prolog = si_need_ps_prolog(&prolog_key);
+
+ parts[need_prolog ? 1 : 0] = ctx.main_fn;
+
+ if (need_prolog) {
+ si_build_ps_prolog_function(&ctx, &prolog_key);
+ parts[0] = ctx.main_fn;
+ }
+
+ si_get_ps_epilog_key(shader, &epilog_key);
+ si_build_ps_epilog_function(&ctx, &epilog_key);
+ parts[need_prolog ? 2 : 1] = ctx.main_fn;
+
+ si_build_wrapper_function(&ctx, parts, need_prolog ? 3 : 2, need_prolog ? 1 : 0);
+ }
+
+ mod = bld_base->base.gallivm->module;
+
+ /* Dump LLVM IR before any optimization passes */
+ if (sscreen->b.debug_flags & DBG_PREOPT_IR &&
+ r600_can_dump_shader(&sscreen->b, ctx.type))
+ LLVMDumpModule(mod);
+
+ si_llvm_finalize_module(&ctx,
+ r600_extra_shader_checks(&sscreen->b, ctx.type));
+
+ /* Post-optimization transformations. */
+ si_eliminate_const_vs_outputs(&ctx);
+
+ /* Compile to bytecode. */
+ r = si_compile_llvm(sscreen, &shader->binary, &shader->config, tm,
+ mod, debug, ctx.type, "TGSI shader");
+ si_llvm_dispose(&ctx);
+ if (r) {
+ fprintf(stderr, "LLVM failed to compile shader\n");
+ return r;
+ }
+
+ /* Validate SGPR and VGPR usage for compute to detect compiler bugs.
+ * LLVM 3.9svn has this bug.
+ */
+ if (sel->type == PIPE_SHADER_COMPUTE) {
+ unsigned *props = sel->info.properties;
+ unsigned wave_size = 64;
+ unsigned max_vgprs = 256;
+ unsigned max_sgprs = sscreen->b.chip_class >= VI ? 800 : 512;
+ unsigned max_sgprs_per_wave = 128;
+ unsigned max_block_threads;
+
+ if (props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH])
+ max_block_threads = props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] *
+ props[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
+ props[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH];
+ else
+ max_block_threads = SI_MAX_VARIABLE_THREADS_PER_BLOCK;
+
+ unsigned min_waves_per_cu = DIV_ROUND_UP(max_block_threads, wave_size);
+ unsigned min_waves_per_simd = DIV_ROUND_UP(min_waves_per_cu, 4);
+
+ max_vgprs = max_vgprs / min_waves_per_simd;
+ max_sgprs = MIN2(max_sgprs / min_waves_per_simd, max_sgprs_per_wave);
+
+ if (shader->config.num_sgprs > max_sgprs ||
+ shader->config.num_vgprs > max_vgprs) {
+ fprintf(stderr, "LLVM failed to compile a shader correctly: "
+ "SGPR:VGPR usage is %u:%u, but the hw limit is %u:%u\n",
+ shader->config.num_sgprs, shader->config.num_vgprs,
+ max_sgprs, max_vgprs);
+
+ /* Just terminate the process, because dependent
+ * shaders can hang due to bad input data, but use
+ * the env var to allow shader-db to work.
+ */
+ if (!debug_get_bool_option("SI_PASS_BAD_SHADERS", false))
+ abort();
+ }
+ }
+
+ /* Add the scratch offset to input SGPRs. */
+ if (shader->config.scratch_bytes_per_wave)
+ shader->info.num_input_sgprs += 1; /* scratch byte offset */
+
+ /* Calculate the number of fragment input VGPRs. */
+ if (ctx.type == PIPE_SHADER_FRAGMENT) {
+ shader->info.num_input_vgprs = 0;
+ shader->info.face_vgpr_index = -1;
+
+ if (G_0286CC_PERSP_SAMPLE_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 2;
+ if (G_0286CC_PERSP_CENTER_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 2;
+ if (G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 2;
+ if (G_0286CC_PERSP_PULL_MODEL_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 3;
+ if (G_0286CC_LINEAR_SAMPLE_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 2;
+ if (G_0286CC_LINEAR_CENTER_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 2;
+ if (G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 2;
+ if (G_0286CC_LINE_STIPPLE_TEX_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 1;
+ if (G_0286CC_POS_X_FLOAT_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 1;
+ if (G_0286CC_POS_Y_FLOAT_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 1;
+ if (G_0286CC_POS_Z_FLOAT_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 1;
+ if (G_0286CC_POS_W_FLOAT_ENA(shader->config.spi_ps_input_addr))
+ shader->info.num_input_vgprs += 1;
+ if (G_0286CC_FRONT_FACE_ENA(shader->config.spi_ps_input_addr)) {
+ shader->info.face_vgpr_index = shader->info.num_input_vgprs;
+ shader->info.num_input_vgprs += 1;
+ }
+ if (G_0286CC_ANCILLARY_ENA(shader->config.spi_ps_input_addr))
shader->info.num_input_vgprs += 1;
if (G_0286CC_SAMPLE_COVERAGE_ENA(shader->config.spi_ps_input_addr))
shader->info.num_input_vgprs += 1;
shader->gs_copy_shader = CALLOC_STRUCT(si_shader);
shader->gs_copy_shader->selector = shader->selector;
ctx.shader = shader->gs_copy_shader;
- if ((r = si_generate_gs_copy_shader(sscreen, &ctx,
- shader, debug))) {
+ r = si_generate_gs_copy_shader(sscreen, &ctx,
+ shader, debug);
+ if (r) {
free(shader->gs_copy_shader);
shader->gs_copy_shader = NULL;
- goto out;
+ return r;
}
}
-out:
- for (int i = 0; i < SI_NUM_CONST_BUFFERS; i++)
- FREE(ctx.constants[i]);
- return r;
+ return 0;
}
/**
}
/**
- * Create a vertex shader prolog.
+ * Build the vertex shader prolog function.
*
* The inputs are the same as VS (a lot of SGPRs and 4 VGPR system values).
* All inputs are returned unmodified. The vertex load indices are
- * stored after them, which will used by the API VS for fetching inputs.
+ * stored after them, which will be used by the API VS for fetching inputs.
*
* For example, the expected outputs for instance_divisors[] = {0, 1, 2} are:
* input_v0,
* (InstanceID + StartInstance),
* (InstanceID / 2 + StartInstance)
*/
-static bool si_compile_vs_prolog(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
- struct pipe_debug_callback *debug,
- struct si_shader_part *out)
+static void si_build_vs_prolog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key)
{
- union si_shader_part_key *key = &out->key;
- struct si_shader shader = {};
- struct si_shader_context ctx;
- struct gallivm_state *gallivm = &ctx.radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMTypeRef *params, *returns;
LLVMValueRef ret, func;
int last_sgpr, num_params, num_returns, i;
- bool status = true;
- si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = PIPE_SHADER_VERTEX;
- ctx.param_vertex_id = key->vs_prolog.num_input_sgprs;
- ctx.param_instance_id = key->vs_prolog.num_input_sgprs + 3;
+ ctx->param_vertex_id = key->vs_prolog.num_input_sgprs;
+ ctx->param_instance_id = key->vs_prolog.num_input_sgprs + 3;
/* 4 preloaded VGPRs + vertex load indices as prolog outputs */
params = alloca((key->vs_prolog.num_input_sgprs + 4) *
/* Declare input and output SGPRs. */
num_params = 0;
for (i = 0; i < key->vs_prolog.num_input_sgprs; i++) {
- params[num_params++] = ctx.i32;
- returns[num_returns++] = ctx.i32;
+ params[num_params++] = ctx->i32;
+ returns[num_returns++] = ctx->i32;
}
last_sgpr = num_params - 1;
/* 4 preloaded VGPRs (outputs must be floats) */
for (i = 0; i < 4; i++) {
- params[num_params++] = ctx.i32;
- returns[num_returns++] = ctx.f32;
+ params[num_params++] = ctx->i32;
+ returns[num_returns++] = ctx->f32;
}
/* Vertex load indices. */
for (i = 0; i <= key->vs_prolog.last_input; i++)
- returns[num_returns++] = ctx.f32;
+ returns[num_returns++] = ctx->f32;
/* Create the function. */
- si_create_function(&ctx, returns, num_returns, params,
+ si_create_function(ctx, "vs_prolog", returns, num_returns, params,
num_params, last_sgpr);
- func = ctx.radeon_bld.main_fn;
+ func = ctx->main_fn;
/* Copy inputs to outputs. This should be no-op, as the registers match,
* but it will prevent the compiler from overwriting them unintentionally.
*/
- ret = ctx.return_value;
+ ret = ctx->return_value;
for (i = 0; i < key->vs_prolog.num_input_sgprs; i++) {
LLVMValueRef p = LLVMGetParam(func, i);
ret = LLVMBuildInsertValue(gallivm->builder, ret, p, i, "");
}
for (i = num_params - 4; i < num_params; i++) {
LLVMValueRef p = LLVMGetParam(func, i);
- p = LLVMBuildBitCast(gallivm->builder, p, ctx.f32, "");
+ p = LLVMBuildBitCast(gallivm->builder, p, ctx->f32, "");
ret = LLVMBuildInsertValue(gallivm->builder, ret, p, i, "");
}
if (divisor) {
/* InstanceID / Divisor + StartInstance */
- index = get_instance_index_for_fetch(&ctx.radeon_bld,
+ index = get_instance_index_for_fetch(ctx,
SI_SGPR_START_INSTANCE,
divisor);
} else {
/* VertexID + BaseVertex */
index = LLVMBuildAdd(gallivm->builder,
- LLVMGetParam(func, ctx.param_vertex_id),
+ LLVMGetParam(func, ctx->param_vertex_id),
LLVMGetParam(func, SI_SGPR_BASE_VERTEX), "");
}
- index = LLVMBuildBitCast(gallivm->builder, index, ctx.f32, "");
+ index = LLVMBuildBitCast(gallivm->builder, index, ctx->f32, "");
ret = LLVMBuildInsertValue(gallivm->builder, ret, index,
num_params++, "");
}
+ si_llvm_build_ret(ctx, ret);
+}
+
+/**
+ * Create a vertex shader prolog.
+ */
+static bool si_compile_vs_prolog(struct si_screen *sscreen,
+ LLVMTargetMachineRef tm,
+ struct pipe_debug_callback *debug,
+ struct si_shader_part *out)
+{
+ union si_shader_part_key *key = &out->key;
+ struct si_shader shader = {};
+ struct si_shader_context ctx;
+ struct gallivm_state *gallivm = &ctx.gallivm;
+ bool status = true;
+
+ si_init_shader_ctx(&ctx, sscreen, &shader, tm);
+ ctx.type = PIPE_SHADER_VERTEX;
+
+ si_build_vs_prolog_function(&ctx, key);
+
/* Compile. */
- si_llvm_build_ret(&ctx, ret);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ si_llvm_finalize_module(&ctx,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
"Vertex Shader Prolog"))
status = false;
- radeon_llvm_dispose(&ctx.radeon_bld);
+ si_llvm_dispose(&ctx);
return status;
}
/**
- * Compile the vertex shader epilog. This is also used by the tessellation
+ * Build the vertex shader epilog function. This is also used by the tessellation
* evaluation shader compiled as VS.
*
* The input is PrimitiveID.
* If PrimitiveID is required by the pixel shader, export it.
* Otherwise, do nothing.
*/
-static bool si_compile_vs_epilog(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
- struct pipe_debug_callback *debug,
- struct si_shader_part *out)
+static void si_build_vs_epilog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key)
{
- union si_shader_part_key *key = &out->key;
- struct si_shader_context ctx;
- struct gallivm_state *gallivm = &ctx.radeon_bld.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx.radeon_bld.soa.bld_base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
LLVMTypeRef params[5];
int num_params, i;
- bool status = true;
-
- si_init_shader_ctx(&ctx, sscreen, NULL, tm);
- ctx.type = PIPE_SHADER_VERTEX;
/* Declare input VGPRs. */
num_params = key->vs_epilog.states.export_prim_id ?
assert(num_params <= ARRAY_SIZE(params));
for (i = 0; i < num_params; i++)
- params[i] = ctx.f32;
+ params[i] = ctx->f32;
/* Create the function. */
- si_create_function(&ctx, NULL, 0, params, num_params, -1);
+ si_create_function(ctx, "vs_epilog", NULL, 0, params, num_params, -1);
/* Emit exports. */
if (key->vs_epilog.states.export_prim_id) {
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.radeon_bld.main_fn,
+ args[5] = LLVMGetParam(ctx->main_fn,
VS_EPILOG_PRIMID_LOC); /* X */
- args[6] = uint->undef; /* Y */
- args[7] = uint->undef; /* Z */
- args[8] = uint->undef; /* W */
+ args[6] = base->undef; /* Y */
+ args[7] = base->undef; /* Z */
+ args[8] = base->undef; /* W */
lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
LLVMVoidTypeInContext(base->gallivm->context),
args, 9, 0);
}
+ LLVMBuildRetVoid(gallivm->builder);
+}
+
+/**
+ * Compile the vertex shader epilog. This is also used by the tessellation
+ * evaluation shader compiled as VS.
+ */
+static bool si_compile_vs_epilog(struct si_screen *sscreen,
+ LLVMTargetMachineRef tm,
+ struct pipe_debug_callback *debug,
+ struct si_shader_part *out)
+{
+ union si_shader_part_key *key = &out->key;
+ struct si_shader_context ctx;
+ struct gallivm_state *gallivm = &ctx.gallivm;
+ bool status = true;
+
+ si_init_shader_ctx(&ctx, sscreen, NULL, tm);
+ ctx.type = PIPE_SHADER_VERTEX;
+
+ si_build_vs_epilog_function(&ctx, key);
+
/* Compile. */
- LLVMBuildRetVoid(gallivm->builder);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ si_llvm_finalize_module(&ctx,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
"Vertex Shader Epilog"))
status = false;
- radeon_llvm_dispose(&ctx.radeon_bld);
+ si_llvm_dispose(&ctx);
return status;
}
{
union si_shader_part_key epilog_key;
- memset(&epilog_key, 0, sizeof(epilog_key));
- epilog_key.vs_epilog.states = *states;
-
- /* Set up the PrimitiveID output. */
- if (shader->key.vs.epilog.export_prim_id) {
- unsigned index = shader->selector->info.num_outputs;
- unsigned offset = shader->info.nr_param_exports++;
-
- epilog_key.vs_epilog.prim_id_param_offset = offset;
- assert(index < ARRAY_SIZE(shader->info.vs_output_param_offset));
- shader->info.vs_output_param_offset[index] = offset;
- }
+ si_get_vs_epilog_key(shader, states, &epilog_key);
shader->epilog = si_get_shader_part(sscreen, &sscreen->vs_epilogs,
&epilog_key, tm, debug,
{
struct tgsi_shader_info *info = &shader->selector->info;
union si_shader_part_key prolog_key;
- unsigned i;
/* Get the prolog. */
- memset(&prolog_key, 0, sizeof(prolog_key));
- prolog_key.vs_prolog.states = shader->key.vs.prolog;
- prolog_key.vs_prolog.num_input_sgprs = shader->info.num_input_sgprs;
- prolog_key.vs_prolog.last_input = MAX2(1, info->num_inputs) - 1;
+ si_get_vs_prolog_key(shader, &prolog_key);
/* The prolog is a no-op if there are no inputs. */
if (info->num_inputs) {
&shader->key.vs.epilog))
return false;
- /* Set the instanceID flag. */
- for (i = 0; i < info->num_inputs; i++)
- if (prolog_key.vs_prolog.states.instance_divisors[i])
- shader->info.uses_instanceid = true;
-
return true;
}
union si_shader_part_key *key = &out->key;
struct si_shader shader = {};
struct si_shader_context ctx;
- struct gallivm_state *gallivm = &ctx.radeon_bld.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx.radeon_bld.soa.bld_base;
+ struct gallivm_state *gallivm = &ctx.gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx.soa.bld_base;
LLVMTypeRef params[16];
LLVMValueRef func;
int last_sgpr, num_params;
params[num_params++] = ctx.i32; /* LDS offset where tess factors should be loaded from */
/* Create the function. */
- si_create_function(&ctx, NULL, 0, params, num_params, last_sgpr);
+ si_create_function(&ctx, "tcs_epilog", NULL, 0, params, num_params, last_sgpr);
declare_tess_lds(&ctx);
- func = ctx.radeon_bld.main_fn;
+ func = ctx.main_fn;
si_write_tess_factors(bld_base,
LLVMGetParam(func, last_sgpr + 1),
/* Compile. */
LLVMBuildRetVoid(gallivm->builder);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ si_llvm_finalize_module(&ctx,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_TESS_CTRL));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
"Tessellation Control Shader Epilog"))
status = false;
- radeon_llvm_dispose(&ctx.radeon_bld);
+ si_llvm_dispose(&ctx);
return status;
}
}
/**
- * Compile the pixel shader prolog. This handles:
+ * Build the pixel shader prolog function. This handles:
* - two-side color selection and interpolation
* - overriding interpolation parameters for the API PS
* - polygon stippling
* overriden by other states. (e.g. per-sample interpolation)
* Interpolated colors are stored after the preloaded VGPRs.
*/
-static bool si_compile_ps_prolog(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
- struct pipe_debug_callback *debug,
- struct si_shader_part *out)
+static void si_build_ps_prolog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key)
{
- union si_shader_part_key *key = &out->key;
- struct si_shader shader = {};
- struct si_shader_context ctx;
- struct gallivm_state *gallivm = &ctx.radeon_bld.gallivm;
+ struct gallivm_state *gallivm = &ctx->gallivm;
LLVMTypeRef *params;
LLVMValueRef ret, func;
int last_sgpr, num_params, num_returns, i, num_color_channels;
- bool status = true;
- si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = PIPE_SHADER_FRAGMENT;
- shader.key.ps.prolog = key->ps_prolog.states;
+ assert(si_need_ps_prolog(key));
/* Number of inputs + 8 color elements. */
params = alloca((key->ps_prolog.num_input_sgprs +
/* Declare inputs. */
num_params = 0;
for (i = 0; i < key->ps_prolog.num_input_sgprs; i++)
- params[num_params++] = ctx.i32;
+ params[num_params++] = ctx->i32;
last_sgpr = num_params - 1;
for (i = 0; i < key->ps_prolog.num_input_vgprs; i++)
- params[num_params++] = ctx.f32;
+ params[num_params++] = ctx->f32;
/* Declare outputs (same as inputs + add colors if needed) */
num_returns = num_params;
num_color_channels = util_bitcount(key->ps_prolog.colors_read);
for (i = 0; i < num_color_channels; i++)
- params[num_returns++] = ctx.f32;
+ params[num_returns++] = ctx->f32;
/* Create the function. */
- si_create_function(&ctx, params, num_returns, params,
+ si_create_function(ctx, "ps_prolog", params, num_returns, params,
num_params, last_sgpr);
- func = ctx.radeon_bld.main_fn;
+ func = ctx->main_fn;
/* Copy inputs to outputs. This should be no-op, as the registers match,
* but it will prevent the compiler from overwriting them unintentionally.
*/
- ret = ctx.return_value;
+ ret = ctx->return_value;
for (i = 0; i < num_params; i++) {
LLVMValueRef p = LLVMGetParam(func, i);
ret = LLVMBuildInsertValue(gallivm->builder, ret, p, i, "");
ptr[0] = LLVMGetParam(func, SI_SGPR_RW_BUFFERS);
ptr[1] = LLVMGetParam(func, SI_SGPR_RW_BUFFERS_HI);
list = lp_build_gather_values(gallivm, ptr, 2);
- list = LLVMBuildBitCast(gallivm->builder, list, ctx.i64, "");
+ list = LLVMBuildBitCast(gallivm->builder, list, ctx->i64, "");
list = LLVMBuildIntToPtr(gallivm->builder, list,
- const_array(ctx.v16i8, SI_NUM_RW_BUFFERS), "");
+ const_array(ctx->v16i8, SI_NUM_RW_BUFFERS), "");
- si_llvm_emit_polygon_stipple(&ctx, list, pos);
+ si_llvm_emit_polygon_stipple(ctx, list, pos);
}
if (key->ps_prolog.states.bc_optimize_for_persp ||
*/
bc_optimize = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
bc_optimize = LLVMBuildLShr(gallivm->builder, bc_optimize,
- LLVMConstInt(ctx.i32, 31, 0), "");
+ LLVMConstInt(ctx->i32, 31, 0), "");
bc_optimize = LLVMBuildTrunc(gallivm->builder, bc_optimize,
- ctx.i1, "");
+ ctx->i1, "");
if (key->ps_prolog.states.bc_optimize_for_persp) {
/* Read PERSP_CENTER. */
}
}
- /* Interpolate colors. */
- for (i = 0; i < 2; i++) {
- unsigned writemask = (key->ps_prolog.colors_read >> (i * 4)) & 0xf;
- unsigned face_vgpr = key->ps_prolog.num_input_sgprs +
- key->ps_prolog.face_vgpr_index;
- LLVMValueRef interp[2], color[4];
- LLVMValueRef interp_ij = NULL, prim_mask = NULL, face = NULL;
-
- if (!writemask)
- continue;
-
- /* If the interpolation qualifier is not CONSTANT (-1). */
- if (key->ps_prolog.color_interp_vgpr_index[i] != -1) {
- unsigned interp_vgpr = key->ps_prolog.num_input_sgprs +
- key->ps_prolog.color_interp_vgpr_index[i];
-
- /* Get the (i,j) updated by bc_optimize handling. */
- interp[0] = LLVMBuildExtractValue(gallivm->builder, ret,
- interp_vgpr, "");
- interp[1] = LLVMBuildExtractValue(gallivm->builder, ret,
- interp_vgpr + 1, "");
- interp_ij = lp_build_gather_values(gallivm, interp, 2);
- interp_ij = LLVMBuildBitCast(gallivm->builder, interp_ij,
- ctx.v2i32, "");
- }
-
- /* Use the absolute location of the input. */
- prim_mask = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
-
- if (key->ps_prolog.states.color_two_side) {
- face = LLVMGetParam(func, face_vgpr);
- face = LLVMBuildBitCast(gallivm->builder, face, ctx.i32, "");
- }
-
- interp_fs_input(&ctx,
- key->ps_prolog.color_attr_index[i],
- TGSI_SEMANTIC_COLOR, i,
- key->ps_prolog.num_interp_inputs,
- key->ps_prolog.colors_read, interp_ij,
- prim_mask, face, color);
-
- while (writemask) {
- unsigned chan = u_bit_scan(&writemask);
- ret = LLVMBuildInsertValue(gallivm->builder, ret, color[chan],
- num_params++, "");
- }
- }
-
/* Force per-sample interpolation. */
if (key->ps_prolog.states.force_persp_sample_interp) {
unsigned i, base = key->ps_prolog.num_input_sgprs;
linear_center[i], base + 10 + i, "");
}
+ /* Interpolate colors. */
+ for (i = 0; i < 2; i++) {
+ unsigned writemask = (key->ps_prolog.colors_read >> (i * 4)) & 0xf;
+ unsigned face_vgpr = key->ps_prolog.num_input_sgprs +
+ key->ps_prolog.face_vgpr_index;
+ LLVMValueRef interp[2], color[4];
+ LLVMValueRef interp_ij = NULL, prim_mask = NULL, face = NULL;
+
+ if (!writemask)
+ continue;
+
+ /* If the interpolation qualifier is not CONSTANT (-1). */
+ if (key->ps_prolog.color_interp_vgpr_index[i] != -1) {
+ unsigned interp_vgpr = key->ps_prolog.num_input_sgprs +
+ key->ps_prolog.color_interp_vgpr_index[i];
+
+ /* Get the (i,j) updated by bc_optimize handling. */
+ interp[0] = LLVMBuildExtractValue(gallivm->builder, ret,
+ interp_vgpr, "");
+ interp[1] = LLVMBuildExtractValue(gallivm->builder, ret,
+ interp_vgpr + 1, "");
+ interp_ij = lp_build_gather_values(gallivm, interp, 2);
+ interp_ij = LLVMBuildBitCast(gallivm->builder, interp_ij,
+ ctx->v2i32, "");
+ }
+
+ /* Use the absolute location of the input. */
+ prim_mask = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
+
+ if (key->ps_prolog.states.color_two_side) {
+ face = LLVMGetParam(func, face_vgpr);
+ face = LLVMBuildBitCast(gallivm->builder, face, ctx->i32, "");
+ }
+
+ interp_fs_input(ctx,
+ key->ps_prolog.color_attr_index[i],
+ TGSI_SEMANTIC_COLOR, i,
+ key->ps_prolog.num_interp_inputs,
+ key->ps_prolog.colors_read, interp_ij,
+ prim_mask, face, color);
+
+ while (writemask) {
+ unsigned chan = u_bit_scan(&writemask);
+ ret = LLVMBuildInsertValue(gallivm->builder, ret, color[chan],
+ num_params++, "");
+ }
+ }
+
/* Tell LLVM to insert WQM instruction sequence when needed. */
if (key->ps_prolog.wqm) {
LLVMAddTargetDependentFunctionAttr(func,
"amdgpu-ps-wqm-outputs", "");
}
+ si_llvm_build_ret(ctx, ret);
+}
+
+/**
+ * Compile the pixel shader prolog.
+ */
+static bool si_compile_ps_prolog(struct si_screen *sscreen,
+ LLVMTargetMachineRef tm,
+ struct pipe_debug_callback *debug,
+ struct si_shader_part *out)
+{
+ union si_shader_part_key *key = &out->key;
+ struct si_shader shader = {};
+ struct si_shader_context ctx;
+ struct gallivm_state *gallivm = &ctx.gallivm;
+ bool status = true;
+
+ si_init_shader_ctx(&ctx, sscreen, &shader, tm);
+ ctx.type = PIPE_SHADER_FRAGMENT;
+ shader.key.ps.prolog = key->ps_prolog.states;
+
+ si_build_ps_prolog_function(&ctx, key);
+
/* Compile. */
- si_llvm_build_ret(&ctx, ret);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ si_llvm_finalize_module(&ctx,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
"Fragment Shader Prolog"))
status = false;
- radeon_llvm_dispose(&ctx.radeon_bld);
+ si_llvm_dispose(&ctx);
return status;
}
/**
- * Compile the pixel shader epilog. This handles everything that must be
+ * Build the pixel shader epilog function. This handles everything that must be
* emulated for pixel shader exports. (alpha-test, format conversions, etc)
*/
-static bool si_compile_ps_epilog(struct si_screen *sscreen,
- LLVMTargetMachineRef tm,
- struct pipe_debug_callback *debug,
- struct si_shader_part *out)
+static void si_build_ps_epilog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key)
{
- union si_shader_part_key *key = &out->key;
- struct si_shader shader = {};
- struct si_shader_context ctx;
- struct gallivm_state *gallivm = &ctx.radeon_bld.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx.radeon_bld.soa.bld_base;
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
LLVMTypeRef params[16+8*4+3];
LLVMValueRef depth = NULL, stencil = NULL, samplemask = NULL;
int last_sgpr, num_params, i;
- bool status = true;
struct si_ps_exports exp = {};
- si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = PIPE_SHADER_FRAGMENT;
- shader.key.ps.epilog = key->ps_epilog.states;
-
/* Declare input SGPRs. */
- params[SI_PARAM_RW_BUFFERS] = ctx.i64;
- params[SI_PARAM_CONST_BUFFERS] = ctx.i64;
- params[SI_PARAM_SAMPLERS] = ctx.i64;
- params[SI_PARAM_IMAGES] = ctx.i64;
- params[SI_PARAM_SHADER_BUFFERS] = ctx.i64;
- params[SI_PARAM_ALPHA_REF] = ctx.f32;
+ params[SI_PARAM_RW_BUFFERS] = ctx->i64;
+ params[SI_PARAM_CONST_BUFFERS] = ctx->i64;
+ params[SI_PARAM_SAMPLERS] = ctx->i64;
+ params[SI_PARAM_IMAGES] = ctx->i64;
+ params[SI_PARAM_SHADER_BUFFERS] = ctx->i64;
+ params[SI_PARAM_ALPHA_REF] = ctx->f32;
last_sgpr = SI_PARAM_ALPHA_REF;
/* Declare input VGPRs. */
assert(num_params <= ARRAY_SIZE(params));
for (i = last_sgpr + 1; i < num_params; i++)
- params[i] = ctx.f32;
+ params[i] = ctx->f32;
/* Create the function. */
- si_create_function(&ctx, NULL, 0, params, num_params, last_sgpr);
+ si_create_function(ctx, "ps_epilog", NULL, 0, params, num_params, last_sgpr);
/* Disable elimination of unused inputs. */
- radeon_llvm_add_attribute(ctx.radeon_bld.main_fn,
+ si_llvm_add_attribute(ctx->main_fn,
"InitialPSInputAddr", 0xffffff);
/* Process colors. */
int mrt = u_bit_scan(&colors_written);
for (i = 0; i < 4; i++)
- color[i] = LLVMGetParam(ctx.radeon_bld.main_fn, vgpr++);
+ color[i] = LLVMGetParam(ctx->main_fn, vgpr++);
si_export_mrt_color(bld_base, color, mrt,
num_params - 1,
/* Process depth, stencil, samplemask. */
if (key->ps_epilog.writes_z)
- depth = LLVMGetParam(ctx.radeon_bld.main_fn, vgpr++);
+ depth = LLVMGetParam(ctx->main_fn, vgpr++);
if (key->ps_epilog.writes_stencil)
- stencil = LLVMGetParam(ctx.radeon_bld.main_fn, vgpr++);
+ stencil = LLVMGetParam(ctx->main_fn, vgpr++);
if (key->ps_epilog.writes_samplemask)
- samplemask = LLVMGetParam(ctx.radeon_bld.main_fn, vgpr++);
+ samplemask = LLVMGetParam(ctx->main_fn, vgpr++);
if (depth || stencil || samplemask)
si_export_mrt_z(bld_base, depth, stencil, samplemask, &exp);
si_export_null(bld_base);
if (exp.num)
- si_emit_ps_exports(&ctx, &exp);
+ si_emit_ps_exports(ctx, &exp);
/* Compile. */
LLVMBuildRetVoid(gallivm->builder);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+}
+
+
+/**
+ * Compile the pixel shader epilog to a binary for concatenation.
+ */
+static bool si_compile_ps_epilog(struct si_screen *sscreen,
+ LLVMTargetMachineRef tm,
+ struct pipe_debug_callback *debug,
+ struct si_shader_part *out)
+{
+ union si_shader_part_key *key = &out->key;
+ struct si_shader shader = {};
+ struct si_shader_context ctx;
+ struct gallivm_state *gallivm = &ctx.gallivm;
+ bool status = true;
+
+ si_init_shader_ctx(&ctx, sscreen, &shader, tm);
+ ctx.type = PIPE_SHADER_FRAGMENT;
+ shader.key.ps.epilog = key->ps_epilog.states;
+
+ si_build_ps_epilog_function(&ctx, key);
+
+ /* Compile. */
+ si_llvm_finalize_module(&ctx,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
"Fragment Shader Epilog"))
status = false;
- radeon_llvm_dispose(&ctx.radeon_bld);
+ si_llvm_dispose(&ctx);
return status;
}
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
- struct tgsi_shader_info *info = &shader->selector->info;
union si_shader_part_key prolog_key;
union si_shader_part_key epilog_key;
- unsigned i;
/* Get the prolog. */
- memset(&prolog_key, 0, sizeof(prolog_key));
- prolog_key.ps_prolog.states = shader->key.ps.prolog;
- prolog_key.ps_prolog.colors_read = info->colors_read;
- prolog_key.ps_prolog.num_input_sgprs = shader->info.num_input_sgprs;
- prolog_key.ps_prolog.num_input_vgprs = shader->info.num_input_vgprs;
- prolog_key.ps_prolog.wqm = info->uses_derivatives &&
- (prolog_key.ps_prolog.colors_read ||
- prolog_key.ps_prolog.states.force_persp_sample_interp ||
- prolog_key.ps_prolog.states.force_linear_sample_interp ||
- prolog_key.ps_prolog.states.force_persp_center_interp ||
- prolog_key.ps_prolog.states.force_linear_center_interp ||
- prolog_key.ps_prolog.states.bc_optimize_for_persp ||
- prolog_key.ps_prolog.states.bc_optimize_for_linear);
-
- if (info->colors_read) {
- unsigned *color = shader->selector->color_attr_index;
-
- if (shader->key.ps.prolog.color_two_side) {
- /* BCOLORs are stored after the last input. */
- prolog_key.ps_prolog.num_interp_inputs = info->num_inputs;
- prolog_key.ps_prolog.face_vgpr_index = shader->info.face_vgpr_index;
- shader->config.spi_ps_input_ena |= S_0286CC_FRONT_FACE_ENA(1);
- }
-
- for (i = 0; i < 2; i++) {
- unsigned interp = info->input_interpolate[color[i]];
- unsigned location = info->input_interpolate_loc[color[i]];
-
- if (!(info->colors_read & (0xf << i*4)))
- continue;
-
- prolog_key.ps_prolog.color_attr_index[i] = color[i];
-
- if (shader->key.ps.prolog.flatshade_colors &&
- interp == TGSI_INTERPOLATE_COLOR)
- interp = TGSI_INTERPOLATE_CONSTANT;
-
- switch (interp) {
- case TGSI_INTERPOLATE_CONSTANT:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = -1;
- break;
- case TGSI_INTERPOLATE_PERSPECTIVE:
- case TGSI_INTERPOLATE_COLOR:
- /* Force the interpolation location for colors here. */
- if (shader->key.ps.prolog.force_persp_sample_interp)
- location = TGSI_INTERPOLATE_LOC_SAMPLE;
- if (shader->key.ps.prolog.force_persp_center_interp)
- location = TGSI_INTERPOLATE_LOC_CENTER;
-
- switch (location) {
- case TGSI_INTERPOLATE_LOC_SAMPLE:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = 0;
- shader->config.spi_ps_input_ena |=
- S_0286CC_PERSP_SAMPLE_ENA(1);
- break;
- case TGSI_INTERPOLATE_LOC_CENTER:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = 2;
- shader->config.spi_ps_input_ena |=
- S_0286CC_PERSP_CENTER_ENA(1);
- break;
- case TGSI_INTERPOLATE_LOC_CENTROID:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = 4;
- shader->config.spi_ps_input_ena |=
- S_0286CC_PERSP_CENTROID_ENA(1);
- break;
- default:
- assert(0);
- }
- break;
- case TGSI_INTERPOLATE_LINEAR:
- /* Force the interpolation location for colors here. */
- if (shader->key.ps.prolog.force_linear_sample_interp)
- location = TGSI_INTERPOLATE_LOC_SAMPLE;
- if (shader->key.ps.prolog.force_linear_center_interp)
- location = TGSI_INTERPOLATE_LOC_CENTER;
-
- switch (location) {
- case TGSI_INTERPOLATE_LOC_SAMPLE:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = 6;
- shader->config.spi_ps_input_ena |=
- S_0286CC_LINEAR_SAMPLE_ENA(1);
- break;
- case TGSI_INTERPOLATE_LOC_CENTER:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = 8;
- shader->config.spi_ps_input_ena |=
- S_0286CC_LINEAR_CENTER_ENA(1);
- break;
- case TGSI_INTERPOLATE_LOC_CENTROID:
- prolog_key.ps_prolog.color_interp_vgpr_index[i] = 10;
- shader->config.spi_ps_input_ena |=
- S_0286CC_LINEAR_CENTROID_ENA(1);
- break;
- default:
- assert(0);
- }
- break;
- default:
- assert(0);
- }
- }
- }
+ si_get_ps_prolog_key(shader, &prolog_key, true);
/* The prolog is a no-op if these aren't set. */
- if (prolog_key.ps_prolog.colors_read ||
- prolog_key.ps_prolog.states.force_persp_sample_interp ||
- prolog_key.ps_prolog.states.force_linear_sample_interp ||
- prolog_key.ps_prolog.states.force_persp_center_interp ||
- prolog_key.ps_prolog.states.force_linear_center_interp ||
- prolog_key.ps_prolog.states.bc_optimize_for_persp ||
- prolog_key.ps_prolog.states.bc_optimize_for_linear ||
- prolog_key.ps_prolog.states.poly_stipple) {
+ if (si_need_ps_prolog(&prolog_key)) {
shader->prolog =
si_get_shader_part(sscreen, &sscreen->ps_prologs,
&prolog_key, tm, debug,
}
/* Get the epilog. */
- memset(&epilog_key, 0, sizeof(epilog_key));
- epilog_key.ps_epilog.colors_written = info->colors_written;
- epilog_key.ps_epilog.writes_z = info->writes_z;
- epilog_key.ps_epilog.writes_stencil = info->writes_stencil;
- epilog_key.ps_epilog.writes_samplemask = info->writes_samplemask;
- epilog_key.ps_epilog.states = shader->key.ps.epilog;
+ si_get_ps_epilog_key(shader, &epilog_key);
shader->epilog =
si_get_shader_part(sscreen, &sscreen->ps_epilogs,
struct si_shader *shader,
struct pipe_debug_callback *debug)
{
- struct si_shader *mainp = shader->selector->main_shader_part;
+ struct si_shader_selector *sel = shader->selector;
+ struct si_shader *mainp = sel->main_shader_part;
int r;
/* LS, ES, VS are compiled on demand if the main part hasn't been
* compiled for that stage.
*/
if (!mainp ||
- (shader->selector->type == PIPE_SHADER_VERTEX &&
+ (sel->type == PIPE_SHADER_VERTEX &&
(shader->key.vs.as_es != mainp->key.vs.as_es ||
shader->key.vs.as_ls != mainp->key.vs.as_ls)) ||
- (shader->selector->type == PIPE_SHADER_TESS_EVAL &&
+ (sel->type == PIPE_SHADER_TESS_EVAL &&
shader->key.tes.as_es != mainp->key.tes.as_es) ||
- (shader->selector->type == PIPE_SHADER_TESS_CTRL &&
+ (sel->type == PIPE_SHADER_TESS_CTRL &&
shader->key.tcs.epilog.inputs_to_copy) ||
- shader->selector->type == PIPE_SHADER_COMPUTE) {
+ sel->type == PIPE_SHADER_COMPUTE) {
/* Monolithic shader (compiled as a whole, has many variants,
* may take a long time to compile).
*/
shader->info.nr_param_exports = mainp->info.nr_param_exports;
/* Select prologs and/or epilogs. */
- switch (shader->selector->type) {
+ switch (sel->type) {
case PIPE_SHADER_VERTEX:
if (!si_shader_select_vs_parts(sscreen, tm, shader, debug))
return -1;
}
si_fix_num_sgprs(shader);
- si_shader_dump(sscreen, shader, debug, shader->selector->info.processor,
+ si_shader_dump(sscreen, shader, debug, sel->info.processor,
stderr);
/* Upload. */