diff options
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 82 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 42 |
2 files changed, 83 insertions, 41 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 165c2b41b..e6a010a7d 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -146,12 +146,25 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } + case OpCode::Id::LD: case OpCode::Id::LDG: { + const auto type = [instr, &opcode]() -> Tegra::Shader::UniformType { + switch (opcode->get().GetId()) { + case OpCode::Id::LD: + UNIMPLEMENTED_IF_MSG(!instr.generic.extended, "Unextended LD is not implemented"); + return instr.generic.type; + case OpCode::Id::LDG: + return instr.ldg.type; + default: + UNREACHABLE(); + return {}; + } + }(); + const auto [real_address_base, base_address, descriptor] = - TrackAndGetGlobalMemory(bb, GetRegister(instr.gpr8), - static_cast<u32>(instr.ldg.immediate_offset.Value()), false); + TrackAndGetGlobalMemory(bb, instr, false); - const u32 count = GetUniformTypeElementsCount(instr.ldg.type); + const u32 count = GetUniformTypeElementsCount(type); for (u32 i = 0; i < count; ++i) { const Node it_offset = Immediate(i * 4); const Node real_address = @@ -165,28 +178,6 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } - case OpCode::Id::STG: { - const auto [real_address_base, base_address, descriptor] = - TrackAndGetGlobalMemory(bb, GetRegister(instr.gpr8), - static_cast<u32>(instr.stg.immediate_offset.Value()), true); - - // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} - SetTemporal(bb, 0, real_address_base); - - const u32 count = GetUniformTypeElementsCount(instr.stg.type); - for (u32 i = 0; i < count; ++i) { - SetTemporal(bb, i + 1, GetRegister(instr.gpr0.Value() + i)); - } - for (u32 i = 0; i < count; ++i) { - const Node it_offset = Immediate(i * 4); - const Node real_address = - Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); - const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor)); - - bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1))); - } - break; - } case OpCode::Id::ST_A: { UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, "Indirect attribute loads are not supported"); @@ -242,6 +233,41 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } + case OpCode::Id::ST: + case OpCode::Id::STG: { + const auto type = [instr, &opcode]() -> Tegra::Shader::UniformType { + switch (opcode->get().GetId()) { + case OpCode::Id::ST: + UNIMPLEMENTED_IF_MSG(!instr.generic.extended, "Unextended ST is not implemented"); + return instr.generic.type; + case OpCode::Id::STG: + return instr.stg.type; + default: + UNREACHABLE(); + return {}; + } + }(); + + const auto [real_address_base, base_address, descriptor] = + TrackAndGetGlobalMemory(bb, instr, true); + + // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} + SetTemporal(bb, 0, real_address_base); + + const u32 count = GetUniformTypeElementsCount(type); + for (u32 i = 0; i < count; ++i) { + SetTemporal(bb, i + 1, GetRegister(instr.gpr0.Value() + i)); + } + for (u32 i = 0; i < count; ++i) { + const Node it_offset = Immediate(i * 4); + const Node real_address = + Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); + const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor)); + + bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1))); + } + break; + } case OpCode::Id::AL2P: { // Ignore al2p.direction since we don't care about it. @@ -265,9 +291,11 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, - Node addr_register, - u32 immediate_offset, + Instruction instr, bool is_write) { + const auto addr_register{GetRegister(instr.gmem.gpr)}; + const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; + const Node base_address{ TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))}; const auto cbuf = std::get_if<CbufNode>(base_address); diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index ca7af72e1..a6c123573 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp @@ -14,6 +14,7 @@ using Tegra::Shader::ConditionCode; using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; using Tegra::Shader::Register; +using Tegra::Shader::SystemVariable; u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; @@ -59,20 +60,33 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { break; } case OpCode::Id::MOV_SYS: { - switch (instr.sys20) { - case Tegra::Shader::SystemVariable::InvocationInfo: { - LOG_WARNING(HW_GPU, "MOV_SYS instruction with InvocationInfo is incomplete"); - SetRegister(bb, instr.gpr0, Immediate(0u)); - break; - } - case Tegra::Shader::SystemVariable::Ydirection: { - // Config pack's third value is Y_NEGATE's state. - SetRegister(bb, instr.gpr0, Operation(OperationCode::YNegate)); - break; - } - default: - UNIMPLEMENTED_MSG("Unhandled system move: {}", static_cast<u32>(instr.sys20.Value())); - } + const Node value = [&]() { + switch (instr.sys20) { + case SystemVariable::Ydirection: + return Operation(OperationCode::YNegate); + case SystemVariable::InvocationInfo: + LOG_WARNING(HW_GPU, "MOV_SYS instruction with InvocationInfo is incomplete"); + return Immediate(0u); + case SystemVariable::TidX: + return Operation(OperationCode::LocalInvocationIdX); + case SystemVariable::TidY: + return Operation(OperationCode::LocalInvocationIdY); + case SystemVariable::TidZ: + return Operation(OperationCode::LocalInvocationIdZ); + case SystemVariable::CtaIdX: + return Operation(OperationCode::WorkGroupIdX); + case SystemVariable::CtaIdY: + return Operation(OperationCode::WorkGroupIdY); + case SystemVariable::CtaIdZ: + return Operation(OperationCode::WorkGroupIdZ); + default: + UNIMPLEMENTED_MSG("Unhandled system move: {}", + static_cast<u32>(instr.sys20.Value())); + return Immediate(0u); + } + }(); + SetRegister(bb, instr.gpr0, value); + break; } case OpCode::Id::BRA: { |
