brw: Add brw_load_payload_inst

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36730>
This commit is contained in:
Caio Oliveira
2025-08-22 00:08:22 -07:00
committed by Marge Bot
parent 388bac06ce
commit 90967e7b16
10 changed files with 102 additions and 66 deletions
+8 -7
View File
@@ -765,19 +765,20 @@ public:
/**
* Collect a number of registers in a contiguous range of registers.
*/
brw_inst *
brw_load_payload_inst *
LOAD_PAYLOAD(const brw_reg &dst, const brw_reg *src,
unsigned sources, unsigned header_size) const
{
brw_inst *inst = emit(SHADER_OPCODE_LOAD_PAYLOAD, dst, src, sources);
inst->header_size = header_size;
inst->size_written = header_size * REG_SIZE;
brw_load_payload_inst *lp =
emit(SHADER_OPCODE_LOAD_PAYLOAD, dst, src, sources)->as_load_payload();
lp->header_size = header_size;
lp->size_written = header_size * REG_SIZE;
for (unsigned i = header_size; i < sources; i++) {
inst->size_written += dispatch_width() * brw_type_size_bytes(src[i].type) *
dst.stride;
lp->size_written += dispatch_width() * brw_type_size_bytes(src[i].type) *
dst.stride;
}
return inst;
return lp;
}
brw_inst *
+5 -1
View File
@@ -17,6 +17,7 @@ brw_inst_kind_size(brw_inst_kind kind)
STATIC_ASSERT(sizeof(brw_send_inst) >= sizeof(brw_tex_inst));
STATIC_ASSERT(sizeof(brw_send_inst) >= sizeof(brw_mem_inst));
STATIC_ASSERT(sizeof(brw_send_inst) >= sizeof(brw_dpas_inst));
STATIC_ASSERT(sizeof(brw_send_inst) >= sizeof(brw_load_payload_inst));
/* TODO: Temporarily here to ensure all instructions can be converted to
* SEND. Once all new kinds are added, change so that BASE allocate only
@@ -188,6 +189,9 @@ brw_inst_kind_for_opcode(enum opcode opcode)
case BRW_OPCODE_DPAS:
return BRW_KIND_DPAS;
case SHADER_OPCODE_LOAD_PAYLOAD:
return BRW_KIND_LOAD_PAYLOAD;
default:
return BRW_KIND_BASE;
}
@@ -549,7 +553,7 @@ brw_inst::size_read(const struct intel_device_info *devinfo, int arg) const
break;
case SHADER_OPCODE_LOAD_PAYLOAD:
if (arg < this->header_size)
if (arg < as_load_payload()->header_size)
return retype(src[arg], BRW_TYPE_UD).component_size(8);
break;
+10 -3
View File
@@ -45,6 +45,7 @@ enum ENUM_PACKED brw_inst_kind {
BRW_KIND_TEX,
BRW_KIND_MEM,
BRW_KIND_DPAS,
BRW_KIND_LOAD_PAYLOAD,
};
brw_inst_kind brw_inst_kind_for_opcode(enum opcode opcode);
@@ -74,6 +75,7 @@ struct brw_inst : brw_exec_node {
KIND_HELPERS(as_tex, brw_tex_inst, BRW_KIND_TEX);
KIND_HELPERS(as_mem, brw_mem_inst, BRW_KIND_MEM);
KIND_HELPERS(as_dpas, brw_dpas_inst, BRW_KIND_DPAS);
KIND_HELPERS(as_load_payload, brw_load_payload_inst, BRW_KIND_LOAD_PAYLOAD);
#undef KIND_HELPERS
@@ -168,9 +170,6 @@ struct brw_inst : brw_exec_node {
*/
uint8_t group;
/** The number of hardware registers used for a message header. */
uint8_t header_size;
uint32_t offset; /**< spill/unspill offset or texture offset bitfield */
uint16_t size_written; /**< Data written to the destination register in bytes. */
@@ -238,6 +237,9 @@ struct brw_send_inst : brw_inst {
uint8_t ex_mlen;
uint8_t sfid;
/** The number of hardware registers used for a message header. */
uint8_t header_size;
union {
struct {
/**
@@ -296,6 +298,11 @@ struct brw_dpas_inst : brw_inst {
uint8_t rcount;
};
struct brw_load_payload_inst : brw_inst {
/** The number of hardware registers used for a message header. */
uint8_t header_size;
};
/**
* Make the execution of \p inst dependent on the evaluation of a possibly
* inverted predicate.
+18 -16
View File
@@ -56,41 +56,43 @@ brw_lower_load_payload(brw_shader &s)
if (inst->opcode != SHADER_OPCODE_LOAD_PAYLOAD)
continue;
assert(inst->dst.file == VGRF);
assert(inst->saturate == false);
brw_reg dst = inst->dst;
brw_load_payload_inst *lp = inst->as_load_payload();
const brw_builder ibld(inst);
assert(lp->dst.file == VGRF);
assert(lp->saturate == false);
brw_reg dst = lp->dst;
const brw_builder ibld(lp);
const brw_builder ubld = ibld.exec_all();
for (uint8_t i = 0; i < inst->header_size;) {
for (uint8_t i = 0; i < lp->header_size;) {
/* Number of header GRFs to initialize at once with a single MOV
* instruction.
*/
const unsigned n =
(i + 1 < inst->header_size &&
(inst->src[i].file == IMM ||
(inst->src[i].is_contiguous() &&
inst->src[i + 1].equals(byte_offset(inst->src[i], REG_SIZE))))) ?
(i + 1 < lp->header_size &&
(lp->src[i].file == IMM ||
(lp->src[i].is_contiguous() &&
lp->src[i + 1].equals(byte_offset(lp->src[i], REG_SIZE))))) ?
2 : 1;
if (inst->src[i].file != BAD_FILE)
if (lp->src[i].file != BAD_FILE)
ubld.group(8 * n, 0).MOV(retype(dst, BRW_TYPE_UD),
retype(inst->src[i], BRW_TYPE_UD));
retype(lp->src[i], BRW_TYPE_UD));
dst = byte_offset(dst, n * REG_SIZE);
i += n;
}
for (uint8_t i = inst->header_size; i < inst->sources; i++) {
dst.type = inst->src[i].type;
if (inst->src[i].file != BAD_FILE) {
ibld.MOV(dst, inst->src[i]);
for (uint8_t i = lp->header_size; i < lp->sources; i++) {
dst.type = lp->src[i].type;
if (lp->src[i].file != BAD_FILE) {
ibld.MOV(dst, lp->src[i]);
}
dst = offset(dst, ibld, 1);
}
inst->remove();
lp->remove();
progress = true;
}
@@ -45,7 +45,6 @@ lower_urb_read_logical_send(const brw_builder &bld, brw_inst *inst)
inst->src[URB_LOGICAL_SRC_PER_SLOT_OFFSETS].file != BAD_FILE;
assert(inst->size_written % REG_SIZE == 0);
assert(inst->header_size == 0);
brw_reg payload_sources[2];
unsigned header_size = 0;
@@ -86,7 +85,6 @@ lower_urb_read_logical_send_xe2(const brw_builder &bld, brw_inst *inst)
assert(devinfo->has_lsc);
assert(inst->size_written % (REG_SIZE * reg_unit(devinfo)) == 0);
assert(inst->header_size == 0);
/* Get the logical send arguments. */
const brw_reg handle = inst->src[URB_LOGICAL_SRC_HANDLE];
@@ -146,8 +144,6 @@ lower_urb_write_logical_send(const brw_builder &bld, brw_inst *inst)
const bool channel_mask_present =
inst->src[URB_LOGICAL_SRC_CHANNEL_MASK].file != BAD_FILE;
assert(inst->header_size == 0);
const unsigned length = 1 + per_slot_present + channel_mask_present +
inst->components_read(URB_LOGICAL_SRC_DATA);
+9 -7
View File
@@ -437,8 +437,10 @@ brw_get_lowered_simd_width(const brw_shader *shader, const brw_inst *inst)
}
case SHADER_OPCODE_LOAD_PAYLOAD: {
const brw_load_payload_inst *lp = inst->as_load_payload();
const unsigned reg_count =
DIV_ROUND_UP(inst->dst.component_size(inst->exec_size),
DIV_ROUND_UP(lp->dst.component_size(lp->exec_size),
REG_SIZE * reg_unit(devinfo));
if (reg_count > 2) {
@@ -446,14 +448,14 @@ brw_get_lowered_simd_width(const brw_shader *shader, const brw_inst *inst)
* can be easily lowered (which excludes headers and heterogeneous
* types).
*/
assert(!inst->header_size);
for (unsigned i = 0; i < inst->sources; i++)
assert(brw_type_size_bits(inst->dst.type) == brw_type_size_bits(inst->src[i].type) ||
inst->src[i].file == BAD_FILE);
assert(!lp->header_size);
for (unsigned i = 0; i < lp->sources; i++)
assert(brw_type_size_bits(lp->dst.type) == brw_type_size_bits(lp->src[i].type) ||
lp->src[i].file == BAD_FILE);
return inst->exec_size / DIV_ROUND_UP(reg_count, 2);
return lp->exec_size / DIV_ROUND_UP(reg_count, 2);
} else {
return inst->exec_size;
return lp->exec_size;
}
}
default:
+9 -5
View File
@@ -234,7 +234,7 @@ brw_optimize(brw_shader &s)
}
static unsigned
load_payload_sources_read_for_size(brw_inst *lp, unsigned size_read)
load_payload_sources_read_for_size(brw_load_payload_inst *lp, unsigned size_read)
{
assert(lp->opcode == SHADER_OPCODE_LOAD_PAYLOAD);
assert(size_read >= lp->header_size * REG_SIZE);
@@ -283,11 +283,13 @@ brw_opt_zero_samples(brw_shader &s)
if (send->ex_mlen > 0)
continue;
brw_inst *lp = (brw_inst *) send->prev;
brw_inst *prev = (brw_inst *) send->prev;
if (lp->is_head_sentinel() || lp->opcode != SHADER_OPCODE_LOAD_PAYLOAD)
if (prev->is_head_sentinel() || prev->opcode != SHADER_OPCODE_LOAD_PAYLOAD)
continue;
brw_load_payload_inst *lp = prev->as_load_payload();
/* How much of the payload are actually read by this SEND. */
const unsigned params =
load_payload_sources_read_for_size(lp, send->mlen * REG_SIZE);
@@ -353,11 +355,13 @@ brw_opt_split_sends(brw_shader &s)
continue;
/* Currently don't split sends that reuse a previously used payload. */
brw_inst *lp = (brw_inst *) send->prev;
brw_inst *prev = (brw_inst *) send->prev;
if (lp->is_head_sentinel() || lp->opcode != SHADER_OPCODE_LOAD_PAYLOAD)
if (prev->is_head_sentinel() || prev->opcode != SHADER_OPCODE_LOAD_PAYLOAD)
continue;
brw_load_payload_inst *lp = prev->as_load_payload();
if (lp->dst.file != send->src[SEND_SRC_PAYLOAD1].file ||
lp->dst.nr != send->src[SEND_SRC_PAYLOAD1].nr)
continue;
+16 -15
View File
@@ -1482,25 +1482,26 @@ opt_copy_propagation_local(brw_shader &s, linear_ctx *lin_ctx,
acp.add(entry);
} else if (inst->opcode == SHADER_OPCODE_LOAD_PAYLOAD &&
inst->dst.file == VGRF) {
brw_load_payload_inst *lp = inst->as_load_payload();
int offset = 0;
for (int i = 0; i < inst->sources; i++) {
int effective_width = i < inst->header_size ? 8 : inst->exec_size;
for (int i = 0; i < lp->sources; i++) {
int effective_width = i < lp->header_size ? 8 : lp->exec_size;
const unsigned size_written =
effective_width * brw_type_size_bytes(inst->src[i].type);
if (inst->src[i].file == VGRF ||
(inst->src[i].file == FIXED_GRF &&
inst->src[i].is_contiguous())) {
const brw_reg_type t = i < inst->header_size ?
BRW_TYPE_UD : inst->src[i].type;
brw_reg dst = byte_offset(retype(inst->dst, t), offset);
if (!dst.equals(inst->src[i])) {
effective_width * brw_type_size_bytes(lp->src[i].type);
if (lp->src[i].file == VGRF ||
(lp->src[i].file == FIXED_GRF &&
lp->src[i].is_contiguous())) {
const brw_reg_type t = i < lp->header_size ?
BRW_TYPE_UD : lp->src[i].type;
brw_reg dst = byte_offset(retype(lp->dst, t), offset);
if (!dst.equals(lp->src[i])) {
acp_entry *entry = linear_zalloc(lin_ctx, acp_entry);
entry->dst = dst;
entry->src = retype(inst->src[i], t);
entry->src = retype(lp->src[i], t);
entry->size_written = size_written;
entry->size_read = inst->size_read(devinfo, i);
entry->opcode = inst->opcode;
entry->force_writemask_all = inst->force_writemask_all;
entry->size_read = lp->size_read(devinfo, i);
entry->opcode = lp->opcode;
entry->force_writemask_all = lp->force_writemask_all;
acp.add(entry);
}
}
@@ -1866,7 +1867,7 @@ find_value_for_offset(brw_inst *def, const brw_reg &src, unsigned src_size)
break;
case SHADER_OPCODE_LOAD_PAYLOAD: {
unsigned offset = 0;
for (int i = def->header_size; i < def->sources; i++) {
for (int i = def->as_load_payload()->header_size; i < def->sources; i++) {
/* Ignore the source splat if the source is a scalar. In that case
* always use just the first component.
*/
+19 -2
View File
@@ -246,6 +246,7 @@ send_inst_match(brw_send_inst *a, brw_send_inst *b)
return a->mlen == b->mlen &&
a->ex_mlen == b->ex_mlen &&
a->sfid == b->sfid &&
a->header_size == b->header_size &&
a->desc == b->desc &&
a->ex_desc == b->ex_desc &&
a->send_bits == b->send_bits;
@@ -280,6 +281,12 @@ dpas_inst_match(brw_dpas_inst *a, brw_dpas_inst *b)
a->rcount == b->rcount;
}
static bool
load_payload_inst_match(brw_load_payload_inst *a, brw_load_payload_inst *b)
{
return a->header_size == b->header_size;
}
static bool
instructions_match(brw_inst *a, brw_inst *b, bool *negate)
{
@@ -290,6 +297,8 @@ instructions_match(brw_inst *a, brw_inst *b, bool *negate)
(a->kind != BRW_KIND_TEX || tex_inst_match(a->as_tex(), b->as_tex())) &&
(a->kind != BRW_KIND_MEM || mem_inst_match(a->as_mem(), b->as_mem())) &&
(a->kind != BRW_KIND_DPAS || dpas_inst_match(a->as_dpas(), b->as_dpas())) &&
(a->kind != BRW_KIND_LOAD_PAYLOAD ||
load_payload_inst_match(a->as_load_payload(), b->as_load_payload())) &&
a->exec_size == b->exec_size &&
a->group == b->group &&
a->predicate == b->predicate &&
@@ -297,7 +306,6 @@ instructions_match(brw_inst *a, brw_inst *b, bool *negate)
a->dst.type == b->dst.type &&
a->offset == b->offset &&
a->size_written == b->size_written &&
a->header_size == b->header_size &&
a->sources == b->sources &&
a->bits == b->bits &&
operands_match(a, b, negate);
@@ -339,7 +347,6 @@ hash_inst(const void *v)
inst->sources,
inst->exec_size,
inst->group,
inst->header_size,
inst->conditional_mod,
inst->predicate,
@@ -364,6 +371,7 @@ hash_inst(const void *v)
send->ex_mlen,
send->sfid,
send->send_bits,
send->header_size,
};
const uint32_t send_u32data[] = {
send->desc,
@@ -415,6 +423,15 @@ hash_inst(const void *v)
break;
}
case BRW_KIND_LOAD_PAYLOAD: {
const brw_load_payload_inst *lp = inst->as_load_payload();
const uint8_t lp_u8data[] = {
lp->header_size,
};
hash = HASH(hash, lp_u8data);
break;
}
case BRW_KIND_BASE:
/* Nothing else to do. */
break;
@@ -48,14 +48,16 @@ static bool
is_nop_mov(const brw_inst *inst)
{
if (inst->opcode == SHADER_OPCODE_LOAD_PAYLOAD) {
brw_reg dst = inst->dst;
for (int i = 0; i < inst->sources; i++) {
if (!dst.equals(inst->src[i])) {
const brw_load_payload_inst *lp = inst->as_load_payload();
brw_reg dst = lp->dst;
for (int i = 0; i < lp->sources; i++) {
if (!dst.equals(lp->src[i])) {
return false;
}
dst.offset += (i < inst->header_size ? REG_SIZE :
inst->exec_size * dst.stride *
brw_type_size_bytes(inst->src[i].type));
dst.offset += (i < lp->header_size ? REG_SIZE :
lp->exec_size * dst.stride *
brw_type_size_bytes(lp->src[i].type));
}
return true;
} else if (inst->opcode == BRW_OPCODE_MOV) {