mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
refactor(shader): compact paired 64-bit lowering
This commit is contained in:
@@ -134,14 +134,14 @@ U32 IREmitter::BitCastU32(F16 value) {
|
||||
return U32(Emit(ValueOpcode::ConvertU32U16, {half}));
|
||||
}
|
||||
|
||||
U64 IREmitter::PackUint2x32(U32 low, U32 high) {
|
||||
const auto pair = Emit(ValueOpcode::CompositeConstructU32x2, {low, high});
|
||||
return U64(Emit(ValueOpcode::PackUint2x32, {pair}));
|
||||
U64 IREmitter::ConstructU64(U32 low, U32 high) {
|
||||
return U64(Emit(ValueOpcode::CompositeConstructU64, {low, high}));
|
||||
}
|
||||
|
||||
U32 IREmitter::CompositeExtract(Value composite, uint32_t index) {
|
||||
ValueOpcode opcode;
|
||||
switch (composite.GetType()) {
|
||||
case Type::U64: opcode = ValueOpcode::CompositeExtractU64; break;
|
||||
case Type::U32x2: opcode = ValueOpcode::CompositeExtractU32x2; break;
|
||||
case Type::U32x3: opcode = ValueOpcode::CompositeExtractU32x3; break;
|
||||
case Type::U32x4: opcode = ValueOpcode::CompositeExtractU32x4; break;
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
U32 BitCastU32(F32 value);
|
||||
F16 BitCastF16(U32 value);
|
||||
U32 BitCastU32(F16 value);
|
||||
U64 PackUint2x32(U32 low, U32 high);
|
||||
U64 ConstructU64(U32 low, U32 high);
|
||||
U32 CompositeExtract(Value composite, uint32_t index);
|
||||
|
||||
U32 IAdd(U32 lhs, U32 rhs);
|
||||
|
||||
@@ -317,9 +317,9 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
||||
return Fail(error, fmt::format("{} has an invalid memory-info index",
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
const auto& memory = program.memory_info[memory_index];
|
||||
const bool scalar_buffer = inst.GetOpcode() == ValueOpcode::ReadConstBuffer;
|
||||
const bool scalar_address = memory.kind == ResourceKind::ScalarAddress;
|
||||
const auto& memory = program.memory_info[memory_index];
|
||||
const bool scalar_buffer = inst.GetOpcode() == ValueOpcode::ReadConstBuffer;
|
||||
const bool scalar_address = memory.kind == ResourceKind::ScalarAddress;
|
||||
if ((scalar_buffer && memory.kind != ResourceKind::ScalarBuffer) ||
|
||||
(!scalar_buffer && !scalar_address && memory.kind != ResourceKind::Flat &&
|
||||
memory.kind != ResourceKind::Global && memory.kind != ResourceKind::Scratch)) {
|
||||
@@ -328,12 +328,13 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
||||
}
|
||||
const bool scalar_memory = scalar_buffer || scalar_address;
|
||||
const bool valid_group_width =
|
||||
scalar_memory ? memory.component_count == 1u || memory.component_count == 2u ||
|
||||
memory.component_count == 4u || memory.component_count == 8u ||
|
||||
memory.component_count == 16u
|
||||
: memory.component_count >= 1u && memory.component_count <= 4u;
|
||||
if (memory.data_bits != 32u || memory.data_dwords != 1u ||
|
||||
!valid_group_width || memory.component_index >= memory.component_count) {
|
||||
scalar_memory
|
||||
? memory.component_count == 1u || memory.component_count == 2u ||
|
||||
memory.component_count == 4u || memory.component_count == 8u ||
|
||||
memory.component_count == 16u
|
||||
: memory.component_count >= 1u && memory.component_count <= 4u;
|
||||
if (memory.data_bits != 32u || memory.data_dwords != 1u || !valid_group_width ||
|
||||
memory.component_index >= memory.component_count) {
|
||||
return Fail(error, fmt::format("{} has inconsistent scalar-memory metadata",
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
@@ -395,6 +396,7 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
||||
}
|
||||
uint32_t composite_components = 0u;
|
||||
switch (inst.GetOpcode()) {
|
||||
case ValueOpcode::CompositeExtractU64: composite_components = 2u; break;
|
||||
case ValueOpcode::CompositeExtractU32x2: composite_components = 2u; break;
|
||||
case ValueOpcode::CompositeExtractU32x3: composite_components = 3u; break;
|
||||
case ValueOpcode::CompositeExtractU32x4: composite_components = 4u; break;
|
||||
|
||||
@@ -56,15 +56,15 @@ VALUE_OPCODE(ConvertS32F32, U32, F32)
|
||||
VALUE_OPCODE(ConvertU32F32, U32, F32)
|
||||
VALUE_OPCODE(ConvertF32S32, F32, U32)
|
||||
VALUE_OPCODE(ConvertF32U32, F32, U32)
|
||||
VALUE_OPCODE(CompositeConstructU64, U64, U32, U32)
|
||||
VALUE_OPCODE(CompositeConstructU32x2, U32x2, U32, U32)
|
||||
VALUE_OPCODE(CompositeConstructU32x3, U32x3, U32, U32, U32)
|
||||
VALUE_OPCODE(CompositeConstructF32x2, F32x2, F32, F32)
|
||||
VALUE_OPCODE(CompositeConstructU32x4, U32x4, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(CompositeExtractU64, U32, U64, U32)
|
||||
VALUE_OPCODE(CompositeExtractU32x2, U32, U32x2, U32)
|
||||
VALUE_OPCODE(CompositeExtractU32x3, U32, U32x3, U32)
|
||||
VALUE_OPCODE(CompositeExtractU32x4, U32, U32x4, U32)
|
||||
VALUE_OPCODE(PackUint2x32, U64, U32x2)
|
||||
VALUE_OPCODE(UnpackUint2x32, U32x2, U64)
|
||||
VALUE_OPCODE(PackHalf2x16, U32, F32x2)
|
||||
VALUE_OPCODE(PackSnorm2x16, U32, F32x2)
|
||||
VALUE_OPCODE(PackUnorm2x16, U32, F32x2)
|
||||
@@ -105,7 +105,6 @@ VALUE_OPCODE(ShiftRightArithmetic64, U64, U64, U32)
|
||||
VALUE_OPCODE(BitwiseAnd32, U32, U32, U32)
|
||||
VALUE_OPCODE(BitwiseAnd64, U64, U64, U64)
|
||||
VALUE_OPCODE(BitwiseOr32, U32, U32, U32)
|
||||
VALUE_OPCODE(BitwiseOr64, U64, U64, U64)
|
||||
VALUE_OPCODE(BitwiseXor32, U32, U32, U32)
|
||||
VALUE_OPCODE(BitwiseNot32, U32, U32)
|
||||
VALUE_OPCODE(BitReverse32, U32, U32)
|
||||
|
||||
@@ -170,6 +170,10 @@ bool FoldCompositeExtract(Inst& inst, ValueOpcode construct, size_t components)
|
||||
}
|
||||
const auto component = index.U32();
|
||||
const auto* producer = composite.TryInstruction();
|
||||
if (IsImmediate(composite, Type::U64)) {
|
||||
Replace(inst, Value(static_cast<uint32_t>(composite.U64() >> (component * 32u))));
|
||||
return true;
|
||||
}
|
||||
if (producer != nullptr && producer->GetOpcode() == construct) {
|
||||
Replace(inst, producer->Arg(component));
|
||||
return true;
|
||||
@@ -185,14 +189,6 @@ bool FoldCompositeExtract(Inst& inst, ValueOpcode construct, size_t components)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (component < 2u && producer != nullptr &&
|
||||
producer->GetOpcode() == ValueOpcode::UnpackUint2x32) {
|
||||
const auto packed = producer->Arg(0).Resolve();
|
||||
if (IsImmediate(packed, Type::U64)) {
|
||||
Replace(inst, Value(static_cast<uint32_t>(packed.U64() >> (component * 32u))));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -284,6 +280,9 @@ void FoldInstruction(Inst& inst) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ValueOpcode::CompositeExtractU64:
|
||||
FoldCompositeExtract(inst, ValueOpcode::CompositeConstructU64, 2);
|
||||
return;
|
||||
case ValueOpcode::CompositeExtractU32x2:
|
||||
FoldCompositeExtract(inst, ValueOpcode::CompositeConstructU32x2, 2);
|
||||
return;
|
||||
@@ -293,27 +292,12 @@ void FoldInstruction(Inst& inst) {
|
||||
case ValueOpcode::CompositeExtractU32x4:
|
||||
FoldCompositeExtract(inst, ValueOpcode::CompositeConstructU32x4, 4);
|
||||
return;
|
||||
case ValueOpcode::PackUint2x32: {
|
||||
const auto value = Arg(inst, 0);
|
||||
const auto* producer = value.TryInstruction();
|
||||
if (producer != nullptr && producer->GetOpcode() == ValueOpcode::UnpackUint2x32) {
|
||||
Replace(inst, producer->Arg(0));
|
||||
} else if (producer != nullptr &&
|
||||
producer->GetOpcode() == ValueOpcode::CompositeConstructU32x2) {
|
||||
const auto low = producer->Arg(0).Resolve();
|
||||
const auto high = producer->Arg(1).Resolve();
|
||||
if (IsImmediate(low, Type::U32) && IsImmediate(high, Type::U32)) {
|
||||
Replace(inst, Value(static_cast<uint64_t>(low.U32()) |
|
||||
(static_cast<uint64_t>(high.U32()) << 32u)));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ValueOpcode::UnpackUint2x32: {
|
||||
const auto value = Arg(inst, 0);
|
||||
const auto* producer = value.TryInstruction();
|
||||
if (producer != nullptr && producer->GetOpcode() == ValueOpcode::PackUint2x32) {
|
||||
Replace(inst, producer->Arg(0));
|
||||
case ValueOpcode::CompositeConstructU64: {
|
||||
const auto low = Arg(inst, 0);
|
||||
const auto high = Arg(inst, 1);
|
||||
if (IsImmediate(low, Type::U32) && IsImmediate(high, Type::U32)) {
|
||||
Replace(inst, Value(static_cast<uint64_t>(low.U32()) |
|
||||
(static_cast<uint64_t>(high.U32()) << 32u)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -367,8 +351,8 @@ void FoldInstruction(Inst& inst) {
|
||||
};
|
||||
const auto low = expand(static_cast<uint32_t>(value.U64()));
|
||||
const auto high = expand(static_cast<uint32_t>(value.U64() >> 32u));
|
||||
Replace(inst, Value(static_cast<uint64_t>(low) |
|
||||
(static_cast<uint64_t>(high) << 32u)));
|
||||
Replace(inst,
|
||||
Value(static_cast<uint64_t>(low) | (static_cast<uint64_t>(high) << 32u)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -461,11 +445,6 @@ void FoldInstruction(Inst& inst) {
|
||||
ReplaceBinaryIdentity(inst, Type::U32, 0u);
|
||||
}
|
||||
return;
|
||||
case ValueOpcode::BitwiseOr64:
|
||||
if (!FoldU64(inst, [](uint64_t a, uint64_t b) { return a | b; })) {
|
||||
ReplaceBinaryIdentity(inst, Type::U64, 0u);
|
||||
}
|
||||
return;
|
||||
case ValueOpcode::BitwiseNot32: {
|
||||
const auto value = Arg(inst, 0);
|
||||
if (IsImmediate(value, Type::U32)) {
|
||||
|
||||
@@ -76,10 +76,10 @@ bool IsDescriptorHandle(ValueOpcode opcode) {
|
||||
|
||||
bool IsRuntimeIntegerOp(ValueOpcode op) {
|
||||
switch (op) {
|
||||
case ValueOpcode::CompositeConstructU64:
|
||||
case ValueOpcode::CompositeExtractU64:
|
||||
case ValueOpcode::CompositeConstructU32x2:
|
||||
case ValueOpcode::CompositeExtractU32x2:
|
||||
case ValueOpcode::PackUint2x32:
|
||||
case ValueOpcode::UnpackUint2x32:
|
||||
case ValueOpcode::BitFieldInsert:
|
||||
case ValueOpcode::BitFieldUExtract:
|
||||
case ValueOpcode::BitFieldSExtract:
|
||||
@@ -100,7 +100,6 @@ bool IsRuntimeIntegerOp(ValueOpcode op) {
|
||||
case ValueOpcode::BitwiseAnd32:
|
||||
case ValueOpcode::BitwiseAnd64:
|
||||
case ValueOpcode::BitwiseOr32:
|
||||
case ValueOpcode::BitwiseOr64:
|
||||
case ValueOpcode::BitwiseXor32:
|
||||
case ValueOpcode::BitwiseNot32:
|
||||
case ValueOpcode::SelectU1:
|
||||
@@ -211,10 +210,10 @@ private:
|
||||
reason = fmt::format("contains a non-scalar {}", ValueOpcodeName(op));
|
||||
return finish(false);
|
||||
}
|
||||
} else if (op == ValueOpcode::PackUint2x32) {
|
||||
const auto* pair = inst->NumArgs() == 1 ? inst->Arg(0).ResolveInstruction() : nullptr;
|
||||
if (pair == nullptr || pair->GetOpcode() != ValueOpcode::CompositeConstructU32x2) {
|
||||
reason = "contains an unsupported packed runtime value";
|
||||
} else if (op == ValueOpcode::CompositeExtractU64) {
|
||||
const auto index = inst->NumArgs() == 2 ? inst->Arg(1).Resolve() : Value {};
|
||||
if (!index.IsImmediate() || index.GetType() != Type::U32 || index.U32() >= 2u) {
|
||||
reason = "contains an invalid U64 component index";
|
||||
return finish(false);
|
||||
}
|
||||
} else if (op == ValueOpcode::CompositeExtractU32x2) {
|
||||
@@ -223,7 +222,6 @@ private:
|
||||
if (source == nullptr || !index.IsImmediate() || index.GetType() != Type::U32 ||
|
||||
index.U32() >= 2u ||
|
||||
(source->GetOpcode() != ValueOpcode::CompositeConstructU32x2 &&
|
||||
source->GetOpcode() != ValueOpcode::UnpackUint2x32 &&
|
||||
source->GetOpcode() != ValueOpcode::IAddCarry32)) {
|
||||
reason = "contains an unsupported composite runtime source";
|
||||
return finish(false);
|
||||
@@ -484,22 +482,25 @@ private:
|
||||
if (!index.IsImmediate() || index.GetType() != Type::U32) {
|
||||
return Fail(error, "dynamic composite extract in runtime expression");
|
||||
}
|
||||
const auto component = index.U32();
|
||||
const auto* source = inst.Arg(0).ResolveInstruction();
|
||||
if (source == nullptr || component >= 2u) {
|
||||
const auto component = index.U32();
|
||||
if (component >= 2u) {
|
||||
return Fail(error, "unsupported composite runtime source");
|
||||
}
|
||||
if (source->GetOpcode() == ValueOpcode::CompositeConstructU32x2) {
|
||||
return EvaluateWide(source->Arg(component), result, error);
|
||||
}
|
||||
if (source->GetOpcode() == ValueOpcode::UnpackUint2x32) {
|
||||
if (inst.GetOpcode() == ValueOpcode::CompositeExtractU64) {
|
||||
uint64_t packed = 0;
|
||||
if (!Arg(*source, 0, packed, error)) {
|
||||
if (!Arg(inst, 0, packed, error)) {
|
||||
return false;
|
||||
}
|
||||
result = static_cast<uint32_t>(packed >> (component * 32u));
|
||||
return true;
|
||||
}
|
||||
const auto* source = inst.Arg(0).ResolveInstruction();
|
||||
if (source == nullptr) {
|
||||
return Fail(error, "unsupported composite runtime source");
|
||||
}
|
||||
if (source->GetOpcode() == ValueOpcode::CompositeConstructU32x2) {
|
||||
return EvaluateWide(source->Arg(component), result, error);
|
||||
}
|
||||
if (source->GetOpcode() == ValueOpcode::IAddCarry32) {
|
||||
uint64_t lhs = 0;
|
||||
uint64_t rhs = 0;
|
||||
@@ -596,17 +597,15 @@ private:
|
||||
}
|
||||
case ValueOpcode::GetShaderBase: result = m_runtime.shader_base; return true;
|
||||
case ValueOpcode::Phi: return EvaluatePhi(inst, result, error);
|
||||
case ValueOpcode::CompositeExtractU64:
|
||||
case ValueOpcode::CompositeExtractU32x2: return EvaluateExtract(inst, result, error);
|
||||
case ValueOpcode::PackUint2x32: {
|
||||
const auto* pair = inst.Arg(0).ResolveInstruction();
|
||||
if (pair == nullptr || pair->GetOpcode() != ValueOpcode::CompositeConstructU32x2 ||
|
||||
!Arg(*pair, 0, a, error) || !Arg(*pair, 1, b, error)) {
|
||||
return Fail(error, "unsupported packed runtime value");
|
||||
case ValueOpcode::CompositeConstructU64:
|
||||
if (!binary()) {
|
||||
return false;
|
||||
}
|
||||
result = static_cast<uint32_t>(a) |
|
||||
(static_cast<uint64_t>(static_cast<uint32_t>(b)) << 32u);
|
||||
return true;
|
||||
}
|
||||
case ValueOpcode::ReadConst: {
|
||||
const auto slot = inst.Arg(1).Resolve();
|
||||
if (!slot.IsImmediate() || slot.GetType() != Type::U32 ||
|
||||
@@ -687,12 +686,6 @@ private:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case ValueOpcode::BitwiseOr64:
|
||||
if (binary()) {
|
||||
result = a | b;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case ValueOpcode::BitwiseXor32:
|
||||
if (binary()) {
|
||||
result = static_cast<uint32_t>(a ^ b);
|
||||
|
||||
Reference in New Issue
Block a user