static LLVMValueRef emit_fetch_temporary( struct lp_build_tgsi_context *bld_base, const struct tgsi_full_src_register *reg, enum tgsi_opcode_type type, unsigned swizzle) { struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base); LLVMBuilderRef builder = bld_base->base.gallivm->builder; if (swizzle == ~0) { LLVMValueRef values[TGSI_NUM_CHANNELS] = {}; unsigned chan; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { values[chan] = emit_fetch_temporary(bld_base, reg, type, chan); } return lp_build_gather_values(bld_base->base.gallivm, values, TGSI_NUM_CHANNELS); } if (reg->Register.Indirect) { LLVMValueRef array_index = emit_array_index(bld, reg, swizzle); LLVMValueRef ptr = LLVMBuildGEP(builder, bld->temps_array, &array_index, 1, ""); return LLVMBuildLoad(builder, ptr, ""); } else { LLVMValueRef temp_ptr; temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle); return bitcast(bld_base,type,LLVMBuildLoad(builder, temp_ptr, "")); } }
static LLVMValueRef emit_fetch( struct lp_build_tgsi_context *bld_base, const struct tgsi_full_src_register *reg, enum tgsi_opcode_type type, unsigned swizzle) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base); LLVMBuilderRef builder = bld_base->base.gallivm->builder; LLVMValueRef result, ptr; if (swizzle == ~0) { LLVMValueRef values[TGSI_NUM_CHANNELS]; unsigned chan; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { values[chan] = emit_fetch(bld_base, reg, type, chan); } return lp_build_gather_values(bld_base->base.gallivm, values, TGSI_NUM_CHANNELS); } if (reg->Register.Indirect) { struct tgsi_declaration_range range = get_array_range(bld_base, reg->Register.File, ®->Indirect); return LLVMBuildExtractElement(builder, emit_array_fetch(bld_base, reg->Register.File, type, range, swizzle), emit_array_index(bld, ®->Indirect, reg->Register.Index - range.First), ""); } switch(reg->Register.File) { case TGSI_FILE_IMMEDIATE: { LLVMTypeRef ctype = tgsi2llvmtype(bld_base, type); return LLVMConstBitCast(bld->immediates[reg->Register.Index][swizzle], ctype); } case TGSI_FILE_INPUT: result = ctx->inputs[radeon_llvm_reg_index_soa(reg->Register.Index, swizzle)]; break; case TGSI_FILE_TEMPORARY: ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle); result = LLVMBuildLoad(builder, ptr, ""); break; case TGSI_FILE_OUTPUT: ptr = lp_get_output_ptr(bld, reg->Register.Index, swizzle); result = LLVMBuildLoad(builder, ptr, ""); break; default: return LLVMGetUndef(tgsi2llvmtype(bld_base, type)); } return bitcast(bld_base, type, result); }
static void emit_not(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { LLVMBuilderRef builder = bld_base->base.gallivm->builder; LLVMValueRef v = bitcast(bld_base, TGSI_TYPE_UNSIGNED, emit_data->args[0]); emit_data->output[emit_data->chan] = LLVMBuildNot(builder, v, ""); }
static LLVMValueRef fetch_system_value( struct lp_build_tgsi_context * bld_base, const struct tgsi_full_src_register *reg, enum tgsi_opcode_type type, unsigned swizzle) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); LLVMValueRef cval = ctx->system_values[reg->Register.Index]; return bitcast(bld_base, type, cval); }
static LLVMValueRef fetch_constant( 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); struct lp_build_context * base = &bld_base->base; const struct tgsi_ind_register *ireg = ®->Indirect; unsigned idx; LLVMValueRef args[2]; LLVMValueRef addr; LLVMValueRef result; if (swizzle == LP_CHAN_ALL) { unsigned chan; LLVMValueRef values[4]; for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) values[chan] = fetch_constant(bld_base, reg, type, chan); return lp_build_gather_values(bld_base->base.gallivm, values, 4); } idx = reg->Register.Index * 4 + swizzle; if (!reg->Register.Indirect) return bitcast(bld_base, type, si_shader_ctx->constants[idx]); args[0] = si_shader_ctx->const_resource; args[1] = lp_build_const_int32(base->gallivm, idx * 4); addr = si_shader_ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle]; addr = LLVMBuildLoad(base->gallivm->builder, addr, "load addr reg"); addr = lp_build_mul_imm(&bld_base->uint_bld, addr, 16); args[1] = lp_build_add(&bld_base->uint_bld, addr, args[1]); result = build_intrinsic(base->gallivm->builder, "llvm.SI.load.const", base->elem_type, args, 2, LLVMReadNoneAttribute | LLVMNoUnwindAttribute); return bitcast(bld_base, type, result); }
static LLVMValueRef llvm_fetch_const( struct lp_build_tgsi_context * bld_base, const struct tgsi_full_src_register *reg, enum tgsi_opcode_type type, unsigned swizzle) { LLVMValueRef idx = lp_build_const_int32(bld_base->base.gallivm, radeon_llvm_reg_index_soa(reg->Register.Index, swizzle)); LLVMValueRef cval = build_intrinsic(bld_base->base.gallivm->builder, "llvm.AMDGPU.load.const", bld_base->base.elem_type, &idx, 1, LLVMReadNoneAttribute); return bitcast(bld_base, type, cval); }
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { LLVMValueRef value = dst[chan_index]; if (inst->Instruction.Saturate != TGSI_SAT_NONE) { struct lp_build_emit_data clamp_emit_data; memset(&clamp_emit_data, 0, sizeof(clamp_emit_data)); clamp_emit_data.arg_count = 3; clamp_emit_data.args[0] = value; clamp_emit_data.args[2] = base.one; switch(inst->Instruction.Saturate) { case TGSI_SAT_ZERO_ONE: clamp_emit_data.args[1] = base.zero; break; case TGSI_SAT_MINUS_PLUS_ONE: clamp_emit_data.args[1] = LLVMConstReal( base.elem_type, -1.0f); break; default: assert(0); } value = lp_build_emit_llvm(bld_base, TGSI_OPCODE_CLAMP, &clamp_emit_data); } switch(reg->Register.File) { case TGSI_FILE_ADDRESS: temp_ptr = bld->addr[reg->Register.Index][chan_index]; LLVMBuildStore(builder, value, temp_ptr); continue; case TGSI_FILE_OUTPUT: temp_ptr = bld->outputs[reg->Register.Index][chan_index]; break; case TGSI_FILE_TEMPORARY: temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index); break; default: return; } value = bitcast(bld_base, TGSI_TYPE_FLOAT, value); LLVMBuildStore(builder, value, temp_ptr); }
static LLVMValueRef llvm_fetch_const( struct lp_build_tgsi_context * bld_base, const struct tgsi_full_src_register *reg, enum tgsi_opcode_type type, unsigned swizzle) { LLVMValueRef offset = lp_build_const_int32(bld_base->base.gallivm, reg->Register.Index); if (reg->Register.Indirect) { struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base); LLVMValueRef index = LLVMBuildLoad(bld_base->base.gallivm->builder, bld->addr[reg->Indirect.Index][reg->Indirect.Swizzle], ""); offset = LLVMBuildAdd(bld_base->base.gallivm->builder, offset, index, ""); } unsigned ConstantAddressSpace = CONSTANT_BUFFER_0_ADDR_SPACE ; if (reg->Register.Dimension) { ConstantAddressSpace += reg->Dimension.Index; } LLVMValueRef cvecval = llvm_load_const_buffer(bld_base, offset, ConstantAddressSpace); LLVMValueRef cval = LLVMBuildExtractElement(bld_base->base.gallivm->builder, cvecval, lp_build_const_int32(bld_base->base.gallivm, swizzle), ""); return bitcast(bld_base, type, cval); }
static LLVMValueRef emit_fetch_input( struct lp_build_tgsi_context *bld_base, const struct tgsi_full_src_register *reg, enum tgsi_opcode_type type, unsigned swizzle) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); if (swizzle == ~0) { LLVMValueRef values[TGSI_NUM_CHANNELS] = {}; unsigned chan; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { values[chan] = ctx->inputs[radeon_llvm_reg_index_soa( reg->Register.Index, chan)]; } return lp_build_gather_values(bld_base->base.gallivm, values, TGSI_NUM_CHANNELS); } else { return bitcast(bld_base, type, ctx->inputs[radeon_llvm_reg_index_soa(reg->Register.Index, swizzle)]); } }
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { LLVMValueRef value = dst[chan_index]; if (inst->Instruction.Saturate != TGSI_SAT_NONE) { struct lp_build_emit_data clamp_emit_data; memset(&clamp_emit_data, 0, sizeof(clamp_emit_data)); clamp_emit_data.arg_count = 3; clamp_emit_data.args[0] = value; clamp_emit_data.args[2] = base.one; switch(inst->Instruction.Saturate) { case TGSI_SAT_ZERO_ONE: clamp_emit_data.args[1] = base.zero; break; case TGSI_SAT_MINUS_PLUS_ONE: clamp_emit_data.args[1] = LLVMConstReal( base.elem_type, -1.0f); break; default: assert(0); } value = lp_build_emit_llvm(bld_base, TGSI_OPCODE_CLAMP, &clamp_emit_data); } if (reg->Register.File == TGSI_FILE_ADDRESS) { temp_ptr = bld->addr[reg->Register.Index][chan_index]; LLVMBuildStore(builder, value, temp_ptr); continue; } value = bitcast(bld_base, TGSI_TYPE_FLOAT, value); if (reg->Register.Indirect) { struct tgsi_declaration_range range = get_array_range(bld_base, reg->Register.File, ®->Indirect); unsigned i, size = range.Last - range.First + 1; LLVMValueRef array = LLVMBuildInsertElement(builder, emit_array_fetch(bld_base, reg->Register.File, TGSI_TYPE_FLOAT, range, chan_index), value, emit_array_index(bld, ®->Indirect, reg->Register.Index - range.First), ""); for (i = 0; i < size; ++i) { switch(reg->Register.File) { case TGSI_FILE_OUTPUT: temp_ptr = bld->outputs[i + range.First][chan_index]; break; case TGSI_FILE_TEMPORARY: temp_ptr = lp_get_temp_ptr_soa(bld, i + range.First, chan_index); break; default: return; } value = LLVMBuildExtractElement(builder, array, lp_build_const_int32(gallivm, i), ""); LLVMBuildStore(builder, value, temp_ptr); } } else { switch(reg->Register.File) { case TGSI_FILE_OUTPUT: temp_ptr = bld->outputs[reg->Register.Index][chan_index]; break; case TGSI_FILE_TEMPORARY: temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index); break; default: return; } LLVMBuildStore(builder, value, temp_ptr); } }