X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fradeonsi%2Fsi_shader.c;h=ac1c1be7a79cf447413776c5f172a0ec4094531a;hb=e7a52a5cb810de49a8282cb9f9caea5d554c3348;hp=037811edd18bd780dc549144032441b17ed15a00;hpb=645b471d619b654d3bacfa8598f759833e08db4e;p=mesa.git diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 037811edd18..ac1c1be7a79 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -31,11 +31,14 @@ #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 "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 "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi/tgsi_dump.h" @@ -46,6 +49,12 @@ #include +static const char *scratch_rsrc_dword0_symbol = + "SCRATCH_RSRC_DWORD0"; + +static const char *scratch_rsrc_dword1_symbol = + "SCRATCH_RSRC_DWORD1"; + struct si_shader_output_values { LLVMValueRef values[4]; @@ -56,25 +65,32 @@ struct si_shader_output_values struct si_shader_context { struct radeon_llvm_context radeon_bld; - struct tgsi_parse_context parse; - struct tgsi_token * tokens; struct si_shader *shader; + struct si_screen *screen; unsigned type; /* TGSI_PROCESSOR_* specifies the type of shader. */ int param_streamout_config; int param_streamout_write_index; int param_streamout_offset[4]; int param_vertex_id; + int param_rel_auto_id; + int param_vs_prim_id; int param_instance_id; + int param_tes_u; + int param_tes_v; + int param_tes_rel_patch_id; + int param_tes_patch_id; + int param_es2gs_offset; + LLVMTargetMachineRef tm; LLVMValueRef const_md; LLVMValueRef const_resource[SI_NUM_CONST_BUFFERS]; - LLVMValueRef ddxy_lds; + LLVMValueRef lds; LLVMValueRef *constants[SI_NUM_CONST_BUFFERS]; LLVMValueRef resources[SI_NUM_SAMPLER_VIEWS]; LLVMValueRef samplers[SI_NUM_SAMPLER_STATES]; LLVMValueRef so_buffers[4]; LLVMValueRef esgs_ring; - LLVMValueRef gsvs_ring; - LLVMValueRef gs_next_vertex; + LLVMValueRef gsvs_ring[4]; + LLVMValueRef gs_next_vertex[4]; }; static struct si_shader_context * si_shader_context( @@ -120,24 +136,30 @@ unsigned si_shader_io_get_unique_index(unsigned semantic_name, unsigned index) case TGSI_SEMANTIC_CLIPDIST: assert(index <= 1); return 2 + index; - case TGSI_SEMANTIC_CLIPVERTEX: - return 4; - case TGSI_SEMANTIC_COLOR: - assert(index <= 1); - return 5 + index; - case TGSI_SEMANTIC_BCOLOR: - assert(index <= 1); - return 7 + index; - case TGSI_SEMANTIC_FOG: - return 9; - case TGSI_SEMANTIC_EDGEFLAG: - return 10; case TGSI_SEMANTIC_GENERIC: - assert(index <= 63-11); - return 11 + index; + if (index <= 63-4) + return 4 + index; + else + /* same explanation as in the default statement, + * the only user hitting this is st/nine. + */ + return 0; + + /* patch indices are completely separate and thus start from 0 */ + case TGSI_SEMANTIC_TESSOUTER: + return 0; + case TGSI_SEMANTIC_TESSINNER: + return 1; + case TGSI_SEMANTIC_PATCH: + return 2 + index; + default: - assert(0); - return 63; + /* Don't fail here. The result of this function is only used + * for LS, TCS, TES, and GS, where legacy GL semantics can't + * occur, but this function is called for all vertex shaders + * before it's known whether LS will be compiled or not. + */ + return 0; } } @@ -184,6 +206,160 @@ static int get_param_index(unsigned semantic_name, unsigned index, return -1; } +/** + * Get the value of a shader input parameter and extract a bitfield. + */ +static LLVMValueRef unpack_param(struct si_shader_context *si_shader_ctx, + unsigned param, unsigned rshift, + unsigned bitwidth) +{ + struct gallivm_state *gallivm = &si_shader_ctx->radeon_bld.gallivm; + LLVMValueRef value = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + param); + + if (rshift) + value = LLVMBuildLShr(gallivm->builder, value, + lp_build_const_int32(gallivm, rshift), ""); + + if (rshift + bitwidth < 32) { + unsigned mask = (1 << bitwidth) - 1; + value = LLVMBuildAnd(gallivm->builder, value, + lp_build_const_int32(gallivm, mask), ""); + } + + return value; +} + +static LLVMValueRef get_rel_patch_id(struct si_shader_context *si_shader_ctx) +{ + switch (si_shader_ctx->type) { + case TGSI_PROCESSOR_TESS_CTRL: + return unpack_param(si_shader_ctx, SI_PARAM_REL_IDS, 0, 8); + + case TGSI_PROCESSOR_TESS_EVAL: + return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + si_shader_ctx->param_tes_rel_patch_id); + + default: + assert(0); + return NULL; + } +} + +/* Tessellation shaders pass outputs to the next shader using LDS. + * + * LS outputs = TCS inputs + * TCS outputs = TES inputs + * + * The LDS layout is: + * - TCS inputs for patch 0 + * - TCS inputs for patch 1 + * - TCS inputs for patch 2 = get_tcs_in_current_patch_offset (if RelPatchID==2) + * - ... + * - TCS outputs for patch 0 = get_tcs_out_patch0_offset + * - Per-patch TCS outputs for patch 0 = get_tcs_out_patch0_patch_data_offset + * - TCS outputs for patch 1 + * - Per-patch TCS outputs for patch 1 + * - TCS outputs for patch 2 = get_tcs_out_current_patch_offset (if RelPatchID==2) + * - Per-patch TCS outputs for patch 2 = get_tcs_out_current_patch_data_offset (if RelPatchID==2) + * - ... + * + * All three shaders VS(LS), TCS, TES share the same LDS space. + */ + +static LLVMValueRef +get_tcs_in_patch_stride(struct si_shader_context *si_shader_ctx) +{ + if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) + return unpack_param(si_shader_ctx, SI_PARAM_LS_OUT_LAYOUT, 0, 13); + else if (si_shader_ctx->type == TGSI_PROCESSOR_TESS_CTRL) + return unpack_param(si_shader_ctx, SI_PARAM_TCS_IN_LAYOUT, 0, 13); + else { + assert(0); + return NULL; + } +} + +static LLVMValueRef +get_tcs_out_patch_stride(struct si_shader_context *si_shader_ctx) +{ + return unpack_param(si_shader_ctx, SI_PARAM_TCS_OUT_LAYOUT, 0, 13); +} + +static LLVMValueRef +get_tcs_out_patch0_offset(struct si_shader_context *si_shader_ctx) +{ + return lp_build_mul_imm(&si_shader_ctx->radeon_bld.soa.bld_base.uint_bld, + unpack_param(si_shader_ctx, + SI_PARAM_TCS_OUT_OFFSETS, + 0, 16), + 4); +} + +static LLVMValueRef +get_tcs_out_patch0_patch_data_offset(struct si_shader_context *si_shader_ctx) +{ + return lp_build_mul_imm(&si_shader_ctx->radeon_bld.soa.bld_base.uint_bld, + unpack_param(si_shader_ctx, + SI_PARAM_TCS_OUT_OFFSETS, + 16, 16), + 4); +} + +static LLVMValueRef +get_tcs_in_current_patch_offset(struct si_shader_context *si_shader_ctx) +{ + struct gallivm_state *gallivm = &si_shader_ctx->radeon_bld.gallivm; + LLVMValueRef patch_stride = get_tcs_in_patch_stride(si_shader_ctx); + LLVMValueRef rel_patch_id = get_rel_patch_id(si_shader_ctx); + + return LLVMBuildMul(gallivm->builder, patch_stride, rel_patch_id, ""); +} + +static LLVMValueRef +get_tcs_out_current_patch_offset(struct si_shader_context *si_shader_ctx) +{ + struct gallivm_state *gallivm = &si_shader_ctx->radeon_bld.gallivm; + LLVMValueRef patch0_offset = get_tcs_out_patch0_offset(si_shader_ctx); + LLVMValueRef patch_stride = get_tcs_out_patch_stride(si_shader_ctx); + LLVMValueRef rel_patch_id = get_rel_patch_id(si_shader_ctx); + + return LLVMBuildAdd(gallivm->builder, patch0_offset, + LLVMBuildMul(gallivm->builder, patch_stride, + rel_patch_id, ""), + ""); +} + +static LLVMValueRef +get_tcs_out_current_patch_data_offset(struct si_shader_context *si_shader_ctx) +{ + struct gallivm_state *gallivm = &si_shader_ctx->radeon_bld.gallivm; + LLVMValueRef patch0_patch_data_offset = + get_tcs_out_patch0_patch_data_offset(si_shader_ctx); + LLVMValueRef patch_stride = get_tcs_out_patch_stride(si_shader_ctx); + LLVMValueRef rel_patch_id = get_rel_patch_id(si_shader_ctx); + + return LLVMBuildAdd(gallivm->builder, patch0_patch_data_offset, + LLVMBuildMul(gallivm->builder, patch_stride, + rel_patch_id, ""), + ""); +} + +static void build_indexed_store(struct si_shader_context *si_shader_ctx, + LLVMValueRef base_ptr, LLVMValueRef index, + LLVMValueRef value) +{ + struct lp_build_tgsi_context *bld_base = &si_shader_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); +} + /** * Build an LLVM bytecode indexed load using LLVMBuildGEP + LLVMBuildLoad. * It's equivalent to doing a load from &base_ptr[index]. @@ -228,14 +404,14 @@ static LLVMValueRef get_instance_index_for_fetch( LLVMValueRef result = LLVMGetParam(radeon_bld->main_fn, si_shader_ctx->param_instance_id); - result = LLVMBuildAdd(gallivm->builder, result, LLVMGetParam( - radeon_bld->main_fn, SI_PARAM_START_INSTANCE), ""); + /* The division must be done before START_INSTANCE is added. */ if (divisor > 1) result = LLVMBuildUDiv(gallivm->builder, result, lp_build_const_int32(gallivm, divisor), ""); - return result; + return LLVMBuildAdd(gallivm->builder, result, LLVMGetParam( + radeon_bld->main_fn, SI_PARAM_START_INSTANCE), ""); } static void declare_input_vs( @@ -287,7 +463,7 @@ static void declare_input_vs( args[0] = t_list; args[1] = attribute_offset; args[2] = buffer_index; - input = build_intrinsic(gallivm->builder, + input = lp_build_intrinsic(gallivm->builder, "llvm.SI.vs.load.input", vec4_type, args, 3, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); @@ -302,6 +478,285 @@ static void declare_input_vs( } } +static LLVMValueRef get_primitive_id(struct lp_build_tgsi_context *bld_base, + unsigned swizzle) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + + if (swizzle > 0) + return bld_base->uint_bld.zero; + + switch (si_shader_ctx->type) { + case TGSI_PROCESSOR_VERTEX: + return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + si_shader_ctx->param_vs_prim_id); + case TGSI_PROCESSOR_TESS_CTRL: + return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + SI_PARAM_PATCH_ID); + case TGSI_PROCESSOR_TESS_EVAL: + return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + si_shader_ctx->param_tes_patch_id); + case TGSI_PROCESSOR_GEOMETRY: + return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + SI_PARAM_PRIMITIVE_ID); + default: + assert(0); + return bld_base->uint_bld.zero; + } +} + +/** + * Return the value of tgsi_ind_register for indexing. + * This is the indirect index with the constant offset added to it. + */ +static LLVMValueRef get_indirect_index(struct si_shader_context *si_shader_ctx, + const struct tgsi_ind_register *ind, + int rel_index) +{ + struct gallivm_state *gallivm = si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm; + LLVMValueRef result; + + result = si_shader_ctx->radeon_bld.soa.addr[ind->Index][ind->Swizzle]; + result = LLVMBuildLoad(gallivm->builder, result, ""); + result = LLVMBuildAdd(gallivm->builder, result, + lp_build_const_int32(gallivm, rel_index), ""); + return result; +} + +/** + * Calculate a dword address given an input or output register and a stride. + */ +static LLVMValueRef get_dw_address(struct si_shader_context *si_shader_ctx, + const struct tgsi_full_dst_register *dst, + const struct tgsi_full_src_register *src, + LLVMValueRef vertex_dw_stride, + LLVMValueRef base_addr) +{ + struct gallivm_state *gallivm = si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm; + struct tgsi_shader_info *info = &si_shader_ctx->shader->selector->info; + ubyte *name, *index, *array_first; + int first, param; + struct tgsi_full_dst_register reg; + + /* Set the register description. The address computation is the same + * for sources and destinations. */ + if (src) { + reg.Register.File = src->Register.File; + reg.Register.Index = src->Register.Index; + reg.Register.Indirect = src->Register.Indirect; + reg.Register.Dimension = src->Register.Dimension; + reg.Indirect = src->Indirect; + reg.Dimension = src->Dimension; + reg.DimIndirect = src->DimIndirect; + } else + reg = *dst; + + /* If the register is 2-dimensional (e.g. an array of vertices + * in a primitive), calculate the base address of the vertex. */ + if (reg.Register.Dimension) { + LLVMValueRef index; + + if (reg.Dimension.Indirect) + index = get_indirect_index(si_shader_ctx, ®.DimIndirect, + reg.Dimension.Index); + else + index = lp_build_const_int32(gallivm, reg.Dimension.Index); + + base_addr = LLVMBuildAdd(gallivm->builder, base_addr, + LLVMBuildMul(gallivm->builder, index, + vertex_dw_stride, ""), ""); + } + + /* 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) { + /* Add the relative address of the element. */ + LLVMValueRef ind_index; + + if (reg.Indirect.ArrayID) + first = array_first[reg.Indirect.ArrayID]; + else + first = reg.Register.Index; + + ind_index = get_indirect_index(si_shader_ctx, ®.Indirect, + reg.Register.Index - first); + + base_addr = LLVMBuildAdd(gallivm->builder, base_addr, + LLVMBuildMul(gallivm->builder, ind_index, + lp_build_const_int32(gallivm, 4), ""), ""); + + param = si_shader_io_get_unique_index(name[first], index[first]); + } else { + param = si_shader_io_get_unique_index(name[reg.Register.Index], + index[reg.Register.Index]); + } + + /* Add the base address of the element. */ + return LLVMBuildAdd(gallivm->builder, base_addr, + lp_build_const_int32(gallivm, param * 4), ""); +} + +/** + * Load from LDS. + * + * \param type output value type + * \param swizzle offset (typically 0..3); it can be ~0, which loads a vec4 + * \param dw_addr address in dwords + */ +static LLVMValueRef lds_load(struct lp_build_tgsi_context *bld_base, + enum tgsi_opcode_type type, unsigned swizzle, + LLVMValueRef dw_addr) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + LLVMValueRef value; + + if (swizzle == ~0) { + LLVMValueRef values[TGSI_NUM_CHANNELS]; + + for (unsigned chan = 0; chan < TGSI_NUM_CHANNELS; chan++) + values[chan] = lds_load(bld_base, type, chan, dw_addr); + + return lp_build_gather_values(bld_base->base.gallivm, values, + TGSI_NUM_CHANNELS); + } + + dw_addr = lp_build_add(&bld_base->uint_bld, dw_addr, + lp_build_const_int32(gallivm, swizzle)); + + value = build_indexed_load(si_shader_ctx, si_shader_ctx->lds, dw_addr); + return LLVMBuildBitCast(gallivm->builder, value, + tgsi2llvmtype(bld_base, type), ""); +} + +/** + * Store to LDS. + * + * \param swizzle offset (typically 0..3) + * \param dw_addr address in dwords + * \param value value to store + */ +static void lds_store(struct lp_build_tgsi_context * bld_base, + unsigned swizzle, LLVMValueRef dw_addr, + LLVMValueRef value) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + + dw_addr = lp_build_add(&bld_base->uint_bld, dw_addr, + lp_build_const_int32(gallivm, swizzle)); + + value = LLVMBuildBitCast(gallivm->builder, value, + LLVMInt32TypeInContext(gallivm->context), ""); + build_indexed_store(si_shader_ctx, si_shader_ctx->lds, + dw_addr, value); +} + +static LLVMValueRef fetch_input_tcs( + struct lp_build_tgsi_context *bld_base, + const struct tgsi_full_src_register *reg, + enum tgsi_opcode_type type, unsigned swizzle) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + LLVMValueRef dw_addr, stride; + + stride = unpack_param(si_shader_ctx, SI_PARAM_TCS_IN_LAYOUT, 13, 8); + dw_addr = get_tcs_in_current_patch_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, NULL, reg, stride, dw_addr); + + return lds_load(bld_base, type, swizzle, dw_addr); +} + +static LLVMValueRef fetch_output_tcs( + struct lp_build_tgsi_context *bld_base, + const struct tgsi_full_src_register *reg, + enum tgsi_opcode_type type, unsigned swizzle) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + LLVMValueRef dw_addr, stride; + + if (reg->Register.Dimension) { + stride = unpack_param(si_shader_ctx, SI_PARAM_TCS_OUT_LAYOUT, 13, 8); + dw_addr = get_tcs_out_current_patch_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, NULL, reg, stride, dw_addr); + } else { + dw_addr = get_tcs_out_current_patch_data_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, NULL, reg, NULL, dw_addr); + } + + return lds_load(bld_base, type, swizzle, dw_addr); +} + +static LLVMValueRef fetch_input_tes( + struct lp_build_tgsi_context *bld_base, + const struct tgsi_full_src_register *reg, + enum tgsi_opcode_type type, unsigned swizzle) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + LLVMValueRef dw_addr, stride; + + if (reg->Register.Dimension) { + stride = unpack_param(si_shader_ctx, SI_PARAM_TCS_OUT_LAYOUT, 13, 8); + dw_addr = get_tcs_out_current_patch_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, NULL, reg, stride, dw_addr); + } else { + dw_addr = get_tcs_out_current_patch_data_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, NULL, reg, NULL, dw_addr); + } + + return lds_load(bld_base, type, swizzle, dw_addr); +} + +static void store_output_tcs(struct lp_build_tgsi_context * bld_base, + const struct tgsi_full_instruction * inst, + const struct tgsi_opcode_info * info, + LLVMValueRef dst[4]) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + const struct tgsi_full_dst_register *reg = &inst->Dst[0]; + unsigned chan_index; + LLVMValueRef dw_addr, stride; + + /* Only handle per-patch and per-vertex outputs here. + * Vectors will be lowered to scalars and this function will be called again. + */ + if (reg->Register.File != TGSI_FILE_OUTPUT || + (dst[0] && LLVMGetTypeKind(LLVMTypeOf(dst[0])) == LLVMVectorTypeKind)) { + radeon_llvm_emit_store(bld_base, inst, info, dst); + return; + } + + if (reg->Register.Dimension) { + stride = unpack_param(si_shader_ctx, SI_PARAM_TCS_OUT_LAYOUT, 13, 8); + dw_addr = get_tcs_out_current_patch_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, reg, NULL, stride, dw_addr); + } else { + dw_addr = get_tcs_out_current_patch_data_offset(si_shader_ctx); + dw_addr = get_dw_address(si_shader_ctx, reg, NULL, NULL, dw_addr); + } + + TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) { + LLVMValueRef value = dst[chan_index]; + + if (inst->Instruction.Saturate) + value = radeon_llvm_saturate(bld_base, value); + + lds_store(bld_base, chan_index, dw_addr, value); + } +} + static LLVMValueRef fetch_input_gs( struct lp_build_tgsi_context *bld_base, const struct tgsi_full_src_register *reg, @@ -321,13 +776,8 @@ static LLVMValueRef fetch_input_gs( unsigned semantic_name = info->input_semantic_name[reg->Register.Index]; unsigned semantic_index = info->input_semantic_index[reg->Register.Index]; - if (swizzle != ~0 && semantic_name == TGSI_SEMANTIC_PRIMID) { - if (swizzle == 0) - return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, - SI_PARAM_PRIMITIVE_ID); - else - return uint->zero; - } + if (swizzle != ~0 && semantic_name == TGSI_SEMANTIC_PRIMID) + return get_primitive_id(bld_base, swizzle); if (!reg->Register.Dimension) return NULL; @@ -359,7 +809,7 @@ static LLVMValueRef fetch_input_gs( args[1] = vtx_offset; args[2] = lp_build_const_int32(gallivm, (get_param_index(semantic_name, semantic_index, - shader->selector->gs_used_inputs) * 4 + + shader->selector->inputs_read) * 4 + swizzle) * 256); args[3] = uint->zero; args[4] = uint->one; /* OFFEN */ @@ -369,13 +819,42 @@ static LLVMValueRef fetch_input_gs( args[8] = uint->zero; /* TFE */ return LLVMBuildBitCast(gallivm->builder, - build_intrinsic(gallivm->builder, + lp_build_intrinsic(gallivm->builder, "llvm.SI.buffer.load.dword.i32.i32", i32, args, 9, LLVMReadOnlyAttribute | LLVMNoUnwindAttribute), tgsi2llvmtype(bld_base, type), ""); } +static int lookup_interp_param_index(unsigned interpolate, unsigned location) +{ + switch (interpolate) { + case TGSI_INTERPOLATE_CONSTANT: + return 0; + + case TGSI_INTERPOLATE_LINEAR: + if (location == TGSI_INTERPOLATE_LOC_SAMPLE) + return SI_PARAM_LINEAR_SAMPLE; + else if (location == TGSI_INTERPOLATE_LOC_CENTROID) + return SI_PARAM_LINEAR_CENTROID; + else + return SI_PARAM_LINEAR_CENTER; + break; + case TGSI_INTERPOLATE_COLOR: + case TGSI_INTERPOLATE_PERSPECTIVE: + if (location == TGSI_INTERPOLATE_LOC_SAMPLE) + return SI_PARAM_PERSP_SAMPLE; + else if (location == TGSI_INTERPOLATE_LOC_CENTROID) + return SI_PARAM_PERSP_CENTROID; + else + return SI_PARAM_PERSP_CENTER; + break; + default: + fprintf(stderr, "Warning: Unhandled interpolation mode.\n"); + return -1; + } +} + static void declare_input_fs( struct radeon_llvm_context *radeon_bld, unsigned input_index, @@ -390,7 +869,8 @@ static void declare_input_fs( LLVMTypeRef input_type = LLVMFloatTypeInContext(gallivm->context); LLVMValueRef main_fn = radeon_bld->main_fn; - LLVMValueRef interp_param; + LLVMValueRef interp_param = NULL; + int interp_param_idx; const char * intr_name; /* This value is: @@ -439,40 +919,26 @@ static void declare_input_fs( attr_number = lp_build_const_int32(gallivm, shader->ps_input_param_offset[input_index]); - switch (decl->Interp.Interpolate) { - case TGSI_INTERPOLATE_CONSTANT: - interp_param = 0; - break; - case TGSI_INTERPOLATE_LINEAR: - if (decl->Interp.Location == TGSI_INTERPOLATE_LOC_SAMPLE) - interp_param = LLVMGetParam(main_fn, SI_PARAM_LINEAR_SAMPLE); - else if (decl->Interp.Location == TGSI_INTERPOLATE_LOC_CENTROID) - interp_param = LLVMGetParam(main_fn, SI_PARAM_LINEAR_CENTROID); - else - interp_param = LLVMGetParam(main_fn, SI_PARAM_LINEAR_CENTER); - break; - case TGSI_INTERPOLATE_COLOR: - if (si_shader_ctx->shader->key.ps.flatshade) { - interp_param = 0; - break; - } - /* fall through to perspective */ - case TGSI_INTERPOLATE_PERSPECTIVE: - if (decl->Interp.Location == TGSI_INTERPOLATE_LOC_SAMPLE) - interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_SAMPLE); - else if (decl->Interp.Location == TGSI_INTERPOLATE_LOC_CENTROID) - interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_CENTROID); - else - interp_param = LLVMGetParam(main_fn, SI_PARAM_PERSP_CENTER); - break; - default: - fprintf(stderr, "Warning: Unhandled interpolation mode.\n"); + shader->ps_input_interpolate[input_index] = decl->Interp.Interpolate; + interp_param_idx = lookup_interp_param_index(decl->Interp.Interpolate, + decl->Interp.Location); + if (interp_param_idx == -1) return; - } + else if (interp_param_idx) + interp_param = LLVMGetParam(main_fn, interp_param_idx); + /* fs.constant returns the param from the middle vertex, so it's not + * really useful for flat shading. It's meant to be used for custom + * interpolation (but the intrinsic can't fetch from the other two + * vertices). + * + * Luckily, it doesn't matter, because we rely on the FLAT_SHADE state + * to do the right thing. The only reason we use fs.constant is that + * fs.interp cannot be used on integers, because they can be equal + * to NaN. + */ intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant"; - /* XXX: Could there be more than TGSI_NUM_CHANNELS (4) ? */ if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR && si_shader_ctx->shader->key.ps.color_two_side) { LLVMValueRef args[4]; @@ -484,7 +950,7 @@ static void declare_input_fs( face = LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE); is_face_positive = LLVMBuildFCmp(gallivm->builder, - LLVMRealUGT, face, + LLVMRealOGT, face, lp_build_const_float(gallivm, 0.0f), ""); @@ -497,12 +963,12 @@ static void declare_input_fs( args[0] = llvm_chan; args[1] = attr_number; - front = build_intrinsic(gallivm->builder, intr_name, + front = lp_build_intrinsic(gallivm->builder, intr_name, input_type, args, args[3] ? 4 : 3, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); args[1] = back_attr_number; - back = build_intrinsic(gallivm->builder, intr_name, + back = lp_build_intrinsic(gallivm->builder, intr_name, input_type, args, args[3] ? 4 : 3, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); @@ -523,7 +989,7 @@ static void declare_input_fs( args[2] = params; args[3] = interp_param; radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)] = - build_intrinsic(gallivm->builder, intr_name, + lp_build_intrinsic(gallivm->builder, intr_name, input_type, args, args[3] ? 4 : 3, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 1)] = @@ -541,7 +1007,7 @@ static void declare_input_fs( args[2] = params; args[3] = interp_param; radeon_bld->inputs[soa_index] = - build_intrinsic(gallivm->builder, intr_name, + lp_build_intrinsic(gallivm->builder, intr_name, input_type, args, args[3] ? 4 : 3, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); } @@ -550,14 +1016,8 @@ static void declare_input_fs( static LLVMValueRef get_sample_id(struct radeon_llvm_context *radeon_bld) { - struct gallivm_state *gallivm = &radeon_bld->gallivm; - LLVMValueRef value = LLVMGetParam(radeon_bld->main_fn, - SI_PARAM_ANCILLARY); - value = LLVMBuildLShr(gallivm->builder, value, - lp_build_const_int32(gallivm, 8), ""); - value = LLVMBuildAnd(gallivm->builder, value, - lp_build_const_int32(gallivm, 0xf), ""); - return value; + return unpack_param(si_shader_context(&radeon_bld->soa.bld_base), + SI_PARAM_ANCILLARY, 8, 4); } /** @@ -568,10 +1028,35 @@ static LLVMValueRef buffer_load_const(LLVMBuilderRef builder, LLVMValueRef resou { LLVMValueRef args[2] = {resource, offset}; - return build_intrinsic(builder, "llvm.SI.load.const", return_type, args, 2, + return lp_build_intrinsic(builder, "llvm.SI.load.const", return_type, args, 2, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); } +static LLVMValueRef load_sample_position(struct radeon_llvm_context *radeon_bld, LLVMValueRef sample_id) +{ + struct si_shader_context *si_shader_ctx = + si_shader_context(&radeon_bld->soa.bld_base); + struct lp_build_context *uint_bld = &radeon_bld->soa.bld_base.uint_bld; + struct gallivm_state *gallivm = &radeon_bld->gallivm; + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef desc = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_CONST); + LLVMValueRef buf_index = lp_build_const_int32(gallivm, SI_DRIVER_STATE_CONST_BUF); + LLVMValueRef resource = build_indexed_load_const(si_shader_ctx, desc, buf_index); + + /* offset = sample_id * 8 (8 = 2 floats containing samplepos.xy) */ + LLVMValueRef offset0 = lp_build_mul_imm(uint_bld, sample_id, 8); + LLVMValueRef offset1 = LLVMBuildAdd(builder, offset0, lp_build_const_int32(gallivm, 4), ""); + + LLVMValueRef pos[4] = { + buffer_load_const(builder, resource, offset0, radeon_bld->soa.bld_base.base.elem_type), + buffer_load_const(builder, resource, offset1, radeon_bld->soa.bld_base.base.elem_type), + lp_build_const_float(gallivm, 0), + lp_build_const_float(gallivm, 0) + }; + + return lp_build_gather_values(gallivm, pos, 4); +} + static void declare_system_value( struct radeon_llvm_context * radeon_bld, unsigned index, @@ -579,6 +1064,7 @@ static void declare_system_value( { struct si_shader_context *si_shader_ctx = si_shader_context(&radeon_bld->soa.bld_base); + struct lp_build_context *bld = &radeon_bld->soa.bld_base.base; struct lp_build_context *uint_bld = &radeon_bld->soa.bld_base.uint_bld; struct gallivm_state *gallivm = &radeon_bld->gallivm; LLVMValueRef value = 0; @@ -590,35 +1076,92 @@ static void declare_system_value( break; case TGSI_SEMANTIC_VERTEXID: + value = LLVMBuildAdd(gallivm->builder, + LLVMGetParam(radeon_bld->main_fn, + si_shader_ctx->param_vertex_id), + LLVMGetParam(radeon_bld->main_fn, + SI_PARAM_BASE_VERTEX), ""); + break; + + case TGSI_SEMANTIC_VERTEXID_NOBASE: value = LLVMGetParam(radeon_bld->main_fn, si_shader_ctx->param_vertex_id); break; + case TGSI_SEMANTIC_BASEVERTEX: + value = LLVMGetParam(radeon_bld->main_fn, + SI_PARAM_BASE_VERTEX); + break; + + case TGSI_SEMANTIC_INVOCATIONID: + if (si_shader_ctx->type == TGSI_PROCESSOR_TESS_CTRL) + value = unpack_param(si_shader_ctx, SI_PARAM_REL_IDS, 8, 5); + else if (si_shader_ctx->type == TGSI_PROCESSOR_GEOMETRY) + value = LLVMGetParam(radeon_bld->main_fn, + SI_PARAM_GS_INSTANCE_ID); + else + assert(!"INVOCATIONID not implemented"); + break; + case TGSI_SEMANTIC_SAMPLEID: value = get_sample_id(radeon_bld); break; case TGSI_SEMANTIC_SAMPLEPOS: + value = load_sample_position(radeon_bld, get_sample_id(radeon_bld)); + break; + + case TGSI_SEMANTIC_SAMPLEMASK: + /* Smoothing isn't MSAA in GL, but it's MSAA in hardware. + * Therefore, force gl_SampleMaskIn to 1 for GL. */ + if (si_shader_ctx->shader->key.ps.poly_line_smoothing) + value = uint_bld->one; + else + value = LLVMGetParam(radeon_bld->main_fn, SI_PARAM_SAMPLE_COVERAGE); + break; + + case TGSI_SEMANTIC_TESSCOORD: { - LLVMBuilderRef builder = gallivm->builder; - LLVMValueRef desc = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_CONST); - LLVMValueRef buf_index = lp_build_const_int32(gallivm, SI_DRIVER_STATE_CONST_BUF); - LLVMValueRef resource = build_indexed_load_const(si_shader_ctx, desc, buf_index); - - /* offset = sample_id * 8 (8 = 2 floats containing samplepos.xy) */ - LLVMValueRef offset0 = lp_build_mul_imm(uint_bld, get_sample_id(radeon_bld), 8); - LLVMValueRef offset1 = LLVMBuildAdd(builder, offset0, lp_build_const_int32(gallivm, 4), ""); - - LLVMValueRef pos[4] = { - buffer_load_const(builder, resource, offset0, radeon_bld->soa.bld_base.base.elem_type), - buffer_load_const(builder, resource, offset1, radeon_bld->soa.bld_base.base.elem_type), - lp_build_const_float(gallivm, 0), - lp_build_const_float(gallivm, 0) + LLVMValueRef coord[4] = { + LLVMGetParam(radeon_bld->main_fn, si_shader_ctx->param_tes_u), + LLVMGetParam(radeon_bld->main_fn, si_shader_ctx->param_tes_v), + bld->zero, + bld->zero }; - value = lp_build_gather_values(gallivm, pos, 4); + + /* For triangles, the vector should be (u, v, 1-u-v). */ + if (si_shader_ctx->shader->selector->info.properties[TGSI_PROPERTY_TES_PRIM_MODE] == + PIPE_PRIM_TRIANGLES) + coord[2] = lp_build_sub(bld, bld->one, + lp_build_add(bld, coord[0], coord[1])); + + value = lp_build_gather_values(gallivm, coord, 4); + break; + } + + case TGSI_SEMANTIC_VERTICESIN: + value = unpack_param(si_shader_ctx, SI_PARAM_TCS_OUT_LAYOUT, 26, 6); + break; + + case TGSI_SEMANTIC_TESSINNER: + case TGSI_SEMANTIC_TESSOUTER: + { + LLVMValueRef dw_addr; + int param = si_shader_io_get_unique_index(decl->Semantic.Name, 0); + + dw_addr = get_tcs_out_current_patch_data_offset(si_shader_ctx); + dw_addr = LLVMBuildAdd(gallivm->builder, dw_addr, + lp_build_const_int32(gallivm, param * 4), ""); + + value = lds_load(&radeon_bld->soa.bld_base, TGSI_TYPE_FLOAT, + ~0, dw_addr); break; } + case TGSI_SEMANTIC_PRIMID: + value = get_primitive_id(&radeon_bld->soa.bld_base, 0); + break; + default: assert(!"unknown system value"); return; @@ -638,7 +1181,7 @@ static LLVMValueRef fetch_constant( const struct tgsi_ind_register *ireg = ®->Indirect; unsigned buf, idx; - LLVMValueRef addr; + LLVMValueRef addr, bufp; LLVMValueRef result; if (swizzle == LP_CHAN_ALL) { @@ -653,8 +1196,24 @@ static LLVMValueRef fetch_constant( buf = reg->Register.Dimension ? reg->Dimension.Index : 0; idx = reg->Register.Index * 4 + swizzle; - if (!reg->Register.Indirect) - return bitcast(bld_base, type, si_shader_ctx->constants[buf][idx]); + if (!reg->Register.Indirect && !reg->Dimension.Indirect) { + if (type != TGSI_TYPE_DOUBLE) + return bitcast(bld_base, type, si_shader_ctx->constants[buf][idx]); + else { + return radeon_llvm_emit_fetch_double(bld_base, + si_shader_ctx->constants[buf][idx], + si_shader_ctx->constants[buf][idx + 1]); + } + } + + if (reg->Register.Dimension && reg->Dimension.Indirect) { + LLVMValueRef ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_CONST); + LLVMValueRef index; + index = get_indirect_index(si_shader_ctx, ®->DimIndirect, + reg->Dimension.Index); + bufp = build_indexed_load_const(si_shader_ctx, ptr, index); + } else + bufp = si_shader_ctx->const_resource[buf]; addr = si_shader_ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle]; addr = LLVMBuildLoad(base->gallivm->builder, addr, "load addr reg"); @@ -662,10 +1221,26 @@ static LLVMValueRef fetch_constant( addr = lp_build_add(&bld_base->uint_bld, addr, lp_build_const_int32(base->gallivm, idx * 4)); - result = buffer_load_const(base->gallivm->builder, si_shader_ctx->const_resource[buf], - addr, base->elem_type); + result = buffer_load_const(base->gallivm->builder, bufp, + addr, bld_base->base.elem_type); + + if (type != TGSI_TYPE_DOUBLE) + result = bitcast(bld_base, type, result); + else { + LLVMValueRef addr2, result2; + addr2 = si_shader_ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle + 1]; + addr2 = LLVMBuildLoad(base->gallivm->builder, addr2, "load addr reg2"); + addr2 = lp_build_mul_imm(&bld_base->uint_bld, addr2, 16); + addr2 = lp_build_add(&bld_base->uint_bld, addr2, + lp_build_const_int32(base->gallivm, idx * 4)); - return bitcast(bld_base, type, result); + result2 = buffer_load_const(base->gallivm->builder, si_shader_ctx->const_resource[buf], + addr2, bld_base->base.elem_type); + + result = radeon_llvm_emit_fetch_double(bld_base, + result, result2); + } + return result; } /* Initialize arguments for the shader export intrinsic */ @@ -704,7 +1279,7 @@ static void si_llvm_init_export_args(struct lp_build_tgsi_context *bld_base, args[0] = values[2 * chan]; args[1] = values[2 * chan + 1]; args[chan + 5] = - build_intrinsic(base->gallivm->builder, + lp_build_intrinsic(base->gallivm->builder, "llvm.SI.packf16", LLVMInt32TypeInContext(base->gallivm->context), args, 2, @@ -766,7 +1341,7 @@ static void si_llvm_init_export_args_load(struct lp_build_tgsi_context *bld_base } static void si_alpha_test(struct lp_build_tgsi_context *bld_base, - LLVMValueRef *out_ptr) + LLVMValueRef alpha_ptr) { struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); struct gallivm_state *gallivm = bld_base->base.gallivm; @@ -778,7 +1353,7 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base, LLVMValueRef alpha_pass = lp_build_cmp(&bld_base->base, si_shader_ctx->shader->key.ps.alpha_func, - LLVMBuildLoad(gallivm->builder, out_ptr[3], ""), + LLVMBuildLoad(gallivm->builder, alpha_ptr, ""), alpha_ref); LLVMValueRef arg = lp_build_select(&bld_base->base, @@ -786,12 +1361,12 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base, lp_build_const_float(gallivm, 1.0f), lp_build_const_float(gallivm, -1.0f)); - build_intrinsic(gallivm->builder, + lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill", LLVMVoidTypeInContext(gallivm->context), &arg, 1, 0); } else { - build_intrinsic(gallivm->builder, + lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kilp", LLVMVoidTypeInContext(gallivm->context), NULL, 0, 0); @@ -800,11 +1375,38 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base, si_shader_ctx->shader->db_shader_control |= S_02880C_KILL_ENABLE(1); } +static void si_scale_alpha_by_sample_mask(struct lp_build_tgsi_context *bld_base, + LLVMValueRef alpha_ptr) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + LLVMValueRef coverage, alpha; + + /* alpha = alpha * popcount(coverage) / SI_NUM_SMOOTH_AA_SAMPLES */ + coverage = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + SI_PARAM_SAMPLE_COVERAGE); + coverage = bitcast(bld_base, TGSI_TYPE_SIGNED, coverage); + + coverage = lp_build_intrinsic(gallivm->builder, "llvm.ctpop.i32", + bld_base->int_bld.elem_type, + &coverage, 1, LLVMReadNoneAttribute); + + coverage = LLVMBuildUIToFP(gallivm->builder, coverage, + bld_base->base.elem_type, ""); + + coverage = LLVMBuildFMul(gallivm->builder, coverage, + lp_build_const_float(gallivm, + 1.0 / SI_NUM_SMOOTH_AA_SAMPLES), ""); + + alpha = LLVMBuildLoad(gallivm->builder, alpha_ptr, ""); + alpha = LLVMBuildFMul(gallivm->builder, alpha, coverage, ""); + LLVMBuildStore(gallivm->builder, alpha, alpha_ptr); +} + static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context * bld_base, LLVMValueRef (*pos)[9], LLVMValueRef *out_elts) { struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); - struct si_shader *shader = si_shader_ctx->shader; struct lp_build_context *base = &bld_base->base; struct lp_build_context *uint = &si_shader_ctx->radeon_bld.soa.bld_base.uint_bld; unsigned reg_index; @@ -818,8 +1420,6 @@ static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context * bld_base, for (reg_index = 0; reg_index < 2; reg_index ++) { LLVMValueRef *args = pos[2 + reg_index]; - shader->clip_dist_write |= 0xf << (4 * reg_index); - args[5] = args[6] = args[7] = @@ -917,16 +1517,16 @@ static void build_tbuffer_store(struct si_shader_context *shader, lp_build_intrinsic(gallivm->builder, name, LLVMVoidTypeInContext(gallivm->context), - args, Elements(args)); + args, Elements(args), 0); } -static void build_streamout_store(struct si_shader_context *shader, - LLVMValueRef rsrc, - LLVMValueRef vdata, - unsigned num_channels, - LLVMValueRef vaddr, - LLVMValueRef soffset, - unsigned inst_offset) +static void build_tbuffer_store_dwords(struct si_shader_context *shader, + LLVMValueRef rsrc, + LLVMValueRef vdata, + unsigned num_channels, + LLVMValueRef vaddr, + LLVMValueRef soffset, + unsigned inst_offset) { static unsigned dfmt[] = { V_008F0C_BUF_DATA_FORMAT_32, @@ -955,24 +1555,20 @@ static void si_llvm_emit_streamout(struct si_shader_context *shader, LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context); - LLVMValueRef so_param = - LLVMGetParam(shader->radeon_bld.main_fn, - shader->param_streamout_config); - /* Get bits [22:16], i.e. (so_param >> 16) & 127; */ LLVMValueRef so_vtx_count = - LLVMBuildAnd(builder, - LLVMBuildLShr(builder, so_param, - LLVMConstInt(i32, 16, 0), ""), - LLVMConstInt(i32, 127, 0), ""); + unpack_param(shader, shader->param_streamout_config, 16, 7); - LLVMValueRef tid = build_intrinsic(builder, "llvm.SI.tid", i32, + LLVMValueRef tid = lp_build_intrinsic(builder, "llvm.SI.tid", i32, NULL, 0, LLVMReadNoneAttribute); /* can_emit = tid < so_vtx_count; */ LLVMValueRef can_emit = LLVMBuildICmp(builder, LLVMIntULT, tid, so_vtx_count, ""); + LLVMValueRef stream_id = + unpack_param(shader, shader->param_streamout_config, 24, 2); + /* Emit the streamout code conditionally. This actually avoids * out-of-bounds buffer access. The hw tells us via the SGPR * (so_vtx_count) which threads are allowed to emit streamout data. */ @@ -1012,7 +1608,9 @@ static void si_llvm_emit_streamout(struct si_shader_context *shader, unsigned reg = so->output[i].register_index; unsigned start = so->output[i].start_component; unsigned num_comps = so->output[i].num_components; + unsigned stream = so->output[i].stream; LLVMValueRef out[4]; + struct lp_build_if_state if_ctx_stream; assert(num_comps && num_comps <= 4); if (!num_comps || num_comps > 4) @@ -1046,11 +1644,18 @@ static void si_llvm_emit_streamout(struct si_shader_context *shader, break; } - build_streamout_store(shader, shader->so_buffers[buf_idx], - vdata, num_comps, - so_write_offset[buf_idx], - LLVMConstInt(i32, 0, 0), - so->output[i].dst_offset*4); + LLVMValueRef can_emit_stream = + LLVMBuildICmp(builder, LLVMIntEQ, + stream_id, + lp_build_const_int32(gallivm, stream), ""); + + lp_build_if(&if_ctx_stream, gallivm, can_emit_stream); + build_tbuffer_store_dwords(shader, shader->so_buffers[buf_idx], + vdata, num_comps, + so_write_offset[buf_idx], + LLVMConstInt(i32, 0, 0), + so->output[i].dst_offset*4); + lp_build_endif(&if_ctx_stream); } } lp_build_endif(&if_ctx); @@ -1069,7 +1674,7 @@ static void si_llvm_export_vs(struct lp_build_tgsi_context *bld_base, &si_shader_ctx->radeon_bld.soa.bld_base.uint_bld; LLVMValueRef args[9]; LLVMValueRef pos_args[4][9] = { { 0 } }; - LLVMValueRef psize_value = NULL, edgeflag_value = NULL, layer_value = NULL; + LLVMValueRef psize_value = NULL, edgeflag_value = NULL, layer_value = NULL, viewport_index_value = NULL; unsigned semantic_name, semantic_index; unsigned target; unsigned param_count = 0; @@ -1088,20 +1693,19 @@ handle_semantic: /* Select the correct target */ switch(semantic_name) { case TGSI_SEMANTIC_PSIZE: - shader->vs_out_misc_write = true; - shader->vs_out_point_size = true; psize_value = outputs[i].values[0]; continue; case TGSI_SEMANTIC_EDGEFLAG: - shader->vs_out_misc_write = true; - shader->vs_out_edgeflag = true; edgeflag_value = outputs[i].values[0]; continue; case TGSI_SEMANTIC_LAYER: - shader->vs_out_misc_write = true; - shader->vs_out_layer = true; layer_value = outputs[i].values[0]; - continue; + semantic_name = TGSI_SEMANTIC_GENERIC; + goto handle_semantic; + case TGSI_SEMANTIC_VIEWPORT_INDEX: + viewport_index_value = outputs[i].values[0]; + semantic_name = TGSI_SEMANTIC_GENERIC; + goto handle_semantic; case TGSI_SEMANTIC_POSITION: target = V_008DFC_SQ_EXP_POS; break; @@ -1112,8 +1716,6 @@ handle_semantic: param_count++; break; case TGSI_SEMANTIC_CLIPDIST: - shader->clip_dist_write |= - 0xf << (semantic_index * 4); target = V_008DFC_SQ_EXP_POS + 2 + semantic_index; break; case TGSI_SEMANTIC_CLIPVERTEX: @@ -1121,6 +1723,7 @@ handle_semantic: continue; case TGSI_SEMANTIC_PRIMID: case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_TEXCOORD: case TGSI_SEMANTIC_GENERIC: target = V_008DFC_SQ_EXP_PARAM + param_count; shader->vs_output_param_offset[i] = param_count; @@ -1143,7 +1746,7 @@ handle_semantic: lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - args, 9); + args, 9, 0); } if (semantic_name == TGSI_SEMANTIC_CLIPDIST) { @@ -1152,6 +1755,8 @@ handle_semantic: } } + shader->nr_param_exports = param_count; + /* We need to add the position output manually if it's missing. */ if (!pos_args[0][0]) { pos_args[0][0] = lp_build_const_int32(base->gallivm, 0xf); /* writemask */ @@ -1166,11 +1771,15 @@ handle_semantic: } /* Write the misc vector (point size, edgeflag, layer, viewport). */ - if (shader->vs_out_misc_write) { + if (shader->selector->info.writes_psize || + shader->selector->info.writes_edgeflag || + shader->selector->info.writes_viewport_index || + shader->selector->info.writes_layer) { pos_args[1][0] = lp_build_const_int32(base->gallivm, /* writemask */ - shader->vs_out_point_size | - (shader->vs_out_edgeflag << 1) | - (shader->vs_out_layer << 2)); + shader->selector->info.writes_psize | + (shader->selector->info.writes_edgeflag << 1) | + (shader->selector->info.writes_layer << 2) | + (shader->selector->info.writes_viewport_index << 3)); pos_args[1][1] = uint->zero; /* EXEC mask */ pos_args[1][2] = uint->zero; /* last export? */ pos_args[1][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + 1); @@ -1180,10 +1789,10 @@ handle_semantic: pos_args[1][7] = base->zero; /* Z */ pos_args[1][8] = base->zero; /* W */ - if (shader->vs_out_point_size) + if (shader->selector->info.writes_psize) pos_args[1][5] = psize_value; - if (shader->vs_out_edgeflag) { + if (shader->selector->info.writes_edgeflag) { /* The output is a float, but the hw expects an integer * with the first bit containing the edge flag. */ edgeflag_value = LLVMBuildFPToUI(base->gallivm->builder, @@ -1199,8 +1808,11 @@ handle_semantic: base->elem_type, ""); } - if (shader->vs_out_layer) + if (shader->selector->info.writes_layer) pos_args[1][7] = layer_value; + + if (shader->selector->info.writes_viewport_index) + pos_args[1][8] = viewport_index_value; } for (i = 0; i < 4; i++) @@ -1215,14 +1827,140 @@ handle_semantic: /* Specify the target we are exporting */ pos_args[i][3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_POS + pos_idx++); - if (pos_idx == shader->nr_pos_exports) - /* Specify that this is the last export */ - pos_args[i][2] = uint->one; + if (pos_idx == shader->nr_pos_exports) + /* Specify that this is the last export */ + pos_args[i][2] = uint->one; + + lp_build_intrinsic(base->gallivm->builder, + "llvm.SI.export", + LLVMVoidTypeInContext(base->gallivm->context), + pos_args[i], 9, 0); + } +} + +/* This only writes the tessellation factor levels. */ +static void si_llvm_emit_tcs_epilogue(struct lp_build_tgsi_context *bld_base) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + struct si_shader *shader = si_shader_ctx->shader; + unsigned tess_inner_index, tess_outer_index; + LLVMValueRef lds_base, lds_inner, lds_outer; + LLVMValueRef tf_base, rel_patch_id, byteoffset, buffer, rw_buffers; + LLVMValueRef out[6], vec0, vec1, invocation_id; + unsigned stride, outer_comps, inner_comps, i; + struct lp_build_if_state if_ctx; + + invocation_id = unpack_param(si_shader_ctx, SI_PARAM_REL_IDS, 8, 5); + + /* Do this only for invocation 0, because the tess levels are per-patch, + * not per-vertex. + * + * This can't jump, because invocation 0 executes this. It should + * at least mask out the loads and stores for other invocations. + */ + lp_build_if(&if_ctx, gallivm, + LLVMBuildICmp(gallivm->builder, LLVMIntEQ, + invocation_id, bld_base->uint_bld.zero, "")); + + /* Determine the layout of one tess factor element in the buffer. */ + switch (shader->key.tcs.prim_mode) { + case PIPE_PRIM_LINES: + stride = 2; /* 2 dwords, 1 vec2 store */ + outer_comps = 2; + inner_comps = 0; + break; + case PIPE_PRIM_TRIANGLES: + stride = 4; /* 4 dwords, 1 vec4 store */ + outer_comps = 3; + inner_comps = 1; + break; + case PIPE_PRIM_QUADS: + stride = 6; /* 6 dwords, 2 stores (vec4 + vec2) */ + outer_comps = 4; + inner_comps = 2; + break; + default: + assert(0); + return; + } + + /* Load tess_inner and tess_outer from LDS. + * Any invocation can write them, so we can't get them from a temporary. + */ + tess_inner_index = si_shader_io_get_unique_index(TGSI_SEMANTIC_TESSINNER, 0); + tess_outer_index = si_shader_io_get_unique_index(TGSI_SEMANTIC_TESSOUTER, 0); + + lds_base = get_tcs_out_current_patch_data_offset(si_shader_ctx); + lds_inner = LLVMBuildAdd(gallivm->builder, lds_base, + lp_build_const_int32(gallivm, + tess_inner_index * 4), ""); + lds_outer = LLVMBuildAdd(gallivm->builder, lds_base, + lp_build_const_int32(gallivm, + tess_outer_index * 4), ""); + + for (i = 0; i < outer_comps; i++) + out[i] = lds_load(bld_base, TGSI_TYPE_SIGNED, i, lds_outer); + for (i = 0; i < inner_comps; i++) + out[outer_comps+i] = lds_load(bld_base, TGSI_TYPE_SIGNED, i, lds_inner); + + /* Convert the outputs to vectors for stores. */ + vec0 = lp_build_gather_values(gallivm, out, MIN2(stride, 4)); + vec1 = NULL; + + if (stride > 4) + vec1 = lp_build_gather_values(gallivm, out+4, stride - 4); + + /* Get the buffer. */ + rw_buffers = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + SI_PARAM_RW_BUFFERS); + buffer = build_indexed_load_const(si_shader_ctx, rw_buffers, + lp_build_const_int32(gallivm, SI_RING_TESS_FACTOR)); + + /* Get the offset. */ + tf_base = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + SI_PARAM_TESS_FACTOR_OFFSET); + rel_patch_id = get_rel_patch_id(si_shader_ctx); + byteoffset = LLVMBuildMul(gallivm->builder, rel_patch_id, + lp_build_const_int32(gallivm, 4 * stride), ""); + + /* Store the outputs. */ + build_tbuffer_store_dwords(si_shader_ctx, buffer, vec0, + MIN2(stride, 4), byteoffset, tf_base, 0); + if (vec1) + build_tbuffer_store_dwords(si_shader_ctx, buffer, vec1, + stride - 4, byteoffset, tf_base, 16); + lp_build_endif(&if_ctx); +} + +static void si_llvm_emit_ls_epilogue(struct lp_build_tgsi_context * bld_base) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct si_shader *shader = si_shader_ctx->shader; + struct tgsi_shader_info *info = &shader->selector->info; + struct gallivm_state *gallivm = bld_base->base.gallivm; + unsigned i, chan; + LLVMValueRef vertex_id = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + si_shader_ctx->param_rel_auto_id); + LLVMValueRef vertex_dw_stride = + unpack_param(si_shader_ctx, SI_PARAM_LS_OUT_LAYOUT, 13, 8); + LLVMValueRef base_dw_addr = LLVMBuildMul(gallivm->builder, vertex_id, + vertex_dw_stride, ""); + + /* Write outputs to LDS. The next shader (TCS aka HS) will read + * its inputs from it. */ + for (i = 0; i < info->num_outputs; i++) { + LLVMValueRef *out_ptr = si_shader_ctx->radeon_bld.soa.outputs[i]; + unsigned name = info->output_semantic_name[i]; + unsigned index = info->output_semantic_index[i]; + int param = si_shader_io_get_unique_index(name, index); + LLVMValueRef dw_addr = LLVMBuildAdd(gallivm->builder, base_dw_addr, + lp_build_const_int32(gallivm, param * 4), ""); - lp_build_intrinsic(base->gallivm->builder, - "llvm.SI.export", - LLVMVoidTypeInContext(base->gallivm->context), - pos_args[i], 9); + for (chan = 0; chan < 4; chan++) { + lds_store(bld_base, chan, dw_addr, + LLVMBuildLoad(gallivm->builder, out_ptr[chan], "")); + } } } @@ -1234,17 +1972,25 @@ static void si_llvm_emit_es_epilogue(struct lp_build_tgsi_context * bld_base) struct tgsi_shader_info *info = &es->selector->info; LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context); LLVMValueRef soffset = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, - SI_PARAM_ES2GS_OFFSET); + si_shader_ctx->param_es2gs_offset); + uint64_t enabled_outputs = si_shader_ctx->type == TGSI_PROCESSOR_TESS_EVAL ? + es->key.tes.es_enabled_outputs : + es->key.vs.es_enabled_outputs; unsigned chan; int i; for (i = 0; i < info->num_outputs; i++) { LLVMValueRef *out_ptr = si_shader_ctx->radeon_bld.soa.outputs[i]; - int param_index = get_param_index(info->output_semantic_name[i], - info->output_semantic_index[i], - es->key.vs.gs_used_inputs); + int param_index; + + if (info->output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX || + info->output_semantic_name[i] == TGSI_SEMANTIC_LAYER) + continue; + param_index = get_param_index(info->output_semantic_name[i], + info->output_semantic_index[i], + enabled_outputs); if (param_index < 0) continue; @@ -1272,7 +2018,7 @@ static void si_llvm_emit_gs_epilogue(struct lp_build_tgsi_context *bld_base) args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_NOP | SENDMSG_GS_DONE); args[1] = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_GS_WAVE_ID); - build_intrinsic(gallivm->builder, "llvm.SI.sendmsg", + lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg", LLVMVoidTypeInContext(gallivm->context), args, 2, LLVMNoUnwindAttribute); } @@ -1285,7 +2031,7 @@ static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context * bld_base) struct si_shader_output_values *outputs = NULL; int i,j; - outputs = MALLOC(info->num_outputs * sizeof(outputs[0])); + outputs = MALLOC((info->num_outputs + 1) * sizeof(outputs[0])); for (i = 0; i < info->num_outputs; i++) { outputs[i].name = info->output_semantic_name[i]; @@ -1298,7 +2044,19 @@ static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context * bld_base) ""); } - si_llvm_export_vs(bld_base, outputs, info->num_outputs); + /* Export PrimitiveID when PS needs it. */ + if (si_vs_exports_prim_id(si_shader_ctx->shader)) { + outputs[i].name = TGSI_SEMANTIC_PRIMID; + outputs[i].sid = 0; + outputs[i].values[0] = bitcast(bld_base, TGSI_TYPE_FLOAT, + get_primitive_id(bld_base, 0)); + outputs[i].values[1] = bld_base->base.undef; + outputs[i].values[2] = bld_base->base.undef; + outputs[i].values[3] = bld_base->base.undef; + i++; + } + + si_llvm_export_vs(bld_base, outputs, i); FREE(outputs); } @@ -1318,6 +2076,7 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) unsigned semantic_name = info->output_semantic_name[i]; unsigned semantic_index = info->output_semantic_index[i]; unsigned target; + LLVMValueRef alpha_ptr; /* Select the correct target */ switch (semantic_name) { @@ -1332,15 +2091,18 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) continue; case TGSI_SEMANTIC_COLOR: target = V_008DFC_SQ_EXP_MRT + semantic_index; + alpha_ptr = si_shader_ctx->radeon_bld.soa.outputs[i][3]; + if (si_shader_ctx->shader->key.ps.alpha_to_one) - LLVMBuildStore(bld_base->base.gallivm->builder, - bld_base->base.one, - si_shader_ctx->radeon_bld.soa.outputs[i][3]); + LLVMBuildStore(base->gallivm->builder, + base->one, alpha_ptr); if (semantic_index == 0 && si_shader_ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS) - si_alpha_test(bld_base, - si_shader_ctx->radeon_bld.soa.outputs[i]); + si_alpha_test(bld_base, alpha_ptr); + + if (si_shader_ctx->shader->key.ps.poly_line_smoothing) + si_scale_alpha_by_sample_mask(bld_base, alpha_ptr); break; default: target = 0; @@ -1359,7 +2121,7 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - last_args, 9); + last_args, 9, 0); } /* This instruction will be emitted at the end of the shader. */ @@ -1376,14 +2138,14 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - args, 9); + args, 9, 0); } } } else { lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - args, 9); + args, 9, 0); } } @@ -1409,10 +2171,7 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) if (stencil_index >= 0) { out_ptr = si_shader_ctx->radeon_bld.soa.outputs[stencil_index][1]; args[6] = LLVMBuildLoad(base->gallivm->builder, out_ptr, ""); - /* Only setting the stencil component bit (0x2) here - * breaks some stencil piglit tests - */ - mask |= 0x3; + mask |= 0x2; si_shader_ctx->shader->db_shader_control |= S_02880C_STENCIL_TEST_VAL_EXPORT_ENABLE(1); } @@ -1420,10 +2179,16 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) if (samplemask_index >= 0) { out_ptr = si_shader_ctx->radeon_bld.soa.outputs[samplemask_index][0]; args[7] = LLVMBuildLoad(base->gallivm->builder, out_ptr, ""); - mask |= 0xf; /* Set all components. */ + mask |= 0x4; si_shader_ctx->shader->db_shader_control |= S_02880C_MASK_EXPORT_ENABLE(1); } + /* SI (except OLAND) has a bug that it only looks + * at the X writemask component. */ + if (si_shader_ctx->screen->b.chip_class == SI && + si_shader_ctx->screen->b.family != CHIP_OLAND) + mask |= 0x1; + if (samplemask_index >= 0) si_shader_ctx->shader->spi_shader_z_format = V_028710_SPI_SHADER_32_ABGR; else if (stencil_index >= 0) @@ -1442,7 +2207,7 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - args, 9); + args, 9, 0); else memcpy(last_args, args, sizeof(args)); } @@ -1473,7 +2238,7 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base) lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - last_args, 9); + last_args, 9, 0); } static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, @@ -1502,15 +2267,36 @@ static void tex_fetch_args( const struct tgsi_full_instruction * inst = emit_data->inst; unsigned opcode = inst->Instruction.Opcode; unsigned target = inst->Texture.Texture; - LLVMValueRef coords[4]; + LLVMValueRef coords[5], derivs[6]; LLVMValueRef address[16]; int ref_pos; unsigned num_coords = tgsi_util_get_texture_coord_dim(target, &ref_pos); unsigned count = 0; unsigned chan; - unsigned sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1; - unsigned sampler_index = emit_data->inst->Src[sampler_src].Register.Index; + unsigned sampler_src; + unsigned sampler_index; + unsigned num_deriv_channels = 0; bool has_offset = HAVE_LLVM >= 0x0305 ? inst->Texture.NumOffsets > 0 : false; + LLVMValueRef res_ptr, samp_ptr; + + 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_indirect_index(si_shader_ctx, ®->Indirect, reg->Register.Index); + + res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE); + res_ptr = build_indexed_load_const(si_shader_ctx, res_ptr, ind_index); + + samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER); + samp_ptr = build_indexed_load_const(si_shader_ctx, samp_ptr, ind_index); + } else { + res_ptr = si_shader_ctx->resources[sampler_index]; + samp_ptr = si_shader_ctx->samplers[sampler_index]; + } if (target == TGSI_TEXTURE_BUFFER) { LLVMTypeRef i128 = LLVMIntTypeInContext(gallivm->context, 128); @@ -1519,9 +2305,9 @@ static void tex_fetch_args( LLVMTypeRef v16i8 = LLVMVectorType(i8, 16); /* Bitcast and truncate v8i32 to v16i8. */ - LLVMValueRef res = si_shader_ctx->resources[sampler_index]; + LLVMValueRef res = res_ptr; res = LLVMBuildBitCast(gallivm->builder, res, v2i128, ""); - res = LLVMBuildExtractElement(gallivm->builder, res, bld_base->uint_bld.zero, ""); + res = LLVMBuildExtractElement(gallivm->builder, res, bld_base->uint_bld.one, ""); res = LLVMBuildBitCast(gallivm->builder, res, v16i8, ""); emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4); @@ -1588,18 +2374,13 @@ static void tex_fetch_args( } } - if (target == TGSI_TEXTURE_CUBE || - target == TGSI_TEXTURE_CUBE_ARRAY || - target == TGSI_TEXTURE_SHADOWCUBE || - target == TGSI_TEXTURE_SHADOWCUBE_ARRAY) - radeon_llvm_emit_prepare_cube_coords(bld_base, emit_data, coords); - /* Pack user derivatives */ if (opcode == TGSI_OPCODE_TXD) { - int num_deriv_channels, param; + int param, num_src_deriv_channels; switch (target) { case TGSI_TEXTURE_3D: + num_src_deriv_channels = 3; num_deriv_channels = 3; break; case TGSI_TEXTURE_2D: @@ -1608,27 +2389,44 @@ static void tex_fetch_args( case TGSI_TEXTURE_SHADOWRECT: case TGSI_TEXTURE_2D_ARRAY: case TGSI_TEXTURE_SHADOW2D_ARRAY: + num_src_deriv_channels = 2; + num_deriv_channels = 2; + break; case TGSI_TEXTURE_CUBE: case TGSI_TEXTURE_SHADOWCUBE: case TGSI_TEXTURE_CUBE_ARRAY: case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + /* Cube derivatives will be converted to 2D. */ + num_src_deriv_channels = 3; num_deriv_channels = 2; break; case TGSI_TEXTURE_1D: case TGSI_TEXTURE_SHADOW1D: case TGSI_TEXTURE_1D_ARRAY: case TGSI_TEXTURE_SHADOW1D_ARRAY: + num_src_deriv_channels = 1; num_deriv_channels = 1; break; default: assert(0); /* no other targets are valid here */ } - for (param = 1; param <= 2; param++) - for (chan = 0; chan < num_deriv_channels; chan++) - address[count++] = lp_build_emit_fetch(bld_base, inst, param, chan); + for (param = 0; param < 2; param++) + for (chan = 0; chan < num_src_deriv_channels; chan++) + derivs[param * num_src_deriv_channels + chan] = + lp_build_emit_fetch(bld_base, inst, param+1, chan); } + if (target == TGSI_TEXTURE_CUBE || + target == TGSI_TEXTURE_CUBE_ARRAY || + target == TGSI_TEXTURE_SHADOWCUBE || + target == TGSI_TEXTURE_SHADOWCUBE_ARRAY) + radeon_llvm_emit_prepare_cube_coords(bld_base, emit_data, coords, derivs); + + if (opcode == TGSI_OPCODE_TXD) + for (int i = 0; i < num_deriv_channels * 2; i++) + address[count++] = derivs[i]; + /* Pack texture coordinates */ address[count++] = coords[0]; if (num_coords > 1) @@ -1745,7 +2543,7 @@ static void tex_fetch_args( } /* Resource */ - emit_data->args[1] = si_shader_ctx->resources[sampler_index]; + emit_data->args[1] = res_ptr; if (opcode == TGSI_OPCODE_TXF) { /* add tex offsets */ @@ -1828,7 +2626,7 @@ static void tex_fetch_args( dmask = 1 << gather_comp; } - emit_data->args[2] = si_shader_ctx->samplers[sampler_index]; + emit_data->args[2] = samp_ptr; emit_data->args[3] = lp_build_const_int32(gallivm, dmask); emit_data->args[4] = lp_build_const_int32(gallivm, is_rect); /* unorm */ emit_data->args[5] = lp_build_const_int32(gallivm, 0); /* r128 */ @@ -1844,7 +2642,7 @@ static void tex_fetch_args( LLVMFloatTypeInContext(gallivm->context), 4); } else { - emit_data->args[2] = si_shader_ctx->samplers[sampler_index]; + emit_data->args[2] = samp_ptr; emit_data->args[3] = lp_build_const_int32(gallivm, target); emit_data->arg_count = 4; @@ -1879,7 +2677,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, emit_data->inst->Texture.NumOffsets > 0 : false; if (target == TGSI_TEXTURE_BUFFER) { - emit_data->output[emit_data->chan] = build_intrinsic( + 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, @@ -1928,7 +2726,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, is_shadow ? ".c" : "", infix, has_offset ? ".o" : "", LLVMGetVectorSize(LLVMTypeOf(emit_data->args[0]))); - emit_data->output[emit_data->chan] = build_intrinsic( + 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); @@ -1975,7 +2773,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action * action, sprintf(intr_name, "%s.v%ui32", name, LLVMGetVectorSize(LLVMTypeOf(emit_data->args[0]))); - emit_data->output[emit_data->chan] = build_intrinsic( + 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); @@ -1990,16 +2788,29 @@ static void txq_fetch_args( const struct tgsi_full_instruction *inst = emit_data->inst; struct gallivm_state *gallivm = bld_base->base.gallivm; unsigned target = inst->Texture.Texture; + LLVMValueRef res_ptr; + + if (inst->Src[1].Register.Indirect) { + const struct tgsi_full_src_register *reg = &inst->Src[1]; + LLVMValueRef ind_index; + + ind_index = get_indirect_index(si_shader_ctx, ®->Indirect, reg->Register.Index); + + res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE); + res_ptr = build_indexed_load_const(si_shader_ctx, res_ptr, + ind_index); + } else + res_ptr = si_shader_ctx->resources[inst->Src[1].Register.Index]; if (target == TGSI_TEXTURE_BUFFER) { LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context); LLVMTypeRef v8i32 = LLVMVectorType(i32, 8); /* Read the size from the buffer descriptor directly. */ - LLVMValueRef size = si_shader_ctx->resources[inst->Src[1].Register.Index]; + LLVMValueRef size = res_ptr; size = LLVMBuildBitCast(gallivm->builder, size, v8i32, ""); size = LLVMBuildExtractElement(gallivm->builder, size, - lp_build_const_int32(gallivm, 2), ""); + lp_build_const_int32(gallivm, 6), ""); emit_data->args[0] = size; return; } @@ -2008,7 +2819,7 @@ static void txq_fetch_args( emit_data->args[0] = lp_build_emit_fetch(bld_base, inst, 0, TGSI_CHAN_X); /* Resource */ - emit_data->args[1] = si_shader_ctx->resources[inst->Src[1].Register.Index]; + emit_data->args[1] = res_ptr; /* Texture target */ if (target == TGSI_TEXTURE_CUBE_ARRAY || @@ -2055,6 +2866,35 @@ static void build_txq_intrinsic(const struct lp_build_tgsi_action * action, } } +/* + * SI implements derivatives using the local data store (LDS) + * All writes to the LDS happen in all executing threads at + * the same time. TID is the Thread ID for the current + * thread and is a value between 0 and 63, representing + * the thread's position in the wavefront. + * + * For the pixel shader threads are grouped into quads of four pixels. + * The TIDs of the pixels of a quad are: + * + * +------+------+ + * |4n + 0|4n + 1| + * +------+------+ + * |4n + 2|4n + 3| + * +------+------+ + * + * So, masking the TID with 0xfffffffc yields the TID of the top left pixel + * of the quad, masking with 0xfffffffd yields the TID of the top pixel of + * the current pixel's column, and masking with 0xfffffffe yields the TID + * of the left pixel of the current pixel's row. + * + * Adding 1 yields the TID of the pixel to the right of the left pixel, and + * adding 2 yields the TID of the pixel below the top pixel. + */ +/* masks for thread ID. */ +#define TID_MASK_TOP_LEFT 0xfffffffc +#define TID_MASK_TOP 0xfffffffd +#define TID_MASK_LEFT 0xfffffffe + static void si_llvm_emit_ddxy( const struct lp_build_tgsi_action * action, struct lp_build_tgsi_context * bld_base, @@ -2071,25 +2911,34 @@ static void si_llvm_emit_ddxy( LLVMTypeRef i32; unsigned swizzle[4]; unsigned c; + int idx; + unsigned mask; i32 = LLVMInt32TypeInContext(gallivm->context); indices[0] = bld_base->uint_bld.zero; - indices[1] = build_intrinsic(gallivm->builder, "llvm.SI.tid", i32, + indices[1] = lp_build_intrinsic(gallivm->builder, "llvm.SI.tid", i32, NULL, 0, LLVMReadNoneAttribute); - store_ptr = LLVMBuildGEP(gallivm->builder, si_shader_ctx->ddxy_lds, + store_ptr = LLVMBuildGEP(gallivm->builder, si_shader_ctx->lds, indices, 2, ""); + if (opcode == TGSI_OPCODE_DDX_FINE) + mask = TID_MASK_LEFT; + else if (opcode == TGSI_OPCODE_DDY_FINE) + mask = TID_MASK_TOP; + else + mask = TID_MASK_TOP_LEFT; + indices[1] = LLVMBuildAnd(gallivm->builder, indices[1], - lp_build_const_int32(gallivm, 0xfffffffc), ""); - load_ptr0 = LLVMBuildGEP(gallivm->builder, si_shader_ctx->ddxy_lds, + lp_build_const_int32(gallivm, mask), ""); + load_ptr0 = LLVMBuildGEP(gallivm->builder, si_shader_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; indices[1] = LLVMBuildAdd(gallivm->builder, indices[1], - lp_build_const_int32(gallivm, - opcode == TGSI_OPCODE_DDX ? 1 : 2), - ""); - load_ptr1 = LLVMBuildGEP(gallivm->builder, si_shader_ctx->ddxy_lds, + lp_build_const_int32(gallivm, idx), ""); + load_ptr1 = LLVMBuildGEP(gallivm->builder, si_shader_ctx->lds, indices, 2, ""); for (c = 0; c < 4; ++c) { @@ -2123,6 +2972,247 @@ static void si_llvm_emit_ddxy( emit_data->output[0] = lp_build_gather_values(gallivm, result, 4); } +/* + * this takes an I,J coordinate pair, + * and works out the X and Y derivatives. + * it returns DDX(I), DDX(J), DDY(I), DDY(J). + */ +static LLVMValueRef si_llvm_emit_ddxy_interp( + struct lp_build_tgsi_context *bld_base, + LLVMValueRef interp_ij) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + struct lp_build_context *base = &bld_base->base; + 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]; + LLVMTypeRef i32; + unsigned c; + + i32 = LLVMInt32TypeInContext(gallivm->context); + + indices[0] = bld_base->uint_bld.zero; + indices[1] = lp_build_intrinsic(gallivm->builder, "llvm.SI.tid", i32, + NULL, 0, LLVMReadNoneAttribute); + store_ptr = LLVMBuildGEP(gallivm->builder, si_shader_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, si_shader_ctx->lds, + indices, 2, ""); + + indices[1] = temp2; + load_ptr_y = LLVMBuildGEP(gallivm->builder, si_shader_ctx->lds, + indices, 2, ""); + + indices[1] = LLVMBuildAdd(gallivm->builder, temp, + lp_build_const_int32(gallivm, 1), ""); + load_ptr_ddx = LLVMBuildGEP(gallivm->builder, si_shader_ctx->lds, + indices, 2, ""); + + indices[1] = LLVMBuildAdd(gallivm->builder, temp2, + lp_build_const_int32(gallivm, 2), ""); + load_ptr_ddy = LLVMBuildGEP(gallivm->builder, si_shader_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, base->elem_type, ""); + + tr = LLVMBuildLoad(gallivm->builder, load_ptr_ddx, ""); + tr = LLVMBuildBitCast(gallivm->builder, tr, base->elem_type, ""); + + result[c] = LLVMBuildFSub(gallivm->builder, tr, tl, ""); + + tl = LLVMBuildLoad(gallivm->builder, load_ptr_y, ""); + tl = LLVMBuildBitCast(gallivm->builder, tl, base->elem_type, ""); + + bl = LLVMBuildLoad(gallivm->builder, load_ptr_ddy, ""); + bl = LLVMBuildBitCast(gallivm->builder, bl, base->elem_type, ""); + + result[c + 2] = LLVMBuildFSub(gallivm->builder, bl, tl, ""); + } + + return lp_build_gather_values(gallivm, result, 4); +} + +static void interp_fetch_args( + struct lp_build_tgsi_context *bld_base, + struct lp_build_emit_data *emit_data) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + const struct tgsi_full_instruction *inst = emit_data->inst; + + if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET) { + /* offset is in second src, first two channels */ + emit_data->args[0] = lp_build_emit_fetch(bld_base, + emit_data->inst, 1, + 0); + emit_data->args[1] = lp_build_emit_fetch(bld_base, + emit_data->inst, 1, + 1); + emit_data->arg_count = 2; + } else if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) { + LLVMValueRef sample_position; + LLVMValueRef sample_id; + LLVMValueRef halfval = lp_build_const_float(gallivm, 0.5f); + + /* fetch sample ID, then fetch its sample position, + * and place into first two channels. + */ + sample_id = lp_build_emit_fetch(bld_base, + emit_data->inst, 1, 0); + sample_id = LLVMBuildBitCast(gallivm->builder, sample_id, + LLVMInt32TypeInContext(gallivm->context), + ""); + sample_position = load_sample_position(&si_shader_ctx->radeon_bld, sample_id); + + emit_data->args[0] = LLVMBuildExtractElement(gallivm->builder, + sample_position, + lp_build_const_int32(gallivm, 0), ""); + + emit_data->args[0] = LLVMBuildFSub(gallivm->builder, emit_data->args[0], halfval, ""); + emit_data->args[1] = LLVMBuildExtractElement(gallivm->builder, + sample_position, + lp_build_const_int32(gallivm, 1), ""); + emit_data->args[1] = LLVMBuildFSub(gallivm->builder, emit_data->args[1], halfval, ""); + emit_data->arg_count = 2; + } +} + +static void build_interp_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 *si_shader_ctx = si_shader_context(bld_base); + struct si_shader *shader = si_shader_ctx->shader; + struct gallivm_state *gallivm = bld_base->base.gallivm; + LLVMValueRef interp_param; + const struct tgsi_full_instruction *inst = emit_data->inst; + const char *intr_name; + int input_index; + int chan; + int i; + LLVMValueRef attr_number; + LLVMTypeRef input_type = LLVMFloatTypeInContext(gallivm->context); + LLVMValueRef params = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_PRIM_MASK); + int interp_param_idx; + unsigned location; + + assert(inst->Src[0].Register.File == TGSI_FILE_INPUT); + input_index = inst->Src[0].Register.Index; + + if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET || + inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) + location = TGSI_INTERPOLATE_LOC_CENTER; + else + location = TGSI_INTERPOLATE_LOC_CENTROID; + + interp_param_idx = lookup_interp_param_index(shader->ps_input_interpolate[input_index], + location); + if (interp_param_idx == -1) + return; + else if (interp_param_idx) + interp_param = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, interp_param_idx); + else + interp_param = NULL; + + attr_number = lp_build_const_int32(gallivm, + shader->ps_input_param_offset[input_index]); + + if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET || + inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) { + LLVMValueRef ij_out[2]; + LLVMValueRef ddxy_out = si_llvm_emit_ddxy_interp(bld_base, interp_param); + + /* + * take the I then J parameters, and the DDX/Y for it, and + * calculate the IJ inputs for the interpolator. + * temp1 = ddx * offset/sample.x + I; + * interp_param.I = ddy * offset/sample.y + temp1; + * temp1 = ddx * offset/sample.x + J; + * interp_param.J = ddy * offset/sample.y + temp1; + */ + for (i = 0; i < 2; i++) { + LLVMValueRef ix_ll = lp_build_const_int32(gallivm, i); + LLVMValueRef iy_ll = lp_build_const_int32(gallivm, i + 2); + LLVMValueRef ddx_el = LLVMBuildExtractElement(gallivm->builder, + ddxy_out, ix_ll, ""); + LLVMValueRef ddy_el = LLVMBuildExtractElement(gallivm->builder, + ddxy_out, iy_ll, ""); + LLVMValueRef interp_el = LLVMBuildExtractElement(gallivm->builder, + interp_param, ix_ll, ""); + LLVMValueRef temp1, temp2; + + interp_el = LLVMBuildBitCast(gallivm->builder, interp_el, + LLVMFloatTypeInContext(gallivm->context), ""); + + temp1 = LLVMBuildFMul(gallivm->builder, ddx_el, emit_data->args[0], ""); + + temp1 = LLVMBuildFAdd(gallivm->builder, temp1, interp_el, ""); + + temp2 = LLVMBuildFMul(gallivm->builder, ddy_el, emit_data->args[1], ""); + + temp2 = LLVMBuildFAdd(gallivm->builder, temp2, temp1, ""); + + ij_out[i] = LLVMBuildBitCast(gallivm->builder, + temp2, + LLVMIntTypeInContext(gallivm->context, 32), ""); + } + interp_param = lp_build_gather_values(bld_base->base.gallivm, ij_out, 2); + } + + intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant"; + for (chan = 0; chan < 2; chan++) { + LLVMValueRef args[4]; + LLVMValueRef llvm_chan; + unsigned schan; + + schan = tgsi_util_get_full_src_register_swizzle(&inst->Src[0], chan); + llvm_chan = lp_build_const_int32(gallivm, schan); + + args[0] = llvm_chan; + args[1] = attr_number; + args[2] = params; + args[3] = interp_param; + + emit_data->output[chan] = + lp_build_intrinsic(gallivm->builder, intr_name, + input_type, args, args[3] ? 4 : 3, + LLVMReadNoneAttribute | LLVMNoUnwindAttribute); + } +} + +static unsigned si_llvm_get_stream(struct lp_build_tgsi_context *bld_base, + struct lp_build_emit_data *emit_data) +{ + LLVMValueRef (*imms)[4] = lp_soa_context(bld_base)->immediates; + struct tgsi_src_register src0 = emit_data->inst->Src[0].Register; + unsigned stream; + + assert(src0.File == TGSI_FILE_IMMEDIATE); + + stream = LLVMConstIntGetZExtValue(imms[src0.Index][src0.SwizzleX]) & 0x3; + return stream; +} + /* Emit one vertex from the geometry shader */ static void si_llvm_emit_vertex( const struct lp_build_tgsi_action *action, @@ -2142,9 +3232,14 @@ static void si_llvm_emit_vertex( LLVMValueRef args[2]; unsigned chan; int i; + unsigned stream; + + stream = si_llvm_get_stream(bld_base, emit_data); /* Write vertex attribute values to GSVS ring */ - gs_next_vertex = LLVMBuildLoad(gallivm->builder, si_shader_ctx->gs_next_vertex, ""); + gs_next_vertex = LLVMBuildLoad(gallivm->builder, + si_shader_ctx->gs_next_vertex[stream], + ""); /* If this thread has already emitted the declared maximum number of * vertices, kill it: excessive vertex emissions are not supposed to @@ -2157,8 +3252,9 @@ static void si_llvm_emit_vertex( kill = lp_build_select(&bld_base->base, can_emit, lp_build_const_float(gallivm, 1.0f), lp_build_const_float(gallivm, -1.0f)); - build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill", - LLVMVoidTypeInContext(gallivm->context), &kill, 1, 0); + + lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill", + LLVMVoidTypeInContext(gallivm->context), &kill, 1, 0); for (i = 0; i < info->num_outputs; i++) { LLVMValueRef *out_ptr = @@ -2176,7 +3272,7 @@ static void si_llvm_emit_vertex( out_val = LLVMBuildBitCast(gallivm->builder, out_val, i32, ""); build_tbuffer_store(si_shader_ctx, - si_shader_ctx->gsvs_ring, + si_shader_ctx->gsvs_ring[stream], out_val, 1, voffset, soffset, 0, V_008F0C_BUF_DATA_FORMAT_32, @@ -2186,12 +3282,13 @@ static void si_llvm_emit_vertex( } gs_next_vertex = lp_build_add(uint, gs_next_vertex, lp_build_const_int32(gallivm, 1)); - LLVMBuildStore(gallivm->builder, gs_next_vertex, si_shader_ctx->gs_next_vertex); + + LLVMBuildStore(gallivm->builder, gs_next_vertex, si_shader_ctx->gs_next_vertex[stream]); /* Signal vertex emission */ - args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_EMIT | SENDMSG_GS); + args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_EMIT | SENDMSG_GS | (stream << 8)); args[1] = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_GS_WAVE_ID); - build_intrinsic(gallivm->builder, "llvm.SI.sendmsg", + lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg", LLVMVoidTypeInContext(gallivm->context), args, 2, LLVMNoUnwindAttribute); } @@ -2205,15 +3302,28 @@ static void si_llvm_emit_primitive( struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMValueRef args[2]; + unsigned stream; /* Signal primitive cut */ - args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_CUT | SENDMSG_GS); + stream = si_llvm_get_stream(bld_base, emit_data); + args[0] = lp_build_const_int32(gallivm, SENDMSG_GS_OP_CUT | SENDMSG_GS | (stream << 8)); args[1] = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_GS_WAVE_ID); - build_intrinsic(gallivm->builder, "llvm.SI.sendmsg", + lp_build_intrinsic(gallivm->builder, "llvm.SI.sendmsg", LLVMVoidTypeInContext(gallivm->context), args, 2, LLVMNoUnwindAttribute); } +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) +{ + struct gallivm_state *gallivm = bld_base->base.gallivm; + + lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.barrier.local", + LLVMVoidTypeInContext(gallivm->context), NULL, 0, + LLVMNoUnwindAttribute); +} + static const struct lp_build_tgsi_action tex_action = { .fetch_args = tex_fetch_args, .emit = build_tex_intrinsic, @@ -2225,6 +3335,11 @@ static const struct lp_build_tgsi_action txq_action = { .intr_name = "llvm.SI.resinfo" }; +static const struct lp_build_tgsi_action interp_action = { + .fetch_args = interp_fetch_args, + .emit = build_interp_intrinsic, +}; + static void create_meta_data(struct si_shader_context *si_shader_ctx) { struct gallivm_state *gallivm = si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm; @@ -2243,6 +3358,27 @@ static LLVMTypeRef const_array(LLVMTypeRef elem_type, int num_elements) CONST_ADDR_SPACE); } +static void declare_streamout_params(struct si_shader_context *si_shader_ctx, + struct pipe_stream_output_info *so, + LLVMTypeRef *params, LLVMTypeRef i32, + unsigned *num_params) +{ + int i; + + /* Streamout SGPRs. */ + if (so->num_outputs) { + params[si_shader_ctx->param_streamout_config = (*num_params)++] = i32; + params[si_shader_ctx->param_streamout_write_index = (*num_params)++] = i32; + } + /* A streamout buffer offset is loaded if the stride is non-zero. */ + for (i = 0; i < 4; i++) { + if (!so->stride[i]) + continue; + + params[si_shader_ctx->param_streamout_offset[i] = (*num_params)++] = i32; + } +} + static void create_function(struct si_shader_context *si_shader_ctx) { struct lp_build_tgsi_context *bld_base = &si_shader_ctx->radeon_bld.soa.bld_base; @@ -2275,8 +3411,10 @@ static void create_function(struct si_shader_context *si_shader_ctx) num_params = SI_PARAM_START_INSTANCE+1; if (shader->key.vs.as_es) { - params[SI_PARAM_ES2GS_OFFSET] = i32; - num_params++; + params[si_shader_ctx->param_es2gs_offset = num_params++] = i32; + } else if (shader->key.vs.as_ls) { + params[SI_PARAM_LS_OUT_LAYOUT] = i32; + num_params = SI_PARAM_LS_OUT_LAYOUT+1; } else { if (shader->is_gs_copy_shader) { last_array_pointer = SI_PARAM_CONST; @@ -2284,30 +3422,52 @@ static void create_function(struct si_shader_context *si_shader_ctx) } /* The locations of the other parameters are assigned dynamically. */ - - /* Streamout SGPRs. */ - if (shader->selector->so.num_outputs) { - params[si_shader_ctx->param_streamout_config = num_params++] = i32; - params[si_shader_ctx->param_streamout_write_index = num_params++] = i32; - } - /* A streamout buffer offset is loaded if the stride is non-zero. */ - for (i = 0; i < 4; i++) { - if (!shader->selector->so.stride[i]) - continue; - - params[si_shader_ctx->param_streamout_offset[i] = num_params++] = i32; - } + declare_streamout_params(si_shader_ctx, &shader->selector->so, + params, i32, &num_params); } last_sgpr = num_params-1; /* VGPRs */ params[si_shader_ctx->param_vertex_id = num_params++] = i32; - params[num_params++] = i32; /* unused*/ - params[num_params++] = i32; /* unused */ + params[si_shader_ctx->param_rel_auto_id = num_params++] = i32; + params[si_shader_ctx->param_vs_prim_id = num_params++] = i32; params[si_shader_ctx->param_instance_id = num_params++] = i32; break; + case TGSI_PROCESSOR_TESS_CTRL: + params[SI_PARAM_TCS_OUT_OFFSETS] = i32; + params[SI_PARAM_TCS_OUT_LAYOUT] = i32; + params[SI_PARAM_TCS_IN_LAYOUT] = i32; + params[SI_PARAM_TESS_FACTOR_OFFSET] = i32; + last_sgpr = SI_PARAM_TESS_FACTOR_OFFSET; + + /* VGPRs */ + params[SI_PARAM_PATCH_ID] = i32; + params[SI_PARAM_REL_IDS] = i32; + num_params = SI_PARAM_REL_IDS+1; + break; + + case TGSI_PROCESSOR_TESS_EVAL: + params[SI_PARAM_TCS_OUT_OFFSETS] = i32; + params[SI_PARAM_TCS_OUT_LAYOUT] = i32; + num_params = SI_PARAM_TCS_OUT_LAYOUT+1; + + if (shader->key.tes.as_es) { + params[si_shader_ctx->param_es2gs_offset = num_params++] = i32; + } else { + declare_streamout_params(si_shader_ctx, &shader->selector->so, + params, i32, &num_params); + } + last_sgpr = num_params - 1; + + /* VGPRs */ + params[si_shader_ctx->param_tes_u = num_params++] = f32; + params[si_shader_ctx->param_tes_v = num_params++] = f32; + params[si_shader_ctx->param_tes_rel_patch_id = num_params++] = i32; + params[si_shader_ctx->param_tes_patch_id = num_params++] = i32; + break; + case TGSI_PROCESSOR_GEOMETRY: params[SI_PARAM_GS2VS_OFFSET] = i32; params[SI_PARAM_GS_WAVE_ID] = i32; @@ -2357,6 +3517,10 @@ static void create_function(struct si_shader_context *si_shader_ctx) radeon_llvm_create_func(&si_shader_ctx->radeon_bld, params, num_params); radeon_llvm_shader_type(si_shader_ctx->radeon_bld.main_fn, si_shader_ctx->type); + if (shader->dx10_clamp_mode) + LLVMAddTargetDependentFunctionAttr(si_shader_ctx->radeon_bld.main_fn, + "enable-no-nans-fp-math", "true"); + for (i = 0; i <= last_sgpr; ++i) { LLVMValueRef P = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, i); @@ -2370,12 +3534,35 @@ static void create_function(struct si_shader_context *si_shader_ctx) if (bld_base->info && (bld_base->info->opcode_count[TGSI_OPCODE_DDX] > 0 || - bld_base->info->opcode_count[TGSI_OPCODE_DDY] > 0)) - si_shader_ctx->ddxy_lds = + bld_base->info->opcode_count[TGSI_OPCODE_DDY] > 0 || + bld_base->info->opcode_count[TGSI_OPCODE_DDX_FINE] > 0 || + bld_base->info->opcode_count[TGSI_OPCODE_DDY_FINE] > 0 || + bld_base->info->opcode_count[TGSI_OPCODE_INTERP_OFFSET] > 0 || + bld_base->info->opcode_count[TGSI_OPCODE_INTERP_SAMPLE] > 0)) + si_shader_ctx->lds = LLVMAddGlobalInAddressSpace(gallivm->module, LLVMArrayType(i32, 64), "ddxy_lds", LOCAL_ADDR_SPACE); + + if ((si_shader_ctx->type == TGSI_PROCESSOR_VERTEX && shader->key.vs.as_ls) || + si_shader_ctx->type == TGSI_PROCESSOR_TESS_CTRL || + si_shader_ctx->type == TGSI_PROCESSOR_TESS_EVAL) { + /* 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; + + /* The actual size is computed outside of the shader to reduce + * the number of shader variants. */ + si_shader_ctx->lds = + LLVMAddGlobalInAddressSpace(gallivm->module, + LLVMArrayType(i32, lds_dwords), + "tess_lds", + LOCAL_ADDR_SPACE); + } } static void preload_constants(struct si_shader_context *si_shader_ctx) @@ -2452,9 +3639,13 @@ static void preload_streamout_buffers(struct si_shader_context *si_shader_ctx) struct gallivm_state * gallivm = bld_base->base.gallivm; unsigned i; - if (si_shader_ctx->type != TGSI_PROCESSOR_VERTEX || - si_shader_ctx->shader->key.vs.as_es || - !si_shader_ctx->shader->selector->so.num_outputs) + /* Streamout can only be used if the shader is compiled as VS. */ + if (!si_shader_ctx->shader->selector->so.num_outputs || + (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX && + (si_shader_ctx->shader->key.vs.as_es || + si_shader_ctx->shader->key.vs.as_ls)) || + (si_shader_ctx->type == TGSI_PROCESSOR_TESS_EVAL && + si_shader_ctx->shader->key.tes.as_es)) return; LLVMValueRef buf_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, @@ -2485,6 +3676,8 @@ static void preload_ring_buffers(struct si_shader_context *si_shader_ctx) if ((si_shader_ctx->type == TGSI_PROCESSOR_VERTEX && si_shader_ctx->shader->key.vs.as_es) || + (si_shader_ctx->type == TGSI_PROCESSOR_TESS_EVAL && + si_shader_ctx->shader->key.tes.as_es) || si_shader_ctx->type == TGSI_PROCESSOR_GEOMETRY) { LLVMValueRef offset = lp_build_const_int32(gallivm, SI_RING_ESGS); @@ -2492,28 +3685,37 @@ static void preload_ring_buffers(struct si_shader_context *si_shader_ctx) build_indexed_load_const(si_shader_ctx, buf_ptr, offset); } - if (si_shader_ctx->type == TGSI_PROCESSOR_GEOMETRY || - si_shader_ctx->shader->is_gs_copy_shader) { + if (si_shader_ctx->shader->is_gs_copy_shader) { LLVMValueRef offset = lp_build_const_int32(gallivm, SI_RING_GSVS); - si_shader_ctx->gsvs_ring = + si_shader_ctx->gsvs_ring[0] = build_indexed_load_const(si_shader_ctx, buf_ptr, offset); } + if (si_shader_ctx->type == TGSI_PROCESSOR_GEOMETRY) { + int i; + for (i = 0; i < 4; i++) { + LLVMValueRef offset = lp_build_const_int32(gallivm, SI_RING_GSVS + i); + + si_shader_ctx->gsvs_ring[i] = + build_indexed_load_const(si_shader_ctx, buf_ptr, offset); + } + } } -void si_shader_binary_read_config(const struct radeon_shader_binary *binary, +void si_shader_binary_read_config(const struct si_screen *sscreen, struct si_shader *shader, unsigned symbol_offset) { unsigned i; const unsigned char *config = - radeon_shader_binary_config_start(binary, symbol_offset); + radeon_shader_binary_config_start(&shader->binary, + symbol_offset); /* XXX: We may be able to emit some of these values directly rather than * extracting fields to be emitted later. */ - for (i = 0; i < binary->config_size_per_symbol; i+= 8) { + for (i = 0; i < shader->binary.config_size_per_symbol; i+= 8) { unsigned reg = util_le32_to_cpu(*(uint32_t*)(config + i)); unsigned value = util_le32_to_cpu(*(uint32_t*)(config + i + 4)); switch (reg) { @@ -2523,6 +3725,7 @@ void si_shader_binary_read_config(const struct radeon_shader_binary *binary, case R_00B848_COMPUTE_PGM_RSRC1: shader->num_sgprs = MAX2(shader->num_sgprs, (G_00B028_SGPRS(value) + 1) * 8); shader->num_vgprs = MAX2(shader->num_vgprs, (G_00B028_VGPRS(value) + 1) * 4); + shader->float_mode = G_00B028_FLOAT_MODE(value); break; case R_00B02C_SPI_SHADER_PGM_RSRC2_PS: shader->lds_size = MAX2(shader->lds_size, G_00B02C_EXTRA_LDS_SIZE(value)); @@ -2533,6 +3736,7 @@ void si_shader_binary_read_config(const struct radeon_shader_binary *binary, case R_0286CC_SPI_PS_INPUT_ENA: shader->spi_ps_input_ena = value; break; + case R_0286E8_SPI_TMPRING_SIZE: case R_00B860_COMPUTE_TMPRING_SIZE: /* WAVESIZE is in units of 256 dwords. */ shader->scratch_bytes_per_wave = @@ -2546,68 +3750,113 @@ void si_shader_binary_read_config(const struct radeon_shader_binary *binary, } } -int si_shader_binary_read(struct si_screen *sscreen, +void si_shader_apply_scratch_relocs(struct si_context *sctx, struct si_shader *shader, - const struct radeon_shader_binary *binary) + uint64_t scratch_va) { - unsigned i; - unsigned code_size; - unsigned char *ptr; - bool dump = r600_can_dump_shader(&sscreen->b, - shader->selector ? shader->selector->tokens : NULL); - - if (dump && !binary->disassembled) { - fprintf(stderr, "SI CODE:\n"); - for (i = 0; i < binary->code_size; i+=4 ) { - fprintf(stderr, "@0x%x: %02x%02x%02x%02x\n", i, binary->code[i + 3], - binary->code[i + 2], binary->code[i + 1], - binary->code[i]); + uint32_t scratch_rsrc_dword0 = scratch_va & 0xffffffff; + uint32_t scratch_rsrc_dword1 = + S_008F04_BASE_ADDRESS_HI(scratch_va >> 32) + | S_008F04_STRIDE(shader->scratch_bytes_per_wave / 64); + + for (i = 0 ; i < shader->binary.reloc_count; i++) { + const struct radeon_shader_reloc *reloc = + &shader->binary.relocs[i]; + if (!strcmp(scratch_rsrc_dword0_symbol, reloc->name)) { + util_memcpy_cpu_to_le32(shader->binary.code + reloc->offset, + &scratch_rsrc_dword0, 4); + } else if (!strcmp(scratch_rsrc_dword1_symbol, reloc->name)) { + util_memcpy_cpu_to_le32(shader->binary.code + reloc->offset, + &scratch_rsrc_dword1, 4); } } +} - si_shader_binary_read_config(binary, shader, 0); +int si_shader_binary_upload(struct si_screen *sscreen, struct si_shader *shader) +{ + const struct radeon_shader_binary *binary = &shader->binary; + unsigned code_size = binary->code_size + binary->rodata_size; + unsigned char *ptr; - /* copy new shader */ - code_size = binary->code_size + binary->rodata_size; r600_resource_reference(&shader->bo, NULL); - shader->bo = si_resource_create_custom(&sscreen->b.b, PIPE_USAGE_IMMUTABLE, + shader->bo = si_resource_create_custom(&sscreen->b.b, + PIPE_USAGE_IMMUTABLE, code_size); - if (shader->bo == NULL) { + if (!shader->bo) return -ENOMEM; - } - - ptr = sscreen->b.ws->buffer_map(shader->bo->cs_buf, NULL, PIPE_TRANSFER_READ_WRITE); + ptr = sscreen->b.ws->buffer_map(shader->bo->cs_buf, NULL, + PIPE_TRANSFER_READ_WRITE); util_memcpy_cpu_to_le32(ptr, binary->code, binary->code_size); if (binary->rodata_size > 0) { ptr += binary->code_size; - util_memcpy_cpu_to_le32(ptr, binary->rodata, binary->rodata_size); + util_memcpy_cpu_to_le32(ptr, binary->rodata, + binary->rodata_size); } sscreen->b.ws->buffer_unmap(shader->bo->cs_buf); + return 0; +} + +int si_shader_binary_read(struct si_screen *sscreen, struct si_shader *shader) +{ + const struct radeon_shader_binary *binary = &shader->binary; + unsigned i; + bool dump = r600_can_dump_shader(&sscreen->b, + shader->selector ? shader->selector->tokens : NULL); + si_shader_binary_read_config(sscreen, shader, 0); + si_shader_binary_upload(sscreen, shader); + + if (dump) { + if (!(sscreen->b.debug_flags & DBG_NO_ASM)) { + if (binary->disasm_string) { + fprintf(stderr, "\nShader Disassembly:\n\n"); + fprintf(stderr, "%s\n", binary->disasm_string); + } else { + fprintf(stderr, "SI CODE:\n"); + for (i = 0; i < binary->code_size; i+=4 ) { + fprintf(stderr, "@0x%x: %02x%02x%02x%02x\n", i, binary->code[i + 3], + binary->code[i + 2], binary->code[i + 1], + binary->code[i]); + } + } + } + + fprintf(stderr, "*** SHADER STATS ***\n" + "SGPRS: %d\nVGPRS: %d\nCode Size: %d bytes\nLDS: %d blocks\n" + "Scratch: %d bytes per wave\n********************\n", + shader->num_sgprs, shader->num_vgprs, binary->code_size, + shader->lds_size, shader->scratch_bytes_per_wave); + } return 0; } int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, - LLVMModuleRef mod) + LLVMTargetMachineRef tm, LLVMModuleRef mod) { int r = 0; - struct radeon_shader_binary binary; - bool dump = r600_can_dump_shader(&sscreen->b, - shader->selector ? shader->selector->tokens : NULL); - memset(&binary, 0, sizeof(binary)); - r = radeon_llvm_compile(mod, &binary, - r600_get_llvm_processor_name(sscreen->b.family), dump); + bool dump_asm = r600_can_dump_shader(&sscreen->b, + shader->selector ? shader->selector->tokens : NULL); + bool dump_ir = dump_asm && !(sscreen->b.debug_flags & DBG_NO_IR); - if (r) { + r = radeon_llvm_compile(mod, &shader->binary, + r600_get_llvm_processor_name(sscreen->b.family), dump_ir, dump_asm, tm); + if (r) return r; + + r = si_shader_binary_read(sscreen, shader); + + FREE(shader->binary.config); + FREE(shader->binary.rodata); + FREE(shader->binary.global_symbol_offsets); + if (shader->scratch_bytes_per_wave == 0) { + FREE(shader->binary.code); + FREE(shader->binary.relocs); + memset(&shader->binary, 0, + offsetof(struct radeon_shader_binary, disasm_string)); } - r = si_shader_binary_read(sscreen, shader, &binary); - FREE(binary.code); - FREE(binary.config); - FREE(binary.rodata); return r; } @@ -2638,7 +3887,7 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, preload_streamout_buffers(si_shader_ctx); preload_ring_buffers(si_shader_ctx); - args[0] = si_shader_ctx->gsvs_ring; + args[0] = si_shader_ctx->gsvs_ring[0]; args[1] = lp_build_mul_imm(uint, LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, si_shader_ctx->param_vertex_id), @@ -2664,7 +3913,7 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, outputs[i].values[chan] = LLVMBuildBitCast(gallivm->builder, - build_intrinsic(gallivm->builder, + lp_build_intrinsic(gallivm->builder, "llvm.SI.buffer.load.dword.i32.i32", LLVMInt32TypeInContext(gallivm->context), args, 9, @@ -2681,7 +3930,7 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, fprintf(stderr, "Copy Vertex Shader for Geometry Shader:\n\n"); r = si_compile_llvm(sscreen, si_shader_ctx->shader, - bld_base->base.gallivm->module); + si_shader_ctx->tm, bld_base->base.gallivm->module); radeon_llvm_dispose(&si_shader_ctx->radeon_bld); @@ -2689,19 +3938,80 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, return r; } -int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) +static void si_dump_key(unsigned shader, union si_shader_key *key) +{ + int i; + + fprintf(stderr, "SHADER KEY\n"); + + switch (shader) { + case PIPE_SHADER_VERTEX: + fprintf(stderr, " instance_divisors = {"); + for (i = 0; i < Elements(key->vs.instance_divisors); i++) + fprintf(stderr, !i ? "%u" : ", %u", + key->vs.instance_divisors[i]); + fprintf(stderr, "}\n"); + + if (key->vs.as_es) + fprintf(stderr, " es_enabled_outputs = 0x%"PRIx64"\n", + key->vs.es_enabled_outputs); + fprintf(stderr, " as_es = %u\n", key->vs.as_es); + fprintf(stderr, " as_es = %u\n", key->vs.as_ls); + break; + + case PIPE_SHADER_TESS_CTRL: + fprintf(stderr, " prim_mode = %u\n", key->tcs.prim_mode); + break; + + case PIPE_SHADER_TESS_EVAL: + if (key->tes.as_es) + fprintf(stderr, " es_enabled_outputs = 0x%"PRIx64"\n", + key->tes.es_enabled_outputs); + fprintf(stderr, " as_es = %u\n", key->tes.as_es); + break; + + case PIPE_SHADER_GEOMETRY: + break; + + case PIPE_SHADER_FRAGMENT: + fprintf(stderr, " export_16bpc = 0x%X\n", key->ps.export_16bpc); + fprintf(stderr, " last_cbuf = %u\n", key->ps.last_cbuf); + fprintf(stderr, " color_two_side = %u\n", key->ps.color_two_side); + fprintf(stderr, " alpha_func = %u\n", key->ps.alpha_func); + fprintf(stderr, " alpha_to_one = %u\n", key->ps.alpha_to_one); + fprintf(stderr, " poly_stipple = %u\n", key->ps.poly_stipple); + break; + + default: + assert(0); + } +} + +int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, + struct si_shader *shader) { struct si_shader_selector *sel = shader->selector; + struct tgsi_token *tokens = sel->tokens; struct si_shader_context si_shader_ctx; struct lp_build_tgsi_context * bld_base; + struct tgsi_shader_info stipple_shader_info; LLVMModuleRef mod; int r = 0; + bool poly_stipple = sel->type == PIPE_SHADER_FRAGMENT && + shader->key.ps.poly_stipple; bool dump = r600_can_dump_shader(&sscreen->b, sel->tokens); + if (poly_stipple) { + tokens = util_pstipple_create_fragment_shader(tokens, NULL, + SI_POLY_STIPPLE_SAMPLER); + tgsi_scan_shader(tokens, &stipple_shader_info); + } + /* Dump TGSI code before doing TGSI->LLVM conversion in case the * conversion fails. */ - if (dump) { - tgsi_dump(sel->tokens, 0); + if (dump && !(sscreen->b.debug_flags & DBG_NO_TGSI)) { + si_dump_key(sel->type, &shader->key); + tgsi_dump(tokens, 0); si_dump_streamout(&sel->so); } @@ -2711,13 +4021,20 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) radeon_llvm_context_init(&si_shader_ctx.radeon_bld); bld_base = &si_shader_ctx.radeon_bld.soa.bld_base; + if (sel->type != PIPE_SHADER_COMPUTE) + shader->dx10_clamp_mode = true; + if (sel->info.uses_kill) shader->db_shader_control |= S_02880C_KILL_ENABLE(1); shader->uses_instanceid = sel->info.uses_instanceid; - bld_base->info = &sel->info; + bld_base->info = poly_stipple ? &stipple_shader_info : &sel->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_INTERP_SAMPLE] = interp_action; + bld_base->op_actions[TGSI_OPCODE_INTERP_OFFSET] = interp_action; + bld_base->op_actions[TGSI_OPCODE_TEX] = tex_action; bld_base->op_actions[TGSI_OPCODE_TEX2] = tex_action; bld_base->op_actions[TGSI_OPCODE_TXB] = tex_action; @@ -2733,9 +4050,12 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) bld_base->op_actions[TGSI_OPCODE_DDX].emit = si_llvm_emit_ddxy; bld_base->op_actions[TGSI_OPCODE_DDY].emit = si_llvm_emit_ddxy; + bld_base->op_actions[TGSI_OPCODE_DDX_FINE].emit = si_llvm_emit_ddxy; + bld_base->op_actions[TGSI_OPCODE_DDY_FINE].emit = si_llvm_emit_ddxy; bld_base->op_actions[TGSI_OPCODE_EMIT].emit = si_llvm_emit_vertex; bld_base->op_actions[TGSI_OPCODE_ENDPRIM].emit = si_llvm_emit_primitive; + bld_base->op_actions[TGSI_OPCODE_BARRIER].emit = si_llvm_emit_barrier; if (HAVE_LLVM >= 0x0306) { bld_base->op_actions[TGSI_OPCODE_MAX].emit = build_tgsi_intrinsic_nomem; @@ -2745,19 +4065,33 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) } si_shader_ctx.radeon_bld.load_system_value = declare_system_value; - si_shader_ctx.tokens = sel->tokens; - tgsi_parse_init(&si_shader_ctx.parse, si_shader_ctx.tokens); si_shader_ctx.shader = shader; - si_shader_ctx.type = si_shader_ctx.parse.FullHeader.Processor.Processor; + si_shader_ctx.type = tgsi_get_processor_type(tokens); + si_shader_ctx.screen = sscreen; + si_shader_ctx.tm = tm; switch (si_shader_ctx.type) { case TGSI_PROCESSOR_VERTEX: si_shader_ctx.radeon_bld.load_input = declare_input_vs; - if (shader->key.vs.as_es) { + if (shader->key.vs.as_ls) + bld_base->emit_epilogue = si_llvm_emit_ls_epilogue; + else if (shader->key.vs.as_es) bld_base->emit_epilogue = si_llvm_emit_es_epilogue; - } else { + else + bld_base->emit_epilogue = si_llvm_emit_vs_epilogue; + break; + case TGSI_PROCESSOR_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: + 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: bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_gs; @@ -2791,12 +4125,15 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) preload_ring_buffers(&si_shader_ctx); if (si_shader_ctx.type == TGSI_PROCESSOR_GEOMETRY) { - si_shader_ctx.gs_next_vertex = - lp_build_alloca(bld_base->base.gallivm, - bld_base->uint_bld.elem_type, ""); + int i; + for (i = 0; i < 4; i++) { + si_shader_ctx.gs_next_vertex[i] = + lp_build_alloca(bld_base->base.gallivm, + bld_base->uint_bld.elem_type, ""); + } } - if (!lp_build_tgsi_llvm(bld_base, sel->tokens)) { + if (!lp_build_tgsi_llvm(bld_base, tokens)) { fprintf(stderr, "Failed to translate shader from TGSI to LLVM\n"); goto out; } @@ -2804,7 +4141,7 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) radeon_llvm_finalize_module(&si_shader_ctx.radeon_bld); mod = bld_base->base.gallivm->module; - r = si_compile_llvm(sscreen, shader, mod); + r = si_compile_llvm(sscreen, shader, tm, mod); if (r) { fprintf(stderr, "LLVM failed to compile shader\n"); goto out; @@ -2825,12 +4162,11 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) } } - tgsi_parse_free(&si_shader_ctx.parse); - out: for (int i = 0; i < SI_NUM_CONST_BUFFERS; i++) FREE(si_shader_ctx.constants[i]); - + if (poly_stipple) + tgsi_free_tokens(tokens); return r; } @@ -2839,6 +4175,12 @@ void si_shader_destroy(struct pipe_context *ctx, struct si_shader *shader) if (shader->gs_copy_shader) si_shader_destroy(ctx, shader->gs_copy_shader); + if (shader->scratch_bo) + r600_resource_reference(&shader->scratch_bo, NULL); + r600_resource_reference(&shader->bo, NULL); - r600_resource_reference(&shader->scratch_bo, NULL); + + FREE(shader->binary.code); + FREE(shader->binary.relocs); + FREE(shader->binary.disasm_string); }