X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fradeonsi%2Fsi_shader.c;h=61d36430bcf2b5448038a94d34eac06420a278e5;hb=8e11be0ddb0920633c5fab8d6a6460b7591a2627;hp=e76b969df87653bd1969f2aae3d5a74c0a043dcb;hpb=8860584045f8c534264f9d456bfafdb545d81437;p=mesa.git diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index e76b969df87..61d36430bcf 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -31,10 +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" @@ -45,35 +49,47 @@ #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]; unsigned name; - unsigned index; unsigned sid; - unsigned usage; }; 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_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; - LLVMValueRef *samplers; + LLVMValueRef resources[SI_NUM_SAMPLER_VIEWS]; + LLVMValueRef samplers[SI_NUM_SAMPLER_STATES]; LLVMValueRef so_buffers[4]; - LLVMValueRef gs_next_vertex; + LLVMValueRef esgs_ring; + LLVMValueRef gsvs_ring[4]; + LLVMValueRef gs_next_vertex[4]; }; static struct si_shader_context * si_shader_context( @@ -109,7 +125,7 @@ static struct si_shader_context * si_shader_context( * less than 64, so that a 64-bit bitmask of used inputs or outputs can be * calculated. */ -static unsigned get_unique_index(unsigned semantic_name, unsigned index) +unsigned si_shader_io_get_unique_index(unsigned semantic_name, unsigned index) { switch (semantic_name) { case TGSI_SEMANTIC_POSITION: @@ -119,24 +135,30 @@ static unsigned 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; } } @@ -160,7 +182,7 @@ static unsigned get_unique_index(unsigned semantic_name, unsigned index) static int get_param_index(unsigned semantic_name, unsigned index, uint64_t mask) { - unsigned unique_index = get_unique_index(semantic_name, index); + unsigned unique_index = si_shader_io_get_unique_index(semantic_name, index); int i, param_index = 0; /* If not present... */ @@ -184,32 +206,189 @@ static int get_param_index(unsigned semantic_name, unsigned index, } /** - * Build an LLVM bytecode indexed load using LLVMBuildGEP + LLVMBuildLoad + * 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. * - * @param offset The offset parameter specifies the number of - * elements to offset, not the number of bytes or dwords. An element is the - * the type pointed to by the base_ptr parameter (e.g. int is the element of - * an int* pointer) + * LS outputs = TCS inputs + * TCS outputs = TES inputs * - * When LLVM lowers the load instruction, it will convert the element offset - * into a dword offset automatically. + * 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 build_indexed_load( - struct si_shader_context * si_shader_ctx, - LLVMValueRef base_ptr, - LLVMValueRef offset) + +static LLVMValueRef +get_tcs_in_patch_stride(struct si_shader_context *si_shader_ctx) { - struct lp_build_context * base = &si_shader_ctx->radeon_bld.soa.bld_base.base; + 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; + } +} - LLVMValueRef indices[2] = { - LLVMConstInt(LLVMInt64TypeInContext(base->gallivm->context), 0, false), - offset - }; - LLVMValueRef computed_ptr = LLVMBuildGEP( - base->gallivm->builder, base_ptr, indices, 2, ""); +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, ""), + ""); +} - LLVMValueRef result = LLVMBuildLoad(base->gallivm->builder, computed_ptr, ""); +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]. + * + * \param base_ptr Where the array starts. + * \param index The element index into the array. + */ +static LLVMValueRef build_indexed_load(struct si_shader_context *si_shader_ctx, + LLVMValueRef base_ptr, LLVMValueRef index) +{ + 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, ""); + return LLVMBuildLoad(gallivm->builder, pointer, ""); +} + +/** + * Do a load from &base_ptr[index], but also add a flag that it's loading + * a constant. + */ +static LLVMValueRef build_indexed_load_const( + struct si_shader_context * si_shader_ctx, + LLVMValueRef base_ptr, LLVMValueRef index) +{ + LLVMValueRef result = build_indexed_load(si_shader_ctx, base_ptr, index); LLVMSetMetadata(result, 1, si_shader_ctx->const_md); return result; } @@ -224,43 +403,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; -} - -static int si_store_shader_io_attribs(struct si_shader *shader, - const struct tgsi_full_declaration *d) -{ - int i = -1; - - switch (d->Declaration.File) { - case TGSI_FILE_INPUT: - i = shader->ninput++; - assert(i < Elements(shader->input)); - shader->input[i].name = d->Semantic.Name; - shader->input[i].sid = d->Semantic.Index; - shader->input[i].index = d->Range.First; - shader->input[i].interpolate = d->Interp.Interpolate; - shader->input[i].centroid = d->Interp.Location == TGSI_INTERPOLATE_LOC_CENTROID; - return -1; - - case TGSI_FILE_OUTPUT: - i = shader->noutput++; - assert(i < Elements(shader->output)); - shader->output[i].name = d->Semantic.Name; - shader->output[i].sid = d->Semantic.Index; - shader->output[i].index = d->Range.First; - shader->output[i].usage = d->Declaration.UsageMask; - break; - } - - return i; + return LLVMBuildAdd(gallivm->builder, result, LLVMGetParam( + radeon_bld->main_fn, SI_PARAM_START_INSTANCE), ""); } static void declare_input_vs( @@ -290,7 +440,7 @@ static void declare_input_vs( t_offset = lp_build_const_int32(gallivm, input_index); - t_list = build_indexed_load(si_shader_ctx, t_list_ptr, t_offset); + t_list = build_indexed_load_const(si_shader_ctx, t_list_ptr, t_offset); /* Build the attribute offset */ attribute_offset = lp_build_const_int32(gallivm, 0); @@ -312,7 +462,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); @@ -327,22 +477,279 @@ static void declare_input_vs( } } -static void declare_input_gs( - struct radeon_llvm_context *radeon_bld, - unsigned input_index, - const struct tgsi_full_declaration *decl) +static LLVMValueRef get_primitive_id(struct lp_build_tgsi_context *bld_base, + unsigned swizzle) { - struct si_shader_context *si_shader_ctx = - si_shader_context(&radeon_bld->soa.bld_base); - struct si_shader *shader = si_shader_ctx->shader; + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); - si_store_shader_io_attribs(shader, decl); + if (swizzle > 0) + return bld_base->uint_bld.zero; - if (decl->Semantic.Name != TGSI_SEMANTIC_PRIMID) { - shader->gs_used_inputs |= - 1llu << get_unique_index(decl->Semantic.Name, - decl->Semantic.Index); - shader->nparam++; + switch (si_shader_ctx->type) { + 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); } } @@ -359,20 +766,14 @@ static LLVMValueRef fetch_input_gs( struct gallivm_state *gallivm = base->gallivm; LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context); LLVMValueRef vtx_offset; - LLVMValueRef t_list_ptr; - LLVMValueRef t_list; LLVMValueRef args[9]; unsigned vtx_offset_param; - struct si_shader_input *input = &shader->input[reg->Register.Index]; + struct tgsi_shader_info *info = &shader->selector->info; + unsigned semantic_name = info->input_semantic_name[reg->Register.Index]; + unsigned semantic_index = info->input_semantic_index[reg->Register.Index]; - if (swizzle != ~0 && - shader->input[reg->Register.Index].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; @@ -400,17 +801,11 @@ static LLVMValueRef fetch_input_gs( vtx_offset_param), 4); - /* Load the ESGS ring resource descriptor */ - t_list_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, - SI_PARAM_RW_BUFFERS); - t_list = build_indexed_load(si_shader_ctx, t_list_ptr, - lp_build_const_int32(gallivm, SI_RING_ESGS)); - - args[0] = t_list; + args[0] = si_shader_ctx->esgs_ring; args[1] = vtx_offset; args[2] = lp_build_const_int32(gallivm, - (get_param_index(input->name, input->sid, - shader->gs_used_inputs) * 4 + + (get_param_index(semantic_name, semantic_index, + shader->selector->inputs_read) * 4 + swizzle) * 256); args[3] = uint->zero; args[4] = uint->one; /* OFFEN */ @@ -420,13 +815,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, @@ -441,7 +865,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: @@ -475,21 +900,8 @@ static void declare_input_fs( } if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) { - LLVMValueRef face, is_face_positive; - - face = LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE); - - is_face_positive = LLVMBuildFCmp(gallivm->builder, - LLVMRealUGT, face, - lp_build_const_float(gallivm, 0.0f), - ""); - radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)] = - LLVMBuildSelect(gallivm->builder, - is_face_positive, - lp_build_const_float(gallivm, 1.0f), - lp_build_const_float(gallivm, 0.0f), - ""); + LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE); radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 1)] = radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 2)] = lp_build_const_float(gallivm, 0.0f); @@ -499,56 +911,42 @@ static void declare_input_fs( return; } - shader->input[input_index].param_offset = shader->nparam++; + shader->ps_input_param_offset[input_index] = shader->nparam++; attr_number = lp_build_const_int32(gallivm, - shader->input[input_index].param_offset); + shader->ps_input_param_offset[input_index]); - switch (decl->Interp.Interpolate) { - case TGSI_INTERPOLATE_CONSTANT: - interp_param = 0; - break; - case TGSI_INTERPOLATE_LINEAR: - if (si_shader_ctx->shader->key.ps.interp_at_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 (si_shader_ctx->shader->key.ps.interp_at_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]; LLVMValueRef face, is_face_positive; LLVMValueRef back_attr_number = lp_build_const_int32(gallivm, - shader->input[input_index].param_offset + 1); + shader->ps_input_param_offset[input_index] + 1); 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), ""); @@ -561,12 +959,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); @@ -587,7 +985,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)] = @@ -605,7 +1003,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); } @@ -614,25 +1012,47 @@ 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); } -static LLVMValueRef load_const(LLVMBuilderRef builder, LLVMValueRef resource, - LLVMValueRef offset, LLVMTypeRef return_type) +/** + * Load a dword from a constant buffer. + */ +static LLVMValueRef buffer_load_const(LLVMBuilderRef builder, LLVMValueRef resource, + LLVMValueRef offset, LLVMTypeRef return_type) { 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, @@ -640,6 +1060,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; @@ -651,35 +1072,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(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] = { - load_const(builder, resource, offset0, radeon_bld->soa.bld_base.base.elem_type), - 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; @@ -699,7 +1177,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) { @@ -714,8 +1192,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"); @@ -723,10 +1217,26 @@ static LLVMValueRef fetch_constant( addr = lp_build_add(&bld_base->uint_bld, addr, lp_build_const_int32(base->gallivm, idx * 4)); - result = 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); - return bitcast(bld_base, type, result); + 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)); + + 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 */ @@ -765,7 +1275,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, @@ -827,7 +1337,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; @@ -839,7 +1349,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, @@ -847,12 +1357,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); @@ -861,11 +1371,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; @@ -874,16 +1411,11 @@ static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context * bld_base, LLVMValueRef base_elt; LLVMValueRef ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_CONST); LLVMValueRef constbuf_index = lp_build_const_int32(base->gallivm, SI_DRIVER_STATE_CONST_BUF); - LLVMValueRef const_resource = build_indexed_load(si_shader_ctx, ptr, constbuf_index); + LLVMValueRef const_resource = build_indexed_load_const(si_shader_ctx, ptr, constbuf_index); for (reg_index = 0; reg_index < 2; reg_index ++) { LLVMValueRef *args = pos[2 + reg_index]; - if (!(shader->key.vs.ucps_enabled & (1 << reg_index))) - continue; - - shader->clip_dist_write |= 0xf << (4 * reg_index); - args[5] = args[6] = args[7] = @@ -895,7 +1427,7 @@ static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context * bld_base, args[1] = lp_build_const_int32(base->gallivm, ((reg_index * 4 + chan) * 4 + const_chan) * 4); - base_elt = load_const(base->gallivm->builder, const_resource, + base_elt = buffer_load_const(base->gallivm->builder, const_resource, args[1], base->elem_type); args[5 + chan] = lp_build_add(base, args[5 + chan], @@ -981,16 +1513,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, @@ -1019,24 +1551,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. */ @@ -1076,30 +1604,24 @@ 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) continue; + if (reg >= noutput) + continue; + /* Load the output as int. */ for (j = 0; j < num_comps; j++) { - unsigned outidx = 0; - - while (outidx < noutput && outputs[outidx].index != reg) - outidx++; - - if (outidx < noutput) - out[j] = LLVMBuildBitCast(builder, - outputs[outidx].values[start+j], - i32, ""); - else - out[j] = NULL; + out[j] = LLVMBuildBitCast(builder, + outputs[reg].values[start+j], + i32, ""); } - if (!out[0]) - continue; - /* Pack the output. */ LLVMValueRef vdata = NULL; @@ -1118,11 +1640,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); @@ -1141,8 +1670,8 @@ 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; - unsigned semantic_name, semantic_index, semantic_usage; + 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; unsigned pos_idx; @@ -1155,41 +1684,34 @@ static void si_llvm_export_vs(struct lp_build_tgsi_context *bld_base, for (i = 0; i < noutput; i++) { semantic_name = outputs[i].name; semantic_index = outputs[i].sid; - semantic_usage = outputs[i].usage; 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; case TGSI_SEMANTIC_COLOR: case TGSI_SEMANTIC_BCOLOR: target = V_008DFC_SQ_EXP_PARAM + param_count; - shader->output[i].param_offset = param_count; + shader->vs_output_param_offset[i] = param_count; param_count++; break; case TGSI_SEMANTIC_CLIPDIST: - if (!(si_shader_ctx->shader->key.vs.ucps_enabled & - (1 << semantic_index))) - continue; - shader->clip_dist_write |= - semantic_usage << (semantic_index << 2); target = V_008DFC_SQ_EXP_POS + 2 + semantic_index; break; case TGSI_SEMANTIC_CLIPVERTEX: @@ -1197,9 +1719,10 @@ 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->output[i].param_offset = param_count; + shader->vs_output_param_offset[i] = param_count; param_count++; break; default: @@ -1219,7 +1742,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) { @@ -1228,6 +1751,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 */ @@ -1242,11 +1767,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); @@ -1256,10 +1785,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, @@ -1275,8 +1804,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++) @@ -1298,7 +1830,133 @@ handle_semantic: lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - pos_args[i], 9); + 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), ""); + + for (chan = 0; chan < 4; chan++) { + lds_store(bld_base, chan, dw_addr, + LLVMBuildLoad(gallivm->builder, out_ptr[chan], "")); + } } } @@ -1307,40 +1965,28 @@ static void si_llvm_emit_es_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 *es = si_shader_ctx->shader; - struct tgsi_parse_context *parse = &si_shader_ctx->parse; + 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); - LLVMValueRef t_list_ptr; - LLVMValueRef t_list; + 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; - while (!tgsi_parse_end_of_tokens(parse)) { - struct tgsi_full_declaration *d = - &parse->FullToken.FullDeclaration; - - tgsi_parse_token(parse); + for (i = 0; i < info->num_outputs; i++) { + LLVMValueRef *out_ptr = + si_shader_ctx->radeon_bld.soa.outputs[i]; + int param_index; - if (parse->FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION) + if (info->output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX || + info->output_semantic_name[i] == TGSI_SEMANTIC_LAYER) continue; - si_store_shader_io_attribs(es, d); - } - - /* Load the ESGS ring resource descriptor */ - t_list_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, - SI_PARAM_RW_BUFFERS); - t_list = build_indexed_load(si_shader_ctx, t_list_ptr, - lp_build_const_int32(gallivm, SI_RING_ESGS)); - - for (i = 0; i < es->noutput; i++) { - LLVMValueRef *out_ptr = - si_shader_ctx->radeon_bld.soa.outputs[es->output[i].index]; - int param_index = get_param_index(es->output[i].name, - es->output[i].sid, - es->key.vs.gs_used_inputs); - + param_index = get_param_index(info->output_semantic_name[i], + info->output_semantic_index[i], + enabled_outputs); if (param_index < 0) continue; @@ -1348,7 +1994,9 @@ static void si_llvm_emit_es_epilogue(struct lp_build_tgsi_context * bld_base) LLVMValueRef out_val = LLVMBuildLoad(gallivm->builder, out_ptr[chan], ""); out_val = LLVMBuildBitCast(gallivm->builder, out_val, i32, ""); - build_tbuffer_store(si_shader_ctx, t_list, out_val, 1, + build_tbuffer_store(si_shader_ctx, + si_shader_ctx->esgs_ring, + out_val, 1, LLVMGetUndef(i32), soffset, (4 * param_index + chan) * 4, V_008F0C_BUF_DATA_FORMAT_32, @@ -1366,7 +2014,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); } @@ -1375,44 +2023,24 @@ static void si_llvm_emit_vs_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; - struct tgsi_parse_context *parse = &si_shader_ctx->parse; + struct tgsi_shader_info *info = &si_shader_ctx->shader->selector->info; struct si_shader_output_values *outputs = NULL; - unsigned noutput = 0; - int i; - - while (!tgsi_parse_end_of_tokens(parse)) { - struct tgsi_full_declaration *d = - &parse->FullToken.FullDeclaration; - unsigned index; - - tgsi_parse_token(parse); + int i,j; - if (parse->FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION) - continue; + outputs = MALLOC(info->num_outputs * sizeof(outputs[0])); - i = si_store_shader_io_attribs(shader, d); - if (i < 0) - continue; + for (i = 0; i < info->num_outputs; i++) { + outputs[i].name = info->output_semantic_name[i]; + outputs[i].sid = info->output_semantic_index[i]; - outputs = REALLOC(outputs, noutput * sizeof(outputs[0]), - (noutput + 1) * sizeof(outputs[0])); - for (index = d->Range.First; index <= d->Range.Last; index++) { - outputs[noutput].index = index; - outputs[noutput].name = d->Semantic.Name; - outputs[noutput].sid = d->Semantic.Index; - outputs[noutput].usage = d->Declaration.UsageMask; - - for (i = 0; i < 4; i++) - outputs[noutput].values[i] = - LLVMBuildLoad(gallivm->builder, - si_shader_ctx->radeon_bld.soa.outputs[index][i], - ""); - } - noutput++; + for (j = 0; j < 4; j++) + outputs[i].values[j] = + LLVMBuildLoad(gallivm->builder, + si_shader_ctx->radeon_bld.soa.outputs[i][j], + ""); } - si_llvm_export_vs(bld_base, outputs, noutput); + si_llvm_export_vs(bld_base, outputs, info->num_outputs); FREE(outputs); } @@ -1421,98 +2049,87 @@ static void si_llvm_emit_fs_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 lp_build_context * base = &bld_base->base; - struct lp_build_context * uint = - &si_shader_ctx->radeon_bld.soa.bld_base.uint_bld; - struct tgsi_parse_context *parse = &si_shader_ctx->parse; + struct lp_build_context * uint = &bld_base->uint_bld; + struct tgsi_shader_info *info = &shader->selector->info; LLVMValueRef args[9]; LLVMValueRef last_args[9] = { 0 }; - unsigned semantic_name; int depth_index = -1, stencil_index = -1, samplemask_index = -1; int i; - while (!tgsi_parse_end_of_tokens(parse)) { - struct tgsi_full_declaration *d = - &parse->FullToken.FullDeclaration; + for (i = 0; i < info->num_outputs; i++) { + unsigned semantic_name = info->output_semantic_name[i]; + unsigned semantic_index = info->output_semantic_index[i]; unsigned target; - unsigned index; - - tgsi_parse_token(parse); + LLVMValueRef alpha_ptr; - if (parse->FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION) + /* Select the correct target */ + switch (semantic_name) { + case TGSI_SEMANTIC_POSITION: + depth_index = i; continue; - - i = si_store_shader_io_attribs(shader, d); - if (i < 0) + case TGSI_SEMANTIC_STENCIL: + stencil_index = i; + continue; + case TGSI_SEMANTIC_SAMPLEMASK: + samplemask_index = i; continue; + case TGSI_SEMANTIC_COLOR: + target = V_008DFC_SQ_EXP_MRT + semantic_index; + alpha_ptr = si_shader_ctx->radeon_bld.soa.outputs[i][3]; - semantic_name = d->Semantic.Name; - for (index = d->Range.First; index <= d->Range.Last; index++) { - /* Select the correct target */ - switch(semantic_name) { - case TGSI_SEMANTIC_POSITION: - depth_index = index; - continue; - case TGSI_SEMANTIC_STENCIL: - stencil_index = index; - continue; - case TGSI_SEMANTIC_SAMPLEMASK: - samplemask_index = index; - continue; - case TGSI_SEMANTIC_COLOR: - target = V_008DFC_SQ_EXP_MRT + d->Semantic.Index; - 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[index][3]); - - if (d->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[index]); - break; - default: - target = 0; - fprintf(stderr, - "Warning: SI unhandled fs output type:%d\n", - semantic_name); + if (si_shader_ctx->shader->key.ps.alpha_to_one) + 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, 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; + fprintf(stderr, + "Warning: SI unhandled fs output type:%d\n", + semantic_name); + } + + si_llvm_init_export_args_load(bld_base, + si_shader_ctx->radeon_bld.soa.outputs[i], + target, args); + + if (semantic_name == TGSI_SEMANTIC_COLOR) { + /* If there is an export instruction waiting to be emitted, do so now. */ + if (last_args[0]) { + lp_build_intrinsic(base->gallivm->builder, + "llvm.SI.export", + LLVMVoidTypeInContext(base->gallivm->context), + last_args, 9, 0); } - si_llvm_init_export_args_load(bld_base, - si_shader_ctx->radeon_bld.soa.outputs[index], - target, args); + /* This instruction will be emitted at the end of the shader. */ + memcpy(last_args, args, sizeof(args)); - if (semantic_name == TGSI_SEMANTIC_COLOR) { - /* If there is an export instruction waiting to be emitted, do so now. */ - if (last_args[0]) { + /* Handle FS_COLOR0_WRITES_ALL_CBUFS. */ + if (shader->selector->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS] && + semantic_index == 0 && + si_shader_ctx->shader->key.ps.last_cbuf > 0) { + for (int c = 1; c <= si_shader_ctx->shader->key.ps.last_cbuf; c++) { + si_llvm_init_export_args_load(bld_base, + si_shader_ctx->radeon_bld.soa.outputs[i], + V_008DFC_SQ_EXP_MRT + c, args); lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - last_args, 9); - } - - /* This instruction will be emitted at the end of the shader. */ - memcpy(last_args, args, sizeof(args)); - - /* Handle FS_COLOR0_WRITES_ALL_CBUFS. */ - if (shader->selector->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS][0] && - shader->output[i].sid == 0 && - si_shader_ctx->shader->key.ps.nr_cbufs > 1) { - for (int c = 1; c < si_shader_ctx->shader->key.ps.nr_cbufs; c++) { - si_llvm_init_export_args_load(bld_base, - si_shader_ctx->radeon_bld.soa.outputs[index], - V_008DFC_SQ_EXP_MRT + c, args); - 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); } + } else { + lp_build_intrinsic(base->gallivm->builder, + "llvm.SI.export", + LLVMVoidTypeInContext(base->gallivm->context), + args, 9, 0); } } @@ -1538,10 +2155,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); } @@ -1549,10 +2163,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) @@ -1571,7 +2191,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)); } @@ -1602,7 +2222,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, @@ -1631,15 +2251,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); @@ -1648,9 +2289,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); @@ -1717,18 +2358,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: @@ -1737,26 +2373,43 @@ 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]; @@ -1874,7 +2527,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 */ @@ -1957,7 +2610,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 */ @@ -1973,7 +2626,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; @@ -2008,7 +2661,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, @@ -2057,7 +2710,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); @@ -2104,7 +2757,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); @@ -2119,16 +2772,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; } @@ -2137,7 +2803,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 || @@ -2184,6 +2850,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, @@ -2200,25 +2895,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) { @@ -2252,6 +2956,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, @@ -2261,41 +3206,24 @@ static void si_llvm_emit_vertex( struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); struct lp_build_context *uint = &bld_base->uint_bld; struct si_shader *shader = si_shader_ctx->shader; + struct tgsi_shader_info *info = &shader->selector->info; struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context); LLVMValueRef soffset = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_GS2VS_OFFSET); LLVMValueRef gs_next_vertex; LLVMValueRef can_emit, kill; - LLVMValueRef t_list_ptr; - LLVMValueRef t_list; LLVMValueRef args[2]; unsigned chan; int i; + unsigned stream; - /* Load the GSVS ring resource descriptor */ - t_list_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, - SI_PARAM_RW_BUFFERS); - t_list = build_indexed_load(si_shader_ctx, t_list_ptr, - lp_build_const_int32(gallivm, SI_RING_GSVS)); - - if (shader->noutput == 0) { - struct tgsi_parse_context *parse = &si_shader_ctx->parse; - - while (!tgsi_parse_end_of_tokens(parse)) { - tgsi_parse_token(parse); - - if (parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_DECLARATION) { - struct tgsi_full_declaration *d = &parse->FullToken.FullDeclaration; - - if (d->Declaration.File == TGSI_FILE_OUTPUT) - si_store_shader_io_attribs(shader, d); - } - } - } + 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 @@ -2304,29 +3232,32 @@ static void si_llvm_emit_vertex( */ can_emit = LLVMBuildICmp(gallivm->builder, LLVMIntULE, gs_next_vertex, lp_build_const_int32(gallivm, - shader->gs_max_out_vertices), ""); + shader->selector->gs_max_out_vertices), ""); 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); - for (i = 0; i < shader->noutput; i++) { + 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 = - si_shader_ctx->radeon_bld.soa.outputs[shader->output[i].index]; + si_shader_ctx->radeon_bld.soa.outputs[i]; for (chan = 0; chan < 4; chan++) { LLVMValueRef out_val = LLVMBuildLoad(gallivm->builder, out_ptr[chan], ""); LLVMValueRef voffset = lp_build_const_int32(gallivm, (i * 4 + chan) * - shader->gs_max_out_vertices); + shader->selector->gs_max_out_vertices); voffset = lp_build_add(uint, voffset, gs_next_vertex); voffset = lp_build_mul_imm(uint, voffset, 4); out_val = LLVMBuildBitCast(gallivm->builder, out_val, i32, ""); - build_tbuffer_store(si_shader_ctx, t_list, out_val, 1, + build_tbuffer_store(si_shader_ctx, + si_shader_ctx->gsvs_ring[stream], + out_val, 1, voffset, soffset, 0, V_008F0C_BUF_DATA_FORMAT_32, V_008F0C_BUF_NUM_FORMAT_UINT, @@ -2335,12 +3266,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); } @@ -2354,15 +3286,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, @@ -2374,6 +3319,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; @@ -2392,13 +3342,34 @@ 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; struct gallivm_state *gallivm = bld_base->base.gallivm; struct si_shader *shader = si_shader_ctx->shader; LLVMTypeRef params[SI_NUM_PARAMS], f32, i8, i32, v2i32, v3i32, v16i8, v4i32, v8i32; - unsigned i, last_sgpr, num_params; + unsigned i, last_array_pointer, last_sgpr, num_params; i8 = LLVMInt8TypeInContext(gallivm->context); i32 = LLVMInt32TypeInContext(gallivm->context); @@ -2409,46 +3380,78 @@ static void create_function(struct si_shader_context *si_shader_ctx) v8i32 = LLVMVectorType(i32, 8); v16i8 = LLVMVectorType(i8, 16); - params[SI_PARAM_CONST] = const_array(v16i8, SI_NUM_CONST_BUFFERS); params[SI_PARAM_RW_BUFFERS] = const_array(v16i8, SI_NUM_RW_BUFFERS); + params[SI_PARAM_CONST] = const_array(v16i8, SI_NUM_CONST_BUFFERS); params[SI_PARAM_SAMPLER] = const_array(v4i32, SI_NUM_SAMPLER_STATES); params[SI_PARAM_RESOURCE] = const_array(v8i32, SI_NUM_SAMPLER_VIEWS); + last_array_pointer = SI_PARAM_RESOURCE; switch (si_shader_ctx->type) { case TGSI_PROCESSOR_VERTEX: params[SI_PARAM_VERTEX_BUFFER] = const_array(v16i8, SI_NUM_VERTEX_BUFFERS); + last_array_pointer = SI_PARAM_VERTEX_BUFFER; params[SI_PARAM_BASE_VERTEX] = i32; params[SI_PARAM_START_INSTANCE] = i32; 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 { - /* 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; + if (shader->is_gs_copy_shader) { + last_array_pointer = SI_PARAM_CONST; + num_params = SI_PARAM_CONST+1; } - /* 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; - } + /* The locations of the other parameters are assigned dynamically. */ + 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[si_shader_ctx->param_rel_auto_id = num_params++] = i32; params[num_params++] = i32; /* unused */ 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; @@ -2498,30 +3501,52 @@ 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); - switch (i) { - default: - LLVMAddAttribute(P, LLVMInRegAttribute); - break; + /* We tell llvm that array inputs are passed by value to allow Sinking pass * to move load. Inputs are constant so this is fine. */ - case SI_PARAM_CONST: - case SI_PARAM_SAMPLER: - case SI_PARAM_RESOURCE: + if (i <= last_array_pointer) LLVMAddAttribute(P, LLVMByValAttribute); - break; - } + else + LLVMAddAttribute(P, LLVMInRegAttribute); } 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) @@ -2543,12 +3568,12 @@ static void preload_constants(struct si_shader_context *si_shader_ctx) /* Load the resource descriptor */ si_shader_ctx->const_resource[buf] = - build_indexed_load(si_shader_ctx, ptr, lp_build_const_int32(gallivm, buf)); + build_indexed_load_const(si_shader_ctx, ptr, lp_build_const_int32(gallivm, buf)); /* Load the constants, we rely on the code sinking to do the rest */ for (i = 0; i < num_const * 4; ++i) { si_shader_ctx->constants[buf][i] = - load_const(gallivm->builder, + buffer_load_const(gallivm->builder, si_shader_ctx->const_resource[buf], lp_build_const_int32(gallivm, i * 4), bld_base->base.elem_type); @@ -2570,10 +3595,6 @@ static void preload_samplers(struct si_shader_context *si_shader_ctx) if (num_samplers == 0) return; - /* Allocate space for the values */ - si_shader_ctx->resources = CALLOC(SI_NUM_SAMPLER_VIEWS, sizeof(LLVMValueRef)); - si_shader_ctx->samplers = CALLOC(num_samplers, sizeof(LLVMValueRef)); - res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE); samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER); @@ -2581,17 +3602,17 @@ static void preload_samplers(struct si_shader_context *si_shader_ctx) for (i = 0; i < num_samplers; ++i) { /* Resource */ offset = lp_build_const_int32(gallivm, i); - si_shader_ctx->resources[i] = build_indexed_load(si_shader_ctx, res_ptr, offset); + si_shader_ctx->resources[i] = build_indexed_load_const(si_shader_ctx, res_ptr, offset); /* Sampler */ offset = lp_build_const_int32(gallivm, i); - si_shader_ctx->samplers[i] = build_indexed_load(si_shader_ctx, samp_ptr, offset); + si_shader_ctx->samplers[i] = build_indexed_load_const(si_shader_ctx, samp_ptr, offset); /* FMASK resource */ if (info->is_msaa_sampler[i]) { offset = lp_build_const_int32(gallivm, SI_FMASK_TEX_OFFSET + i); si_shader_ctx->resources[SI_FMASK_TEX_OFFSET + i] = - build_indexed_load(si_shader_ctx, res_ptr, offset); + build_indexed_load_const(si_shader_ctx, res_ptr, offset); } } } @@ -2602,9 +3623,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, @@ -2616,61 +3641,86 @@ static void preload_streamout_buffers(struct si_shader_context *si_shader_ctx) LLVMValueRef offset = lp_build_const_int32(gallivm, SI_SO_BUF_OFFSET + i); - si_shader_ctx->so_buffers[i] = build_indexed_load(si_shader_ctx, buf_ptr, offset); + si_shader_ctx->so_buffers[i] = build_indexed_load_const(si_shader_ctx, buf_ptr, offset); } } } -int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, - LLVMModuleRef mod) +/** + * Load ESGS and GSVS ring buffer resource descriptors and save the variables + * for later use. + */ +static void preload_ring_buffers(struct si_shader_context *si_shader_ctx) { - unsigned r; /* llvm_compile result */ - unsigned i; - unsigned char *ptr; - struct radeon_shader_binary binary; - bool dump = r600_can_dump_shader(&sscreen->b, - shader->selector ? shader->selector->tokens : NULL); - const char * gpu_family = r600_get_llvm_processor_name(sscreen->b.family); - unsigned code_size; - - /* Use LLVM to compile shader */ - memset(&binary, 0, sizeof(binary)); - r = radeon_llvm_compile(mod, &binary, gpu_family, dump); - - /* Output binary dump if rscreen->debug_flags are set */ - if (dump && ! binary.disassembled) { - fprintf(stderr, "SI CODE:\n"); - for (i = 0; i < binary.code_size; i+=4 ) { - fprintf(stderr, "%02x%02x%02x%02x\n", binary.code[i + 3], - binary.code[i + 2], binary.code[i + 1], - binary.code[i]); + struct gallivm_state *gallivm = + si_shader_ctx->radeon_bld.soa.bld_base.base.gallivm; + + LLVMValueRef buf_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + SI_PARAM_RW_BUFFERS); + + 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); + + si_shader_ctx->esgs_ring = + build_indexed_load_const(si_shader_ctx, buf_ptr, offset); + } + + if (si_shader_ctx->shader->is_gs_copy_shader) { + LLVMValueRef offset = lp_build_const_int32(gallivm, SI_RING_GSVS); + + 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 si_screen *sscreen, + struct si_shader *shader, + unsigned symbol_offset) +{ + unsigned i; + const unsigned char *config = + 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. */ - /* Parse config data in compiled binary */ - for (i = 0; i < binary.config_size; i+= 8) { - unsigned reg = util_le32_to_cpu(*(uint32_t*)(binary.config + i)); - unsigned value = util_le32_to_cpu(*(uint32_t*)(binary.config + i + 4)); + + 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) { case R_00B028_SPI_SHADER_PGM_RSRC1_PS: case R_00B128_SPI_SHADER_PGM_RSRC1_VS: case R_00B228_SPI_SHADER_PGM_RSRC1_GS: case R_00B848_COMPUTE_PGM_RSRC1: - shader->num_sgprs = (G_00B028_SGPRS(value) + 1) * 8; - shader->num_vgprs = (G_00B028_VGPRS(value) + 1) * 4; + 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 = G_00B02C_EXTRA_LDS_SIZE(value); + shader->lds_size = MAX2(shader->lds_size, G_00B02C_EXTRA_LDS_SIZE(value)); break; case R_00B84C_COMPUTE_PGM_RSRC2: - shader->lds_size = G_00B84C_LDS_SIZE(value); + shader->lds_size = MAX2(shader->lds_size, G_00B84C_LDS_SIZE(value)); break; 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 = @@ -2682,65 +3732,146 @@ int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, break; } } +} + +void si_shader_apply_scratch_relocs(struct si_context *sctx, + struct si_shader *shader, + uint64_t scratch_va) +{ + unsigned 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); + } + } +} + +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_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); + 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); } 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]); + } + } + } - free(binary.code); - free(binary.config); - free(binary.rodata); + 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, + LLVMTargetMachineRef tm, LLVMModuleRef mod) +{ + int r = 0; + 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); + + 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)); + } return r; } /* Generate code for the hardware VS shader stage to go with a geometry shader */ static int si_generate_gs_copy_shader(struct si_screen *sscreen, struct si_shader_context *si_shader_ctx, - bool dump) + struct si_shader *gs, bool dump) { struct gallivm_state *gallivm = &si_shader_ctx->radeon_bld.gallivm; struct lp_build_tgsi_context *bld_base = &si_shader_ctx->radeon_bld.soa.bld_base; struct lp_build_context *base = &bld_base->base; struct lp_build_context *uint = &bld_base->uint_bld; struct si_shader *shader = si_shader_ctx->shader; - struct si_shader *gs = si_shader_ctx->shader->selector->current; struct si_shader_output_values *outputs; - LLVMValueRef t_list_ptr, t_list; + struct tgsi_shader_info *gsinfo = &gs->selector->info; LLVMValueRef args[9]; int i, r; - outputs = MALLOC(gs->noutput * sizeof(outputs[0])); + outputs = MALLOC(gsinfo->num_outputs * sizeof(outputs[0])); si_shader_ctx->type = TGSI_PROCESSOR_VERTEX; + shader->is_gs_copy_shader = true; radeon_llvm_context_init(&si_shader_ctx->radeon_bld); create_meta_data(si_shader_ctx); create_function(si_shader_ctx); preload_streamout_buffers(si_shader_ctx); + preload_ring_buffers(si_shader_ctx); - /* Load the GSVS ring resource descriptor */ - t_list_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, - SI_PARAM_RW_BUFFERS); - t_list = build_indexed_load(si_shader_ctx, t_list_ptr, - lp_build_const_int32(gallivm, SI_RING_GSVS)); - - args[0] = t_list; + 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), @@ -2753,25 +3884,20 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, args[8] = uint->zero; /* TFE */ /* Fetch vertex data from GSVS ring */ - for (i = 0; i < gs->noutput; ++i) { - struct si_shader_output *out = gs->output + i; + for (i = 0; i < gsinfo->num_outputs; ++i) { unsigned chan; - shader->output[i] = *out; - - outputs[i].name = out->name; - outputs[i].index = out->index; - outputs[i].sid = out->sid; - outputs[i].usage = out->usage; + outputs[i].name = gsinfo->output_semantic_name[i]; + outputs[i].sid = gsinfo->output_semantic_index[i]; for (chan = 0; chan < 4; chan++) { args[2] = lp_build_const_int32(gallivm, (i * 4 + chan) * - gs->gs_max_out_vertices * 16 * 4); + gs->selector->gs_max_out_vertices * 16 * 4); 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, @@ -2779,9 +3905,8 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen, base->elem_type, ""); } } - shader->noutput = gs->noutput; - si_llvm_export_vs(bld_base, outputs, gs->noutput); + si_llvm_export_vs(bld_base, outputs, gsinfo->num_outputs); radeon_llvm_finalize_module(&si_shader_ctx->radeon_bld); @@ -2789,7 +3914,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); @@ -2797,37 +3922,103 @@ 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); } - assert(shader->noutput == 0); assert(shader->nparam == 0); - assert(shader->ninput == 0); memset(&si_shader_ctx, 0, sizeof(si_shader_ctx)); 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; @@ -2843,42 +4034,58 @@ 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; + bld_base->op_actions[TGSI_OPCODE_MAX].intr_name = "llvm.maxnum.f32"; + bld_base->op_actions[TGSI_OPCODE_MIN].emit = build_tgsi_intrinsic_nomem; + bld_base->op_actions[TGSI_OPCODE_MIN].intr_name = "llvm.minnum.f32"; + } 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: - si_shader_ctx.radeon_bld.load_input = declare_input_gs; bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_gs; bld_base->emit_epilogue = si_llvm_emit_gs_epilogue; - - shader->gs_input_prim = - sel->info.properties[TGSI_PROPERTY_GS_INPUT_PRIM][0]; - shader->gs_output_prim = - sel->info.properties[TGSI_PROPERTY_GS_OUTPUT_PRIM][0]; - shader->gs_max_out_vertices = - sel->info.properties[TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES][0]; break; case TGSI_PROCESSOR_FRAGMENT: si_shader_ctx.radeon_bld.load_input = declare_input_fs; bld_base->emit_epilogue = si_llvm_emit_fs_epilogue; - switch (sel->info.properties[TGSI_PROPERTY_FS_DEPTH_LAYOUT][0]) { + switch (sel->info.properties[TGSI_PROPERTY_FS_DEPTH_LAYOUT]) { case TGSI_FS_DEPTH_LAYOUT_GREATER: shader->db_shader_control |= S_02880C_CONSERVATIVE_Z_EXPORT(V_02880C_EXPORT_GREATER_THAN_Z); @@ -2899,14 +4106,18 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) preload_constants(&si_shader_ctx); preload_samplers(&si_shader_ctx); preload_streamout_buffers(&si_shader_ctx); + 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; } @@ -2914,7 +4125,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; @@ -2927,21 +4138,19 @@ int si_shader_create(struct si_screen *sscreen, struct si_shader *shader) shader->gs_copy_shader->selector = shader->selector; shader->gs_copy_shader->key = shader->key; si_shader_ctx.shader = shader->gs_copy_shader; - if ((r = si_generate_gs_copy_shader(sscreen, &si_shader_ctx, dump))) { + if ((r = si_generate_gs_copy_shader(sscreen, &si_shader_ctx, + shader, dump))) { free(shader->gs_copy_shader); shader->gs_copy_shader = NULL; goto out; } } - tgsi_parse_free(&si_shader_ctx.parse); - out: for (int i = 0; i < SI_NUM_CONST_BUFFERS; i++) FREE(si_shader_ctx.constants[i]); - FREE(si_shader_ctx.resources); - FREE(si_shader_ctx.samplers); - + if (poly_stipple) + tgsi_free_tokens(tokens); return r; } @@ -2950,6 +4159,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); }