#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 "radeon/r600_cs.h"
+#include "gallivm/lp_bld_misc.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_pstipple.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 "si_pipe.h"
-#include "si_shader.h"
#include "sid.h"
-#include <errno.h>
static const char *scratch_rsrc_dword0_symbol =
"SCRATCH_RSRC_DWORD0";
struct si_shader *shader;
struct si_screen *screen;
- unsigned type; /* TGSI_PROCESSOR_* specifies the type of shader. */
+ 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
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;
- LLVMValueRef const_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];
+ unsigned invariant_load_md_kind;
+ unsigned range_md_kind;
+ unsigned uniform_md_kind;
+ LLVMValueRef empty_md;
+
+ /* Preloaded descriptors. */
LLVMValueRef esgs_ring;
LLVMValueRef gsvs_ring[4];
+
+ LLVMValueRef lds;
LLVMValueRef gs_next_vertex[4];
LLVMValueRef return_value;
struct si_shader *shader,
LLVMTargetMachineRef tm);
+static void si_llvm_emit_barrier(const struct lp_build_tgsi_action *action,
+ struct lp_build_tgsi_context *bld_base,
+ struct lp_build_emit_data *emit_data);
+
+static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
+ FILE *f);
+
/* 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
static LLVMValueRef get_rel_patch_id(struct si_shader_context *ctx)
{
switch (ctx->type) {
- case TGSI_PROCESSOR_TESS_CTRL:
+ case PIPE_SHADER_TESS_CTRL:
return unpack_param(ctx, SI_PARAM_REL_IDS, 0, 8);
- case TGSI_PROCESSOR_TESS_EVAL:
+ case PIPE_SHADER_TESS_EVAL:
return LLVMGetParam(ctx->radeon_bld.main_fn,
ctx->param_tes_rel_patch_id);
static LLVMValueRef
get_tcs_in_patch_stride(struct si_shader_context *ctx)
{
- if (ctx->type == TGSI_PROCESSOR_VERTEX)
+ if (ctx->type == PIPE_SHADER_VERTEX)
return unpack_param(ctx, SI_PARAM_LS_OUT_LAYOUT, 0, 13);
- else if (ctx->type == TGSI_PROCESSOR_TESS_CTRL)
+ else if (ctx->type == PIPE_SHADER_TESS_CTRL)
return unpack_param(ctx, SI_PARAM_TCS_IN_LAYOUT, 0, 13);
else {
assert(0);
"");
}
+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->radeon_bld.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 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));
}
/**
*
* \param base_ptr Where the array starts.
* \param index The element index into the array.
+ * \param uniform Whether the base_ptr and index can be assumed to be
+ * dynamically uniform
*/
static LLVMValueRef build_indexed_load(struct si_shader_context *ctx,
- LLVMValueRef base_ptr, LLVMValueRef index)
+ LLVMValueRef base_ptr, LLVMValueRef index,
+ bool uniform)
{
struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.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, "");
}
/**
* Do a load from &base_ptr[index], but also add a flag that it's loading
- * a constant.
+ * a constant from a dynamically uniform index.
*/
static LLVMValueRef build_indexed_load_const(
struct si_shader_context *ctx,
LLVMValueRef base_ptr, LLVMValueRef index)
{
- LLVMValueRef result = build_indexed_load(ctx, base_ptr, index);
- LLVMSetMetadata(result, 1, ctx->const_md);
+ LLVMValueRef result = build_indexed_load(ctx, base_ptr, index, true);
+ LLVMSetMetadata(result, ctx->invariant_load_md_kind, ctx->empty_md);
return result;
}
static void declare_input_vs(
struct radeon_llvm_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;
args[2] = buffer_index;
input = lp_build_intrinsic(gallivm->builder,
"llvm.SI.vs.load.input", ctx->v4f32, args, 3,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
/* 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, "");
}
}
return bld_base->uint_bld.zero;
switch (ctx->type) {
- case TGSI_PROCESSOR_VERTEX:
+ case PIPE_SHADER_VERTEX:
return LLVMGetParam(ctx->radeon_bld.main_fn,
ctx->param_vs_prim_id);
- case TGSI_PROCESSOR_TESS_CTRL:
+ case PIPE_SHADER_TESS_CTRL:
return LLVMGetParam(ctx->radeon_bld.main_fn,
SI_PARAM_PATCH_ID);
- case TGSI_PROCESSOR_TESS_EVAL:
+ case PIPE_SHADER_TESS_EVAL:
return LLVMGetParam(ctx->radeon_bld.main_fn,
ctx->param_tes_patch_id);
- case TGSI_PROCESSOR_GEOMETRY:
+ case PIPE_SHADER_GEOMETRY:
return LLVMGetParam(ctx->radeon_bld.main_fn,
SI_PARAM_PRIMITIVE_ID);
default:
const struct tgsi_ind_register *ind,
int rel_index, unsigned num)
{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef result = get_indirect_index(ctx, ind, rel_index);
- LLVMValueRef c_max = LLVMConstInt(ctx->i32, num - 1, 0);
- LLVMValueRef cc;
- if (util_is_power_of_two(num)) {
- result = LLVMBuildAnd(builder, result, c_max, "");
- } else {
- /* In theory, this MAX pattern should result in code that is
- * as good as the bit-wise AND above.
- *
- * In practice, LLVM generates worse code (at the time of
- * writing), because its value tracking is not strong enough.
- */
- cc = LLVMBuildICmp(builder, LLVMIntULE, result, c_max, "");
- result = LLVMBuildSelect(builder, cc, result, c_max, "");
- }
+ /* LLVM 3.8: If indirect resource indexing is used:
+ * - SI & CIK hang
+ * - VI crashes
+ */
+ if (HAVE_LLVM <= 0x0308)
+ return LLVMGetUndef(ctx->i32);
- return result;
+ return radeon_llvm_bound_index(&ctx->radeon_bld, result, num);
}
lp_build_const_int32(gallivm, param * 4), "");
}
+/* The offchip buffer layout for TCS->TES is
+ *
+ * - attribute 0 of patch 0 vertex 0
+ * - attribute 0 of patch 0 vertex 1
+ * - attribute 0 of patch 0 vertex 2
+ * ...
+ * - attribute 0 of patch 1 vertex 0
+ * - attribute 0 of patch 1 vertex 1
+ * ...
+ * - attribute 1 of patch 0 vertex 0
+ * - attribute 1 of patch 0 vertex 1
+ * ...
+ * - per patch attribute 0 of patch 0
+ * - per patch attribute 0 of patch 1
+ * ...
+ *
+ * Note that every attribute has 4 components.
+ */
+static LLVMValueRef get_tcs_tes_buffer_address(struct si_shader_context *ctx,
+ LLVMValueRef vertex_index,
+ LLVMValueRef param_index)
+{
+ struct gallivm_state *gallivm = ctx->radeon_bld.soa.bld_base.base.gallivm;
+ LLVMValueRef base_addr, vertices_per_patch, num_patches, total_vertices;
+ LLVMValueRef param_stride, constant16;
+
+ vertices_per_patch = unpack_param(ctx, SI_PARAM_TCS_OFFCHIP_LAYOUT, 9, 6);
+ num_patches = unpack_param(ctx, SI_PARAM_TCS_OFFCHIP_LAYOUT, 0, 9);
+ total_vertices = LLVMBuildMul(gallivm->builder, vertices_per_patch,
+ num_patches, "");
+
+ constant16 = lp_build_const_int32(gallivm, 16);
+ if (vertex_index) {
+ base_addr = LLVMBuildMul(gallivm->builder, get_rel_patch_id(ctx),
+ vertices_per_patch, "");
+
+ base_addr = LLVMBuildAdd(gallivm->builder, base_addr,
+ vertex_index, "");
+
+ param_stride = total_vertices;
+ } else {
+ base_addr = get_rel_patch_id(ctx);
+ param_stride = num_patches;
+ }
+
+ base_addr = LLVMBuildAdd(gallivm->builder, base_addr,
+ LLVMBuildMul(gallivm->builder, param_index,
+ param_stride, ""), "");
+
+ base_addr = LLVMBuildMul(gallivm->builder, base_addr, constant16, "");
+
+ if (!vertex_index) {
+ LLVMValueRef patch_data_offset =
+ unpack_param(ctx, SI_PARAM_TCS_OFFCHIP_LAYOUT, 16, 16);
+
+ base_addr = LLVMBuildAdd(gallivm->builder, base_addr,
+ patch_data_offset, "");
+ }
+ return base_addr;
+}
+
+static LLVMValueRef get_tcs_tes_buffer_address_from_reg(
+ struct si_shader_context *ctx,
+ 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 tgsi_shader_info *info = &ctx->shader->selector->info;
+ ubyte *name, *index, *array_first;
+ struct tgsi_full_src_register reg;
+ LLVMValueRef vertex_index = NULL;
+ LLVMValueRef param_index = NULL;
+ unsigned param_index_base, param_base;
+
+ reg = src ? *src : tgsi_full_src_register_from_dst(dst);
+
+ if (reg.Register.Dimension) {
+
+ if (reg.Dimension.Indirect)
+ vertex_index = get_indirect_index(ctx, ®.DimIndirect,
+ reg.Dimension.Index);
+ else
+ vertex_index = lp_build_const_int32(gallivm,
+ reg.Dimension.Index);
+ }
+
+ /* Get information about the register. */
+ if (reg.Register.File == TGSI_FILE_INPUT) {
+ name = info->input_semantic_name;
+ index = info->input_semantic_index;
+ array_first = info->input_array_first;
+ } else if (reg.Register.File == TGSI_FILE_OUTPUT) {
+ name = info->output_semantic_name;
+ index = info->output_semantic_index;
+ array_first = info->output_array_first;
+ } else {
+ assert(0);
+ return NULL;
+ }
+
+ if (reg.Register.Indirect) {
+ if (reg.Indirect.ArrayID)
+ param_base = array_first[reg.Indirect.ArrayID];
+ else
+ param_base = reg.Register.Index;
+
+ param_index = get_indirect_index(ctx, ®.Indirect,
+ reg.Register.Index - param_base);
+
+ } else {
+ param_base = reg.Register.Index;
+ param_index = lp_build_const_int32(gallivm, 0);
+ }
+
+ param_index_base = si_shader_io_get_unique_index(name[param_base],
+ index[param_base]);
+
+ param_index = LLVMBuildAdd(gallivm->builder, param_index,
+ lp_build_const_int32(gallivm, param_index_base),
+ "");
+
+ return get_tcs_tes_buffer_address(ctx, vertex_index, param_index);
+}
+
+/* TBUFFER_STORE_FORMAT_{X,XY,XYZ,XYZW} <- the suffix is selected by num_channels=1..4.
+ * The type of vdata must be one of i32 (num_channels=1), v2i32 (num_channels=2),
+ * or v4i32 (num_channels=3,4). */
+static void build_tbuffer_store(struct si_shader_context *ctx,
+ LLVMValueRef rsrc,
+ LLVMValueRef vdata,
+ unsigned num_channels,
+ LLVMValueRef vaddr,
+ LLVMValueRef soffset,
+ unsigned inst_offset,
+ unsigned dfmt,
+ unsigned nfmt,
+ unsigned offen,
+ unsigned idxen,
+ unsigned glc,
+ unsigned slc,
+ unsigned tfe)
+{
+ struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ LLVMValueRef args[] = {
+ rsrc,
+ vdata,
+ LLVMConstInt(ctx->i32, num_channels, 0),
+ vaddr,
+ soffset,
+ LLVMConstInt(ctx->i32, inst_offset, 0),
+ LLVMConstInt(ctx->i32, dfmt, 0),
+ LLVMConstInt(ctx->i32, nfmt, 0),
+ LLVMConstInt(ctx->i32, offen, 0),
+ LLVMConstInt(ctx->i32, idxen, 0),
+ LLVMConstInt(ctx->i32, glc, 0),
+ LLVMConstInt(ctx->i32, slc, 0),
+ LLVMConstInt(ctx->i32, tfe, 0)
+ };
+
+ /* The instruction offset field has 12 bits */
+ assert(offen || inst_offset < (1 << 12));
+
+ /* The intrinsic is overloaded, we need to add a type suffix for overloading to work. */
+ unsigned func = CLAMP(num_channels, 1, 3) - 1;
+ const char *types[] = {"i32", "v2i32", "v4i32"};
+ char name[256];
+ snprintf(name, sizeof(name), "llvm.SI.tbuffer.store.%s", types[func]);
+
+ lp_build_intrinsic(gallivm->builder, name, ctx->voidt,
+ args, ARRAY_SIZE(args), 0);
+}
+
+static void build_tbuffer_store_dwords(struct si_shader_context *ctx,
+ LLVMValueRef rsrc,
+ LLVMValueRef vdata,
+ unsigned num_channels,
+ LLVMValueRef vaddr,
+ LLVMValueRef soffset,
+ unsigned inst_offset)
+{
+ static unsigned dfmt[] = {
+ V_008F0C_BUF_DATA_FORMAT_32,
+ V_008F0C_BUF_DATA_FORMAT_32_32,
+ V_008F0C_BUF_DATA_FORMAT_32_32_32,
+ V_008F0C_BUF_DATA_FORMAT_32_32_32_32
+ };
+ assert(num_channels >= 1 && num_channels <= 4);
+
+ build_tbuffer_store(ctx, rsrc, vdata, num_channels, vaddr, soffset,
+ inst_offset, dfmt[num_channels-1],
+ V_008F0C_BUF_NUM_FORMAT_UINT, 1, 0, 1, 1, 0);
+}
+
+static LLVMValueRef build_buffer_load(struct si_shader_context *ctx,
+ LLVMValueRef rsrc,
+ int num_channels,
+ LLVMValueRef vindex,
+ LLVMValueRef voffset,
+ LLVMValueRef soffset,
+ unsigned inst_offset,
+ unsigned glc,
+ unsigned slc)
+{
+ struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ unsigned func = CLAMP(num_channels, 1, 3) - 1;
+
+ if (HAVE_LLVM >= 0x309) {
+ LLVMValueRef args[] = {
+ LLVMBuildBitCast(gallivm->builder, rsrc, ctx->v4i32, ""),
+ vindex ? vindex : LLVMConstInt(ctx->i32, 0, 0),
+ LLVMConstInt(ctx->i32, inst_offset, 0),
+ LLVMConstInt(ctx->i1, glc, 0),
+ LLVMConstInt(ctx->i1, slc, 0)
+ };
+
+ LLVMTypeRef types[] = {ctx->f32, LLVMVectorType(ctx->f32, 2),
+ ctx->v4f32};
+ const char *type_names[] = {"f32", "v2f32", "v4f32"};
+ char name[256];
+
+ if (voffset) {
+ args[2] = LLVMBuildAdd(gallivm->builder, args[2], voffset,
+ "");
+ }
+
+ if (soffset) {
+ args[2] = LLVMBuildAdd(gallivm->builder, args[2], soffset,
+ "");
+ }
+
+ snprintf(name, sizeof(name), "llvm.amdgcn.buffer.load.%s",
+ type_names[func]);
+
+ return lp_build_intrinsic(gallivm->builder, name, types[func], args,
+ ARRAY_SIZE(args), LLVMReadOnlyAttribute);
+ } else {
+ LLVMValueRef args[] = {
+ LLVMBuildBitCast(gallivm->builder, rsrc, ctx->v16i8, ""),
+ voffset ? voffset : vindex,
+ soffset,
+ LLVMConstInt(ctx->i32, inst_offset, 0),
+ LLVMConstInt(ctx->i32, voffset ? 1 : 0, 0), // offen
+ LLVMConstInt(ctx->i32, vindex ? 1 : 0, 0), //idxen
+ LLVMConstInt(ctx->i32, glc, 0),
+ LLVMConstInt(ctx->i32, slc, 0),
+ LLVMConstInt(ctx->i32, 0, 0), // TFE
+ };
+
+ LLVMTypeRef types[] = {ctx->i32, LLVMVectorType(ctx->i32, 2),
+ ctx->v4i32};
+ const char *type_names[] = {"i32", "v2i32", "v4i32"};
+ const char *arg_type = "i32";
+ char name[256];
+
+ if (voffset && vindex) {
+ LLVMValueRef vaddr[] = {vindex, voffset};
+
+ arg_type = "v2i32";
+ args[1] = lp_build_gather_values(gallivm, vaddr, 2);
+ }
+
+ snprintf(name, sizeof(name), "llvm.SI.buffer.load.dword.%s.%s",
+ type_names[func], arg_type);
+
+ return lp_build_intrinsic(gallivm->builder, name, types[func], args,
+ ARRAY_SIZE(args), LLVMReadOnlyAttribute);
+ }
+}
+
+static LLVMValueRef buffer_load(struct lp_build_tgsi_context *bld_base,
+ enum tgsi_opcode_type type, unsigned swizzle,
+ LLVMValueRef buffer, LLVMValueRef offset,
+ LLVMValueRef base)
+{
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMValueRef value, value2;
+ LLVMTypeRef llvm_type = tgsi2llvmtype(bld_base, type);
+ LLVMTypeRef vec_type = LLVMVectorType(llvm_type, 4);
+
+ if (swizzle == ~0) {
+ value = build_buffer_load(ctx, buffer, 4, NULL, base, offset,
+ 0, 1, 0);
+
+ return LLVMBuildBitCast(gallivm->builder, value, vec_type, "");
+ }
+
+ if (!tgsi_type_is_64bit(type)) {
+ value = build_buffer_load(ctx, buffer, 4, NULL, base, offset,
+ 0, 1, 0);
+
+ value = LLVMBuildBitCast(gallivm->builder, value, vec_type, "");
+ return LLVMBuildExtractElement(gallivm->builder, value,
+ lp_build_const_int32(gallivm, swizzle), "");
+ }
+
+ value = build_buffer_load(ctx, buffer, 1, NULL, base, offset,
+ swizzle * 4, 1, 0);
+
+ 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);
+}
+
/**
* Load from LDS.
*
dw_addr = lp_build_add(&bld_base->uint_bld, dw_addr,
lp_build_const_int32(gallivm, swizzle));
- value = build_indexed_load(ctx, ctx->lds, dw_addr);
- if (type == TGSI_TYPE_DOUBLE) {
+ value = build_indexed_load(ctx, ctx->lds, dw_addr, false);
+ 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));
- value2 = build_indexed_load(ctx, ctx->lds, dw_addr);
- return radeon_llvm_emit_fetch_double(bld_base, value, value2);
+ value2 = build_indexed_load(ctx, ctx->lds, dw_addr, false);
+ return radeon_llvm_emit_fetch_64bit(bld_base, type, value, value2);
}
return LLVMBuildBitCast(gallivm->builder, value,
enum tgsi_opcode_type type, unsigned swizzle)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- LLVMValueRef dw_addr, stride;
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMValueRef rw_buffers, buffer, base, addr;
- if (reg->Register.Dimension) {
- stride = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 13, 8);
- dw_addr = get_tcs_out_current_patch_offset(ctx);
- dw_addr = get_dw_address(ctx, NULL, reg, stride, dw_addr);
- } else {
- dw_addr = get_tcs_out_current_patch_data_offset(ctx);
- dw_addr = get_dw_address(ctx, NULL, reg, NULL, dw_addr);
- }
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.main_fn,
+ SI_PARAM_RW_BUFFERS);
+ buffer = build_indexed_load_const(ctx, rw_buffers,
+ lp_build_const_int32(gallivm, SI_HS_RING_TESS_OFFCHIP));
- return lds_load(bld_base, type, swizzle, dw_addr);
+ base = LLVMGetParam(ctx->radeon_bld.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);
}
static void store_output_tcs(struct lp_build_tgsi_context *bld_base,
LLVMValueRef dst[4])
{
struct si_shader_context *ctx = si_shader_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
const struct tgsi_full_dst_register *reg = &inst->Dst[0];
unsigned chan_index;
LLVMValueRef dw_addr, stride;
+ LLVMValueRef rw_buffers, buffer, base, buf_addr;
+ LLVMValueRef values[4];
/* Only handle per-patch and per-vertex outputs here.
* Vectors will be lowered to scalars and this function will be called again.
dw_addr = get_dw_address(ctx, reg, NULL, NULL, dw_addr);
}
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.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);
+ buf_addr = get_tcs_tes_buffer_address_from_reg(ctx, reg, NULL);
+
+
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
LLVMValueRef value = dst[chan_index];
value = radeon_llvm_saturate(bld_base, value);
lds_store(bld_base, chan_index, dw_addr, value);
+
+ value = LLVMBuildBitCast(gallivm->builder, value, ctx->i32, "");
+ values[chan_index] = value;
+
+ if (inst->Dst[0].Register.WriteMask != 0xF) {
+ build_tbuffer_store_dwords(ctx, buffer, value, 1,
+ buf_addr, base,
+ 4 * chan_index);
+ }
+ }
+
+ if (inst->Dst[0].Register.WriteMask == 0xF) {
+ LLVMValueRef value = lp_build_gather_values(bld_base->base.gallivm,
+ values, 4);
+ build_tbuffer_store_dwords(ctx, buffer, value, 4, buf_addr,
+ base, 0);
}
}
value = lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LLVMReadOnlyAttribute | LLVMNoUnwindAttribute);
- if (type == TGSI_TYPE_DOUBLE) {
+ LLVMReadOnlyAttribute);
+ if (tgsi_type_is_64bit(type)) {
LLVMValueRef value2;
args[2] = lp_build_const_int32(gallivm, (param * 4 + swizzle + 1) * 256);
value2 = lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LLVMReadOnlyAttribute | LLVMNoUnwindAttribute);
- return radeon_llvm_emit_fetch_double(bld_base,
- value, value2);
+ LLVMReadOnlyAttribute);
+ return radeon_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->shader->key.ps.prolog.force_persample_interp ||
- !ctx->is_monolithic)
+ if (!ctx->is_monolithic)
return param;
- /* If the shader doesn't use center/centroid, just return the parameter.
- *
- * If the shader only uses one set of (i,j), "si_emit_spi_ps_input" can
- * switch between center/centroid and sample without shader changes.
- */
- switch (param) {
- case SI_PARAM_PERSP_CENTROID:
- case SI_PARAM_PERSP_CENTER:
- return SI_PARAM_PERSP_SAMPLE;
-
- case SI_PARAM_LINEAR_CENTROID:
- case SI_PARAM_LINEAR_CENTER:
- return SI_PARAM_LINEAR_SAMPLE;
-
- default:
- return param;
+ if (ctx->shader->key.ps.prolog.force_persp_sample_interp) {
+ switch (param) {
+ case SI_PARAM_PERSP_CENTROID:
+ case SI_PARAM_PERSP_CENTER:
+ return SI_PARAM_PERSP_SAMPLE;
+ }
+ }
+ if (ctx->shader->key.ps.prolog.force_linear_sample_interp) {
+ switch (param) {
+ case SI_PARAM_LINEAR_CENTROID:
+ case SI_PARAM_LINEAR_CENTER:
+ return SI_PARAM_LINEAR_SAMPLE;
+ }
+ }
+ if (ctx->shader->key.ps.prolog.force_persp_center_interp) {
+ switch (param) {
+ case SI_PARAM_PERSP_CENTROID:
+ case SI_PARAM_PERSP_SAMPLE:
+ return SI_PARAM_PERSP_CENTER;
+ }
+ }
+ if (ctx->shader->key.ps.prolog.force_linear_center_interp) {
+ switch (param) {
+ case SI_PARAM_LINEAR_CENTROID:
+ case SI_PARAM_LINEAR_SAMPLE:
+ return SI_PARAM_LINEAR_CENTER;
+ }
}
+
+ return param;
}
/**
args[1] = attr_number;
front = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
args[1] = back_attr_number;
back = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
result[chan] = LLVMBuildSelect(gallivm->builder,
is_face_positive,
args[3] = interp_param;
result[0] = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
result[1] =
result[2] = lp_build_const_float(gallivm, 0.0f);
result[3] = lp_build_const_float(gallivm, 1.0f);
args[3] = interp_param;
result[chan] = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
}
}
}
+/* LLVMGetParam with bc_optimize resolved. */
+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;
+ LLVMValueRef param = NULL;
+
+ /* Handle PRIM_MASK[31] (bc_optimize). */
+ if (ctx->is_monolithic &&
+ ((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 &&
+ interp_param_idx == SI_PARAM_LINEAR_CENTROID))) {
+ /* The shader should do: if (PRIM_MASK[31]) CENTROID = CENTER;
+ * The hw doesn't compute CENTROID if the whole wave only
+ * contains fully-covered quads.
+ */
+ LLVMValueRef bc_optimize =
+ LLVMGetParam(main_fn, SI_PARAM_PRIM_MASK);
+ bc_optimize = LLVMBuildLShr(builder,
+ bc_optimize,
+ LLVMConstInt(ctx->i32, 31, 0), "");
+ bc_optimize = LLVMBuildTrunc(builder, bc_optimize, ctx->i1, "");
+
+ if (ctx->shader->key.ps.prolog.bc_optimize_for_persp &&
+ interp_param_idx == SI_PARAM_PERSP_CENTROID) {
+ param = LLVMBuildSelect(builder, bc_optimize,
+ LLVMGetParam(main_fn,
+ SI_PARAM_PERSP_CENTER),
+ LLVMGetParam(main_fn,
+ SI_PARAM_PERSP_CENTROID),
+ "");
+ }
+ if (ctx->shader->key.ps.prolog.bc_optimize_for_linear &&
+ interp_param_idx == SI_PARAM_LINEAR_CENTROID) {
+ param = LLVMBuildSelect(builder, bc_optimize,
+ LLVMGetParam(main_fn,
+ SI_PARAM_LINEAR_CENTER),
+ LLVMGetParam(main_fn,
+ SI_PARAM_LINEAR_CENTROID),
+ "");
+ }
+ }
+
+ if (!param)
+ param = LLVMGetParam(main_fn, interp_param_idx);
+ return param;
+}
+
static void declare_input_fs(
struct radeon_llvm_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 =
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;
}
else if (interp_param_idx) {
interp_param_idx = select_interp_param(ctx,
interp_param_idx);
- interp_param = LLVMGetParam(main_fn, interp_param_idx);
+ interp_param = get_interp_param(ctx, interp_param_idx);
}
+ if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
+ decl->Interp.Interpolate == TGSI_INTERPOLATE_COLOR &&
+ ctx->shader->key.ps.prolog.flatshade_colors)
+ interp_param = NULL; /* load the constant color */
+
interp_fs_input(ctx, input_index, decl->Semantic.Name,
decl->Semantic.Index, shader->selector->info.num_inputs,
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)
SI_PARAM_ANCILLARY, 8, 4);
}
+/**
+ * Set range metadata on an instruction. This can only be used on load and
+ * call instructions. If you know an instruction can only produce the values
+ * 0, 1, 2, you would do set_range_metadata(value, 0, 3);
+ * \p lo is the minimum value inclusive.
+ * \p hi is the maximum value exclusive.
+ */
+static void set_range_metadata(struct si_shader_context *ctx,
+ LLVMValueRef value, unsigned lo, unsigned hi)
+{
+ LLVMValueRef range_md, md_args[2];
+ LLVMTypeRef type = LLVMTypeOf(value);
+ LLVMContextRef context = LLVMGetTypeContext(type);
+
+ md_args[0] = LLVMConstInt(type, lo, false);
+ md_args[1] = LLVMConstInt(type, hi, false);
+ range_md = LLVMMDNodeInContext(context, md_args, 2);
+ LLVMSetMetadata(value, ctx->range_md_kind, range_md);
+}
+
+static LLVMValueRef get_thread_id(struct si_shader_context *ctx)
+{
+ struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ LLVMValueRef tid;
+
+ if (HAVE_LLVM < 0x0308) {
+ tid = lp_build_intrinsic(gallivm->builder, "llvm.SI.tid",
+ ctx->i32, NULL, 0, LLVMReadNoneAttribute);
+ } else {
+ LLVMValueRef tid_args[2];
+ tid_args[0] = lp_build_const_int32(gallivm, 0xffffffff);
+ tid_args[1] = lp_build_const_int32(gallivm, 0);
+ tid_args[1] = lp_build_intrinsic(gallivm->builder,
+ "llvm.amdgcn.mbcnt.lo", ctx->i32,
+ tid_args, 2, LLVMReadNoneAttribute);
+
+ tid = lp_build_intrinsic(gallivm->builder,
+ "llvm.amdgcn.mbcnt.hi", ctx->i32,
+ tid_args, 2, LLVMReadNoneAttribute);
+ }
+ set_range_metadata(ctx, tid, 0, 64);
+ return tid;
+}
+
/**
* Load a dword from a constant buffer.
*/
-static LLVMValueRef buffer_load_const(LLVMBuilderRef builder, LLVMValueRef resource,
- LLVMValueRef offset, LLVMTypeRef return_type)
+static LLVMValueRef buffer_load_const(struct si_shader_context *ctx,
+ LLVMValueRef resource,
+ LLVMValueRef offset)
{
+ LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
LLVMValueRef args[2] = {resource, offset};
- return lp_build_intrinsic(builder, "llvm.SI.load.const", return_type, args, 2,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ 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)
LLVMValueRef offset1 = LLVMBuildAdd(builder, offset0, lp_build_const_int32(gallivm, 4), "");
LLVMValueRef pos[4] = {
- buffer_load_const(builder, resource, offset0, ctx->f32),
- buffer_load_const(builder, resource, offset1, ctx->f32),
+ buffer_load_const(ctx, resource, offset0),
+ buffer_load_const(ctx, resource, offset1),
lp_build_const_float(gallivm, 0),
lp_build_const_float(gallivm, 0)
};
SI_PARAM_BASE_VERTEX);
break;
+ case TGSI_SEMANTIC_BASEINSTANCE:
+ value = LLVMGetParam(radeon_bld->main_fn,
+ SI_PARAM_START_INSTANCE);
+ break;
+
+ case TGSI_SEMANTIC_DRAWID:
+ value = LLVMGetParam(radeon_bld->main_fn,
+ SI_PARAM_DRAWID);
+ break;
+
case TGSI_SEMANTIC_INVOCATIONID:
- if (ctx->type == TGSI_PROCESSOR_TESS_CTRL)
+ if (ctx->type == PIPE_SHADER_TESS_CTRL)
value = unpack_param(ctx, SI_PARAM_REL_IDS, 8, 5);
- else if (ctx->type == TGSI_PROCESSOR_GEOMETRY)
+ else if (ctx->type == PIPE_SHADER_GEOMETRY)
value = LLVMGetParam(radeon_bld->main_fn,
SI_PARAM_GS_INSTANCE_ID);
else
}
case TGSI_SEMANTIC_VERTICESIN:
- value = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 26, 6);
+ if (ctx->type == PIPE_SHADER_TESS_CTRL)
+ value = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 26, 6);
+ else if (ctx->type == PIPE_SHADER_TESS_EVAL)
+ value = unpack_param(ctx, SI_PARAM_TCS_OFFCHIP_LAYOUT, 9, 7);
+ else
+ assert(!"invalid shader stage for TGSI_SEMANTIC_VERTICESIN");
break;
case TGSI_SEMANTIC_TESSINNER:
case TGSI_SEMANTIC_TESSOUTER:
{
- LLVMValueRef dw_addr;
+ LLVMValueRef rw_buffers, buffer, base, addr;
int param = si_shader_io_get_unique_index(decl->Semantic.Name, 0);
- dw_addr = get_tcs_out_current_patch_data_offset(ctx);
- dw_addr = LLVMBuildAdd(gallivm->builder, dw_addr,
- lp_build_const_int32(gallivm, param * 4), "");
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.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);
+ addr = get_tcs_tes_buffer_address(ctx, NULL,
+ lp_build_const_int32(gallivm, param));
+
+ value = buffer_load(&radeon_bld->soa.bld_base, TGSI_TYPE_FLOAT,
+ ~0, buffer, base, addr);
- value = lds_load(&radeon_bld->soa.bld_base, TGSI_TYPE_FLOAT,
- ~0, dw_addr);
break;
}
offset = decl->Semantic.Name == TGSI_SEMANTIC_DEFAULT_TESSINNER_SI ? 4 : 0;
for (i = 0; i < 4; i++)
- val[i] = buffer_load_const(gallivm->builder, buf,
- lp_build_const_int32(gallivm, (offset + i) * 4),
- ctx->f32);
+ val[i] = buffer_load_const(ctx, buf,
+ lp_build_const_int32(gallivm, (offset + i) * 4));
value = lp_build_gather_values(gallivm, val, 4);
break;
}
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;
}
value = LLVMGetParam(radeon_bld->main_fn, SI_PARAM_THREAD_ID);
break;
+#if HAVE_LLVM >= 0x0309
+ case TGSI_SEMANTIC_HELPER_INVOCATION:
+ value = lp_build_intrinsic(gallivm->builder,
+ "llvm.amdgcn.ps.live",
+ ctx->i1, NULL, 0,
+ LLVMReadNoneAttribute);
+ value = LLVMBuildNot(gallivm->builder, value, "");
+ value = LLVMBuildSExt(gallivm->builder, value, ctx->i32, "");
+ break;
+#endif
+
default:
assert(!"unknown system value");
return;
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->radeon_bld.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,
idx = reg->Register.Index * 4 + swizzle;
if (!reg->Register.Indirect && !reg->Dimension.Indirect) {
- if (type != TGSI_TYPE_DOUBLE)
- return bitcast(bld_base, type, ctx->constants[buf][idx]);
+ LLVMValueRef c0, c1, desc;
+
+ desc = load_const_buffer_desc(ctx, buf);
+ c0 = buffer_load_const(ctx, desc,
+ LLVMConstInt(ctx->i32, idx * 4, 0));
+
+ if (!tgsi_type_is_64bit(type))
+ return bitcast(bld_base, type, c0);
else {
- return radeon_llvm_emit_fetch_double(bld_base,
- ctx->constants[buf][idx],
- ctx->constants[buf][idx + 1]);
+ c1 = buffer_load_const(ctx, desc,
+ LLVMConstInt(ctx->i32,
+ (idx + 1) * 4, 0));
+ return radeon_llvm_emit_fetch_64bit(bld_base, type,
+ c0, c1);
}
}
SI_NUM_CONST_BUFFERS);
bufp = build_indexed_load_const(ctx, ptr, index);
} else
- bufp = ctx->const_buffers[buf];
+ bufp = load_const_buffer_desc(ctx, buf);
addr = ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle];
addr = LLVMBuildLoad(base->gallivm->builder, addr, "load addr reg");
addr = lp_build_add(&bld_base->uint_bld, addr,
lp_build_const_int32(base->gallivm, idx * 4));
- result = buffer_load_const(base->gallivm->builder, bufp,
- addr, ctx->f32);
+ result = buffer_load_const(ctx, bufp, addr);
- if (type != TGSI_TYPE_DOUBLE)
+ if (!tgsi_type_is_64bit(type))
result = bitcast(bld_base, type, result);
else {
LLVMValueRef addr2, result2;
addr2 = lp_build_add(&bld_base->uint_bld, addr2,
lp_build_const_int32(base->gallivm, idx * 4));
- result2 = buffer_load_const(base->gallivm->builder, ctx->const_buffers[buf],
- addr2, ctx->f32);
+ result2 = buffer_load_const(ctx, bufp, addr2);
- result = radeon_llvm_emit_fetch_double(bld_base,
- result, result2);
+ result = radeon_llvm_emit_fetch_64bit(bld_base, type,
+ result, result2);
}
return result;
}
/* Specify the target we are exporting */
args[3] = lp_build_const_int32(base->gallivm, target);
- if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
+ if (ctx->type == PIPE_SHADER_FRAGMENT) {
const union si_shader_key *key = &ctx->shader->key;
unsigned col_formats = key->ps.epilog.spi_shader_col_format;
int cbuf = target - V_008DFC_SQ_EXP_MRT;
packed = lp_build_intrinsic(base->gallivm->builder,
"llvm.SI.packf16",
ctx->i32, pack_args, 2,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
args[chan + 5] =
LLVMBuildBitCast(base->gallivm->builder,
packed, ctx->f32, "");
args[1] = lp_build_const_int32(base->gallivm,
((reg_index * 4 + chan) * 4 +
const_chan) * 4);
- base_elt = buffer_load_const(base->gallivm->builder, const_resource,
- args[1], ctx->f32);
+ base_elt = buffer_load_const(ctx, const_resource,
+ args[1]);
args[5 + chan] =
lp_build_add(base, args[5 + chan],
lp_build_mul(base, base_elt,
static void si_dump_streamout(struct pipe_stream_output_info *so)
{
- unsigned i;
-
- if (so->num_outputs)
- fprintf(stderr, "STREAMOUT\n");
-
- for (i = 0; i < so->num_outputs; i++) {
- unsigned mask = ((1 << so->output[i].num_components) - 1) <<
- so->output[i].start_component;
- fprintf(stderr, " %i: BUF%i[%i..%i] <- OUT[%i].%s%s%s%s\n",
- i, so->output[i].output_buffer,
- so->output[i].dst_offset, so->output[i].dst_offset + so->output[i].num_components - 1,
- so->output[i].register_index,
- mask & 1 ? "x" : "",
- mask & 2 ? "y" : "",
- mask & 4 ? "z" : "",
- mask & 8 ? "w" : "");
- }
-}
-
-/* TBUFFER_STORE_FORMAT_{X,XY,XYZ,XYZW} <- the suffix is selected by num_channels=1..4.
- * The type of vdata must be one of i32 (num_channels=1), v2i32 (num_channels=2),
- * or v4i32 (num_channels=3,4). */
-static void build_tbuffer_store(struct si_shader_context *ctx,
- LLVMValueRef rsrc,
- LLVMValueRef vdata,
- unsigned num_channels,
- LLVMValueRef vaddr,
- LLVMValueRef soffset,
- unsigned inst_offset,
- unsigned dfmt,
- unsigned nfmt,
- unsigned offen,
- unsigned idxen,
- unsigned glc,
- unsigned slc,
- unsigned tfe)
-{
- struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- LLVMValueRef args[] = {
- rsrc,
- vdata,
- LLVMConstInt(ctx->i32, num_channels, 0),
- vaddr,
- soffset,
- LLVMConstInt(ctx->i32, inst_offset, 0),
- LLVMConstInt(ctx->i32, dfmt, 0),
- LLVMConstInt(ctx->i32, nfmt, 0),
- LLVMConstInt(ctx->i32, offen, 0),
- LLVMConstInt(ctx->i32, idxen, 0),
- LLVMConstInt(ctx->i32, glc, 0),
- LLVMConstInt(ctx->i32, slc, 0),
- LLVMConstInt(ctx->i32, tfe, 0)
- };
-
- /* The instruction offset field has 12 bits */
- assert(offen || inst_offset < (1 << 12));
-
- /* The intrinsic is overloaded, we need to add a type suffix for overloading to work. */
- unsigned func = CLAMP(num_channels, 1, 3) - 1;
- const char *types[] = {"i32", "v2i32", "v4i32"};
- char name[256];
- snprintf(name, sizeof(name), "llvm.SI.tbuffer.store.%s", types[func]);
-
- lp_build_intrinsic(gallivm->builder, name, ctx->voidt,
- args, Elements(args), 0);
-}
-
-static void build_tbuffer_store_dwords(struct si_shader_context *ctx,
- LLVMValueRef rsrc,
- LLVMValueRef vdata,
- unsigned num_channels,
- LLVMValueRef vaddr,
- LLVMValueRef soffset,
- unsigned inst_offset)
-{
- static unsigned dfmt[] = {
- V_008F0C_BUF_DATA_FORMAT_32,
- V_008F0C_BUF_DATA_FORMAT_32_32,
- V_008F0C_BUF_DATA_FORMAT_32_32_32,
- V_008F0C_BUF_DATA_FORMAT_32_32_32_32
- };
- assert(num_channels >= 1 && num_channels <= 4);
+ unsigned i;
- build_tbuffer_store(ctx, rsrc, vdata, num_channels, vaddr, soffset,
- inst_offset, dfmt[num_channels-1],
- V_008F0C_BUF_NUM_FORMAT_UINT, 1, 0, 1, 1, 0);
+ if (so->num_outputs)
+ fprintf(stderr, "STREAMOUT\n");
+
+ for (i = 0; i < so->num_outputs; i++) {
+ unsigned mask = ((1 << so->output[i].num_components) - 1) <<
+ so->output[i].start_component;
+ fprintf(stderr, " %i: BUF%i[%i..%i] <- OUT[%i].%s%s%s%s\n",
+ i, so->output[i].output_buffer,
+ so->output[i].dst_offset, so->output[i].dst_offset + so->output[i].num_components - 1,
+ so->output[i].register_index,
+ mask & 1 ? "x" : "",
+ mask & 2 ? "y" : "",
+ mask & 4 ? "z" : "",
+ mask & 8 ? "w" : "");
+ }
}
/* On SI, the vertex shader is responsible for writing streamout data
LLVMBuilderRef builder = gallivm->builder;
int i, j;
struct lp_build_if_state if_ctx;
+ LLVMValueRef so_buffers[4];
+ LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.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 =
unpack_param(ctx, ctx->param_streamout_config, 16, 7);
- LLVMValueRef tid = lp_build_intrinsic(builder, "llvm.SI.tid", ctx->i32,
- NULL, 0, LLVMReadNoneAttribute);
+ LLVMValueRef tid = get_thread_id(ctx);
/* can_emit = tid < so_vtx_count; */
LLVMValueRef can_emit =
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),
}
}
+static void si_copy_tcs_inputs(struct lp_build_tgsi_context *bld_base)
+{
+ struct si_shader_context *ctx = si_shader_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMValueRef invocation_id, rw_buffers, buffer, buffer_offset;
+ LLVMValueRef lds_vertex_stride, lds_vertex_offset, lds_base;
+ uint64_t inputs;
+
+ invocation_id = unpack_param(ctx, SI_PARAM_REL_IDS, 8, 5);
+
+ rw_buffers = LLVMGetParam(ctx->radeon_bld.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);
+
+ lds_vertex_stride = unpack_param(ctx, SI_PARAM_TCS_IN_LAYOUT, 13, 8);
+ lds_vertex_offset = LLVMBuildMul(gallivm->builder, invocation_id,
+ lds_vertex_stride, "");
+ lds_base = get_tcs_in_current_patch_offset(ctx);
+ lds_base = LLVMBuildAdd(gallivm->builder, lds_base, lds_vertex_offset, "");
+
+ inputs = ctx->shader->key.tcs.epilog.inputs_to_copy;
+ while (inputs) {
+ unsigned i = u_bit_scan64(&inputs);
+
+ LLVMValueRef lds_ptr = LLVMBuildAdd(gallivm->builder, lds_base,
+ lp_build_const_int32(gallivm, 4 * i),
+ "");
+
+ LLVMValueRef buffer_addr = get_tcs_tes_buffer_address(ctx,
+ invocation_id,
+ lp_build_const_int32(gallivm, i));
+
+ LLVMValueRef value = lds_load(bld_base, TGSI_TYPE_SIGNED, ~0,
+ lds_ptr);
+
+ build_tbuffer_store_dwords(ctx, buffer, value, 4, buffer_addr,
+ buffer_offset, 0);
+ }
+}
+
static void si_write_tess_factors(struct lp_build_tgsi_context *bld_base,
LLVMValueRef rel_patch_id,
LLVMValueRef invocation_id,
LLVMValueRef lds_base, lds_inner, lds_outer, byteoffset, buffer;
LLVMValueRef out[6], vec0, vec1, rw_buffers, tf_base;
unsigned stride, outer_comps, inner_comps, i;
- struct lp_build_if_state if_ctx;
+ struct lp_build_if_state if_ctx, inner_if_ctx;
+
+ si_llvm_emit_barrier(NULL, bld_base, NULL);
/* Do this only for invocation 0, because the tess levels are per-patch,
* not per-vertex.
byteoffset = LLVMBuildMul(gallivm->builder, rel_patch_id,
lp_build_const_int32(gallivm, 4 * stride), "");
- /* Store the outputs. */
+ lp_build_if(&inner_if_ctx, gallivm,
+ LLVMBuildICmp(gallivm->builder, LLVMIntEQ,
+ rel_patch_id, bld_base->uint_bld.zero, ""));
+
+ /* Store the dynamic HS control word. */
+ build_tbuffer_store_dwords(ctx, buffer,
+ lp_build_const_int32(gallivm, 0x80000000),
+ 1, lp_build_const_int32(gallivm, 0), tf_base, 0);
+
+ lp_build_endif(&inner_if_ctx);
+
+ /* Store the tessellation factors. */
build_tbuffer_store_dwords(ctx, buffer, vec0,
- MIN2(stride, 4), byteoffset, tf_base, 0);
+ MIN2(stride, 4), byteoffset, tf_base, 4);
if (vec1)
build_tbuffer_store_dwords(ctx, buffer, vec1,
- stride - 4, byteoffset, tf_base, 16);
+ stride - 4, byteoffset, tf_base, 20);
lp_build_endif(&if_ctx);
}
tf_soffset = LLVMGetParam(ctx->radeon_bld.main_fn,
SI_PARAM_TESS_FACTOR_OFFSET);
ret = LLVMBuildInsertValue(builder, ret, tf_soffset,
- SI_TCS_NUM_USER_SGPR, "");
+ SI_TCS_NUM_USER_SGPR + 1, "");
/* VGPRs */
rel_patch_id = bitcast(bld_base, TGSI_TYPE_FLOAT, rel_patch_id);
invocation_id = bitcast(bld_base, TGSI_TYPE_FLOAT, invocation_id);
tf_lds_offset = bitcast(bld_base, TGSI_TYPE_FLOAT, tf_lds_offset);
- vgpr = SI_TCS_NUM_USER_SGPR + 1;
+ vgpr = SI_TCS_NUM_USER_SGPR + 2;
ret = LLVMBuildInsertValue(builder, ret, rel_patch_id, vgpr++, "");
ret = LLVMBuildInsertValue(builder, ret, invocation_id, vgpr++, "");
ret = LLVMBuildInsertValue(builder, ret, tf_lds_offset, vgpr++, "");
return;
}
+ si_copy_tcs_inputs(bld_base);
si_write_tess_factors(bld_base, rel_patch_id, invocation_id, tf_lds_offset);
}
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);
lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg",
- ctx->voidt, args, 2, LLVMNoUnwindAttribute);
+ ctx->voidt, args, 2, 0);
}
static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context *bld_base)
* an IF statement is added that clamps all colors if the constant
* is true.
*/
- if (ctx->type == TGSI_PROCESSOR_VERTEX) {
+ if (ctx->type == PIPE_SHADER_VERTEX) {
struct lp_build_if_state if_ctx;
LLVMValueRef cond = NULL;
LLVMValueRef addr, val;
FREE(outputs);
}
+struct si_ps_exports {
+ unsigned num;
+ 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)
+ LLVMValueRef depth, LLVMValueRef stencil,
+ LLVMValueRef samplemask, struct si_ps_exports *exp)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
struct lp_build_context *uint = &bld_base->uint_bld;
LLVMValueRef args[9];
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
/* Specify which components to enable */
args[0] = lp_build_const_int32(base->gallivm, mask);
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- ctx->voidt, args, 9, 0);
+ memcpy(exp->args[exp->num++], args, sizeof(args));
}
static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
LLVMValueRef *color, unsigned index,
unsigned samplemask_param,
- bool is_last)
+ bool is_last, struct si_ps_exports *exp)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
} else if (args[c][0] == bld_base->uint_bld.zero)
continue; /* unnecessary NULL export */
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- ctx->voidt, args[c], 9, 0);
+ memcpy(exp->args[exp->num++], args[c], sizeof(args[c]));
}
} else {
LLVMValueRef args[9];
} else if (args[0] == bld_base->uint_bld.zero)
return; /* unnecessary NULL export */
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- ctx->voidt, args, 9, 0);
+ memcpy(exp->args[exp->num++], args, sizeof(args));
}
}
+static void si_emit_ps_exports(struct si_shader_context *ctx,
+ struct si_ps_exports *exp)
+{
+ for (unsigned i = 0; i < exp->num; i++)
+ lp_build_intrinsic(ctx->radeon_bld.gallivm.builder,
+ "llvm.SI.export", ctx->voidt,
+ exp->args[i], 9, 0);
+}
+
static void si_export_null(struct lp_build_tgsi_context *bld_base)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
args[2] = uint->one; /* DONE bit */
args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_NULL);
args[4] = uint->zero; /* COMPR flag (0 = 32-bit export) */
- args[5] = uint->undef; /* R */
- args[6] = uint->undef; /* G */
- args[7] = uint->undef; /* B */
- args[8] = uint->undef; /* A */
+ args[5] = base->undef; /* R */
+ args[6] = base->undef; /* G */
+ args[7] = base->undef; /* B */
+ args[8] = base->undef; /* A */
lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
ctx->voidt, args, 9, 0);
LLVMValueRef depth = NULL, stencil = NULL, samplemask = NULL;
int last_color_export = -1;
int i;
+ struct si_ps_exports exp = {};
/* Determine the last export. If MRTZ is present, it's always last.
* Otherwise, find the last color export.
si_export_mrt_color(bld_base, color, semantic_index,
SI_PARAM_SAMPLE_COVERAGE,
- last_color_export == i);
+ last_color_export == i, &exp);
break;
default:
fprintf(stderr,
}
if (depth || stencil || samplemask)
- si_export_mrt_z(bld_base, depth, stencil, samplemask);
+ si_export_mrt_z(bld_base, depth, stencil, samplemask, &exp);
+
+ si_emit_ps_exports(ctx, &exp);
}
/**
* 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,
LLVMBuildCall(builder, inlineasm, NULL, 0, "");
}
+static void emit_waitcnt(struct si_shader_context *ctx)
+{
+ struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef args[1] = {
+ lp_build_const_int32(gallivm, 0xf70)
+ };
+ lp_build_intrinsic(builder, "llvm.amdgcn.s.waitcnt",
+ ctx->voidt, args, 1, 0);
+}
+
static void membar_emit(
const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
- /* Since memoryBarrier only makes guarantees about atomics and
- * coherent image accesses (which bypass TC L1), we do not need to emit
- * any special cache handling here.
- *
- * We do have to prevent LLVM from re-ordering loads across
- * the barrier though.
- */
- emit_optimization_barrier(ctx);
+ emit_waitcnt(ctx);
}
static LLVMValueRef
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->radeon_bld.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)
LLVMValueRef *rsrc)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
+ LLVMValueRef rsrc_ptr = LLVMGetParam(ctx->radeon_bld.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(
emit_data->output[emit_data->chan] = lp_build_intrinsic(
builder, intrinsic_name, dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadOnlyAttribute | LLVMNoUnwindAttribute);
+ LLVMReadOnlyAttribute);
}
static LLVMValueRef get_memory_ptr(struct si_shader_context *ctx,
emit_data->output[emit_data->chan] = lp_build_gather_values(gallivm, channels, 4);
}
+static void get_image_intr_name(const char *base_name,
+ LLVMTypeRef coords_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));
+
+ snprintf(out_name, out_len, "%s.%s", base_name, coords_type_name);
+}
+
static void load_emit(
const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
LLVMBuilderRef builder = gallivm->builder;
const struct tgsi_full_instruction * inst = emit_data->inst;
char intrinsic_name[32];
- char coords_type[8];
if (inst->Src[0].Register.File == TGSI_FILE_MEMORY) {
load_emit_memory(ctx, emit_data);
}
if (inst->Memory.Qualifier & TGSI_MEMORY_VOLATILE)
- emit_optimization_barrier(ctx);
+ emit_waitcnt(ctx);
if (inst->Src[0].Register.File == TGSI_FILE_BUFFER) {
load_emit_buffer(ctx, emit_data);
lp_build_intrinsic(
builder, "llvm.amdgcn.buffer.load.format.v4f32", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadOnlyAttribute | LLVMNoUnwindAttribute);
+ 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",
+ LLVMTypeOf(emit_data->args[0]),
+ intrinsic_name, sizeof(intrinsic_name));
emit_data->output[emit_data->chan] =
lp_build_intrinsic(
builder, intrinsic_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadOnlyAttribute | LLVMNoUnwindAttribute);
+ LLVMReadOnlyAttribute);
}
}
lp_build_intrinsic(
builder, intrinsic_name, emit_data->dst_type,
- emit_data->args, emit_data->arg_count,
- LLVMNoUnwindAttribute);
+ emit_data->args, emit_data->arg_count, 0);
}
}
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 gallivm_state *gallivm = bld_base->base.gallivm;
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];
- if (inst->Dst[0].Register.File == TGSI_FILE_BUFFER) {
- store_emit_buffer(si_shader_context(bld_base), emit_data);
+ if (inst->Dst[0].Register.File == TGSI_FILE_MEMORY) {
+ store_emit_memory(ctx, emit_data);
return;
- } else if (inst->Dst[0].Register.File == TGSI_FILE_MEMORY) {
- store_emit_memory(si_shader_context(bld_base), emit_data);
+ }
+
+ if (inst->Memory.Qualifier & TGSI_MEMORY_VOLATILE)
+ emit_waitcnt(ctx);
+
+ if (inst->Dst[0].Register.File == TGSI_FILE_BUFFER) {
+ store_emit_buffer(ctx, emit_data);
return;
}
if (target == TGSI_TEXTURE_BUFFER) {
emit_data->output[emit_data->chan] = lp_build_intrinsic(
builder, "llvm.amdgcn.buffer.store.format.v4f32",
- emit_data->dst_type, emit_data->args, emit_data->arg_count,
- LLVMNoUnwindAttribute);
+ 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[1]),
+ intrinsic_name, sizeof(intrinsic_name));
emit_data->output[emit_data->chan] =
lp_build_intrinsic(
builder, intrinsic_name, emit_data->dst_type,
- emit_data->args, emit_data->arg_count,
- LLVMNoUnwindAttribute);
+ emit_data->args, emit_data->arg_count, 0);
}
}
} else {
char coords_type[8];
- build_int_type_name(LLVMTypeOf(emit_data->args[1]),
+ build_type_name_for_intr(LLVMTypeOf(emit_data->args[1]),
coords_type, sizeof(coords_type));
snprintf(intrinsic_name, sizeof(intrinsic_name),
"llvm.amdgcn.image.atomic.%s.%s",
tmp = lp_build_intrinsic(
builder, intrinsic_name, bld_base->uint_bld.elem_type,
- emit_data->args, emit_data->arg_count,
- LLVMNoUnwindAttribute);
+ emit_data->args, emit_data->arg_count, 0);
emit_data->output[emit_data->chan] =
LLVMBuildBitCast(builder, tmp, bld_base->base.elem_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);
out = lp_build_intrinsic(
builder, "llvm.SI.getresinfo.i32", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
/* Divide the number of layers by 6 to get the number of cubes. */
if (inst->Memory.Texture == TGSI_TEXTURE_CUBE_ARRAY) {
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, "");
}
}
/**
* 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;
LLVMBuilderRef builder = gallivm->builder;
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,
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.
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 (target == TGSI_TEXTURE_2D_MSAA ||
+ target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
+ if (samp_ptr)
*samp_ptr = NULL;
- *fmask_ptr = get_sampler_desc(ctx, ind_index, DESC_FMASK);
- } else {
- *samp_ptr = get_sampler_desc(ctx, ind_index, DESC_SAMPLER);
+ 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);
- *fmask_ptr = NULL;
}
- } else {
- *res_ptr = ctx->sampler_views[sampler_index];
- *samp_ptr = ctx->sampler_states[sampler_index];
- *fmask_ptr = ctx->fmasks[sampler_index];
+ if (fmask_ptr)
+ *fmask_ptr = NULL;
}
}
-static void tex_fetch_args(
+static void txq_fetch_args(
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = gallivm->builder;
const struct tgsi_full_instruction *inst = emit_data->inst;
+ unsigned target = inst->Texture.Texture;
+ LLVMValueRef res_ptr;
+ LLVMValueRef address;
+
+ tex_fetch_ptrs(bld_base, emit_data, &res_ptr, NULL, NULL);
+
+ if (target == TGSI_TEXTURE_BUFFER) {
+ /* Read the size from the buffer descriptor directly. */
+ LLVMValueRef res = LLVMBuildBitCast(builder, res_ptr, ctx->v8i32, "");
+ emit_data->args[0] = get_buffer_size(bld_base, res);
+ return;
+ }
+
+ /* Textures - set the mip level. */
+ address = lp_build_emit_fetch(bld_base, inst, 0, TGSI_CHAN_X);
+
+ set_tex_fetch_args(ctx, emit_data, TGSI_OPCODE_TXQ, target, res_ptr,
+ NULL, &address, 1, 0xf);
+}
+
+static void txq_emit(const struct lp_build_tgsi_action *action,
+ struct lp_build_tgsi_context *bld_base,
+ struct lp_build_emit_data *emit_data)
+{
+ struct lp_build_context *base = &bld_base->base;
+ unsigned target = emit_data->inst->Texture.Texture;
+
+ if (target == TGSI_TEXTURE_BUFFER) {
+ /* Just return the buffer size. */
+ emit_data->output[emit_data->chan] = emit_data->args[0];
+ return;
+ }
+
+ emit_data->output[emit_data->chan] = lp_build_intrinsic(
+ base->gallivm->builder, "llvm.SI.getresinfo.i32",
+ emit_data->dst_type, emit_data->args, emit_data->arg_count,
+ LLVMReadNoneAttribute);
+
+ /* Divide the number of layers by 6 to get the number of cubes. */
+ if (target == TGSI_TEXTURE_CUBE_ARRAY ||
+ target == TGSI_TEXTURE_SHADOWCUBE_ARRAY) {
+ LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ LLVMValueRef two = lp_build_const_int32(bld_base->base.gallivm, 2);
+ LLVMValueRef six = lp_build_const_int32(bld_base->base.gallivm, 6);
+
+ LLVMValueRef v4 = emit_data->output[emit_data->chan];
+ LLVMValueRef z = LLVMBuildExtractElement(builder, v4, two, "");
+ z = LLVMBuildSDiv(builder, z, six, "");
+
+ emit_data->output[emit_data->chan] =
+ LLVMBuildInsertElement(builder, v4, z, two, "");
+ }
+}
+
+static void tex_fetch_args(
+ 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 gallivm_state *gallivm = bld_base->base.gallivm;
+ const struct tgsi_full_instruction *inst = emit_data->inst;
unsigned opcode = inst->Instruction.Opcode;
unsigned target = inst->Texture.Texture;
LLVMValueRef coords[5], derivs[6];
tex_fetch_ptrs(bld_base, emit_data, &res_ptr, &samp_ptr, &fmask_ptr);
- if (opcode == TGSI_OPCODE_TXQ) {
- if (target == TGSI_TEXTURE_BUFFER) {
- /* Read the size from the buffer descriptor directly. */
- LLVMValueRef res = LLVMBuildBitCast(builder, res_ptr, ctx->v8i32, "");
- emit_data->args[0] = get_buffer_size(bld_base, res);
- return;
- }
-
- /* Textures - set the mip level. */
- address[count++] = lp_build_emit_fetch(bld_base, inst, 0, TGSI_CHAN_X);
-
- set_tex_fetch_args(ctx, emit_data, opcode, target, res_ptr,
- NULL, address, count, 0xf);
- return;
- }
-
if (target == TGSI_TEXTURE_BUFFER) {
LLVMTypeRef v2i128 = LLVMVectorType(ctx->i128, 2);
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->radeon_bld.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->radeon_bld.soa.bld_base.uint_bld.zero,
+ 1, 0xf);
+ txq_emit(NULL, &ctx->radeon_bld.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->radeon_bld.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";
const char *infix = "";
- if (opcode == TGSI_OPCODE_TXQ && target == TGSI_TEXTURE_BUFFER) {
- /* Just return the buffer size. */
- emit_data->output[emit_data->chan] = emit_data->args[0];
- return;
- }
-
if (target == TGSI_TEXTURE_BUFFER) {
emit_data->output[emit_data->chan] = lp_build_intrinsic(
base->gallivm->builder,
"llvm.SI.vs.load.input", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
return;
}
is_shadow = false;
has_offset = false;
break;
- case TGSI_OPCODE_TXQ:
- name = "llvm.SI.getresinfo";
- is_shadow = false;
- has_offset = false;
- break;
case TGSI_OPCODE_LODQ:
name = "llvm.SI.getlod";
is_shadow = false;
case TGSI_OPCODE_TEX:
case TGSI_OPCODE_TEX2:
case TGSI_OPCODE_TXP:
+ if (ctx->type != PIPE_SHADER_FRAGMENT)
+ infix = ".lz";
break;
case TGSI_OPCODE_TXB:
case TGSI_OPCODE_TXB2:
+ assert(ctx->type == PIPE_SHADER_FRAGMENT);
infix = ".b";
break;
case TGSI_OPCODE_TXL:
break;
case TGSI_OPCODE_TG4:
name = "llvm.SI.gather4";
+ infix = ".lz";
break;
default:
assert(0);
}
/* 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);
- 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,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
-
- /* Divide the number of layers by 6 to get the number of cubes. */
- if (opcode == TGSI_OPCODE_TXQ &&
- (target == TGSI_TEXTURE_CUBE_ARRAY ||
- target == TGSI_TEXTURE_SHADOWCUBE_ARRAY)) {
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- LLVMValueRef two = lp_build_const_int32(bld_base->base.gallivm, 2);
- LLVMValueRef six = lp_build_const_int32(bld_base->base.gallivm, 6);
+ /* 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;
- LLVMValueRef v4 = emit_data->output[emit_data->chan];
- LLVMValueRef z = LLVMBuildExtractElement(builder, v4, two, "");
- z = LLVMBuildSDiv(builder, z, six, "");
+ assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER);
- emit_data->output[emit_data->chan] =
- LLVMBuildInsertElement(builder, v4, z, two, "");
+ 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,
+ LLVMReadNoneAttribute);
}
static void si_llvm_emit_txqs(
{
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];
- 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] = lp_build_intrinsic(gallivm->builder, "llvm.SI.tid", ctx->i32,
- NULL, 0, LLVMReadNoneAttribute);
- 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;
- indices[1] = LLVMBuildAnd(gallivm->builder, indices[1],
- lp_build_const_int32(gallivm, mask), "");
- load_ptr0 = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
+ tl_tid = LLVMBuildAnd(gallivm->builder, thread_id,
+ lp_build_const_int32(gallivm, mask), "");
/* for DDX we want to next X pixel, DDY next Y pixel. */
idx = (opcode == TGSI_OPCODE_DDX || opcode == TGSI_OPCODE_DDX_FINE) ? 1 : 2;
- indices[1] = LLVMBuildAdd(gallivm->builder, indices[1],
- lp_build_const_int32(gallivm, idx), "");
- load_ptr1 = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- for (c = 0; c < 4; ++c) {
- unsigned i;
+ trbl_tid = LLVMBuildAdd(gallivm->builder, tl_tid,
+ lp_build_const_int32(gallivm, idx), "");
- 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, emit_data->args[0], ctx->i32, "");
+
+ 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 {
+ LLVMValueRef store_ptr, load_ptr0, load_ptr1;
- LLVMBuildStore(gallivm->builder,
- LLVMBuildBitCast(gallivm->builder,
- lp_build_emit_fetch(bld_base, inst, 0, c),
- ctx->i32, ""),
- store_ptr);
+ 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, "");
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
- trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
-
- result[c] = LLVMBuildFSub(gallivm->builder, trbl, tl, "");
}
- 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] = lp_build_intrinsic(gallivm->builder, "llvm.SI.tid", ctx->i32,
- NULL, 0, LLVMReadNoneAttribute);
- 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);
if (interp_param_idx == -1)
return;
else if (interp_param_idx)
- interp_param = LLVMGetParam(ctx->radeon_bld.main_fn, interp_param_idx);
+ interp_param = get_interp_param(ctx, interp_param_idx);
else
interp_param = NULL;
}
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;
emit_data->output[chan] =
lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
+ LLVMReadNoneAttribute);
}
}
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);
lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg",
- ctx->voidt, args, 2, LLVMNoUnwindAttribute);
+ ctx->voidt, args, 2, 0);
}
/* Cut one primitive from the geometry shader */
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);
lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg",
- ctx->voidt, args, 2, LLVMNoUnwindAttribute);
+ ctx->voidt, args, 2, 0);
}
static void si_llvm_emit_barrier(const struct lp_build_tgsi_action *action,
/* The real barrier instruction isn’t needed, because an entire patch
* always fits into a single wave.
*/
- if (ctx->type == TGSI_PROCESSOR_TESS_CTRL) {
+ if (ctx->type == PIPE_SHADER_TESS_CTRL) {
emit_optimization_barrier(ctx);
return;
}
lp_build_intrinsic(gallivm->builder,
HAVE_LLVM >= 0x0309 ? "llvm.amdgcn.s.barrier"
: "llvm.AMDGPU.barrier.local",
- ctx->voidt, NULL, 0, LLVMNoUnwindAttribute);
+ ctx->voidt, NULL, 0, 0);
}
static const struct lp_build_tgsi_action tex_action = {
static void si_create_function(struct si_shader_context *ctx,
LLVMTypeRef *returns, unsigned num_returns,
LLVMTypeRef *params, unsigned num_params,
- int last_array_pointer, int last_sgpr)
+ int last_sgpr)
{
int i;
for (i = 0; i <= last_sgpr; ++i) {
LLVMValueRef P = LLVMGetParam(ctx->radeon_bld.main_fn, i);
- /* We tell llvm that array inputs are passed by value to allow Sinking pass
- * to move load. Inputs are constant so this is fine. */
- if (i <= last_array_pointer)
+ /* The combination of:
+ * - ByVal
+ * - dereferenceable
+ * - invariant.load
+ * allows the optimization passes to move loads and reduces
+ * SGPR spilling significantly.
+ */
+ if (LLVMGetTypeKind(LLVMTypeOf(P)) == LLVMPointerTypeKind) {
LLVMAddAttribute(P, LLVMByValAttribute);
- else
+ lp_add_attr_dereferenceable(P, UINT64_MAX);
+ } else
LLVMAddAttribute(P, LLVMInRegAttribute);
}
+
+ if (ctx->screen->b.debug_flags & DBG_UNSAFE_MATH) {
+ /* These were copied from some LLVM test. */
+ LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ "less-precise-fpmad",
+ "true");
+ LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ "no-infs-fp-math",
+ "true");
+ LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.main_fn,
+ "no-nans-fp-math",
+ "true");
+ LLVMAddTargetDependentFunctionAttr(ctx->radeon_bld.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;
- LLVMValueRef args[3];
- args[0] = LLVMMDStringInContext(gallivm->context, "const", 5);
- args[1] = 0;
- args[2] = lp_build_const_int32(gallivm, 1);
+ ctx->invariant_load_md_kind = LLVMGetMDKindIDInContext(gallivm->context,
+ "invariant.load", 14);
+ ctx->range_md_kind = LLVMGetMDKindIDInContext(gallivm->context,
+ "range", 5);
+ ctx->uniform_md_kind = LLVMGetMDKindIDInContext(gallivm->context,
+ "amdgpu.uniform", 14);
- ctx->const_md = LLVMMDNodeInContext(gallivm->context, args, 3);
+ ctx->empty_md = LLVMMDNodeInContext(gallivm->context, NULL, 0);
}
static void declare_streamout_params(struct si_shader_context *ctx,
/* Streamout SGPRs. */
if (so->num_outputs) {
- params[ctx->param_streamout_config = (*num_params)++] = i32;
+ if (ctx->type != PIPE_SHADER_TESS_EVAL)
+ params[ctx->param_streamout_config = (*num_params)++] = i32;
+ else
+ ctx->param_streamout_config = ctx->param_tess_offchip;
+
params[ctx->param_streamout_write_index = (*num_params)++] = i32;
}
/* A streamout buffer offset is loaded if the stride is non-zero. */
static void declare_tess_lds(struct si_shader_context *ctx)
{
struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
- LLVMTypeRef i32 = ctx->radeon_bld.soa.bld_base.uint_bld.elem_type;
-
- /* This is the upper bound, maximum is 32 inputs times 32 vertices */
- unsigned vertex_data_dw_size = 32*32*4;
- unsigned patch_data_dw_size = 32*4;
- /* The formula is: TCS inputs + TCS outputs + TCS patch outputs. */
- unsigned patch_dw_size = vertex_data_dw_size*2 + patch_data_dw_size;
- unsigned lds_dwords = patch_dw_size;
+ struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
+ struct lp_build_context *uint = &bld_base->uint_bld;
- /* The actual size is computed outside of the shader to reduce
- * the number of shader variants. */
- ctx->lds =
- LLVMAddGlobalInAddressSpace(gallivm->module,
- LLVMArrayType(i32, lds_dwords),
- "tess_lds",
- LOCAL_ADDR_SPACE);
+ unsigned lds_size = ctx->screen->b.chip_class >= CIK ? 65536 : 32768;
+ ctx->lds = LLVMBuildIntToPtr(gallivm->builder, uint->zero,
+ LLVMPointerType(LLVMArrayType(ctx->i32, lds_size / 4), LOCAL_ADDR_SPACE),
+ "tess_lds");
}
static void create_function(struct si_shader_context *ctx)
struct si_shader *shader = ctx->shader;
LLVMTypeRef params[SI_NUM_PARAMS + SI_NUM_VERTEX_BUFFERS], v3i32;
LLVMTypeRef returns[16+32*4];
- unsigned i, last_array_pointer, last_sgpr, num_params, num_return_sgprs;
+ unsigned i, last_sgpr, num_params, num_return_sgprs;
unsigned num_returns = 0;
v3i32 = LLVMVectorType(ctx->i32, 3);
params[SI_PARAM_SAMPLERS] = const_array(ctx->v8i32, SI_NUM_SAMPLERS);
params[SI_PARAM_IMAGES] = const_array(ctx->v8i32, SI_NUM_IMAGES);
params[SI_PARAM_SHADER_BUFFERS] = const_array(ctx->v4i32, SI_NUM_SHADER_BUFFERS);
- last_array_pointer = SI_PARAM_SHADER_BUFFERS;
switch (ctx->type) {
- case TGSI_PROCESSOR_VERTEX:
+ case PIPE_SHADER_VERTEX:
params[SI_PARAM_VERTEX_BUFFERS] = const_array(ctx->v16i8, SI_NUM_VERTEX_BUFFERS);
- last_array_pointer = SI_PARAM_VERTEX_BUFFERS;
params[SI_PARAM_BASE_VERTEX] = ctx->i32;
params[SI_PARAM_START_INSTANCE] = ctx->i32;
- num_params = SI_PARAM_START_INSTANCE+1;
+ params[SI_PARAM_DRAWID] = ctx->i32;
+ num_params = SI_PARAM_DRAWID+1;
if (shader->key.vs.as_es) {
params[ctx->param_es2gs_offset = num_params++] = ctx->i32;
num_params = SI_PARAM_LS_OUT_LAYOUT+1;
} else {
if (ctx->is_gs_copy_shader) {
- last_array_pointer = SI_PARAM_CONST_BUFFERS;
- num_params = SI_PARAM_CONST_BUFFERS+1;
+ num_params = SI_PARAM_RW_BUFFERS+1;
} else {
params[SI_PARAM_VS_STATE_BITS] = ctx->i32;
num_params = SI_PARAM_VS_STATE_BITS+1;
}
break;
- case TGSI_PROCESSOR_TESS_CTRL:
+ case PIPE_SHADER_TESS_CTRL:
+ params[SI_PARAM_TCS_OFFCHIP_LAYOUT] = ctx->i32;
params[SI_PARAM_TCS_OUT_OFFSETS] = ctx->i32;
params[SI_PARAM_TCS_OUT_LAYOUT] = ctx->i32;
params[SI_PARAM_TCS_IN_LAYOUT] = ctx->i32;
+ params[ctx->param_oc_lds = SI_PARAM_TCS_OC_LDS] = ctx->i32;
params[SI_PARAM_TESS_FACTOR_OFFSET] = ctx->i32;
last_sgpr = SI_PARAM_TESS_FACTOR_OFFSET;
num_params = SI_PARAM_REL_IDS+1;
if (!ctx->is_monolithic) {
- /* PARAM_TESS_FACTOR_OFFSET is after user SGPRs. */
- for (i = 0; i <= SI_TCS_NUM_USER_SGPR; i++)
+ /* SI_PARAM_TCS_OC_LDS and PARAM_TESS_FACTOR_OFFSET are
+ * placed after the user SGPRs.
+ */
+ for (i = 0; i < SI_TCS_NUM_USER_SGPR + 2; i++)
returns[num_returns++] = ctx->i32; /* SGPRs */
for (i = 0; i < 3; i++)
}
break;
- case TGSI_PROCESSOR_TESS_EVAL:
- params[SI_PARAM_TCS_OUT_OFFSETS] = ctx->i32;
- params[SI_PARAM_TCS_OUT_LAYOUT] = ctx->i32;
- num_params = SI_PARAM_TCS_OUT_LAYOUT+1;
+ case PIPE_SHADER_TESS_EVAL:
+ params[SI_PARAM_TCS_OFFCHIP_LAYOUT] = ctx->i32;
+ num_params = SI_PARAM_TCS_OFFCHIP_LAYOUT+1;
if (shader->key.tes.as_es) {
+ params[ctx->param_oc_lds = num_params++] = ctx->i32;
+ params[ctx->param_tess_offchip = num_params++] = ctx->i32;
params[ctx->param_es2gs_offset = num_params++] = ctx->i32;
} else {
+ params[ctx->param_tess_offchip = num_params++] = ctx->i32;
declare_streamout_params(ctx, &shader->selector->so,
params, ctx->i32, &num_params);
+ params[ctx->param_oc_lds = num_params++] = ctx->i32;
}
last_sgpr = num_params - 1;
returns[num_returns++] = ctx->f32;
break;
- case TGSI_PROCESSOR_GEOMETRY:
+ case PIPE_SHADER_GEOMETRY:
params[SI_PARAM_GS2VS_OFFSET] = ctx->i32;
params[SI_PARAM_GS_WAVE_ID] = ctx->i32;
last_sgpr = SI_PARAM_GS_WAVE_ID;
num_params = SI_PARAM_GS_INSTANCE_ID+1;
break;
- case TGSI_PROCESSOR_FRAGMENT:
+ case PIPE_SHADER_FRAGMENT:
params[SI_PARAM_ALPHA_REF] = ctx->f32;
params[SI_PARAM_PRIM_MASK] = ctx->i32;
last_sgpr = SI_PARAM_PRIM_MASK;
}
break;
- case TGSI_PROCESSOR_COMPUTE:
+ 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;
return;
}
- assert(num_params <= Elements(params));
+ assert(num_params <= ARRAY_SIZE(params));
si_create_function(ctx, returns, num_returns, params,
- num_params, last_array_pointer, last_sgpr);
+ num_params, last_sgpr);
/* Reserve register locations for VGPR inputs the PS prolog may need. */
- if (ctx->type == TGSI_PROCESSOR_FRAGMENT &&
+ if (ctx->type == PIPE_SHADER_FRAGMENT &&
!ctx->is_monolithic) {
radeon_llvm_add_attribute(ctx->radeon_bld.main_fn,
"InitialPSInputAddr",
S_0286D0_LINEAR_CENTROID_ENA(1) |
S_0286D0_FRONT_FACE_ENA(1) |
S_0286D0_POS_FIXED_PT_ENA(1));
- } else if (ctx->type == TGSI_PROCESSOR_COMPUTE) {
+ } 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_WIDTH] *
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",
/* Unused fragment shader inputs are eliminated by the compiler,
* so we don't know yet how many there will be.
*/
- if (ctx->type != TGSI_PROCESSOR_FRAGMENT)
+ if (ctx->type != PIPE_SHADER_FRAGMENT)
for (; i < num_params; ++i)
shader->info.num_input_vgprs += llvm_get_type_size(params[i]) / 4;
- 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 ||
"ddxy_lds",
LOCAL_ADDR_SPACE);
- if ((ctx->type == TGSI_PROCESSOR_VERTEX && shader->key.vs.as_ls) ||
- ctx->type == TGSI_PROCESSOR_TESS_CTRL ||
- ctx->type == TGSI_PROCESSOR_TESS_EVAL)
+ if ((ctx->type == PIPE_SHADER_VERTEX && shader->key.vs.as_ls) ||
+ ctx->type == PIPE_SHADER_TESS_CTRL ||
+ ctx->type == PIPE_SHADER_TESS_EVAL)
declare_tess_lds(ctx);
}
-static void preload_constants(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;
-
- /* Allocate space for the constant values */
- ctx->constants[buf] = CALLOC(num_const * 4, sizeof(LLVMValueRef));
-
- /* Load the resource descriptor */
- ctx->const_buffers[buf] =
- build_indexed_load_const(ctx, ptr, lp_build_const_int32(gallivm, buf));
-
- /* 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(gallivm->builder,
- ctx->const_buffers[buf],
- lp_build_const_int32(gallivm, i * 4),
- ctx->f32);
- }
- }
-}
-
-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;
-
- 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));
- }
-}
-
-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;
-
- /* 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]);
- }
- }
-}
-
-static void preload_images(struct si_shader_context *ctx)
-{
- struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
- struct tgsi_shader_info *info = &ctx->shader->selector->info;
- 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 == TGSI_PROCESSOR_VERTEX &&
- (ctx->shader->key.vs.as_es ||
- ctx->shader->key.vs.as_ls)) ||
- (ctx->type == TGSI_PROCESSOR_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.
LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
SI_PARAM_RW_BUFFERS);
- if ((ctx->type == TGSI_PROCESSOR_VERTEX &&
+ if ((ctx->type == PIPE_SHADER_VERTEX &&
ctx->shader->key.vs.as_es) ||
- (ctx->type == TGSI_PROCESSOR_TESS_EVAL &&
+ (ctx->type == PIPE_SHADER_TESS_EVAL &&
ctx->shader->key.tes.as_es) ||
- ctx->type == TGSI_PROCESSOR_GEOMETRY) {
+ ctx->type == PIPE_SHADER_GEOMETRY) {
unsigned ring =
- ctx->type == TGSI_PROCESSOR_GEOMETRY ? SI_GS_RING_ESGS
+ ctx->type == PIPE_SHADER_GEOMETRY ? SI_GS_RING_ESGS
: SI_ES_RING_ESGS;
LLVMValueRef offset = lp_build_const_int32(gallivm, ring);
ctx->gsvs_ring[0] =
build_indexed_load_const(ctx, buf_ptr, offset);
}
- if (ctx->type == TGSI_PROCESSOR_GEOMETRY) {
+ 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);
/* The stipple pattern is 32x32, each row has 32 bits. */
offset = LLVMBuildMul(builder, address[1],
LLVMConstInt(ctx->i32, 4, 0), "");
- row = buffer_load_const(builder, desc, offset, ctx->i32);
+ row = buffer_load_const(ctx, desc, offset);
+ row = LLVMBuildBitCast(builder, row, ctx->i32, "");
bit = LLVMBuildLShr(builder, row, address[0], "");
bit = LLVMBuildTrunc(builder, bit, ctx->i1, "");
unsigned i;
const unsigned char *config =
radeon_shader_binary_config_start(binary, symbol_offset);
+ bool really_needs_scratch = false;
+
+ /* LLVM adds SGPR spills to the scratch size.
+ * Find out if we really need the scratch buffer.
+ */
+ for (i = 0; i < binary->reloc_count; i++) {
+ const struct radeon_shader_reloc *reloc = &binary->relocs[i];
+
+ if (!strcmp(scratch_rsrc_dword0_symbol, reloc->name) ||
+ !strcmp(scratch_rsrc_dword1_symbol, reloc->name)) {
+ really_needs_scratch = true;
+ break;
+ }
+ }
/* XXX: We may be able to emit some of these values directly rather than
* extracting fields to be emitted later.
case R_0286E8_SPI_TMPRING_SIZE:
case R_00B860_COMPUTE_TMPRING_SIZE:
/* WAVESIZE is in units of 256 dwords. */
- conf->scratch_bytes_per_wave =
- G_00B860_WAVESIZE(value) * 256 * 4 * 1;
+ if (really_needs_scratch)
+ conf->scratch_bytes_per_wave =
+ G_00B860_WAVESIZE(value) * 256 * 4;
+ break;
+ case 0x4: /* SPILLED_SGPRS */
+ conf->spilled_sgprs = value;
+ break;
+ case 0x8: /* SPILLED_VGPRS */
+ conf->spilled_vgprs = value;
break;
default:
{
}
break;
}
-
- if (!conf->spi_ps_input_addr)
- conf->spi_ps_input_addr = conf->spi_ps_input_ena;
}
+
+ if (!conf->spi_ps_input_addr)
+ conf->spi_ps_input_addr = conf->spi_ps_input_ena;
}
void si_shader_apply_scratch_relocs(struct si_context *sctx,
unsigned i;
uint32_t scratch_rsrc_dword0 = scratch_va;
uint32_t scratch_rsrc_dword1 =
- S_008F04_BASE_ADDRESS_HI(scratch_va >> 32)
- | S_008F04_STRIDE(config->scratch_bytes_per_wave / 64);
+ S_008F04_BASE_ADDRESS_HI(scratch_va >> 32);
+
+ /* Enable scratch coalescing if LLVM sets ELEMENT_SIZE & INDEX_STRIDE
+ * correctly.
+ */
+ if (HAVE_LLVM >= 0x0309)
+ scratch_rsrc_dword1 |= S_008F04_SWIZZLE_ENABLE(1);
+ else
+ scratch_rsrc_dword1 |=
+ S_008F04_STRIDE(config->scratch_bytes_per_wave / 64);
for (i = 0 ; i < shader->binary.reloc_count; i++) {
const struct radeon_shader_reloc *reloc =
unsigned max_simd_waves = 10;
/* Compute LDS usage for PS. */
- if (processor == TGSI_PROCESSOR_FRAGMENT) {
- /* The minimum usage per wave is (num_inputs * 36). The maximum
- * usage is (num_inputs * 36 * 16).
+ if (processor == PIPE_SHADER_FRAGMENT) {
+ /* The minimum usage per wave is (num_inputs * 48). The maximum
+ * usage is (num_inputs * 48 * 16).
* We can get anything in between and it varies between waves.
*
+ * The 48 bytes per input for a single primitive is equal to
+ * 4 bytes/component * 4 components/input * 3 points.
+ *
* Other stages don't know the size at compile time or don't
* allocate LDS per wave, but instead they do it per thread group.
*/
lds_per_wave = conf->lds_size * lds_increment +
- align(num_inputs * 36, lds_increment);
+ align(num_inputs * 48, lds_increment);
}
/* Compute the per-SIMD wave counts. */
if (file != stderr ||
r600_can_dump_shader(&sscreen->b, processor)) {
- if (processor == TGSI_PROCESSOR_FRAGMENT) {
+ if (processor == PIPE_SHADER_FRAGMENT) {
fprintf(file, "*** SHADER CONFIG ***\n"
"SPI_PS_INPUT_ADDR = 0x%04x\n"
"SPI_PS_INPUT_ENA = 0x%04x\n",
fprintf(file, "*** SHADER STATS ***\n"
"SGPRS: %d\n"
"VGPRS: %d\n"
+ "Spilled SGPRs: %d\n"
+ "Spilled VGPRs: %d\n"
"Code Size: %d bytes\n"
"LDS: %d blocks\n"
"Scratch: %d bytes per wave\n"
"Max Waves: %d\n"
- "********************\n",
- conf->num_sgprs, conf->num_vgprs, code_size,
+ "********************\n\n\n",
+ conf->num_sgprs, conf->num_vgprs,
+ conf->spilled_sgprs, conf->spilled_vgprs, code_size,
conf->lds_size, conf->scratch_bytes_per_wave,
max_simd_waves);
}
pipe_debug_message(debug, SHADER_INFO,
"Shader Stats: SGPRS: %d VGPRS: %d Code Size: %d "
- "LDS: %d Scratch: %d Max Waves: %d",
+ "LDS: %d Scratch: %d Max Waves: %d Spilled SGPRs: %d "
+ "Spilled VGPRs: %d",
conf->num_sgprs, conf->num_vgprs, code_size,
conf->lds_size, conf->scratch_bytes_per_wave,
- max_simd_waves);
+ max_simd_waves, conf->spilled_sgprs,
+ conf->spilled_vgprs);
}
static const char *si_get_shader_name(struct si_shader *shader,
unsigned processor)
{
switch (processor) {
- case TGSI_PROCESSOR_VERTEX:
+ case PIPE_SHADER_VERTEX:
if (shader->key.vs.as_es)
return "Vertex Shader as ES";
else if (shader->key.vs.as_ls)
return "Vertex Shader as LS";
else
return "Vertex Shader as VS";
- case TGSI_PROCESSOR_TESS_CTRL:
+ case PIPE_SHADER_TESS_CTRL:
return "Tessellation Control Shader";
- case TGSI_PROCESSOR_TESS_EVAL:
+ case PIPE_SHADER_TESS_EVAL:
if (shader->key.tes.as_es)
return "Tessellation Evaluation Shader as ES";
else
return "Tessellation Evaluation Shader as VS";
- case TGSI_PROCESSOR_GEOMETRY:
+ case PIPE_SHADER_GEOMETRY:
if (shader->gs_copy_shader == NULL)
return "GS Copy Shader as VS";
else
return "Geometry Shader";
- case TGSI_PROCESSOR_FRAGMENT:
+ case PIPE_SHADER_FRAGMENT:
return "Pixel Shader";
- case TGSI_PROCESSOR_COMPUTE:
+ case PIPE_SHADER_COMPUTE:
return "Compute Shader";
default:
return "Unknown Shader";
struct pipe_debug_callback *debug, unsigned processor,
FILE *file)
{
+ if (file != stderr ||
+ r600_can_dump_shader(&sscreen->b, processor))
+ si_dump_shader_key(processor, &shader->key, file);
+
+ if (file != stderr && shader->binary.llvm_ir_string) {
+ fprintf(file, "\n%s - main shader part - LLVM IR:\n\n",
+ si_get_shader_name(shader, processor));
+ fprintf(file, "%s\n", shader->binary.llvm_ir_string);
+ }
+
if (file != stderr ||
(r600_can_dump_shader(&sscreen->b, processor) &&
!(sscreen->b.debug_flags & DBG_NO_ASM))) {
}
}
+ if (sscreen->record_llvm_ir) {
+ char *ir = LLVMPrintModuleToString(mod);
+ binary->llvm_ir_string = strdup(ir);
+ LLVMDisposeMessage(ir);
+ }
+
if (!si_replace_shader(count, binary)) {
- r = radeon_llvm_compile(mod, binary,
- r600_get_llvm_processor_name(sscreen->b.family), tm,
- debug);
+ r = radeon_llvm_compile(mod, binary, tm, debug);
if (r)
return r;
}
* concatenated.
*/
if (binary->rodata_size &&
- (processor == TGSI_PROCESSOR_VERTEX ||
- processor == TGSI_PROCESSOR_TESS_CTRL ||
- processor == TGSI_PROCESSOR_TESS_EVAL ||
- processor == TGSI_PROCESSOR_FRAGMENT)) {
+ (processor == PIPE_SHADER_VERTEX ||
+ processor == PIPE_SHADER_TESS_CTRL ||
+ processor == PIPE_SHADER_TESS_EVAL ||
+ processor == PIPE_SHADER_FRAGMENT)) {
fprintf(stderr, "radeonsi: The shader can't have rodata.");
return -EINVAL;
}
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);
+ else
+ LLVMBuildRet(ctx->radeon_bld.gallivm.builder, ret);
+}
+
/* Generate code for the hardware VS shader stage to go with a geometry shader */
static int si_generate_gs_copy_shader(struct si_screen *sscreen,
struct si_shader_context *ctx,
outputs = MALLOC(gsinfo->num_outputs * sizeof(outputs[0]));
si_init_shader_ctx(ctx, sscreen, ctx->shader, ctx->tm);
- ctx->type = TGSI_PROCESSOR_VERTEX;
+ ctx->type = PIPE_SHADER_VERTEX;
ctx->is_gs_copy_shader = true;
create_meta_data(ctx);
create_function(ctx);
- preload_streamout_buffers(ctx);
preload_ring_buffers(ctx);
args[0] = ctx->gsvs_ring[0];
lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LLVMReadOnlyAttribute | LLVMNoUnwindAttribute),
+ LLVMReadOnlyAttribute),
ctx->f32, "");
}
}
si_llvm_export_vs(bld_base, outputs, gsinfo->num_outputs);
- LLVMBuildRet(gallivm->builder, ctx->return_value);
+ LLVMBuildRetVoid(gallivm->builder);
/* Dump LLVM IR before any optimization passes */
if (sscreen->b.debug_flags & DBG_PREOPT_IR &&
- r600_can_dump_shader(&sscreen->b, TGSI_PROCESSOR_GEOMETRY))
+ r600_can_dump_shader(&sscreen->b, PIPE_SHADER_GEOMETRY))
LLVMDumpModule(bld_base->base.gallivm->module);
- radeon_llvm_finalize_module(&ctx->radeon_bld);
+ radeon_llvm_finalize_module(
+ &ctx->radeon_bld,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_GEOMETRY));
r = si_compile_llvm(sscreen, &ctx->shader->binary,
&ctx->shader->config, ctx->tm,
bld_base->base.gallivm->module,
- debug, TGSI_PROCESSOR_GEOMETRY,
+ debug, PIPE_SHADER_GEOMETRY,
"GS Copy Shader");
if (!r) {
- if (r600_can_dump_shader(&sscreen->b, TGSI_PROCESSOR_GEOMETRY))
+ if (r600_can_dump_shader(&sscreen->b, PIPE_SHADER_GEOMETRY))
fprintf(stderr, "GS Copy Shader:\n");
si_shader_dump(sscreen, ctx->shader, debug,
- TGSI_PROCESSOR_GEOMETRY, stderr);
+ PIPE_SHADER_GEOMETRY, stderr);
r = si_shader_binary_upload(sscreen, ctx->shader);
}
return r;
}
-void si_dump_shader_key(unsigned shader, union si_shader_key *key, FILE *f)
+static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
+ FILE *f)
{
int i;
switch (shader) {
case PIPE_SHADER_VERTEX:
fprintf(f, " instance_divisors = {");
- for (i = 0; i < Elements(key->vs.prolog.instance_divisors); i++)
+ for (i = 0; i < ARRAY_SIZE(key->vs.prolog.instance_divisors); i++)
fprintf(f, !i ? "%u" : ", %u",
key->vs.prolog.instance_divisors[i]);
fprintf(f, "}\n");
case PIPE_SHADER_FRAGMENT:
fprintf(f, " prolog.color_two_side = %u\n", key->ps.prolog.color_two_side);
+ fprintf(f, " prolog.flatshade_colors = %u\n", key->ps.prolog.flatshade_colors);
fprintf(f, " prolog.poly_stipple = %u\n", key->ps.prolog.poly_stipple);
- fprintf(f, " prolog.force_persample_interp = %u\n", key->ps.prolog.force_persample_interp);
+ fprintf(f, " prolog.force_persp_sample_interp = %u\n", key->ps.prolog.force_persp_sample_interp);
+ fprintf(f, " prolog.force_linear_sample_interp = %u\n", key->ps.prolog.force_linear_sample_interp);
+ fprintf(f, " prolog.force_persp_center_interp = %u\n", key->ps.prolog.force_persp_center_interp);
+ fprintf(f, " prolog.force_linear_center_interp = %u\n", key->ps.prolog.force_linear_center_interp);
+ fprintf(f, " prolog.bc_optimize_for_persp = %u\n", key->ps.prolog.bc_optimize_for_persp);
+ fprintf(f, " prolog.bc_optimize_for_linear = %u\n", key->ps.prolog.bc_optimize_for_linear);
fprintf(f, " epilog.spi_shader_col_format = 0x%x\n", key->ps.epilog.spi_shader_col_format);
fprintf(f, " epilog.color_is_int8 = 0x%X\n", key->ps.epilog.color_is_int8);
fprintf(f, " epilog.last_cbuf = %u\n", key->ps.epilog.last_cbuf);
struct lp_build_tgsi_action tmpl = {};
memset(ctx, 0, sizeof(*ctx));
- radeon_llvm_context_init(&ctx->radeon_bld, "amdgcn--");
+ radeon_llvm_context_init(
+ &ctx->radeon_bld, "amdgcn--",
+ (shader && shader->selector) ? &shader->selector->info : NULL,
+ (shader && shader->selector) ? shader->selector->tokens : NULL);
ctx->tm = tm;
ctx->screen = sscreen;
if (shader && shader->selector)
ctx->v8i32 = LLVMVectorType(ctx->i32, 8);
bld_base = &ctx->radeon_bld.soa.bld_base;
- if (shader && shader->selector)
- bld_base->info = &shader->selector->info;
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_TXL] = tex_action;
bld_base->op_actions[TGSI_OPCODE_TXL2] = tex_action;
bld_base->op_actions[TGSI_OPCODE_TXP] = tex_action;
- bld_base->op_actions[TGSI_OPCODE_TXQ] = tex_action;
+ bld_base->op_actions[TGSI_OPCODE_TXQ].fetch_args = txq_fetch_args;
+ bld_base->op_actions[TGSI_OPCODE_TXQ].emit = txq_emit;
bld_base->op_actions[TGSI_OPCODE_TG4] = tex_action;
bld_base->op_actions[TGSI_OPCODE_LODQ] = tex_action;
bld_base->op_actions[TGSI_OPCODE_TXQS].emit = si_llvm_emit_txqs;
* conversion fails. */
if (r600_can_dump_shader(&sscreen->b, sel->info.processor) &&
!(sscreen->b.debug_flags & DBG_NO_TGSI)) {
- si_dump_shader_key(sel->type, &shader->key, stderr);
tgsi_dump(sel->tokens, 0);
si_dump_streamout(&sel->so);
}
ctx.radeon_bld.load_system_value = declare_system_value;
switch (ctx.type) {
- case TGSI_PROCESSOR_VERTEX:
+ case PIPE_SHADER_VERTEX:
ctx.radeon_bld.load_input = declare_input_vs;
if (shader->key.vs.as_ls)
bld_base->emit_epilogue = si_llvm_emit_ls_epilogue;
else
bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
break;
- case TGSI_PROCESSOR_TESS_CTRL:
+ case PIPE_SHADER_TESS_CTRL:
bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_tcs;
bld_base->emit_fetch_funcs[TGSI_FILE_OUTPUT] = fetch_output_tcs;
bld_base->emit_store = store_output_tcs;
bld_base->emit_epilogue = si_llvm_emit_tcs_epilogue;
break;
- case TGSI_PROCESSOR_TESS_EVAL:
+ case PIPE_SHADER_TESS_EVAL:
bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_tes;
if (shader->key.tes.as_es)
bld_base->emit_epilogue = si_llvm_emit_es_epilogue;
else
bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
break;
- case TGSI_PROCESSOR_GEOMETRY:
+ case PIPE_SHADER_GEOMETRY:
bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_gs;
bld_base->emit_epilogue = si_llvm_emit_gs_epilogue;
break;
- case TGSI_PROCESSOR_FRAGMENT:
+ case PIPE_SHADER_FRAGMENT:
ctx.radeon_bld.load_input = declare_input_fs;
if (is_monolithic)
bld_base->emit_epilogue = si_llvm_emit_fs_epilogue;
else
bld_base->emit_epilogue = si_llvm_return_fs_outputs;
break;
- case TGSI_PROCESSOR_COMPUTE:
+ case PIPE_SHADER_COMPUTE:
ctx.radeon_bld.declare_memory_region = declare_compute_memory;
break;
default:
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);
if (ctx.is_monolithic && sel->type == PIPE_SHADER_FRAGMENT &&
SI_PARAM_POS_FIXED_PT);
}
- if (ctx.type == TGSI_PROCESSOR_GEOMETRY) {
+ if (ctx.type == PIPE_SHADER_GEOMETRY) {
int i;
for (i = 0; i < 4; i++) {
ctx.gs_next_vertex[i] =
goto out;
}
- LLVMBuildRet(bld_base->base.gallivm->builder, ctx.return_value);
+ si_llvm_build_ret(&ctx, ctx.return_value);
mod = bld_base->base.gallivm->module;
/* Dump LLVM IR before any optimization passes */
r600_can_dump_shader(&sscreen->b, ctx.type))
LLVMDumpModule(mod);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ radeon_llvm_finalize_module(
+ &ctx.radeon_bld,
+ r600_extra_shader_checks(&sscreen->b, ctx.type));
r = si_compile_llvm(sscreen, &shader->binary, &shader->config, tm,
mod, debug, ctx.type, "TGSI shader");
radeon_llvm_dispose(&ctx.radeon_bld);
+ /* 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 == TGSI_PROCESSOR_FRAGMENT) {
+ if (ctx.type == PIPE_SHADER_FRAGMENT) {
shader->info.num_input_vgprs = 0;
shader->info.face_vgpr_index = -1;
shader->info.num_input_vgprs += 1;
}
- if (ctx.type == TGSI_PROCESSOR_GEOMETRY) {
+ if (ctx.type == PIPE_SHADER_GEOMETRY) {
shader->gs_copy_shader = CALLOC_STRUCT(si_shader);
shader->gs_copy_shader->selector = shader->selector;
ctx.shader = shader->gs_copy_shader;
}
out:
- for (int i = 0; i < SI_NUM_CONST_BUFFERS; i++)
- FREE(ctx.constants[i]);
return r;
}
bool status = true;
si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = TGSI_PROCESSOR_VERTEX;
+ 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;
/* Create the function. */
si_create_function(&ctx, returns, num_returns, params,
- num_params, -1, last_sgpr);
+ num_params, last_sgpr);
func = ctx.radeon_bld.main_fn;
/* Copy inputs to outputs. This should be no-op, as the registers match,
}
/* Compile. */
- LLVMBuildRet(gallivm->builder, ret);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ si_llvm_build_ret(&ctx, ret);
+ radeon_llvm_finalize_module(
+ &ctx.radeon_bld,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
bool status = true;
si_init_shader_ctx(&ctx, sscreen, NULL, tm);
- ctx.type = TGSI_PROCESSOR_VERTEX;
+ ctx.type = PIPE_SHADER_VERTEX;
/* Declare input VGPRs. */
num_params = key->vs_epilog.states.export_prim_id ?
params[i] = ctx.f32;
/* Create the function. */
- si_create_function(&ctx, NULL, 0, params, num_params,
- -1, -1);
+ si_create_function(&ctx, NULL, 0, params, num_params, -1);
/* Emit exports. */
if (key->vs_epilog.states.export_prim_id) {
}
/* Compile. */
- LLVMBuildRet(gallivm->builder, ctx.return_value);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ LLVMBuildRetVoid(gallivm->builder);
+ radeon_llvm_finalize_module(
+ &ctx.radeon_bld,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
struct lp_build_tgsi_context *bld_base = &ctx.radeon_bld.soa.bld_base;
LLVMTypeRef params[16];
LLVMValueRef func;
- int last_array_pointer, last_sgpr, num_params;
+ int last_sgpr, num_params;
bool status = true;
si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = TGSI_PROCESSOR_TESS_CTRL;
+ ctx.type = PIPE_SHADER_TESS_CTRL;
shader.key.tcs.epilog = key->tcs_epilog.states;
/* Declare inputs. Only RW_BUFFERS and TESS_FACTOR_OFFSET are used. */
params[SI_PARAM_RW_BUFFERS] = const_array(ctx.v16i8, SI_NUM_RW_BUFFERS);
- last_array_pointer = SI_PARAM_RW_BUFFERS;
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_TCS_OFFCHIP_LAYOUT] = ctx.i32;
params[SI_PARAM_TCS_OUT_OFFSETS] = ctx.i32;
params[SI_PARAM_TCS_OUT_LAYOUT] = ctx.i32;
params[SI_PARAM_TCS_IN_LAYOUT] = ctx.i32;
+ params[ctx.param_oc_lds = SI_PARAM_TCS_OC_LDS] = ctx.i32;
params[SI_PARAM_TESS_FACTOR_OFFSET] = ctx.i32;
last_sgpr = SI_PARAM_TESS_FACTOR_OFFSET;
num_params = last_sgpr + 1;
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_array_pointer, last_sgpr);
+ si_create_function(&ctx, NULL, 0, params, num_params, last_sgpr);
declare_tess_lds(&ctx);
func = ctx.radeon_bld.main_fn;
LLVMGetParam(func, last_sgpr + 3));
/* Compile. */
- LLVMBuildRet(gallivm->builder, ctx.return_value);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ LLVMBuildRetVoid(gallivm->builder);
+ radeon_llvm_finalize_module(
+ &ctx.radeon_bld,
+ 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,
bool status = true;
si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = TGSI_PROCESSOR_FRAGMENT;
+ ctx.type = PIPE_SHADER_FRAGMENT;
shader.key.ps.prolog = key->ps_prolog.states;
/* Number of inputs + 8 color elements. */
/* Create the function. */
si_create_function(&ctx, params, num_returns, params,
- num_params, -1, last_sgpr);
+ num_params, last_sgpr);
func = ctx.radeon_bld.main_fn;
/* Copy inputs to outputs. This should be no-op, as the registers match,
si_llvm_emit_polygon_stipple(&ctx, list, pos);
}
+ if (key->ps_prolog.states.bc_optimize_for_persp ||
+ key->ps_prolog.states.bc_optimize_for_linear) {
+ unsigned i, base = key->ps_prolog.num_input_sgprs;
+ LLVMValueRef center[2], centroid[2], tmp, bc_optimize;
+
+ /* The shader should do: if (PRIM_MASK[31]) CENTROID = CENTER;
+ * The hw doesn't compute CENTROID if the whole wave only
+ * contains fully-covered quads.
+ *
+ * PRIM_MASK is after user SGPRs.
+ */
+ bc_optimize = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
+ bc_optimize = LLVMBuildLShr(gallivm->builder, bc_optimize,
+ LLVMConstInt(ctx.i32, 31, 0), "");
+ bc_optimize = LLVMBuildTrunc(gallivm->builder, bc_optimize,
+ ctx.i1, "");
+
+ if (key->ps_prolog.states.bc_optimize_for_persp) {
+ /* Read PERSP_CENTER. */
+ for (i = 0; i < 2; i++)
+ center[i] = LLVMGetParam(func, base + 2 + i);
+ /* Read PERSP_CENTROID. */
+ for (i = 0; i < 2; i++)
+ centroid[i] = LLVMGetParam(func, base + 4 + i);
+ /* Select PERSP_CENTROID. */
+ for (i = 0; i < 2; i++) {
+ tmp = LLVMBuildSelect(gallivm->builder, bc_optimize,
+ center[i], centroid[i], "");
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ tmp, base + 4 + i, "");
+ }
+ }
+ if (key->ps_prolog.states.bc_optimize_for_linear) {
+ /* Read LINEAR_CENTER. */
+ for (i = 0; i < 2; i++)
+ center[i] = LLVMGetParam(func, base + 8 + i);
+ /* Read LINEAR_CENTROID. */
+ for (i = 0; i < 2; i++)
+ centroid[i] = LLVMGetParam(func, base + 10 + i);
+ /* Select LINEAR_CENTROID. */
+ for (i = 0; i < 2; i++) {
+ tmp = LLVMBuildSelect(gallivm->builder, bc_optimize,
+ center[i], centroid[i], "");
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ tmp, base + 10 + i, "");
+ }
+ }
+ }
+
+ /* Force per-sample interpolation. */
+ if (key->ps_prolog.states.force_persp_sample_interp) {
+ unsigned i, base = key->ps_prolog.num_input_sgprs;
+ LLVMValueRef persp_sample[2];
+
+ /* Read PERSP_SAMPLE. */
+ for (i = 0; i < 2; i++)
+ persp_sample[i] = LLVMGetParam(func, base + i);
+ /* Overwrite PERSP_CENTER. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ persp_sample[i], base + 2 + i, "");
+ /* Overwrite PERSP_CENTROID. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ persp_sample[i], base + 4 + i, "");
+ }
+ if (key->ps_prolog.states.force_linear_sample_interp) {
+ unsigned i, base = key->ps_prolog.num_input_sgprs;
+ LLVMValueRef linear_sample[2];
+
+ /* Read LINEAR_SAMPLE. */
+ for (i = 0; i < 2; i++)
+ linear_sample[i] = LLVMGetParam(func, base + 6 + i);
+ /* Overwrite LINEAR_CENTER. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ linear_sample[i], base + 8 + i, "");
+ /* Overwrite LINEAR_CENTROID. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ linear_sample[i], base + 10 + i, "");
+ }
+
+ /* Force center interpolation. */
+ if (key->ps_prolog.states.force_persp_center_interp) {
+ unsigned i, base = key->ps_prolog.num_input_sgprs;
+ LLVMValueRef persp_center[2];
+
+ /* Read PERSP_CENTER. */
+ for (i = 0; i < 2; i++)
+ persp_center[i] = LLVMGetParam(func, base + 2 + i);
+ /* Overwrite PERSP_SAMPLE. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ persp_center[i], base + i, "");
+ /* Overwrite PERSP_CENTROID. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ persp_center[i], base + 4 + i, "");
+ }
+ if (key->ps_prolog.states.force_linear_center_interp) {
+ unsigned i, base = key->ps_prolog.num_input_sgprs;
+ LLVMValueRef linear_center[2];
+
+ /* Read LINEAR_CENTER. */
+ for (i = 0; i < 2; i++)
+ linear_center[i] = LLVMGetParam(func, base + 8 + i);
+ /* Overwrite LINEAR_SAMPLE. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ linear_center[i], base + 6 + i, "");
+ /* Overwrite LINEAR_CENTROID. */
+ for (i = 0; i < 2; i++)
+ ret = LLVMBuildInsertValue(gallivm->builder, ret,
+ 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 interp_vgpr = key->ps_prolog.num_input_sgprs +
key->ps_prolog.color_interp_vgpr_index[i];
- interp[0] = LLVMGetParam(func, interp_vgpr);
- interp[1] = LLVMGetParam(func, interp_vgpr + 1);
+ /* 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, "");
}
}
- /* Force per-sample interpolation. */
- if (key->ps_prolog.states.force_persample_interp) {
- unsigned i, base = key->ps_prolog.num_input_sgprs;
- LLVMValueRef persp_sample[2], linear_sample[2];
-
- /* Read PERSP_SAMPLE. */
- for (i = 0; i < 2; i++)
- persp_sample[i] = LLVMGetParam(func, base + i);
- /* Overwrite PERSP_CENTER. */
- for (i = 0; i < 2; i++)
- ret = LLVMBuildInsertValue(gallivm->builder, ret,
- persp_sample[i], base + 2 + i, "");
- /* Overwrite PERSP_CENTROID. */
- for (i = 0; i < 2; i++)
- ret = LLVMBuildInsertValue(gallivm->builder, ret,
- persp_sample[i], base + 4 + i, "");
- /* Read LINEAR_SAMPLE. */
- for (i = 0; i < 2; i++)
- linear_sample[i] = LLVMGetParam(func, base + 6 + i);
- /* Overwrite LINEAR_CENTER. */
- for (i = 0; i < 2; i++)
- ret = LLVMBuildInsertValue(gallivm->builder, ret,
- linear_sample[i], base + 8 + i, "");
- /* Overwrite LINEAR_CENTROID. */
- for (i = 0; i < 2; i++)
- ret = LLVMBuildInsertValue(gallivm->builder, ret,
- linear_sample[i], base + 10 + i, "");
+ /* Tell LLVM to insert WQM instruction sequence when needed. */
+ if (key->ps_prolog.wqm) {
+ LLVMAddTargetDependentFunctionAttr(func,
+ "amdgpu-ps-wqm-outputs", "");
}
/* Compile. */
- LLVMBuildRet(gallivm->builder, ret);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ si_llvm_build_ret(&ctx, ret);
+ radeon_llvm_finalize_module(
+ &ctx.radeon_bld,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
struct lp_build_tgsi_context *bld_base = &ctx.radeon_bld.soa.bld_base;
LLVMTypeRef params[16+8*4+3];
LLVMValueRef depth = NULL, stencil = NULL, samplemask = NULL;
- int last_array_pointer, last_sgpr, num_params, i;
+ int last_sgpr, num_params, i;
bool status = true;
+ struct si_ps_exports exp = {};
si_init_shader_ctx(&ctx, sscreen, &shader, tm);
- ctx.type = TGSI_PROCESSOR_FRAGMENT;
+ ctx.type = PIPE_SHADER_FRAGMENT;
shader.key.ps.epilog = key->ps_epilog.states;
/* Declare input SGPRs. */
params[SI_PARAM_IMAGES] = ctx.i64;
params[SI_PARAM_SHADER_BUFFERS] = ctx.i64;
params[SI_PARAM_ALPHA_REF] = ctx.f32;
- last_array_pointer = -1;
last_sgpr = SI_PARAM_ALPHA_REF;
/* Declare input VGPRs. */
params[i] = ctx.f32;
/* Create the function. */
- si_create_function(&ctx, NULL, 0, params, num_params,
- last_array_pointer, last_sgpr);
+ si_create_function(&ctx, NULL, 0, params, num_params, last_sgpr);
/* Disable elimination of unused inputs. */
radeon_llvm_add_attribute(ctx.radeon_bld.main_fn,
"InitialPSInputAddr", 0xffffff);
si_export_mrt_color(bld_base, color, mrt,
num_params - 1,
- mrt == last_color_export);
+ mrt == last_color_export, &exp);
}
/* Process depth, stencil, samplemask. */
samplemask = LLVMGetParam(ctx.radeon_bld.main_fn, vgpr++);
if (depth || stencil || samplemask)
- si_export_mrt_z(bld_base, depth, stencil, samplemask);
+ si_export_mrt_z(bld_base, depth, stencil, samplemask, &exp);
else if (last_color_export == -1)
si_export_null(bld_base);
+ if (exp.num)
+ si_emit_ps_exports(&ctx, &exp);
+
/* Compile. */
LLVMBuildRetVoid(gallivm->builder);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ radeon_llvm_finalize_module(
+ &ctx.radeon_bld,
+ r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
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;
}
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)))
prolog_key.ps_prolog.color_attr_index[i] = color[i];
- /* Force per-sample interpolation for the colors here. */
- if (shader->key.ps.prolog.force_persample_interp)
- location = TGSI_INTERPOLATE_LOC_SAMPLE;
+ if (shader->key.ps.prolog.flatshade_colors &&
+ interp == TGSI_INTERPOLATE_COLOR)
+ interp = TGSI_INTERPOLATE_CONSTANT;
- switch (info->input_interpolate[color[i]]) {
+ 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;
}
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;
/* The prolog is a no-op if these aren't set. */
if (prolog_key.ps_prolog.colors_read ||
- prolog_key.ps_prolog.states.force_persample_interp ||
+ 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) {
shader->prolog =
si_get_shader_part(sscreen, &sscreen->ps_prologs,
}
/* Set up the enable bits for per-sample shading if needed. */
- if (shader->key.ps.prolog.force_persample_interp) {
- if (G_0286CC_PERSP_CENTER_ENA(shader->config.spi_ps_input_ena) ||
- G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_ena)) {
- shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTER_ENA;
- shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTROID_ENA;
- shader->config.spi_ps_input_ena |= S_0286CC_PERSP_SAMPLE_ENA(1);
- }
- if (G_0286CC_LINEAR_CENTER_ENA(shader->config.spi_ps_input_ena) ||
- G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_ena)) {
- shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTER_ENA;
- shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTROID_ENA;
- shader->config.spi_ps_input_ena |= S_0286CC_LINEAR_SAMPLE_ENA(1);
- }
+ if (shader->key.ps.prolog.force_persp_sample_interp &&
+ (G_0286CC_PERSP_CENTER_ENA(shader->config.spi_ps_input_ena) ||
+ G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
+ shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTER_ENA;
+ shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTROID_ENA;
+ shader->config.spi_ps_input_ena |= S_0286CC_PERSP_SAMPLE_ENA(1);
+ }
+ if (shader->key.ps.prolog.force_linear_sample_interp &&
+ (G_0286CC_LINEAR_CENTER_ENA(shader->config.spi_ps_input_ena) ||
+ G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
+ shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTER_ENA;
+ shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTROID_ENA;
+ shader->config.spi_ps_input_ena |= S_0286CC_LINEAR_SAMPLE_ENA(1);
+ }
+ if (shader->key.ps.prolog.force_persp_center_interp &&
+ (G_0286CC_PERSP_SAMPLE_ENA(shader->config.spi_ps_input_ena) ||
+ G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
+ shader->config.spi_ps_input_ena &= C_0286CC_PERSP_SAMPLE_ENA;
+ shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTROID_ENA;
+ shader->config.spi_ps_input_ena |= S_0286CC_PERSP_CENTER_ENA(1);
+ }
+ if (shader->key.ps.prolog.force_linear_center_interp &&
+ (G_0286CC_LINEAR_SAMPLE_ENA(shader->config.spi_ps_input_ena) ||
+ G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
+ shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_SAMPLE_ENA;
+ shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTROID_ENA;
+ shader->config.spi_ps_input_ena |= S_0286CC_LINEAR_CENTER_ENA(1);
}
/* POW_W_FLOAT requires that one of the perspective weights is enabled. */
shader->key.vs.as_ls != mainp->key.vs.as_ls)) ||
(shader->selector->type == PIPE_SHADER_TESS_EVAL &&
shader->key.tes.as_es != mainp->key.tes.as_es) ||
+ (shader->selector->type == PIPE_SHADER_TESS_CTRL &&
+ shader->key.tcs.epilog.inputs_to_copy) ||
shader->selector->type == PIPE_SHADER_COMPUTE) {
/* Monolithic shader (compiled as a whole, has many variants,
* may take a long time to compile).
if (!shader->is_binary_shared)
radeon_shader_binary_clean(&shader->binary);
+
+ free(shader->shader_log);
}