#include "gallivm/lp_bld_intr.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_arit.h"
-#include "gallivm/lp_bld_bitarit.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_misc.h"
-#include "radeon/r600_cs.h"
#include "radeon/radeon_llvm.h"
#include "radeon/radeon_elf_util.h"
#include "radeon/radeon_llvm_emit.h"
#include "util/u_memory.h"
#include "util/u_string.h"
-#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_dump.h"
#include "si_pipe.h"
-#include "si_shader.h"
#include "sid.h"
-#include <errno.h>
static const char *scratch_rsrc_dword0_symbol =
"SCRATCH_RSRC_DWORD0";
unsigned uniform_md_kind;
LLVMValueRef empty_md;
- LLVMValueRef const_buffers[SI_NUM_CONST_BUFFERS];
- LLVMValueRef lds;
- LLVMValueRef *constants[SI_NUM_CONST_BUFFERS];
- LLVMValueRef shader_buffers[SI_NUM_SHADER_BUFFERS];
- LLVMValueRef sampler_views[SI_NUM_SAMPLERS];
- LLVMValueRef sampler_states[SI_NUM_SAMPLERS];
- LLVMValueRef fmasks[SI_NUM_SAMPLERS];
- LLVMValueRef images[SI_NUM_IMAGES];
- LLVMValueRef so_buffers[4];
+ /* Preloaded descriptors. */
LLVMValueRef esgs_ring;
LLVMValueRef gsvs_ring[4];
+
+ LLVMValueRef lds;
LLVMValueRef gs_next_vertex[4];
LLVMValueRef return_value;
*/
#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 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));
}
/**
{
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, "");
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;
/* 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, "");
}
}
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;
}
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)
}
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:
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;
}
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) {
+ 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, ctx->constants[buf][idx]);
+ return bitcast(bld_base, type, c0);
else {
+ c1 = buffer_load_const(ctx, desc,
+ LLVMConstInt(ctx->i32,
+ (idx + 1) * 4, 0));
return radeon_llvm_emit_fetch_64bit(bld_base, type,
- ctx->constants[buf][idx],
- ctx->constants[buf][idx + 1]);
+ 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");
addr2 = lp_build_add(&bld_base->uint_bld, addr2,
lp_build_const_int32(base->gallivm, idx * 4));
- result2 = buffer_load_const(ctx, ctx->const_buffers[buf],
- addr2);
+ result2 = buffer_load_const(ctx, bufp, addr2);
result = radeon_llvm_emit_fetch_64bit(bld_base, type,
result, result2);
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 =
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),
LLVMValueRef args[10][9];
};
+unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
+ bool writes_samplemask)
+{
+ if (writes_z) {
+ /* Z needs 32 bits. */
+ if (writes_samplemask)
+ return V_028710_SPI_SHADER_32_ABGR;
+ else if (writes_stencil)
+ return V_028710_SPI_SHADER_32_GR;
+ else
+ return V_028710_SPI_SHADER_32_R;
+ } else if (writes_stencil || writes_samplemask) {
+ /* Both stencil and sample mask need only 16 bits. */
+ return V_028710_SPI_SHADER_UINT16_ABGR;
+ } else {
+ return V_028710_SPI_SHADER_ZERO;
+ }
+}
+
static void si_export_mrt_z(struct lp_build_tgsi_context *bld_base,
LLVMValueRef depth, LLVMValueRef stencil,
LLVMValueRef samplemask, struct si_ps_exports *exp)
struct lp_build_context *uint = &bld_base->uint_bld;
LLVMValueRef args[9];
unsigned mask = 0;
+ unsigned format = si_get_spi_shader_z_format(depth != NULL,
+ stencil != NULL,
+ samplemask != NULL);
assert(depth || stencil || samplemask);
args[7] = base->undef; /* B, sample mask */
args[8] = base->undef; /* A, alpha to mask */
- if (depth) {
- args[5] = depth;
- mask |= 0x1;
- }
-
- if (stencil) {
- args[6] = stencil;
- mask |= 0x2;
- }
+ if (format == V_028710_SPI_SHADER_UINT16_ABGR) {
+ assert(!depth);
+ args[4] = uint->one; /* COMPR flag */
- if (samplemask) {
- args[7] = samplemask;
- mask |= 0x4;
+ if (stencil) {
+ /* Stencil should be in X[23:16]. */
+ stencil = bitcast(bld_base, TGSI_TYPE_UNSIGNED, stencil);
+ stencil = LLVMBuildShl(base->gallivm->builder, stencil,
+ LLVMConstInt(ctx->i32, 16, 0), "");
+ args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT, stencil);
+ mask |= 0x3;
+ }
+ if (samplemask) {
+ /* SampleMask should be in Y[15:0]. */
+ args[6] = samplemask;
+ mask |= 0xc;
+ }
+ } else {
+ if (depth) {
+ args[5] = depth;
+ mask |= 0x1;
+ }
+ if (stencil) {
+ args[6] = stencil;
+ mask |= 0x2;
+ }
+ if (samplemask) {
+ args[7] = samplemask;
+ mask |= 0x4;
+ }
}
/* SI (except OLAND) has a bug that it only looks
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);
* 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,
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_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);
emit_data->args, emit_data->arg_count,
LLVMReadOnlyAttribute);
} else {
- build_int_type_name(LLVMTypeOf(emit_data->args[0]),
- coords_type, sizeof(coords_type));
-
- snprintf(intrinsic_name, sizeof(intrinsic_name),
- "llvm.amdgcn.image.load.%s", coords_type);
+ get_image_intr_name("llvm.amdgcn.image.load",
+ LLVMTypeOf(emit_data->args[0]),
+ intrinsic_name, sizeof(intrinsic_name));
emit_data->output[emit_data->chan] =
lp_build_intrinsic(
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_MEMORY) {
store_emit_memory(ctx, emit_data);
emit_data->dst_type, emit_data->args,
emit_data->arg_count, 0);
} else {
- build_int_type_name(LLVMTypeOf(emit_data->args[1]),
- coords_type, sizeof(coords_type));
- snprintf(intrinsic_name, sizeof(intrinsic_name),
- "llvm.amdgcn.image.store.%s", coords_type);
+ get_image_intr_name("llvm.amdgcn.image.store",
+ LLVMTypeOf(emit_data->args[1]),
+ intrinsic_name, sizeof(intrinsic_name));
emit_data->output[emit_data->chan] =
lp_build_intrinsic(
} 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",
const struct tgsi_full_instruction *inst = emit_data->inst;
const struct tgsi_full_src_register *reg = &inst->Src[0];
- emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4);
+ emit_data->dst_type = ctx->v4i32;
if (reg->Register.File == TGSI_FILE_BUFFER) {
emit_data->args[0] = shader_buffer_fetch_rsrc(ctx, reg);
LLVMValueRef imm6 = lp_build_const_int32(gallivm, 6);
LLVMValueRef z = LLVMBuildExtractElement(builder, out, imm2, "");
- z = LLVMBuildBitCast(builder, z, bld_base->uint_bld.elem_type, "");
z = LLVMBuildSDiv(builder, z, imm6, "");
- z = LLVMBuildBitCast(builder, z, bld_base->base.elem_type, "");
out = LLVMBuildInsertElement(builder, out, z, imm2, "");
}
}
/**
* 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 (samp_ptr)
- *samp_ptr = NULL;
- if (fmask_ptr)
- *fmask_ptr = get_sampler_desc(ctx, ind_index, DESC_FMASK);
- } else {
- if (samp_ptr) {
- *samp_ptr = get_sampler_desc(ctx, ind_index, DESC_SAMPLER);
- *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
- }
- if (fmask_ptr)
- *fmask_ptr = NULL;
- }
- } else {
- *res_ptr = ctx->sampler_views[sampler_index];
+ if (target == TGSI_TEXTURE_2D_MSAA ||
+ target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
if (samp_ptr)
- *samp_ptr = ctx->sampler_states[sampler_index];
+ *samp_ptr = NULL;
+ if (fmask_ptr)
+ *fmask_ptr = load_sampler_desc(ctx, index, DESC_FMASK);
+ } else {
+ if (samp_ptr) {
+ *samp_ptr = load_sampler_desc(ctx, index, DESC_SAMPLER);
+ *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
+ }
if (fmask_ptr)
- *fmask_ptr = ctx->fmasks[sampler_index];
+ *fmask_ptr = NULL;
}
}
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";
}
/* Add the type and suffixes .c, .o if needed. */
- build_int_type_name(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
+ build_type_name_for_intr(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
sprintf(intr_name, "%s%s%s%s.%s",
name, is_shadow ? ".c" : "", infix,
has_offset ? ".o" : "", type);
+ /* The hardware needs special lowering for Gather4 with integer formats. */
+ if (opcode == TGSI_OPCODE_TG4) {
+ struct tgsi_shader_info *info = &ctx->shader->selector->info;
+ /* This will also work with non-constant indexing because of how
+ * glsl_to_tgsi works and we intent to preserve that behavior.
+ */
+ const unsigned src_idx = 2;
+ unsigned sampler = inst->Src[src_idx].Register.Index;
+
+ assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER);
+
+ if (info->sampler_type[sampler] == TGSI_RETURN_TYPE_SINT ||
+ info->sampler_type[sampler] == TGSI_RETURN_TYPE_UINT) {
+ /* Texture coordinates start after:
+ * {offset, bias, z-compare, derivatives}
+ * Only the offset and z-compare can occur here.
+ */
+ si_lower_gather4_integer(ctx, emit_data, intr_name,
+ (int)has_offset + (int)is_shadow);
+ return;
+ }
+ }
+
emit_data->output[emit_data->chan] = lp_build_intrinsic(
base->gallivm->builder, intr_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
- const struct tgsi_full_instruction *inst = emit_data->inst;
- unsigned opcode = inst->Instruction.Opcode;
- LLVMValueRef indices[2];
- LLVMValueRef store_ptr, load_ptr0, load_ptr1;
- LLVMValueRef tl, trbl, result[4];
- LLVMValueRef tl_tid, trbl_tid;
- unsigned swizzle[4];
- unsigned c;
+ unsigned opcode = emit_data->info->opcode;
+ LLVMValueRef thread_id, tl, trbl, tl_tid, trbl_tid, val, args[2];
int idx;
unsigned mask;
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = get_thread_id(ctx);
- store_ptr = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
+ thread_id = get_thread_id(ctx);
if (opcode == TGSI_OPCODE_DDX_FINE)
mask = TID_MASK_LEFT;
else
mask = TID_MASK_TOP_LEFT;
- tl_tid = LLVMBuildAnd(gallivm->builder, indices[1],
+ tl_tid = LLVMBuildAnd(gallivm->builder, thread_id,
lp_build_const_int32(gallivm, mask), "");
- indices[1] = tl_tid;
- load_ptr0 = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
/* for DDX we want to next X pixel, DDY next Y pixel. */
idx = (opcode == TGSI_OPCODE_DDX || opcode == TGSI_OPCODE_DDX_FINE) ? 1 : 2;
- trbl_tid = LLVMBuildAdd(gallivm->builder, indices[1],
+ trbl_tid = LLVMBuildAdd(gallivm->builder, tl_tid,
lp_build_const_int32(gallivm, idx), "");
- indices[1] = trbl_tid;
- load_ptr1 = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
- for (c = 0; c < 4; ++c) {
- unsigned i;
- LLVMValueRef val;
- LLVMValueRef args[2];
+ val = LLVMBuildBitCast(gallivm->builder, emit_data->args[0], ctx->i32, "");
- swizzle[c] = tgsi_util_get_full_src_register_swizzle(&inst->Src[0], c);
- for (i = 0; i < c; ++i) {
- if (swizzle[i] == swizzle[c]) {
- result[c] = result[i];
- break;
- }
- }
- if (i != c)
- continue;
-
- val = LLVMBuildBitCast(gallivm->builder,
- lp_build_emit_fetch(bld_base, inst, 0, c),
- ctx->i32, "");
-
- if ((HAVE_LLVM >= 0x0309) && ctx->screen->b.family >= CHIP_TONGA) {
-
- args[0] = LLVMBuildMul(gallivm->builder, tl_tid,
- lp_build_const_int32(gallivm, 4), "");
- args[1] = val;
- tl = lp_build_intrinsic(gallivm->builder,
+ if (ctx->screen->has_ds_bpermute) {
+ args[0] = LLVMBuildMul(gallivm->builder, tl_tid,
+ lp_build_const_int32(gallivm, 4), "");
+ args[1] = val;
+ tl = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.ds.bpermute", ctx->i32,
args, 2, LLVMReadNoneAttribute);
- args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
- lp_build_const_int32(gallivm, 4), "");
- trbl = lp_build_intrinsic(gallivm->builder,
- "llvm.amdgcn.ds.bpermute", ctx->i32,
- args, 2, LLVMReadNoneAttribute);
- } else {
- LLVMBuildStore(gallivm->builder, val, store_ptr);
- tl = LLVMBuildLoad(gallivm->builder, load_ptr0, "");
- trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
- }
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
- trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
- result[c] = LLVMBuildFSub(gallivm->builder, trbl, tl, "");
+ args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
+ lp_build_const_int32(gallivm, 4), "");
+ trbl = lp_build_intrinsic(gallivm->builder,
+ "llvm.amdgcn.ds.bpermute", ctx->i32,
+ args, 2, LLVMReadNoneAttribute);
+ } else {
+ LLVMValueRef store_ptr, load_ptr0, load_ptr1;
+
+ store_ptr = build_gep0(ctx, ctx->lds, thread_id);
+ load_ptr0 = build_gep0(ctx, ctx->lds, tl_tid);
+ load_ptr1 = build_gep0(ctx, ctx->lds, trbl_tid);
+
+ LLVMBuildStore(gallivm->builder, val, store_ptr);
+ tl = LLVMBuildLoad(gallivm->builder, load_ptr0, "");
+ trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
}
- emit_data->output[0] = lp_build_gather_values(gallivm, result, 4);
+ tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
+ trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
+
+ emit_data->output[emit_data->chan] =
+ LLVMBuildFSub(gallivm->builder, trbl, tl, "");
}
/*
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef indices[2];
- LLVMValueRef store_ptr, load_ptr_x, load_ptr_y, load_ptr_ddx, load_ptr_ddy, temp, temp2;
- LLVMValueRef tl, tr, bl, result[4];
- unsigned c;
-
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = get_thread_id(ctx);
- store_ptr = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- temp = LLVMBuildAnd(gallivm->builder, indices[1],
- lp_build_const_int32(gallivm, TID_MASK_LEFT), "");
-
- temp2 = LLVMBuildAnd(gallivm->builder, indices[1],
- lp_build_const_int32(gallivm, TID_MASK_TOP), "");
-
- indices[1] = temp;
- load_ptr_x = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- indices[1] = temp2;
- load_ptr_y = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- indices[1] = LLVMBuildAdd(gallivm->builder, temp,
- lp_build_const_int32(gallivm, 1), "");
- load_ptr_ddx = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- indices[1] = LLVMBuildAdd(gallivm->builder, temp2,
- lp_build_const_int32(gallivm, 2), "");
- load_ptr_ddy = LLVMBuildGEP(gallivm->builder, ctx->lds,
- indices, 2, "");
-
- for (c = 0; c < 2; ++c) {
- LLVMValueRef store_val;
- LLVMValueRef c_ll = lp_build_const_int32(gallivm, c);
-
- store_val = LLVMBuildExtractElement(gallivm->builder,
- interp_ij, c_ll, "");
- LLVMBuildStore(gallivm->builder,
- store_val,
- store_ptr);
-
- tl = LLVMBuildLoad(gallivm->builder, load_ptr_x, "");
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
- tr = LLVMBuildLoad(gallivm->builder, load_ptr_ddx, "");
- tr = LLVMBuildBitCast(gallivm->builder, tr, ctx->f32, "");
-
- result[c] = LLVMBuildFSub(gallivm->builder, tr, tl, "");
-
- tl = LLVMBuildLoad(gallivm->builder, load_ptr_y, "");
- tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
- bl = LLVMBuildLoad(gallivm->builder, load_ptr_ddy, "");
- bl = LLVMBuildBitCast(gallivm->builder, bl, ctx->f32, "");
+ LLVMValueRef result[4], a;
+ unsigned i;
- result[c + 2] = LLVMBuildFSub(gallivm->builder, bl, tl, "");
+ for (i = 0; i < 2; i++) {
+ a = LLVMBuildExtractElement(gallivm->builder, interp_ij,
+ LLVMConstInt(ctx->i32, i, 0), "");
+ result[i] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_DDX, a);
+ result[2+i] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_DDY, a);
}
return lp_build_gather_values(gallivm, result, 4);
}
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;
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;
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",
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 ||
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(ctx,
- ctx->const_buffers[buf],
- lp_build_const_int32(gallivm, i * 4));
- }
- }
-}
-
-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 == PIPE_SHADER_VERTEX &&
- (ctx->shader->key.vs.as_es ||
- ctx->shader->key.vs.as_ls)) ||
- (ctx->type == PIPE_SHADER_TESS_EVAL &&
- ctx->shader->key.tes.as_es))
- return;
-
- LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
- SI_PARAM_RW_BUFFERS);
-
- /* Load the resources, we rely on the code sinking to do the rest */
- for (i = 0; i < 4; ++i) {
- if (ctx->shader->selector->so.stride[i]) {
- LLVMValueRef offset = lp_build_const_int32(gallivm,
- SI_VS_STREAMOUT_BUF0 + i);
-
- ctx->so_buffers[i] = build_indexed_load_const(ctx, buf_ptr, offset);
- }
- }
-}
-
/**
* Load ESGS and GSVS ring buffer resource descriptors and save the variables
* for later use.
create_meta_data(ctx);
create_function(ctx);
- preload_streamout_buffers(ctx);
preload_ring_buffers(ctx);
args[0] = ctx->gsvs_ring[0];
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,
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 &&
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");
unsigned max_vgprs = 256;
unsigned max_sgprs = sscreen->b.chip_class >= VI ? 800 : 512;
unsigned max_sgprs_per_wave = 128;
- unsigned min_waves_per_cu =
- DIV_ROUND_UP(props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] *
- props[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
- props[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH],
- wave_size);
+ unsigned 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;
}
out:
- for (int i = 0; i < SI_NUM_CONST_BUFFERS; i++)
- FREE(ctx.constants[i]);
return r;
}
/* Compile. */
si_llvm_build_ret(&ctx, ret);
- radeon_llvm_finalize_module(&ctx.radeon_bld);
+ 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,
/* 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_VERTEX));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
/* 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_TESS_CTRL));
if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
gallivm->module, debug, ctx.type,
}
}
- /* Interpolate colors. */
- for (i = 0; i < 2; i++) {
- unsigned writemask = (key->ps_prolog.colors_read >> (i * 4)) & 0xf;
- unsigned face_vgpr = key->ps_prolog.num_input_sgprs +
- key->ps_prolog.face_vgpr_index;
- LLVMValueRef interp[2], color[4];
- LLVMValueRef interp_ij = NULL, prim_mask = NULL, face = NULL;
-
- if (!writemask)
- continue;
-
- /* If the interpolation qualifier is not CONSTANT (-1). */
- if (key->ps_prolog.color_interp_vgpr_index[i] != -1) {
- unsigned interp_vgpr = key->ps_prolog.num_input_sgprs +
- key->ps_prolog.color_interp_vgpr_index[i];
-
- /* Get the (i,j) updated by bc_optimize handling. */
- interp[0] = LLVMBuildExtractValue(gallivm->builder, ret,
- interp_vgpr, "");
- interp[1] = LLVMBuildExtractValue(gallivm->builder, ret,
- interp_vgpr + 1, "");
- interp_ij = lp_build_gather_values(gallivm, interp, 2);
- interp_ij = LLVMBuildBitCast(gallivm->builder, interp_ij,
- ctx.v2i32, "");
- }
-
- /* Use the absolute location of the input. */
- prim_mask = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
-
- if (key->ps_prolog.states.color_two_side) {
- face = LLVMGetParam(func, face_vgpr);
- face = LLVMBuildBitCast(gallivm->builder, face, ctx.i32, "");
- }
-
- interp_fs_input(&ctx,
- key->ps_prolog.color_attr_index[i],
- TGSI_SEMANTIC_COLOR, i,
- key->ps_prolog.num_interp_inputs,
- key->ps_prolog.colors_read, interp_ij,
- prim_mask, face, color);
-
- while (writemask) {
- unsigned chan = u_bit_scan(&writemask);
- ret = LLVMBuildInsertValue(gallivm->builder, ret, color[chan],
- num_params++, "");
- }
- }
-
/* Force per-sample interpolation. */
if (key->ps_prolog.states.force_persp_sample_interp) {
unsigned i, base = key->ps_prolog.num_input_sgprs;
linear_center[i], base + 10 + i, "");
}
+ /* Interpolate colors. */
+ for (i = 0; i < 2; i++) {
+ unsigned writemask = (key->ps_prolog.colors_read >> (i * 4)) & 0xf;
+ unsigned face_vgpr = key->ps_prolog.num_input_sgprs +
+ key->ps_prolog.face_vgpr_index;
+ LLVMValueRef interp[2], color[4];
+ LLVMValueRef interp_ij = NULL, prim_mask = NULL, face = NULL;
+
+ if (!writemask)
+ continue;
+
+ /* If the interpolation qualifier is not CONSTANT (-1). */
+ if (key->ps_prolog.color_interp_vgpr_index[i] != -1) {
+ unsigned interp_vgpr = key->ps_prolog.num_input_sgprs +
+ key->ps_prolog.color_interp_vgpr_index[i];
+
+ /* Get the (i,j) updated by bc_optimize handling. */
+ interp[0] = LLVMBuildExtractValue(gallivm->builder, ret,
+ interp_vgpr, "");
+ interp[1] = LLVMBuildExtractValue(gallivm->builder, ret,
+ interp_vgpr + 1, "");
+ interp_ij = lp_build_gather_values(gallivm, interp, 2);
+ interp_ij = LLVMBuildBitCast(gallivm->builder, interp_ij,
+ ctx.v2i32, "");
+ }
+
+ /* Use the absolute location of the input. */
+ prim_mask = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
+
+ if (key->ps_prolog.states.color_two_side) {
+ face = LLVMGetParam(func, face_vgpr);
+ face = LLVMBuildBitCast(gallivm->builder, face, ctx.i32, "");
+ }
+
+ interp_fs_input(&ctx,
+ key->ps_prolog.color_attr_index[i],
+ TGSI_SEMANTIC_COLOR, i,
+ key->ps_prolog.num_interp_inputs,
+ key->ps_prolog.colors_read, interp_ij,
+ prim_mask, face, color);
+
+ while (writemask) {
+ unsigned chan = u_bit_scan(&writemask);
+ ret = LLVMBuildInsertValue(gallivm->builder, ret, color[chan],
+ num_params++, "");
+ }
+ }
+
/* Tell LLVM to insert WQM instruction sequence when needed. */
if (key->ps_prolog.wqm) {
LLVMAddTargetDependentFunctionAttr(func,
/* Compile. */
si_llvm_build_ret(&ctx, ret);
- 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,
/* 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,