mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
shader: own control flow on IR blocks with direct targets
This commit is contained in:
1 parent
8abf99c56e
commit
3df456675d
13 files changed
+477
-472
No files matched your search
+190
-141
@@ -58,8 +58,8 @@ struct Fixture {
|
||||
auto *result = storage.get();
|
||||
program.block_storage.push_back(std::move(storage));
|
||||
program.blocks.push_back(result);
|
||||
program.block_info.push_back(
|
||||
{.id = static_cast<uint32_t>(program.block_info.size())});
|
||||
program.blocks.back()->id =
|
||||
static_cast<uint32_t>(program.blocks.size() - 1u);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ struct Fixture {
|
||||
}
|
||||
|
||||
void PlanAndTrack() {
|
||||
for (size_t index = 0; index < program.block_info.size(); ++index) {
|
||||
const auto condition = program.block_info[index].condition;
|
||||
for (size_t index = 0; index < program.blocks.size(); ++index) {
|
||||
const auto condition = program.blocks[index]->condition;
|
||||
if (!condition.IsEmpty())
|
||||
Emit(ValueOpcode::Reference, {condition}, 0, program.blocks[index]);
|
||||
}
|
||||
@@ -475,9 +475,11 @@ void TestWaterfallImageTable() {
|
||||
{guard, fixture->Emit(ValueOpcode::IEqual32, {image_words[word], local})});
|
||||
}
|
||||
}
|
||||
fixture->program.block_info[0].condition = guard;
|
||||
fixture->program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch, .true_block = 1u, .false_block = 2u};
|
||||
fixture->program.blocks[0]->condition = guard;
|
||||
fixture->program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = fixture->program.blocks[1u],
|
||||
.false_block = fixture->program.blocks[2u]};
|
||||
const auto sample = [&](Value image, Block *block) {
|
||||
const auto sampler = fixture->Sampler({Value(0u), Value(0u), Value(0u), Value(0u)});
|
||||
MemoryInfo memory;
|
||||
@@ -589,19 +591,20 @@ void TestGuardedDirectImageTable() {
|
||||
if (guard != Guard::Plain && guard != Guard::SccNonZero) {
|
||||
condition = fixture.Emit(ValueOpcode::ConditionRef, {condition}, kind);
|
||||
}
|
||||
fixture.program.block_info[0].condition = condition;
|
||||
fixture.program.block_info[0].terminator = {
|
||||
fixture.program.blocks[0]->condition = condition;
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = guard == Guard::Zero ? 1u : 4u,
|
||||
.false_block = guard == Guard::Zero ? 4u : 1u};
|
||||
.true_block = fixture.program.blocks[guard == Guard::Zero ? 1u : 4u],
|
||||
.false_block = fixture.program.blocks[guard == Guard::Zero ? 4u : 1u]};
|
||||
for (uint32_t block = 1; block < 4; ++block) {
|
||||
fixture.program.block_info[block].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = block + 1u};
|
||||
fixture.program.blocks[block]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[block + 1u]};
|
||||
}
|
||||
fixture.program.block_info[4].terminator = {
|
||||
fixture.program.blocks[4]->terminator = {
|
||||
.kind = guard == Guard::Bypass ? CFG::TerminatorKind::Branch
|
||||
: CFG::TerminatorKind::Return,
|
||||
.true_block = 3u};
|
||||
: CFG::TerminatorKind::Return,
|
||||
.true_block = fixture.program.blocks[3u]};
|
||||
const auto srt = fixture.Address(fixture.UserData(0), fixture.UserData(1));
|
||||
std::array<Value, 2> pointer;
|
||||
for (uint32_t word = 0; word < pointer.size(); ++word) {
|
||||
@@ -767,27 +770,40 @@ void TestBoundedComputeImageLoop() {
|
||||
if (variant == Variant::ExitBypass) exit->AddBranch(body);
|
||||
if (variant == Variant::IncrementBypass || variant == Variant::PreviousBound)
|
||||
exit->AddBranch(latch);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = variant == Variant::EntryBypass ? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = 1u, .false_block = 2u};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = variant == Variant::EntryBypass
|
||||
? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = fixture.program.blocks[2u]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = variant == Variant::TrueEdge ? 2u : 4u,
|
||||
.false_block = variant == Variant::TrueEdge ? 4u : 2u};
|
||||
fixture.program.block_info[2].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 3u};
|
||||
fixture.program.block_info[3].terminator = {
|
||||
.kind = variant == Variant::PreviousBound ? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = 1u, .false_block = 5u};
|
||||
fixture.program.block_info[4].terminator = {
|
||||
.true_block =
|
||||
fixture.program.blocks[variant == Variant::TrueEdge ? 2u : 4u],
|
||||
.false_block =
|
||||
fixture.program.blocks[variant == Variant::TrueEdge ? 4u : 2u]};
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[3u]};
|
||||
fixture.program.blocks[3]->terminator = {
|
||||
.kind = variant == Variant::PreviousBound
|
||||
? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = final_exit};
|
||||
fixture.program.blocks[4]->terminator = {
|
||||
.kind = final_exit != exit || variant == Variant::ExitBypass ||
|
||||
variant == Variant::IncrementBypass
|
||||
? CFG::TerminatorKind::Branch : CFG::TerminatorKind::Return,
|
||||
.true_block = final_exit != exit || variant == Variant::IncrementBypass ? 3u : 2u};
|
||||
? CFG::TerminatorKind::Branch
|
||||
: CFG::TerminatorKind::Return,
|
||||
.true_block =
|
||||
fixture.program.blocks[final_exit != exit ||
|
||||
variant == Variant::IncrementBypass
|
||||
? 3u
|
||||
: 2u]};
|
||||
if (final_exit != exit)
|
||||
fixture.program.block_info[5].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[5]->terminator.kind =
|
||||
CFG::TerminatorKind::Return;
|
||||
}
|
||||
|
||||
auto &phi = header->AppendNewInst(ValueOpcode::Phi, {},
|
||||
@@ -859,14 +875,16 @@ void TestBoundedComputeImageLoop() {
|
||||
block->AddBranch(fixture.program.blocks[yes]);
|
||||
block->AddBranch(fixture.program.blocks[no]);
|
||||
const auto inverse = fixture.Emit(ValueOpcode::LogicalNot, {predicate}, 0, block);
|
||||
fixture.program.block_info[index].condition =
|
||||
fixture.program.blocks[index]->condition =
|
||||
fixture.Emit(ValueOpcode::ConditionRef, {inverse}, kind, block);
|
||||
fixture.program.block_info[index].terminator = {
|
||||
fixture.program.blocks[index]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = yes, .false_block = no};
|
||||
.true_block = fixture.program.blocks[yes],
|
||||
.false_block = fixture.program.blocks[no]};
|
||||
};
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
branch(1u, 4u, 5u, active, CFG::BranchCondition::ExecZero);
|
||||
branch(5u, variant == Variant::GuardedDiamondBypass ? 7u : 4u, 6u,
|
||||
diamond ? execute : mask,
|
||||
@@ -877,13 +895,15 @@ void TestBoundedComputeImageLoop() {
|
||||
fixture.Emit(ValueOpcode::IEqual32, {local, Value(1u)}, 0, guard)}, 0, guard);
|
||||
branch(6u, 3u, 2u, image_guard, CFG::BranchCondition::ExecZero);
|
||||
body->AddBranch(latch);
|
||||
fixture.program.block_info[2].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 3u};
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[3u]};
|
||||
branch(3u, 4u, 7u, next_active, CFG::BranchCondition::ExecZero);
|
||||
increment->AddBranch(header);
|
||||
fixture.program.block_info[7].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.block_info[4].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[7]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
fixture.program.blocks[4]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
} else {
|
||||
const auto active = initial_active;
|
||||
const auto allowed = fixture.Emit(variant == Variant::Disjunction
|
||||
@@ -899,14 +919,15 @@ void TestBoundedComputeImageLoop() {
|
||||
: CFG::BranchCondition::ExecZero, header);
|
||||
if (variant == Variant::Nonzero || variant == Variant::WrongPolarity)
|
||||
condition = fixture.Emit(ValueOpcode::LogicalNot, {condition}, 0, header);
|
||||
fixture.program.block_info[1].condition = condition;
|
||||
fixture.program.blocks[1]->condition = condition;
|
||||
if (variant == Variant::PreviousBound) {
|
||||
previous->AddPhiOperand(entry, Value(false));
|
||||
previous->AddPhiOperand(latch, in_range);
|
||||
const auto continuing = fixture.Emit(ValueOpcode::LogicalOr,
|
||||
{in_range, Value(previous)}, 0, latch);
|
||||
fixture.program.block_info[3].condition = fixture.Emit(ValueOpcode::ConditionRef,
|
||||
{continuing}, CFG::BranchCondition::SccNonZero, latch);
|
||||
fixture.program.blocks[3]->condition =
|
||||
fixture.Emit(ValueOpcode::ConditionRef, {continuing},
|
||||
CFG::BranchCondition::SccNonZero, latch);
|
||||
}
|
||||
}
|
||||
const auto step = fixture.Emit(ValueOpcode::IAdd32,
|
||||
@@ -1067,21 +1088,27 @@ void TestUniformizedMaterialImageKeys() {
|
||||
choose->AddBranch(done);
|
||||
if (first_lane) {
|
||||
sample_entry->AddBranch(first_lane_loop ? sample_header : sample);
|
||||
fixture.program.block_info[sample_entry_id].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = first_lane_loop ? 9u : 7u};
|
||||
fixture.program.blocks[sample_entry_id]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[first_lane_loop ? 9u : 7u]};
|
||||
}
|
||||
if (first_lane_loop) {
|
||||
sample_header->AddBranch(sample);
|
||||
sample->AddBranch(sample_header);
|
||||
fixture.program.block_info[9].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 7u,
|
||||
.merge_block = 8u, .continue_block = 7u, .loop_header = true};
|
||||
fixture.program.blocks[9]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[7u],
|
||||
.merge_block = fixture.program.blocks[8u],
|
||||
.continue_block = fixture.program.blocks[7u],
|
||||
.loop_header = true};
|
||||
}
|
||||
sample->AddBranch(done);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 2u};
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[2u]};
|
||||
const auto enabled = fixture.Emit(
|
||||
ValueOpcode::INotEqual32, {fixture.UserData(5u), Value(0u)}, 0, entry);
|
||||
const auto local = fixture.Emit(ValueOpcode::GetBuiltin,
|
||||
@@ -1097,23 +1124,26 @@ void TestUniformizedMaterialImageKeys() {
|
||||
ValueOpcode::Phi, {}, static_cast<uint64_t>(Type::U32));
|
||||
const auto mask = Value(&mask_phi);
|
||||
const auto active = Value(&active_phi);
|
||||
fixture.program.block_info[2].condition = branch(
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {active}, 0, inactive),
|
||||
variant == Variant::WrongExit ? CFG::BranchCondition::ExecNonZero
|
||||
: CFG::BranchCondition::ExecZero, inactive);
|
||||
fixture.program.block_info[2].terminator = {
|
||||
fixture.program.blocks[2]->condition =
|
||||
branch(fixture.Emit(ValueOpcode::LogicalNot, {active}, 0, inactive),
|
||||
variant == Variant::WrongExit ? CFG::BranchCondition::ExecNonZero
|
||||
: CFG::BranchCondition::ExecZero,
|
||||
inactive);
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 5u, .false_block = 3u};
|
||||
.true_block = fixture.program.blocks[5u],
|
||||
.false_block = fixture.program.blocks[3u]};
|
||||
const auto nonzero = fixture.Emit(
|
||||
ValueOpcode::INotEqual32, {Value(0u), mask}, 0, sentinel);
|
||||
const auto bit_guard = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {active, nonzero}, 0, sentinel);
|
||||
fixture.program.block_info[3].condition = branch(
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {bit_guard}, 0, sentinel),
|
||||
CFG::BranchCondition::ExecZero, sentinel);
|
||||
fixture.program.block_info[3].terminator = {
|
||||
fixture.program.blocks[3]->condition =
|
||||
branch(fixture.Emit(ValueOpcode::LogicalNot, {bit_guard}, 0, sentinel),
|
||||
CFG::BranchCondition::ExecZero, sentinel);
|
||||
fixture.program.blocks[3]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 5u, .false_block = 4u};
|
||||
.true_block = fixture.program.blocks[5u],
|
||||
.false_block = fixture.program.blocks[4u]};
|
||||
const auto first = fixture.Emit(ValueOpcode::FindILsb32, {mask}, 0, bit);
|
||||
const auto position = fixture.Emit(
|
||||
ValueOpcode::BitwiseAnd32, {first, Value(31u)}, 0, bit);
|
||||
@@ -1130,11 +1160,12 @@ void TestUniformizedMaterialImageKeys() {
|
||||
{mask, removed}, 0, bit);
|
||||
const auto continuation = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {bit_guard, active_on_entry}, 0, bit);
|
||||
fixture.program.block_info[4].condition = branch(
|
||||
continuation, CFG::BranchCondition::ExecNonZero, bit);
|
||||
fixture.program.block_info[4].terminator = {
|
||||
fixture.program.blocks[4]->condition =
|
||||
branch(continuation, CFG::BranchCondition::ExecNonZero, bit);
|
||||
fixture.program.blocks[4]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 1u, .false_block = 5u};
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = fixture.program.blocks[5u]};
|
||||
active_phi.AddPhiOperand(entry, active_on_entry);
|
||||
active_phi.AddPhiOperand(bit, continuation);
|
||||
mask_phi.AddPhiOperand(entry, fixture.UserData(4u));
|
||||
@@ -1159,8 +1190,9 @@ void TestUniformizedMaterialImageKeys() {
|
||||
ValueOpcode::SGreaterThan32, {Value(32u), index}, 0, merge);
|
||||
const auto material_guard = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {active_on_entry, below}, 0, merge);
|
||||
fixture.program.block_info[5].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 6u};
|
||||
fixture.program.blocks[5]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[6u]};
|
||||
const auto scaled = fixture.Emit(
|
||||
ValueOpcode::ShiftLeftLogical32, {index, Value(4u)}, 0, choose);
|
||||
const auto selected_scale = fixture.Emit(
|
||||
@@ -1202,12 +1234,13 @@ void TestUniformizedMaterialImageKeys() {
|
||||
sample_active_phi->AddPhiOperand(sample_entry, initial);
|
||||
sample_active = Value(sample_active_phi);
|
||||
}
|
||||
fixture.program.block_info[6].condition = branch(
|
||||
variant == Variant::EmptyFirstEntry ? enabled : initial,
|
||||
CFG::BranchCondition::ExecNonZero, choose);
|
||||
fixture.program.block_info[6].terminator = {
|
||||
fixture.program.blocks[6]->condition =
|
||||
branch(variant == Variant::EmptyFirstEntry ? enabled : initial,
|
||||
CFG::BranchCondition::ExecNonZero, choose);
|
||||
fixture.program.blocks[6]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = sample_entry_id, .false_block = 8u};
|
||||
.true_block = fixture.program.blocks[sample_entry_id],
|
||||
.false_block = fixture.program.blocks[8u]};
|
||||
}
|
||||
auto *key_block = first_lane ? sample : choose;
|
||||
const auto key = first_lane
|
||||
@@ -1219,12 +1252,13 @@ void TestUniformizedMaterialImageKeys() {
|
||||
const auto sample_guard = fixture.Emit(
|
||||
ValueOpcode::LogicalAnd, {sample_active, compared}, 0, key_block);
|
||||
if (!first_lane) {
|
||||
fixture.program.block_info[6].condition = branch(
|
||||
fixture.program.blocks[6]->condition = branch(
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {sample_guard}, 0, choose),
|
||||
CFG::BranchCondition::ExecZero, choose);
|
||||
fixture.program.block_info[6].terminator = {
|
||||
fixture.program.blocks[6]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 8u, .false_block = 7u};
|
||||
.true_block = fixture.program.blocks[8u],
|
||||
.false_block = fixture.program.blocks[7u]};
|
||||
}
|
||||
const auto table_offset = fixture.Emit(
|
||||
ValueOpcode::IAdd32,
|
||||
@@ -1272,17 +1306,19 @@ void TestUniformizedMaterialImageKeys() {
|
||||
if (variant == Variant::WideningFirstBackedge)
|
||||
remaining = fixture.Emit(ValueOpcode::LogicalOr, {remaining, enabled}, 0, sample);
|
||||
sample_active_phi->AddPhiOperand(sample, remaining);
|
||||
fixture.program.block_info[7].condition = branch(
|
||||
fixture.program.blocks[7]->condition = branch(
|
||||
variant == Variant::WrongFirstBackedge ? sample_guard : remaining,
|
||||
CFG::BranchCondition::ExecNonZero, sample);
|
||||
fixture.program.block_info[7].terminator = {
|
||||
fixture.program.blocks[7]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 9u, .false_block = 8u};
|
||||
.true_block = fixture.program.blocks[9u],
|
||||
.false_block = fixture.program.blocks[8u]};
|
||||
} else {
|
||||
fixture.program.block_info[7].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 8u};
|
||||
fixture.program.blocks[7]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[8u]};
|
||||
}
|
||||
fixture.program.block_info[8].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[8]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
const auto output = fixture.Emit(
|
||||
ValueOpcode::GetBufferResource,
|
||||
{fixture.UserData(8u), fixture.UserData(9u),
|
||||
@@ -1556,10 +1592,10 @@ void TestComputeBufferFill() {
|
||||
};
|
||||
const auto Run = [](Options options) {
|
||||
Fixture fixture;
|
||||
fixture.program.block_info[0].terminator.kind =
|
||||
fixture.program.blocks[0]->terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
if (options.branch) {
|
||||
fixture.program.block_info[0].terminator.kind = Libs::Graphics::
|
||||
fixture.program.blocks[0]->terminator.kind = Libs::Graphics::
|
||||
ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
}
|
||||
const auto buffer =
|
||||
@@ -2369,16 +2405,20 @@ ResourcePlan ConditionalSamplerPlan(bool diamond, bool reverse, bool reverse_phi
|
||||
alternate->AddBranch(merge);
|
||||
if (diamond) {
|
||||
initial->AddBranch(merge);
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = merge_id};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[merge_id]};
|
||||
}
|
||||
fixture.program.block_info[0].terminator = {
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = reverse ? alternate_id : initial_target,
|
||||
.false_block = reverse ? initial_target : alternate_id};
|
||||
fixture.program.block_info[alternate_id].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = merge_id};
|
||||
fixture.program.block_info[merge_id].terminator.kind =
|
||||
.true_block =
|
||||
fixture.program.blocks[reverse ? alternate_id : initial_target],
|
||||
.false_block =
|
||||
fixture.program.blocks[reverse ? initial_target : alternate_id]};
|
||||
fixture.program.blocks[alternate_id]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[merge_id]};
|
||||
fixture.program.blocks[merge_id]->terminator.kind =
|
||||
CFG::TerminatorKind::Return;
|
||||
const auto control =
|
||||
fixture.Buffer({Value(0x2000u), Value(0u), Value(200u), Value(0u)});
|
||||
@@ -2389,7 +2429,7 @@ ResourcePlan ConditionalSamplerPlan(bool diamond, bool reverse, bool reverse_phi
|
||||
if (nonuniform) {
|
||||
flag = fixture.Emit(ValueOpcode::LaneId);
|
||||
}
|
||||
fixture.program.block_info[0].condition =
|
||||
fixture.program.blocks[0]->condition =
|
||||
fixture.Emit(ValueOpcode::SGreaterThanEqual32, {flag, Value(0u)});
|
||||
if (writable) {
|
||||
MemoryInfo memory;
|
||||
@@ -2590,22 +2630,21 @@ void TestFiniteImageBitScanSentinel() {
|
||||
{Value(uint32_t(StageInputKind::LocalInvocationIndex)), Value(0u)});
|
||||
const auto condition = fixture.Emit(nonzero ? ValueOpcode::INotEqual32 : ValueOpcode::IEqual32,
|
||||
{mask, Value(0u)});
|
||||
auto &guard = fixture.program.block_info[0];
|
||||
auto &guard = *fixture.program.blocks[0];
|
||||
guard.condition = condition;
|
||||
guard.terminator.kind = CFG::TerminatorKind::ConditionalBranch;
|
||||
guard.terminator.true_block = 1;
|
||||
guard.terminator.false_block = 4;
|
||||
guard.terminator.true_block = dispatch;
|
||||
guard.terminator.false_block = exit;
|
||||
fixture.block = dispatch;
|
||||
const auto first = fixture.Emit(ValueOpcode::FindILsb32, {mask});
|
||||
const auto minimum = fixture.Emit(ValueOpcode::UMin32, {first, Value(32u)});
|
||||
const auto selector = fixture.Emit(ValueOpcode::ShiftLeftLogical32, {minimum, Value(2u)});
|
||||
fixture.Emit(ValueOpcode::ReferenceU32, {selector});
|
||||
auto &table = fixture.program.block_info[1];
|
||||
auto &table = *fixture.program.blocks[1];
|
||||
table.indirect_target = selector;
|
||||
table.terminator.kind = CFG::TerminatorKind::IndirectBranch;
|
||||
table.terminator.indirect_selector_code = 0;
|
||||
table.terminator.indirect_selector_values = {0u, 128u};
|
||||
table.terminator.indirect_selector_targets = {2u, 3u};
|
||||
table.terminator.indexed = true;
|
||||
table.terminator.cases = {{0u, load}, {128u, merge}};
|
||||
std::array<Value, 8> words;
|
||||
for (uint32_t word = 0; word < words.size(); ++word) {
|
||||
auto &phi = merge->AppendNewInst(ValueOpcode::Phi, {}, uint64_t(Type::U32));
|
||||
@@ -2743,21 +2782,25 @@ void TestBoundedRelativeRegisterWrites() {
|
||||
header->AddBranch(body);
|
||||
header->AddBranch(exit);
|
||||
body->AddBranch(header);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = variant == Variant::EntryBypass ? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = 1u, .false_block = 2u};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = variant == Variant::EntryBypass
|
||||
? CFG::TerminatorKind::ConditionalBranch
|
||||
: CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u],
|
||||
.false_block = fixture.program.blocks[2u]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 2u, .false_block = 3u};
|
||||
fixture.program.block_info[2].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 1u};
|
||||
fixture.program.block_info[3].terminator.kind = CFG::TerminatorKind::Return;
|
||||
.true_block = fixture.program.blocks[2u],
|
||||
.false_block = fixture.program.blocks[3u]};
|
||||
fixture.program.blocks[2]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[1u]};
|
||||
fixture.program.blocks[3]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
|
||||
const auto lane = fixture.Emit(ValueOpcode::GetBuiltin,
|
||||
{Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)), Value(0u)});
|
||||
const auto enabled = fixture.Emit(ValueOpcode::ULessThan32, {lane, Value(32u)});
|
||||
fixture.program.block_info[0].condition = enabled;
|
||||
fixture.program.blocks[0]->condition = enabled;
|
||||
const auto chunk = fixture.Emit(ValueOpcode::SelectU32,
|
||||
{enabled, Value(64u), Value(512u)});
|
||||
const auto initial_bound = fixture.Emit(ValueOpcode::ShiftRightLogical32,
|
||||
@@ -2769,8 +2812,9 @@ void TestBoundedRelativeRegisterWrites() {
|
||||
auto &records = header->AppendNewInst(ValueOpcode::Phi, {}, uint64_t(Type::U32));
|
||||
const auto in_range = fixture.Emit(ValueOpcode::ULessThan32,
|
||||
{Value(&counter), Value(&bound)}, 0, header);
|
||||
fixture.program.block_info[1].condition = fixture.Emit(
|
||||
ValueOpcode::ConditionRef, {in_range}, CFG::BranchCondition::VccNonZero, header);
|
||||
fixture.program.blocks[1]->condition =
|
||||
fixture.Emit(ValueOpcode::ConditionRef, {in_range},
|
||||
CFG::BranchCondition::VccNonZero, header);
|
||||
const auto m0 = fixture.Emit(ValueOpcode::BitwiseAnd32,
|
||||
{fixture.Emit(ValueOpcode::ShiftLeftLogical32,
|
||||
{Value(&counter), Value(1u)}, 0, body), Value(255u)}, 0, body);
|
||||
@@ -2953,26 +2997,27 @@ ResourcePlan ConditionalBufferPlan(ConditionalBufferUse use) {
|
||||
auto *done = fixture.AddBlock();
|
||||
auto *condition_block = entry;
|
||||
uint32_t condition_index = 0;
|
||||
fixture.program.block_info[0].id = 11;
|
||||
fixture.program.block_info[1].id = 27;
|
||||
fixture.program.block_info[2].id = 42;
|
||||
fixture.program.blocks[0]->id = 11;
|
||||
fixture.program.blocks[1]->id = 27;
|
||||
fixture.program.blocks[2]->id = 42;
|
||||
if (use == ConditionalBufferUse::Loop) {
|
||||
condition_block = fixture.AddBlock();
|
||||
condition_index = 3;
|
||||
fixture.program.block_info[3].id = 55;
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 55};
|
||||
fixture.program.blocks[3]->id = 55;
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = condition_block};
|
||||
entry->AddBranch(condition_block);
|
||||
}
|
||||
condition_block->AddBranch(optional);
|
||||
condition_block->AddBranch(done);
|
||||
optional->AddBranch(use == ConditionalBufferUse::Loop ? condition_block : done);
|
||||
fixture.program.block_info[condition_index].terminator = {
|
||||
fixture.program.blocks[condition_index]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 27, .false_block = 42};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.true_block = optional,
|
||||
.false_block = done};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = use == ConditionalBufferUse::Loop ? 55u : 42u};
|
||||
.true_block = use == ConditionalBufferUse::Loop ? condition_block : done};
|
||||
|
||||
const auto control = fixture.Buffer(
|
||||
{fixture.UserData(0), fixture.UserData(1), fixture.UserData(2),
|
||||
@@ -2988,8 +3033,8 @@ ResourcePlan ConditionalBufferPlan(ConditionalBufferUse use) {
|
||||
phi.AddPhiOperand(optional, Value(1u));
|
||||
flag = Value(&phi);
|
||||
}
|
||||
fixture.program.block_info[condition_index].condition =
|
||||
fixture.Emit(ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, condition_block);
|
||||
fixture.program.blocks[condition_index]->condition = fixture.Emit(
|
||||
ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, condition_block);
|
||||
|
||||
const auto payload = fixture.Buffer(
|
||||
{fixture.UserData(4), fixture.UserData(5), fixture.UserData(6),
|
||||
@@ -3067,11 +3112,14 @@ void TestGuardedScalarDescriptorReads() {
|
||||
entry->AddBranch(optional);
|
||||
entry->AddBranch(done);
|
||||
optional->AddBranch(done);
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch, .true_block = 1, .false_block = 2};
|
||||
fixture.program.block_info[1].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 2};
|
||||
fixture.program.block_info[2].terminator.kind = CFG::TerminatorKind::Return;
|
||||
fixture.program.blocks[0]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = fixture.program.blocks[1],
|
||||
.false_block = fixture.program.blocks[2]};
|
||||
fixture.program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block = fixture.program.blocks[2]};
|
||||
fixture.program.blocks[2]->terminator.kind = CFG::TerminatorKind::Return;
|
||||
const auto control = fixture.Buffer({fixture.UserData(0), fixture.UserData(1),
|
||||
fixture.UserData(2), fixture.UserData(3)});
|
||||
MemoryInfo scalar;
|
||||
@@ -3083,7 +3131,7 @@ void TestGuardedScalarDescriptorReads() {
|
||||
{Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)), Value(0u)});
|
||||
const auto varying = fixture.Emit(ValueOpcode::INotEqual32, {lane, Value(0u)});
|
||||
const auto enabled = fixture.Emit(ValueOpcode::INotEqual32, {flag, Value(0u)});
|
||||
fixture.program.block_info[0].condition =
|
||||
fixture.program.blocks[0]->condition =
|
||||
fixture.Emit(ValueOpcode::LogicalAnd, {varying, enabled});
|
||||
const auto root = fixture.Address(fixture.UserData(4), Value(0u));
|
||||
const auto Load = [&](Block *block) {
|
||||
@@ -3192,15 +3240,16 @@ void TestConditionalIndirectImageMaterialization() {
|
||||
body->AddBranch(done);
|
||||
const auto flag = fixture->Emit(ValueOpcode::GetUserData,
|
||||
{Value(static_cast<ScalarReg>(8))}, 0, entry);
|
||||
fixture->program.block_info[1].condition = fixture->Emit(
|
||||
ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, entry);
|
||||
fixture->program.block_info[1].terminator = {
|
||||
fixture->program.blocks[1]->condition =
|
||||
fixture->Emit(ValueOpcode::INotEqual32, {flag, Value(0u)}, 0, entry);
|
||||
fixture->program.blocks[1]->terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = 0, .false_block = 2};
|
||||
fixture->program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::Branch, .true_block = 2};
|
||||
.true_block = fixture->program.blocks[0],
|
||||
.false_block = fixture->program.blocks[2]};
|
||||
fixture->program.blocks[0]->terminator = {.kind = CFG::TerminatorKind::Branch,
|
||||
.true_block =
|
||||
fixture->program.blocks[2]};
|
||||
std::swap(fixture->program.blocks[0], fixture->program.blocks[1]);
|
||||
std::swap(fixture->program.block_info[0], fixture->program.block_info[1]);
|
||||
fixture->PlanAndTrack();
|
||||
auto plan = ExtractResourcePlan(fixture->program);
|
||||
std::array<uint32_t, 9> user_data{
|
||||
|
||||
Reference in new issue
Block a user