mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 19:36:55 +02:00
refactor(shader): simplify buffer access emission
This commit is contained in:
@@ -71,15 +71,16 @@ std::string_view ValueOpcodeName(ValueOpcode opcode) {
|
||||
}
|
||||
|
||||
bool HasSideEffects(ValueOpcode opcode) {
|
||||
const auto buffer_access = BufferAccessOf(opcode);
|
||||
if (buffer_access == BufferAccess::Write || buffer_access == BufferAccess::Atomic) {
|
||||
return true;
|
||||
}
|
||||
switch (opcode) {
|
||||
case ValueOpcode::Reference:
|
||||
case ValueOpcode::ReferenceU32:
|
||||
case ValueOpcode::StoreAddressU8:
|
||||
case ValueOpcode::StoreAddressU16:
|
||||
case ValueOpcode::StoreAddressU32:
|
||||
case ValueOpcode::StoreBufferU8:
|
||||
case ValueOpcode::StoreBufferU16:
|
||||
case ValueOpcode::StoreBufferU32:
|
||||
case ValueOpcode::WriteSharedU8:
|
||||
case ValueOpcode::WriteSharedU16:
|
||||
case ValueOpcode::WriteSharedU32:
|
||||
@@ -110,18 +111,6 @@ bool HasSideEffects(ValueOpcode opcode) {
|
||||
case ValueOpcode::GdsAtomicAnd32:
|
||||
case ValueOpcode::GdsAtomicOr32:
|
||||
case ValueOpcode::GdsAtomicXor32:
|
||||
case ValueOpcode::BufferAtomicSwap32:
|
||||
case ValueOpcode::BufferAtomicIAdd32:
|
||||
case ValueOpcode::BufferAtomicISub32:
|
||||
case ValueOpcode::BufferAtomicSMin32:
|
||||
case ValueOpcode::BufferAtomicUMin32:
|
||||
case ValueOpcode::BufferAtomicSMax32:
|
||||
case ValueOpcode::BufferAtomicUMax32:
|
||||
case ValueOpcode::BufferAtomicAnd32:
|
||||
case ValueOpcode::BufferAtomicOr32:
|
||||
case ValueOpcode::BufferAtomicXor32:
|
||||
case ValueOpcode::BufferAtomicFMin32:
|
||||
case ValueOpcode::BufferAtomicFMax32:
|
||||
case ValueOpcode::ImageAtomicIAdd32:
|
||||
case ValueOpcode::ImageAtomicUMin32:
|
||||
case ValueOpcode::ImageAtomicUMax32:
|
||||
@@ -139,4 +128,29 @@ bool HasSideEffects(ValueOpcode opcode) {
|
||||
}
|
||||
}
|
||||
|
||||
BufferAccess BufferAccessOf(ValueOpcode opcode) {
|
||||
switch (opcode) {
|
||||
case ValueOpcode::ReadConstBuffer:
|
||||
case ValueOpcode::LoadBufferU8:
|
||||
case ValueOpcode::LoadBufferU16:
|
||||
case ValueOpcode::LoadBufferU32: return BufferAccess::Read;
|
||||
case ValueOpcode::StoreBufferU8:
|
||||
case ValueOpcode::StoreBufferU16:
|
||||
case ValueOpcode::StoreBufferU32: return BufferAccess::Write;
|
||||
case ValueOpcode::BufferAtomicSwap32:
|
||||
case ValueOpcode::BufferAtomicIAdd32:
|
||||
case ValueOpcode::BufferAtomicISub32:
|
||||
case ValueOpcode::BufferAtomicSMin32:
|
||||
case ValueOpcode::BufferAtomicUMin32:
|
||||
case ValueOpcode::BufferAtomicSMax32:
|
||||
case ValueOpcode::BufferAtomicUMax32:
|
||||
case ValueOpcode::BufferAtomicAnd32:
|
||||
case ValueOpcode::BufferAtomicOr32:
|
||||
case ValueOpcode::BufferAtomicXor32:
|
||||
case ValueOpcode::BufferAtomicFMin32:
|
||||
case ValueOpcode::BufferAtomicFMax32: return BufferAccess::Atomic;
|
||||
default: return BufferAccess::None;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -16,6 +16,8 @@ enum class ValueOpcode {
|
||||
Count,
|
||||
};
|
||||
|
||||
enum class BufferAccess { None, Read, Write, Atomic };
|
||||
|
||||
struct DppMoveFlags {
|
||||
uint16_t control = 0;
|
||||
uint8_t row_mask = 0xf;
|
||||
@@ -52,6 +54,7 @@ static_assert(std::is_trivially_copyable_v<ExportFlags>);
|
||||
[[nodiscard]] Type ArgTypeOf(ValueOpcode opcode, size_t index);
|
||||
[[nodiscard]] size_t NumArgsOf(ValueOpcode opcode);
|
||||
[[nodiscard]] bool HasSideEffects(ValueOpcode opcode);
|
||||
[[nodiscard]] BufferAccess BufferAccessOf(ValueOpcode opcode);
|
||||
[[nodiscard]] std::string_view ValueOpcodeName(ValueOpcode opcode);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -25,46 +25,6 @@ const char* StageName(ShaderType stage) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBufferAtomic(ValueOpcode op) {
|
||||
switch (op) {
|
||||
case ValueOpcode::BufferAtomicSwap32:
|
||||
case ValueOpcode::BufferAtomicIAdd32:
|
||||
case ValueOpcode::BufferAtomicISub32:
|
||||
case ValueOpcode::BufferAtomicSMin32:
|
||||
case ValueOpcode::BufferAtomicUMin32:
|
||||
case ValueOpcode::BufferAtomicSMax32:
|
||||
case ValueOpcode::BufferAtomicUMax32:
|
||||
case ValueOpcode::BufferAtomicAnd32:
|
||||
case ValueOpcode::BufferAtomicOr32:
|
||||
case ValueOpcode::BufferAtomicXor32:
|
||||
case ValueOpcode::BufferAtomicFMin32:
|
||||
case ValueOpcode::BufferAtomicFMax32: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBufferStore(ValueOpcode op) {
|
||||
switch (op) {
|
||||
case ValueOpcode::StoreBufferU8:
|
||||
case ValueOpcode::StoreBufferU16:
|
||||
case ValueOpcode::StoreBufferU32: return true;
|
||||
default: return IsBufferAtomic(op);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBuffer(ValueOpcode op) {
|
||||
switch (op) {
|
||||
case ValueOpcode::ReadConstBuffer:
|
||||
case ValueOpcode::LoadBufferU8:
|
||||
case ValueOpcode::LoadBufferU16:
|
||||
case ValueOpcode::LoadBufferU32:
|
||||
case ValueOpcode::StoreBufferU8:
|
||||
case ValueOpcode::StoreBufferU16:
|
||||
case ValueOpcode::StoreBufferU32: return true;
|
||||
default: return IsBufferAtomic(op);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsAddressStore(ValueOpcode op) {
|
||||
switch (op) {
|
||||
case ValueOpcode::StoreAddressU8:
|
||||
@@ -393,7 +353,8 @@ private:
|
||||
for (const auto* block: m_values.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if ((!IsBuffer(op) && !IsAddress(op) && !IsImage(op)) || &inst == &owner) {
|
||||
if ((BufferAccessOf(op) == BufferAccess::None && !IsAddress(op) && !IsImage(op)) ||
|
||||
&inst == &owner) {
|
||||
continue;
|
||||
}
|
||||
if (inst.Flags<MemoryFlags>().index == index) {
|
||||
@@ -669,8 +630,9 @@ private:
|
||||
|
||||
static void Merge(BufferResource& resource, const MemoryInfo& memory, ValueOpcode op,
|
||||
uint32_t pc) {
|
||||
const bool atomic = IsBufferAtomic(op);
|
||||
const bool write = IsBufferStore(op);
|
||||
const auto access = BufferAccessOf(op);
|
||||
const bool atomic = access == BufferAccess::Atomic;
|
||||
const bool write = access == BufferAccess::Write || atomic;
|
||||
resource.first_use_pc = std::min(resource.first_use_pc, pc);
|
||||
resource.max_byte_extent = std::max(resource.max_byte_extent, ByteExtent(memory));
|
||||
resource.read = resource.read || !write || atomic;
|
||||
@@ -813,7 +775,7 @@ private:
|
||||
|
||||
bool Collect(Inst& inst, std::string* error) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (!IsBuffer(op) && !IsAddress(op) && !IsImage(op)) {
|
||||
if (BufferAccessOf(op) == BufferAccess::None && !IsAddress(op) && !IsImage(op)) {
|
||||
return true;
|
||||
}
|
||||
const auto flags = inst.Flags<MemoryFlags>();
|
||||
@@ -832,7 +794,7 @@ private:
|
||||
uint32_t source = 0;
|
||||
uint32_t resource = 0;
|
||||
|
||||
if (IsBuffer(op)) {
|
||||
if (BufferAccessOf(op) != BufferAccess::None) {
|
||||
if (!GetHandle(inst.Arg(0), ValueOpcode::GetBufferResource, 4, flags.pc, handle, source,
|
||||
error)) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user