mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 11:48:06 +02:00
mi-builder: add relocated register/memory writes
When you want to write a value to a register or memory but you don't know just yet that value when you emit the command. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29571>
This commit is contained in:
parent
775db77baf
commit
a623760f82
2 changed files with 154 additions and 0 deletions
|
|
@ -1190,6 +1190,106 @@ mi_udiv32_imm(struct mi_builder *b, struct mi_value N, uint32_t D)
|
|||
/* This assumes addresses of strictly more than 32bits (aka. Gfx8+). */
|
||||
#if MI_BUILDER_CAN_WRITE_BATCH
|
||||
|
||||
struct mi_reloc_imm_token {
|
||||
enum mi_value_type dst_type;
|
||||
uint32_t *ptr[2];
|
||||
};
|
||||
|
||||
/* Emits a immediate write to an address/register where the immediate value
|
||||
* can be updated later.
|
||||
*/
|
||||
static inline struct mi_reloc_imm_token
|
||||
mi_store_relocated_imm(struct mi_builder *b, struct mi_value dst)
|
||||
{
|
||||
mi_builder_flush_math(b);
|
||||
|
||||
struct mi_reloc_imm_token token = {
|
||||
.dst_type = dst.type,
|
||||
};
|
||||
|
||||
uint32_t *dw;
|
||||
switch (dst.type) {
|
||||
case MI_VALUE_TYPE_MEM32:
|
||||
dw = (uint32_t *)__gen_get_batch_dwords(b->user_data,
|
||||
GENX(MI_STORE_DATA_IMM_length));
|
||||
mi_builder_pack(b, GENX(MI_STORE_DATA_IMM), dw, sdm) {
|
||||
sdm.DWordLength = GENX(MI_STORE_DATA_IMM_length) -
|
||||
GENX(MI_STORE_DATA_IMM_length_bias);
|
||||
sdm.Address = dst.addr;
|
||||
}
|
||||
token.ptr[0] = dw + GENX(MI_STORE_DATA_IMM_ImmediateData_start) / 32;
|
||||
break;
|
||||
|
||||
case MI_VALUE_TYPE_MEM64:
|
||||
dw = (uint32_t *)__gen_get_batch_dwords(b->user_data,
|
||||
GENX(MI_STORE_DATA_IMM_length) + 1);
|
||||
mi_builder_pack(b, GENX(MI_STORE_DATA_IMM), dw, sdm) {
|
||||
sdm.DWordLength = GENX(MI_STORE_DATA_IMM_length) + 1 -
|
||||
GENX(MI_STORE_DATA_IMM_length_bias);
|
||||
sdm.Address = dst.addr;
|
||||
}
|
||||
token.ptr[0] = &dw[GENX(MI_STORE_DATA_IMM_ImmediateData_start) / 32];
|
||||
token.ptr[1] = &dw[GENX(MI_STORE_DATA_IMM_ImmediateData_start) / 32 + 1];
|
||||
break;
|
||||
|
||||
case MI_VALUE_TYPE_REG32:
|
||||
dw = (uint32_t *)__gen_get_batch_dwords(b->user_data,
|
||||
GENX(MI_LOAD_REGISTER_IMM_length));
|
||||
mi_builder_pack(b, GENX(MI_LOAD_REGISTER_IMM), dw, lri) {
|
||||
lri.DWordLength = GENX(MI_LOAD_REGISTER_IMM_length) -
|
||||
GENX(MI_LOAD_REGISTER_IMM_length_bias);
|
||||
struct mi_reg_num reg = mi_adjust_reg_num(dst.reg);
|
||||
#if GFX_VER >= 11
|
||||
lri.AddCSMMIOStartOffset = reg.cs;
|
||||
#endif
|
||||
lri.RegisterOffset = reg.num;
|
||||
}
|
||||
token.ptr[0] = &dw[2];
|
||||
break;
|
||||
|
||||
case MI_VALUE_TYPE_REG64: {
|
||||
dw = (uint32_t *)__gen_get_batch_dwords(b->user_data,
|
||||
GENX(MI_LOAD_REGISTER_IMM_length) + 2);
|
||||
struct mi_reg_num reg = mi_adjust_reg_num(dst.reg);
|
||||
mi_builder_pack(b, GENX(MI_LOAD_REGISTER_IMM), dw, lri) {
|
||||
lri.DWordLength = GENX(MI_LOAD_REGISTER_IMM_length) + 2 -
|
||||
GENX(MI_LOAD_REGISTER_IMM_length_bias);
|
||||
#if GFX_VER >= 11
|
||||
lri.AddCSMMIOStartOffset = reg.cs;
|
||||
#endif
|
||||
}
|
||||
dw[1] = reg.num;
|
||||
dw[3] = reg.num + 4;
|
||||
token.ptr[0] = &dw[2];
|
||||
token.ptr[1] = &dw[4];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
unreachable("Invalid value type");
|
||||
}
|
||||
|
||||
mi_value_unref(b, dst);
|
||||
return token;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mi_relocate_store_imm(struct mi_reloc_imm_token token, uint64_t value)
|
||||
{
|
||||
switch (token.dst_type) {
|
||||
case MI_VALUE_TYPE_MEM64:
|
||||
case MI_VALUE_TYPE_REG64:
|
||||
*token.ptr[1] = value >> 32;
|
||||
FALLTHROUGH;
|
||||
case MI_VALUE_TYPE_MEM32:
|
||||
case MI_VALUE_TYPE_REG32:
|
||||
*token.ptr[0] = value & 0xffffffff;
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid value type");
|
||||
}
|
||||
}
|
||||
|
||||
struct mi_address_token {
|
||||
/* Pointers to address memory fields in the batch. */
|
||||
uint64_t *ptrs[2];
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ __gen_address_offset(address addr, uint64_t offset)
|
|||
#define INPUT_DATA_OFFSET 0
|
||||
#define OUTPUT_DATA_OFFSET 2048
|
||||
|
||||
#define MI_BUILDER_CAN_WRITE_BATCH GFX_VER >= 8
|
||||
|
||||
#define __genxml_cmd_length(cmd) cmd ## _length
|
||||
#define __genxml_cmd_length_bias(cmd) cmd ## _length_bias
|
||||
#define __genxml_cmd_header(cmd) cmd ## _header
|
||||
|
|
@ -742,6 +744,58 @@ TEST_F(mi_builder_test, iand)
|
|||
mi_imm(values[1])));
|
||||
}
|
||||
|
||||
#if GFX_VER >= 8
|
||||
TEST_F(mi_builder_test, imm_mem_relocated)
|
||||
{
|
||||
const uint64_t value = 0x0123456789abcdef;
|
||||
|
||||
struct mi_reloc_imm_token r0 = mi_store_relocated_imm(&b, out_mem64(0));
|
||||
struct mi_reloc_imm_token r1 = mi_store_relocated_imm(&b, out_mem32(8));
|
||||
|
||||
mi_relocate_store_imm(r0, value);
|
||||
mi_relocate_store_imm(r1, value);
|
||||
|
||||
submit_batch();
|
||||
|
||||
// 64 -> 64
|
||||
EXPECT_EQ(*(uint64_t *)(output + 0), value);
|
||||
|
||||
// 64 -> 32
|
||||
EXPECT_EQ(*(uint32_t *)(output + 8), (uint32_t)value);
|
||||
EXPECT_EQ(*(uint32_t *)(output + 12), (uint32_t)canary);
|
||||
}
|
||||
|
||||
TEST_F(mi_builder_test, imm_reg_relocated)
|
||||
{
|
||||
const uint64_t value = 0x0123456789abcdef;
|
||||
|
||||
struct mi_reloc_imm_token r0, r1;
|
||||
|
||||
r0 = mi_store_relocated_imm(&b, mi_reg64(RSVD_TEMP_REG));
|
||||
r1 = mi_store_relocated_imm(&b, mi_reg64(RSVD_TEMP_REG));
|
||||
mi_store(&b, out_mem64(0), mi_reg64(RSVD_TEMP_REG));
|
||||
|
||||
mi_relocate_store_imm(r0, canary);
|
||||
mi_relocate_store_imm(r1, value);
|
||||
|
||||
r0 = mi_store_relocated_imm(&b, mi_reg64(RSVD_TEMP_REG));
|
||||
r1 = mi_store_relocated_imm(&b, mi_reg32(RSVD_TEMP_REG));
|
||||
mi_store(&b, out_mem64(8), mi_reg64(RSVD_TEMP_REG));
|
||||
|
||||
mi_relocate_store_imm(r0, canary);
|
||||
mi_relocate_store_imm(r1, value);
|
||||
|
||||
submit_batch();
|
||||
|
||||
// 64 -> 64
|
||||
EXPECT_EQ(*(uint64_t *)(output + 0), value);
|
||||
|
||||
// 64 -> 32
|
||||
EXPECT_EQ(*(uint32_t *)(output + 8), (uint32_t)value);
|
||||
EXPECT_EQ(*(uint32_t *)(output + 12), (uint32_t)canary);
|
||||
}
|
||||
#endif // GFX_VER >= 8
|
||||
|
||||
#if GFX_VERx10 >= 125
|
||||
TEST_F(mi_builder_test, ishl)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue