[Mesa-dev] [PATCH 06/11] gallivm: add support for TGSI instructions with two outputs
Nicolai Hähnle
nhaehnle at gmail.com
Sat Sep 16 11:23:48 UTC 2017
From: Nicolai Hähnle <nicolai.haehnle at amd.com>
---
src/gallium/auxiliary/gallivm/lp_bld_tgsi.c | 18 +++++++++++++++++-
src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.h | 5 +++++
src/gallium/auxiliary/tgsi/tgsi_exec.h | 9 +++++++++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
index 66f752989ab..b33976bb647 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
@@ -257,25 +257,31 @@ lp_build_tgsi_inst_llvm(
break;
}
/* Check if the opcode has been implemented */
if (!action->emit) {
return FALSE;
}
memset(&emit_data, 0, sizeof(emit_data));
- assert(info->num_dst <= 1);
+ assert(info->num_dst <= 2);
if (info->num_dst) {
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
emit_data.output[chan_index] = bld_base->base.undef;
}
+
+ if (info->num_dst >= 2) {
+ TGSI_FOR_EACH_DST1_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_data.output1[chan_index] = bld_base->base.undef;
+ }
+ }
}
emit_data.inst = inst;
emit_data.info = info;
/* Emit the instructions */
if (info->output_mode == TGSI_OUTPUT_COMPONENTWISE && bld_base->soa) {
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
int src_index = get_src_chan_idx(inst->Instruction.Opcode, chan_index);
/* ignore channels 1/3 in double dst */
@@ -302,25 +308,35 @@ lp_build_tgsi_inst_llvm(
}
action->emit(action, bld_base, &emit_data);
/* Replicate the output values */
if (info->output_mode == TGSI_OUTPUT_REPLICATE && bld_base->soa) {
val = emit_data.output[0];
memset(emit_data.output, 0, sizeof(emit_data.output));
TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
emit_data.output[chan_index] = val;
}
+
+ if (info->num_dst >= 2) {
+ val = emit_data.output1[0];
+ memset(emit_data.output1, 0, sizeof(emit_data.output1));
+ TGSI_FOR_EACH_DST1_ENABLED_CHANNEL(inst, chan_index) {
+ emit_data.output1[chan_index] = val;
+ }
+ }
}
}
if (info->num_dst > 0 && info->opcode != TGSI_OPCODE_STORE) {
bld_base->emit_store(bld_base, inst, info, 0, emit_data.output);
+ if (info->num_dst >= 2)
+ bld_base->emit_store(bld_base, inst, info, 1, emit_data.output1);
}
return TRUE;
}
LLVMValueRef
lp_build_emit_fetch_src(
struct lp_build_tgsi_context *bld_base,
const struct tgsi_full_src_register *reg,
enum tgsi_opcode_type stype,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.h
index 463d44eb450..c92517fee28 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.h
@@ -75,20 +75,25 @@ struct lp_build_emit_data {
* This is used to specify the src channel to read from for doubles.
*/
unsigned src_chan;
/** The lp_build_tgsi_action::emit 'executes' the opcode and writes the
* results to this array.
*/
LLVMValueRef output[4];
/**
+ * Secondary output for instruction that have a second destination register.
+ */
+ LLVMValueRef output1[4];
+
+ /**
* The current instruction that is being 'executed'.
*/
const struct tgsi_full_instruction * inst;
const struct tgsi_opcode_info * info;
};
struct lp_build_tgsi_action
{
/**
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 9d7e65f2c51..f656133400d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -51,20 +51,29 @@ extern "C" {
#define TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
((INST)->Dst[0].Register.WriteMask & (1 << (CHAN)))
#define TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
if (TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
#define TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
TGSI_FOR_EACH_CHANNEL( CHAN )\
TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
+#define TGSI_IS_DST1_CHANNEL_ENABLED( INST, CHAN )\
+ ((INST)->Dst[1].Register.WriteMask & (1 << (CHAN)))
+
+#define TGSI_IF_IS_DST1_CHANNEL_ENABLED( INST, CHAN )\
+ if (TGSI_IS_DST1_CHANNEL_ENABLED( INST, CHAN ))
+
+#define TGSI_FOR_EACH_DST1_ENABLED_CHANNEL( INST, CHAN )\
+ TGSI_FOR_EACH_CHANNEL( CHAN )\
+ TGSI_IF_IS_DST1_CHANNEL_ENABLED( INST, CHAN )
/**
* Registers may be treated as float, signed int or unsigned int.
*/
union tgsi_exec_channel
{
float f[TGSI_QUAD_SIZE];
int i[TGSI_QUAD_SIZE];
unsigned u[TGSI_QUAD_SIZE];
};
--
2.11.0
More information about the mesa-dev
mailing list