pan/va: Add flow control lowering pass
Something an instruction has two logic flow controls, namely wait + reconverge. These are orthogonal -- we need to insert a NOP to handle this. Add a lowering pass that works out flow control to replace the ad hoc previous va_pack_flow. Fixes dEQP-GLES31.functional.ssbo.layout.single_basic_type.shared.lowp_vec3. Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15756>
This commit is contained in:
parent
4f5e0e1874
commit
862a19aa4b
|
@ -28,7 +28,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#define CASE(instr, expected) do { \
|
#define CASE(instr, expected) do { \
|
||||||
uint64_t _value = va_pack_instr(instr, 0); \
|
uint64_t _value = va_pack_instr(instr); \
|
||||||
if (_value != expected) { \
|
if (_value != expected) { \
|
||||||
fprintf(stderr, "Got %" PRIx64 ", expected %" PRIx64 "\n", _value, (uint64_t) expected); \
|
fprintf(stderr, "Got %" PRIx64 ", expected %" PRIx64 "\n", _value, (uint64_t) expected); \
|
||||||
bi_print_instr(instr, stderr); \
|
bi_print_instr(instr, stderr); \
|
||||||
|
|
|
@ -40,7 +40,7 @@ void va_repair_fau(bi_builder *b, bi_instr *I);
|
||||||
void va_fuse_add_imm(bi_instr *I);
|
void va_fuse_add_imm(bi_instr *I);
|
||||||
void va_lower_constants(bi_context *ctx, bi_instr *I);
|
void va_lower_constants(bi_context *ctx, bi_instr *I);
|
||||||
void va_lower_isel(bi_instr *I);
|
void va_lower_isel(bi_instr *I);
|
||||||
uint64_t va_pack_instr(const bi_instr *I, unsigned flow);
|
uint64_t va_pack_instr(const bi_instr *I);
|
||||||
|
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
va_fau_page(enum bir_fau value)
|
va_fau_page(enum bir_fau value)
|
||||||
|
|
|
@ -609,11 +609,11 @@ va_pack_register_format(const bi_instr *I)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
va_pack_instr(const bi_instr *I, unsigned flow)
|
va_pack_instr(const bi_instr *I)
|
||||||
{
|
{
|
||||||
struct va_opcode_info info = valhall_opcodes[I->op];
|
struct va_opcode_info info = valhall_opcodes[I->op];
|
||||||
|
|
||||||
uint64_t hex = info.exact | (((uint64_t) flow) << 59);
|
uint64_t hex = info.exact | (((uint64_t) I->flow) << 59);
|
||||||
hex |= ((uint64_t) va_select_fau_page(I)) << 57;
|
hex |= ((uint64_t) va_select_fau_page(I)) << 57;
|
||||||
|
|
||||||
if (info.slot) {
|
if (info.slot) {
|
||||||
|
@ -816,28 +816,6 @@ va_should_return(bi_block *block, bi_instr *I)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum va_flow
|
|
||||||
va_pack_flow(bi_block *block, bi_instr *I)
|
|
||||||
{
|
|
||||||
if (va_should_return(block, I))
|
|
||||||
return VA_FLOW_END;
|
|
||||||
|
|
||||||
if (va_last_in_block(block, I) && bi_reconverge_branches(block))
|
|
||||||
return VA_FLOW_RECONVERGE;
|
|
||||||
|
|
||||||
if (I->op == BI_OPCODE_BARRIER)
|
|
||||||
return VA_FLOW_WAIT;
|
|
||||||
|
|
||||||
if (I->flow)
|
|
||||||
return I->flow;
|
|
||||||
|
|
||||||
/* TODO: Generalize waits */
|
|
||||||
if (valhall_opcodes[I->op].nr_staging_dests > 0 || I->op == BI_OPCODE_BLEND)
|
|
||||||
return VA_FLOW_WAIT0;
|
|
||||||
|
|
||||||
return VA_FLOW_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
va_instructions_in_block(bi_block *block)
|
va_instructions_in_block(bi_block *block)
|
||||||
{
|
{
|
||||||
|
@ -958,6 +936,59 @@ va_lower_blend(bi_context *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a flow control modifier to an instruction. There may be an existing flow
|
||||||
|
* control modifier; if so, we need to add a NOP with the extra flow control
|
||||||
|
* _after_ this instruction
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
va_add_flow(bi_context *ctx, bi_instr *I, enum va_flow flow)
|
||||||
|
{
|
||||||
|
if (I->flow != VA_FLOW_NONE) {
|
||||||
|
bi_builder b = bi_init_builder(ctx, bi_after_instr(I));
|
||||||
|
I = bi_nop(&b);
|
||||||
|
}
|
||||||
|
|
||||||
|
I->flow = flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add flow control modifiers to the program. This is a stop gap until we have a
|
||||||
|
* proper scheduler. For now, this should be conformant while doing little
|
||||||
|
* optimization of message waits.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
va_lower_flow_control(bi_context *ctx)
|
||||||
|
{
|
||||||
|
bi_foreach_block(ctx, block) {
|
||||||
|
bool block_reconverges = bi_reconverge_branches(block);
|
||||||
|
|
||||||
|
bi_foreach_instr_in_block_safe(block, I) {
|
||||||
|
/* If this instruction returns, there is nothing left to do. */
|
||||||
|
if (va_should_return(block, I)) {
|
||||||
|
I->flow = VA_FLOW_END;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We may need to wait */
|
||||||
|
if (I->op == BI_OPCODE_BARRIER)
|
||||||
|
va_add_flow(ctx, I, VA_FLOW_WAIT);
|
||||||
|
else if (valhall_opcodes[I->op].nr_staging_dests > 0 || I->op == BI_OPCODE_BLEND)
|
||||||
|
va_add_flow(ctx, I, VA_FLOW_WAIT0);
|
||||||
|
|
||||||
|
/* Lastly, we may need to reconverge. If we need reconvergence, it
|
||||||
|
* has to be on the last instruction of the block. If we have to
|
||||||
|
* generate a NOP for that reconverge, we need that to be last. So
|
||||||
|
* this ordering is careful.
|
||||||
|
*/
|
||||||
|
if (va_last_in_block(block, I) && block_reconverges)
|
||||||
|
va_add_flow(ctx, I, VA_FLOW_RECONVERGE);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bi_pack_valhall(bi_context *ctx, struct util_dynarray *emission)
|
bi_pack_valhall(bi_context *ctx, struct util_dynarray *emission)
|
||||||
{
|
{
|
||||||
|
@ -969,13 +1000,14 @@ bi_pack_valhall(bi_context *ctx, struct util_dynarray *emission)
|
||||||
if (ctx->stage == MESA_SHADER_FRAGMENT && !ctx->inputs->is_blend)
|
if (ctx->stage == MESA_SHADER_FRAGMENT && !ctx->inputs->is_blend)
|
||||||
va_lower_blend(ctx);
|
va_lower_blend(ctx);
|
||||||
|
|
||||||
|
va_lower_flow_control(ctx);
|
||||||
|
|
||||||
bi_foreach_block(ctx, block) {
|
bi_foreach_block(ctx, block) {
|
||||||
bi_foreach_instr_in_block(block, I) {
|
bi_foreach_instr_in_block(block, I) {
|
||||||
if (I->op == BI_OPCODE_BRANCHZ_I16)
|
if (I->op == BI_OPCODE_BRANCHZ_I16)
|
||||||
va_lower_branch_target(ctx, block, I);
|
va_lower_branch_target(ctx, block, I);
|
||||||
|
|
||||||
unsigned flow = va_pack_flow(block, I);
|
uint64_t hex = va_pack_instr(I);
|
||||||
uint64_t hex = va_pack_instr(I, flow);
|
|
||||||
util_dynarray_append(emission, uint64_t, hex);
|
util_dynarray_append(emission, uint64_t, hex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue