mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 15:38:09 +02:00
radeon/llvm: rework input fetch and output store
Cleanup the code and implement indirect addressing. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Tom Stellard <thomas.stellard@amd.com>
This commit is contained in:
parent
b51f8593d8
commit
c05483fc00
2 changed files with 156 additions and 127 deletions
|
|
@ -35,6 +35,7 @@
|
||||||
#define RADEON_LLVM_MAX_OUTPUTS 32 * 4
|
#define RADEON_LLVM_MAX_OUTPUTS 32 * 4
|
||||||
#define RADEON_LLVM_MAX_BRANCH_DEPTH 16
|
#define RADEON_LLVM_MAX_BRANCH_DEPTH 16
|
||||||
#define RADEON_LLVM_MAX_LOOP_DEPTH 16
|
#define RADEON_LLVM_MAX_LOOP_DEPTH 16
|
||||||
|
#define RADEON_LLVM_MAX_ARRAYS 16
|
||||||
|
|
||||||
#define RADEON_LLVM_MAX_SYSTEM_VALUES 4
|
#define RADEON_LLVM_MAX_SYSTEM_VALUES 4
|
||||||
|
|
||||||
|
|
@ -117,12 +118,32 @@ struct radeon_llvm_context {
|
||||||
unsigned branch_depth;
|
unsigned branch_depth;
|
||||||
unsigned loop_depth;
|
unsigned loop_depth;
|
||||||
|
|
||||||
|
struct tgsi_declaration_range arrays[RADEON_LLVM_MAX_ARRAYS];
|
||||||
|
unsigned num_arrays;
|
||||||
|
|
||||||
LLVMValueRef main_fn;
|
LLVMValueRef main_fn;
|
||||||
|
|
||||||
struct gallivm_state gallivm;
|
struct gallivm_state gallivm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline LLVMTypeRef tgsi2llvmtype(
|
||||||
|
struct lp_build_tgsi_context * bld_base,
|
||||||
|
enum tgsi_opcode_type type)
|
||||||
|
{
|
||||||
|
LLVMContextRef ctx = bld_base->base.gallivm->context;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case TGSI_TYPE_UNSIGNED:
|
||||||
|
case TGSI_TYPE_SIGNED:
|
||||||
|
return LLVMInt32TypeInContext(ctx);
|
||||||
|
case TGSI_TYPE_UNTYPED:
|
||||||
|
case TGSI_TYPE_FLOAT:
|
||||||
|
return LLVMFloatTypeInContext(ctx);
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline LLVMValueRef bitcast(
|
static inline LLVMValueRef bitcast(
|
||||||
struct lp_build_tgsi_context * bld_base,
|
struct lp_build_tgsi_context * bld_base,
|
||||||
enum tgsi_opcode_type type,
|
enum tgsi_opcode_type type,
|
||||||
|
|
@ -130,22 +151,7 @@ static inline LLVMValueRef bitcast(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
|
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
|
||||||
LLVMContextRef ctx = bld_base->base.gallivm->context;
|
LLVMTypeRef dst_type = tgsi2llvmtype(bld_base, type);
|
||||||
LLVMTypeRef dst_type;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case TGSI_TYPE_UNSIGNED:
|
|
||||||
case TGSI_TYPE_SIGNED:
|
|
||||||
dst_type = LLVMInt32TypeInContext(ctx);
|
|
||||||
break;
|
|
||||||
case TGSI_TYPE_UNTYPED:
|
|
||||||
case TGSI_TYPE_FLOAT:
|
|
||||||
dst_type = LLVMFloatTypeInContext(ctx);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dst_type = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst_type)
|
if (dst_type)
|
||||||
return LLVMBuildBitCast(builder, value, dst_type, "");
|
return LLVMBuildBitCast(builder, value, dst_type, "");
|
||||||
|
|
|
||||||
|
|
@ -80,136 +80,124 @@ static LLVMValueRef emit_swizzle(
|
||||||
LLVMConstVector(swizzles, 4), "");
|
LLVMConstVector(swizzles, 4), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct tgsi_declaration_range
|
||||||
|
get_array_range(struct lp_build_tgsi_context *bld_base,
|
||||||
|
unsigned File, const struct tgsi_ind_register *reg)
|
||||||
|
{
|
||||||
|
struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
|
||||||
|
if (File != TGSI_FILE_TEMPORARY || reg->ArrayID == 0 ||
|
||||||
|
reg->ArrayID > RADEON_LLVM_MAX_ARRAYS) {
|
||||||
|
struct tgsi_declaration_range range;
|
||||||
|
range.First = 0;
|
||||||
|
range.Last = bld_base->info->file_max[File];
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->arrays[reg->ArrayID - 1];
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef
|
static LLVMValueRef
|
||||||
emit_array_index(
|
emit_array_index(
|
||||||
struct lp_build_tgsi_soa_context *bld,
|
struct lp_build_tgsi_soa_context *bld,
|
||||||
const struct tgsi_full_src_register *reg,
|
const struct tgsi_ind_register *reg,
|
||||||
unsigned swizzle)
|
unsigned offset)
|
||||||
{
|
{
|
||||||
struct gallivm_state * gallivm = bld->bld_base.base.gallivm;
|
struct gallivm_state * gallivm = bld->bld_base.base.gallivm;
|
||||||
|
|
||||||
LLVMValueRef addr = LLVMBuildLoad(gallivm->builder,
|
LLVMValueRef addr = LLVMBuildLoad(gallivm->builder, bld->addr[reg->Index][reg->Swizzle], "");
|
||||||
bld->addr[reg->Indirect.Index][swizzle], "");
|
return LLVMBuildAdd(gallivm->builder, addr, lp_build_const_int32(gallivm, offset), "");
|
||||||
LLVMValueRef offset = lp_build_const_int32(gallivm, reg->Register.Index);
|
|
||||||
LLVMValueRef hw_index = LLVMBuildAdd(gallivm->builder, addr, offset, "");
|
|
||||||
LLVMValueRef soa_index = LLVMBuildMul(gallivm->builder, hw_index,
|
|
||||||
lp_build_const_int32(gallivm, 4), "");
|
|
||||||
LLVMValueRef array_index = LLVMBuildAdd(gallivm->builder, soa_index,
|
|
||||||
lp_build_const_int32(gallivm, swizzle), "");
|
|
||||||
|
|
||||||
return array_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef
|
static LLVMValueRef
|
||||||
emit_fetch_immediate(
|
emit_fetch(
|
||||||
struct lp_build_tgsi_context *bld_base,
|
struct lp_build_tgsi_context *bld_base,
|
||||||
const struct tgsi_full_src_register *reg,
|
const struct tgsi_full_src_register *reg,
|
||||||
enum tgsi_opcode_type type,
|
enum tgsi_opcode_type type,
|
||||||
|
unsigned swizzle);
|
||||||
|
|
||||||
|
static LLVMValueRef
|
||||||
|
emit_array_fetch(
|
||||||
|
struct lp_build_tgsi_context *bld_base,
|
||||||
|
unsigned File, enum tgsi_opcode_type type,
|
||||||
|
struct tgsi_declaration_range range,
|
||||||
unsigned swizzle)
|
unsigned swizzle)
|
||||||
{
|
{
|
||||||
LLVMTypeRef ctype;
|
|
||||||
LLVMContextRef ctx = bld_base->base.gallivm->context;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case TGSI_TYPE_UNSIGNED:
|
|
||||||
case TGSI_TYPE_SIGNED:
|
|
||||||
ctype = LLVMInt32TypeInContext(ctx);
|
|
||||||
break;
|
|
||||||
case TGSI_TYPE_UNTYPED:
|
|
||||||
case TGSI_TYPE_FLOAT:
|
|
||||||
ctype = LLVMFloatTypeInContext(ctx);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ctype = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
|
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
|
||||||
if (swizzle == ~0) {
|
struct gallivm_state * gallivm = bld->bld_base.base.gallivm;
|
||||||
LLVMValueRef values[TGSI_NUM_CHANNELS] = {};
|
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
|
||||||
unsigned chan;
|
|
||||||
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
|
unsigned i, size = range.Last - range.First + 1;
|
||||||
values[chan] = LLVMConstBitCast(bld->immediates[reg->Register.Index][chan], ctype);
|
LLVMTypeRef vec = LLVMVectorType(tgsi2llvmtype(bld_base, type), size);
|
||||||
}
|
LLVMValueRef result = LLVMGetUndef(vec);
|
||||||
return lp_build_gather_values(bld_base->base.gallivm, values,
|
|
||||||
TGSI_NUM_CHANNELS);
|
struct tgsi_full_src_register tmp_reg = {};
|
||||||
} else {
|
tmp_reg.Register.File = File;
|
||||||
return LLVMConstBitCast(bld->immediates[reg->Register.Index][swizzle], ctype);
|
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
tmp_reg.Register.Index = i + range.First;
|
||||||
|
LLVMValueRef temp = emit_fetch(bld_base, &tmp_reg, type, swizzle);
|
||||||
|
result = LLVMBuildInsertElement(builder, result, temp,
|
||||||
|
lp_build_const_int32(gallivm, i), "");
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef
|
static LLVMValueRef
|
||||||
emit_fetch_input(
|
emit_fetch(
|
||||||
struct lp_build_tgsi_context *bld_base,
|
struct lp_build_tgsi_context *bld_base,
|
||||||
const struct tgsi_full_src_register *reg,
|
const struct tgsi_full_src_register *reg,
|
||||||
enum tgsi_opcode_type type,
|
enum tgsi_opcode_type type,
|
||||||
unsigned swizzle)
|
unsigned swizzle)
|
||||||
{
|
{
|
||||||
struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
|
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)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
|
||||||
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
|
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
|
||||||
|
LLVMValueRef result, ptr;
|
||||||
|
|
||||||
if (swizzle == ~0) {
|
if (swizzle == ~0) {
|
||||||
LLVMValueRef values[TGSI_NUM_CHANNELS] = {};
|
LLVMValueRef values[TGSI_NUM_CHANNELS];
|
||||||
unsigned chan;
|
unsigned chan;
|
||||||
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
|
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
|
||||||
values[chan] = emit_fetch_temporary(bld_base, reg, type, chan);
|
values[chan] = emit_fetch(bld_base, reg, type, chan);
|
||||||
}
|
}
|
||||||
return lp_build_gather_values(bld_base->base.gallivm, values,
|
return lp_build_gather_values(bld_base->base.gallivm, values,
|
||||||
TGSI_NUM_CHANNELS);
|
TGSI_NUM_CHANNELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->Register.Indirect) {
|
if (reg->Register.Indirect) {
|
||||||
LLVMValueRef array_index = emit_array_index(bld, reg, swizzle);
|
struct tgsi_declaration_range range = get_array_range(bld_base,
|
||||||
LLVMValueRef ptr = LLVMBuildGEP(builder, bld->temps_array, &array_index,
|
reg->Register.File, ®->Indirect);
|
||||||
1, "");
|
return LLVMBuildExtractElement(builder,
|
||||||
return LLVMBuildLoad(builder, ptr, "");
|
emit_array_fetch(bld_base, reg->Register.File, type, range, swizzle),
|
||||||
} else {
|
emit_array_index(bld, ®->Indirect, reg->Register.Index - range.First),
|
||||||
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
|
switch(reg->Register.File) {
|
||||||
emit_fetch_output(
|
case TGSI_FILE_IMMEDIATE: {
|
||||||
struct lp_build_tgsi_context *bld_base,
|
LLVMTypeRef ctype = tgsi2llvmtype(bld_base, type);
|
||||||
const struct tgsi_full_src_register *reg,
|
return LLVMConstBitCast(bld->immediates[reg->Register.Index][swizzle], ctype);
|
||||||
enum tgsi_opcode_type type,
|
}
|
||||||
unsigned swizzle)
|
|
||||||
{
|
case TGSI_FILE_INPUT:
|
||||||
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
|
result = ctx->inputs[radeon_llvm_reg_index_soa(reg->Register.Index, swizzle)];
|
||||||
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
|
break;
|
||||||
if (reg->Register.Indirect) {
|
|
||||||
LLVMValueRef array_index = emit_array_index(bld, reg, swizzle);
|
case TGSI_FILE_TEMPORARY:
|
||||||
LLVMValueRef ptr = LLVMBuildGEP(builder, bld->outputs_array, &array_index,
|
ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle);
|
||||||
1, "");
|
result = LLVMBuildLoad(builder, ptr, "");
|
||||||
return LLVMBuildLoad(builder, ptr, "");
|
break;
|
||||||
} else {
|
|
||||||
LLVMValueRef temp_ptr;
|
case TGSI_FILE_OUTPUT:
|
||||||
temp_ptr = lp_get_output_ptr(bld, reg->Register.Index, swizzle);
|
ptr = lp_get_output_ptr(bld, reg->Register.Index, swizzle);
|
||||||
return LLVMBuildLoad(builder, temp_ptr, "");
|
result = LLVMBuildLoad(builder, ptr, "");
|
||||||
}
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return LLVMGetUndef(tgsi2llvmtype(bld_base, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitcast(bld_base, type, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_declaration(
|
static void emit_declaration(
|
||||||
|
|
@ -233,6 +221,8 @@ static void emit_declaration(
|
||||||
}
|
}
|
||||||
|
|
||||||
case TGSI_FILE_TEMPORARY:
|
case TGSI_FILE_TEMPORARY:
|
||||||
|
if (decl->Declaration.Array && decl->Array.ArrayID <= RADEON_LLVM_MAX_ARRAYS)
|
||||||
|
ctx->arrays[decl->Array.ArrayID - 1] = decl->Range;
|
||||||
lp_emit_declaration_soa(bld_base, decl);
|
lp_emit_declaration_soa(bld_base, decl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -291,6 +281,7 @@ emit_store(
|
||||||
LLVMValueRef temp_ptr;
|
LLVMValueRef temp_ptr;
|
||||||
unsigned chan, chan_index;
|
unsigned chan, chan_index;
|
||||||
boolean is_vec_store = FALSE;
|
boolean is_vec_store = FALSE;
|
||||||
|
|
||||||
if (dst[0]) {
|
if (dst[0]) {
|
||||||
LLVMTypeKind k = LLVMGetTypeKind(LLVMTypeOf(dst[0]));
|
LLVMTypeKind k = LLVMGetTypeKind(LLVMTypeOf(dst[0]));
|
||||||
is_vec_store = (k == LLVMVectorTypeKind);
|
is_vec_store = (k == LLVMVectorTypeKind);
|
||||||
|
|
@ -333,26 +324,56 @@ emit_store(
|
||||||
&clamp_emit_data);
|
&clamp_emit_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(reg->Register.File) {
|
if (reg->Register.File == TGSI_FILE_ADDRESS) {
|
||||||
case TGSI_FILE_ADDRESS:
|
|
||||||
temp_ptr = bld->addr[reg->Register.Index][chan_index];
|
temp_ptr = bld->addr[reg->Register.Index][chan_index];
|
||||||
LLVMBuildStore(builder, value, temp_ptr);
|
LLVMBuildStore(builder, value, temp_ptr);
|
||||||
continue;
|
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);
|
value = bitcast(bld_base, TGSI_TYPE_FLOAT, value);
|
||||||
|
|
||||||
LLVMBuildStore(builder, value, temp_ptr);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1128,14 +1149,16 @@ void radeon_llvm_context_init(struct radeon_llvm_context * ctx)
|
||||||
bld_base->emit_declaration = emit_declaration;
|
bld_base->emit_declaration = emit_declaration;
|
||||||
bld_base->emit_immediate = emit_immediate;
|
bld_base->emit_immediate = emit_immediate;
|
||||||
|
|
||||||
bld_base->emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate;
|
bld_base->emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch;
|
||||||
bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input;
|
bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch;
|
||||||
bld_base->emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary;
|
bld_base->emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch;
|
||||||
bld_base->emit_fetch_funcs[TGSI_FILE_OUTPUT] = emit_fetch_output;
|
bld_base->emit_fetch_funcs[TGSI_FILE_OUTPUT] = emit_fetch;
|
||||||
|
|
||||||
/* Allocate outputs */
|
/* Allocate outputs */
|
||||||
ctx->soa.outputs = ctx->outputs;
|
ctx->soa.outputs = ctx->outputs;
|
||||||
|
|
||||||
|
ctx->num_arrays = 0;
|
||||||
|
|
||||||
/* XXX: Is there a better way to initialize all this ? */
|
/* XXX: Is there a better way to initialize all this ? */
|
||||||
|
|
||||||
lp_set_default_actions(bld_base);
|
lp_set_default_actions(bld_base);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue