mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: reflect tessellation strides across forward branches, DS write widths, and packed patch masks
This commit is contained in:
@@ -21,14 +21,17 @@ struct TessellationAddress {
|
|||||||
Kind kind = Kind::Unknown;
|
Kind kind = Kind::Unknown;
|
||||||
uint32_t coefficient = 0;
|
uint32_t coefficient = 0;
|
||||||
uint32_t constant = 0;
|
uint32_t constant = 0;
|
||||||
|
|
||||||
|
bool operator==(const TessellationAddress&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t ReflectTessellationStride(const Decoder::Program& program, bool local,
|
uint32_t ReflectTessellationStride(const Decoder::Program& program, bool local,
|
||||||
uint32_t control_points, uint32_t input_stride) {
|
uint32_t control_points, uint32_t input_stride) {
|
||||||
using namespace Decoder;
|
using namespace Decoder;
|
||||||
using Address = TessellationAddress;
|
using Address = TessellationAddress;
|
||||||
using Kind = Address::Kind;
|
using Kind = Address::Kind;
|
||||||
std::array<Address, IR::NumVectorRegs> registers {};
|
using Registers = std::array<Address, IR::NumVectorRegs>;
|
||||||
|
Registers registers {};
|
||||||
registers[local ? 3u : 1u] =
|
registers[local ? 3u : 1u] =
|
||||||
local ? Address {Kind::Affine, 1u, 0u} : Address {Kind::PackedControlPoint};
|
local ? Address {Kind::Affine, 1u, 0u} : Address {Kind::PackedControlPoint};
|
||||||
const auto constant = [](uint32_t value) { return Address {Kind::Affine, 0u, value}; };
|
const auto constant = [](uint32_t value) { return Address {Kind::Affine, 0u, value}; };
|
||||||
@@ -79,14 +82,28 @@ uint32_t ReflectTessellationStride(const Decoder::Program& program, bool local,
|
|||||||
? value
|
? value
|
||||||
: Address {};
|
: Address {};
|
||||||
};
|
};
|
||||||
|
// A forward branch joins its target with the fallthrough path. Definitions that
|
||||||
|
// differ between the paths are unknown there.
|
||||||
|
std::unordered_map<uint32_t, Registers> joins;
|
||||||
|
|
||||||
|
const auto merge = [](Registers& into, const Registers& from) {
|
||||||
|
for (uint32_t index = 0; index < into.size(); index++) {
|
||||||
|
if (into[index] != from[index]) into[index] = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
uint32_t stride = 0;
|
uint32_t stride = 0;
|
||||||
for (const auto& inst: program.instructions) {
|
for (const auto& inst: program.instructions) {
|
||||||
// Stage exits preserve the active path's definitions. An internal join
|
if (const auto join = joins.find(inst.pc); join != joins.end()) {
|
||||||
// would require merging register definitions.
|
merge(registers, join->second);
|
||||||
EXIT_NOT_IMPLEMENTED(IsDirectBranch(inst.opcode) &&
|
joins.erase(join);
|
||||||
inst.branch_target != program.instructions.back().pc);
|
}
|
||||||
const bool local_store =
|
if (IsDirectBranch(inst.opcode)) {
|
||||||
inst.opcode == Opcode::DS_WRITE_B32 || inst.opcode == Opcode::DS_WRITE2_B32;
|
EXIT_NOT_IMPLEMENTED(inst.branch_target <= inst.pc);
|
||||||
|
if (const auto [join, inserted] = joins.try_emplace(inst.branch_target, registers);
|
||||||
|
!inserted)
|
||||||
|
merge(join->second, registers);
|
||||||
|
}
|
||||||
|
const bool local_store = IsDsWriteOpcode(inst.opcode);
|
||||||
const bool buffer_store = inst.opcode == Opcode::BUFFER_STORE_DWORD ||
|
const bool buffer_store = inst.opcode == Opcode::BUFFER_STORE_DWORD ||
|
||||||
inst.opcode == Opcode::BUFFER_STORE_DWORDX2 ||
|
inst.opcode == Opcode::BUFFER_STORE_DWORDX2 ||
|
||||||
inst.opcode == Opcode::BUFFER_STORE_DWORDX3 ||
|
inst.opcode == Opcode::BUFFER_STORE_DWORDX3 ||
|
||||||
@@ -123,6 +140,12 @@ uint32_t ReflectTessellationStride(const Decoder::Program& program, bool local,
|
|||||||
if (rhs.constant == 0u && third.constant == 8u) value = constant(0u);
|
if (rhs.constant == 0u && third.constant == 8u) value = constant(0u);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Opcode::V_AND_B32:
|
||||||
|
if ((lhs.kind == Kind::PackedControlPoint && rhs == constant(0xffu)) ||
|
||||||
|
(rhs.kind == Kind::PackedControlPoint && lhs == constant(0xffu)))
|
||||||
|
value = constant(0u);
|
||||||
|
break;
|
||||||
|
case Opcode::V_MUL_LO_U32: value = multiply(lhs, rhs); break;
|
||||||
case Opcode::V_MUL_U32_U24: value = multiply(low24(lhs), low24(rhs)); break;
|
case Opcode::V_MUL_U32_U24: value = multiply(low24(lhs), low24(rhs)); break;
|
||||||
case Opcode::V_MAD_U32_U24: value = add(multiply(low24(lhs), low24(rhs)), third); break;
|
case Opcode::V_MAD_U32_U24: value = add(multiply(low24(lhs), low24(rhs)), third); break;
|
||||||
case Opcode::V_LSHL_ADD_U32:
|
case Opcode::V_LSHL_ADD_U32:
|
||||||
@@ -149,7 +172,7 @@ uint32_t ReflectTessellationStride(const Decoder::Program& program, bool local,
|
|||||||
}
|
}
|
||||||
registers.at(inst.dst.reg) = value;
|
registers.at(inst.dst.reg) = value;
|
||||||
}
|
}
|
||||||
EXIT_NOT_IMPLEMENTED(stride == 0u);
|
EXIT_NOT_IMPLEMENTED(!joins.empty() || stride == 0u);
|
||||||
return stride;
|
return stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,8 @@ void ApplyMemoryInfo(Instruction& inst, const MemoryOpcodeInfo* info) {
|
|||||||
inst.formatted = info->formatted;
|
inst.formatted = info->formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
bool IsDsWriteOpcode(Opcode opcode) {
|
bool IsDsWriteOpcode(Opcode opcode) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Opcode::DS_WRITE_B8:
|
case Opcode::DS_WRITE_B8:
|
||||||
@@ -184,6 +186,8 @@ bool IsDsWriteOpcode(Opcode opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
bool IsDsAtomicOpcode(Opcode opcode) {
|
bool IsDsAtomicOpcode(Opcode opcode) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Opcode::DS_ADD_U32:
|
case Opcode::DS_ADD_U32:
|
||||||
|
|||||||
@@ -882,6 +882,7 @@ Program DecodeFrontProgram(std::span<const uint32_t> front);
|
|||||||
void DecodeProgram(std::span<const uint32_t> code, Program& program);
|
void DecodeProgram(std::span<const uint32_t> code, Program& program);
|
||||||
bool IsConditionalBranch(Opcode opcode);
|
bool IsConditionalBranch(Opcode opcode);
|
||||||
bool IsDirectBranch(Opcode opcode);
|
bool IsDirectBranch(Opcode opcode);
|
||||||
|
bool IsDsWriteOpcode(Opcode opcode);
|
||||||
|
|
||||||
void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand);
|
void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand);
|
||||||
void DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand);
|
void DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand);
|
||||||
|
|||||||
Reference in New Issue
Block a user