mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: drop inactive pixel values under whole-quad masks
This commit is contained in:
@@ -125,9 +125,17 @@ bool IsSelect(ValueOpcode opcode) {
|
|||||||
|
|
||||||
bool Implies(Value condition, Value required, uint32_t depth = 0) {
|
bool Implies(Value condition, Value required, uint32_t depth = 0) {
|
||||||
condition = condition.Resolve();
|
condition = condition.Resolve();
|
||||||
|
required = required.Resolve();
|
||||||
if (condition == required) return true;
|
if (condition == required) return true;
|
||||||
|
if (depth >= 64u) return false;
|
||||||
|
const auto* target = required.TryInstruction();
|
||||||
|
if (target != nullptr && target->GetOpcode() == ValueOpcode::LogicalOr &&
|
||||||
|
(Implies(condition, target->Arg(0), depth + 1u) ||
|
||||||
|
Implies(condition, target->Arg(1), depth + 1u))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const auto* inst = condition.TryInstruction();
|
const auto* inst = condition.TryInstruction();
|
||||||
return depth < 64u && inst != nullptr && inst->GetOpcode() == ValueOpcode::LogicalAnd &&
|
return inst != nullptr && inst->GetOpcode() == ValueOpcode::LogicalAnd &&
|
||||||
(Implies(inst->Arg(0), required, depth + 1u) ||
|
(Implies(inst->Arg(0), required, depth + 1u) ||
|
||||||
Implies(inst->Arg(1), required, depth + 1u));
|
Implies(inst->Arg(1), required, depth + 1u));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6036,10 +6036,13 @@ void TestPixelAncillaryLayerInput() {
|
|||||||
|
|
||||||
void TestMaskedValueDemand() {
|
void TestMaskedValueDemand() {
|
||||||
using namespace ShaderRecompiler::IR;
|
using namespace ShaderRecompiler::IR;
|
||||||
enum class Use { Guarded, Conjunction, TrueArm, Unguarded, OtherGuard, Predicate,
|
enum class Use { Guarded, Conjunction, Wqm, WqmConjunction, WqmOtherGuard,
|
||||||
|
TrueArm, Unguarded, OtherGuard, Predicate,
|
||||||
ReadLane, ExplicitLod, ExplicitGradient, LevelZero, ImplicitLod,
|
ReadLane, ExplicitLod, ExplicitGradient, LevelZero, ImplicitLod,
|
||||||
Mixed, Phi, Loop };
|
Mixed, Phi, Loop };
|
||||||
for (const auto use : {Use::Guarded, Use::Conjunction, Use::TrueArm, Use::Unguarded,
|
for (const auto use : {Use::Guarded, Use::Conjunction, Use::Wqm,
|
||||||
|
Use::WqmConjunction, Use::WqmOtherGuard,
|
||||||
|
Use::TrueArm, Use::Unguarded,
|
||||||
Use::OtherGuard, Use::Predicate, Use::ReadLane,
|
Use::OtherGuard, Use::Predicate, Use::ReadLane,
|
||||||
Use::ExplicitLod, Use::ExplicitGradient, Use::LevelZero,
|
Use::ExplicitLod, Use::ExplicitGradient, Use::LevelZero,
|
||||||
Use::ImplicitLod, Use::Mixed, Use::Phi, Use::Loop}) {
|
Use::ImplicitLod, Use::Mixed, Use::Phi, Use::Loop}) {
|
||||||
@@ -6061,8 +6064,17 @@ void TestMaskedValueDemand() {
|
|||||||
{input, Value(0u)}));
|
{input, Value(0u)}));
|
||||||
const auto other = Value(&entry.AppendNewInst(ValueOpcode::IEqual32,
|
const auto other = Value(&entry.AppendNewInst(ValueOpcode::IEqual32,
|
||||||
{input, Value(2u)}));
|
{input, Value(2u)}));
|
||||||
|
auto mask = predicate;
|
||||||
|
if (use == Use::Wqm || use == Use::WqmConjunction || use == Use::WqmOtherGuard) {
|
||||||
|
// WQM includes the original active lanes and additional helper lanes.
|
||||||
|
const auto helpers = Value(&entry.AppendNewInst(ValueOpcode::GetUserData,
|
||||||
|
{Value(static_cast<ScalarReg>(1))}));
|
||||||
|
const auto helper = Value(&entry.AppendNewInst(ValueOpcode::INotEqual32,
|
||||||
|
{helpers, Value(0u)}));
|
||||||
|
mask = Value(&entry.AppendNewInst(ValueOpcode::LogicalOr, {predicate, helper}));
|
||||||
|
}
|
||||||
auto &masked = entry.AppendNewInst(ValueOpcode::SelectU32,
|
auto &masked = entry.AppendNewInst(ValueOpcode::SelectU32,
|
||||||
{predicate, Value(10u), Value(20u)});
|
{mask, Value(10u), Value(20u)});
|
||||||
Value value(&masked);
|
Value value(&masked);
|
||||||
if (use == Use::Phi || use == Use::Loop) {
|
if (use == Use::Phi || use == Use::Loop) {
|
||||||
auto &phi = join.AppendNewInst(ValueOpcode::Phi, {}, static_cast<uint64_t>(Type::U32));
|
auto &phi = join.AppendNewInst(ValueOpcode::Phi, {}, static_cast<uint64_t>(Type::U32));
|
||||||
@@ -6107,8 +6119,10 @@ void TestMaskedValueDemand() {
|
|||||||
value = Value(&join.AppendNewInst(ValueOpcode::CompositeExtractU32x4, {value, Value(0u)}));
|
value = Value(&join.AppendNewInst(ValueOpcode::CompositeExtractU32x4, {value, Value(0u)}));
|
||||||
}
|
}
|
||||||
auto guard = predicate;
|
auto guard = predicate;
|
||||||
if (use == Use::Conjunction) {
|
if (use == Use::Conjunction || use == Use::WqmConjunction) {
|
||||||
guard = Value(&join.AppendNewInst(ValueOpcode::LogicalAnd, {predicate, other}));
|
guard = Value(&join.AppendNewInst(ValueOpcode::LogicalAnd, {predicate, other}));
|
||||||
|
} else if (use == Use::WqmOtherGuard) {
|
||||||
|
guard = Value(&join.AppendNewInst(ValueOpcode::IEqual32, {input, Value(0u)}));
|
||||||
} else if (use == Use::OtherGuard) {
|
} else if (use == Use::OtherGuard) {
|
||||||
guard = other;
|
guard = other;
|
||||||
} else if (use == Use::Unguarded) {
|
} else if (use == Use::Unguarded) {
|
||||||
@@ -6125,7 +6139,8 @@ void TestMaskedValueDemand() {
|
|||||||
if (use == Use::Mixed) join.AppendNewInst(ValueOpcode::SetAttribute, {value, Value(true)});
|
if (use == Use::Mixed) join.AppendNewInst(ValueOpcode::SetAttribute, {value, Value(true)});
|
||||||
EliminateMaskedValues(program);
|
EliminateMaskedValues(program);
|
||||||
const bool removed = Value(&masked).Resolve() == Value(10u);
|
const bool removed = Value(&masked).Resolve() == Value(10u);
|
||||||
const bool safe = use == Use::Guarded || use == Use::Conjunction || use == Use::TrueArm ||
|
const bool safe = use == Use::Guarded || use == Use::Conjunction ||
|
||||||
|
use == Use::Wqm || use == Use::WqmConjunction || use == Use::TrueArm ||
|
||||||
use == Use::ExplicitLod || use == Use::ExplicitGradient ||
|
use == Use::ExplicitLod || use == Use::ExplicitGradient ||
|
||||||
use == Use::LevelZero || use == Use::Phi;
|
use == Use::LevelZero || use == Use::Phi;
|
||||||
Check(removed == safe, "masked value demand crossed an unguarded or nonlocal use");
|
Check(removed == safe, "masked value demand crossed an unguarded or nonlocal use");
|
||||||
|
|||||||
Reference in New Issue
Block a user