Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95c98f963d | ||
|
|
0e91b7102a | ||
|
|
c73854dee0 | ||
|
|
e391516315 | ||
|
|
95ff9dda45 | ||
|
|
24acfb1ee7 | ||
|
|
887c2395da | ||
|
|
02b185cc4a | ||
|
|
831bb4fbb1 | ||
|
|
56346f927e | ||
|
|
5f36b35666 | ||
|
|
2b7dfc9413 | ||
|
|
207dd1b0a8 | ||
|
|
d7e3f79a19 | ||
|
|
13eb8874e0 | ||
|
|
5ee4fb6e12 | ||
|
|
969f0afa4e | ||
|
|
5062728669 | ||
|
|
7fdf991097 | ||
|
|
5328d570df | ||
|
|
1f5401c89c | ||
|
|
012d7f5233 | ||
|
|
5e553a6c26 | ||
|
|
6fe89acf0d | ||
|
|
c4a0aa9207 | ||
|
|
7ecf9f7228 | ||
|
|
1ea07954fb | ||
|
|
8d8e495248 | ||
|
|
d076466f26 | ||
|
|
26c84718c8 | ||
|
|
e433e99191 | ||
|
|
a71e8066a1 | ||
|
|
6947bf8e44 | ||
|
|
b42a74ff2c |
No files matched your search
@@ -55,10 +55,9 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
|
||||
}
|
||||
|
||||
bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) {
|
||||
return desc.type == SaveDataType::CacheStorage ///< Cache Saves
|
||||
|| desc.type == SaveDataType::TemporaryStorage ///< Temp Saves
|
||||
|| (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
|
||||
desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0);
|
||||
return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage ||
|
||||
(space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
|
||||
desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0);
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
@@ -583,36 +583,6 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsControllerSupported(NPadControllerType controller) {
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
// Handheld is not even a supported type, lets stop here
|
||||
if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
|
||||
NPAD_HANDHELD) == supported_npad_id_types.end()) {
|
||||
return false;
|
||||
}
|
||||
// Handheld should not be supported in docked mode
|
||||
if (Settings::values.use_docked_mode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (controller) {
|
||||
case NPadControllerType::ProController:
|
||||
return style.pro_controller;
|
||||
case NPadControllerType::Handheld:
|
||||
return style.handheld;
|
||||
case NPadControllerType::JoyDual:
|
||||
return style.joycon_dual;
|
||||
case NPadControllerType::JoyLeft:
|
||||
return style.joycon_left;
|
||||
case NPadControllerType::JoyRight:
|
||||
return style.joycon_right;
|
||||
case NPadControllerType::Pokeball:
|
||||
return style.pokeball;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||
if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
|
||||
// These are controllers without led patterns
|
||||
@@ -659,25 +629,24 @@ void Controller_NPad::ClearAllConnectedControllers() {
|
||||
}
|
||||
|
||||
void Controller_NPad::DisconnectAllConnectedControllers() {
|
||||
std::for_each(connected_controllers.begin(), connected_controllers.end(),
|
||||
[](ControllerHolder& controller) { controller.is_connected = false; });
|
||||
for (ControllerHolder& controller : connected_controllers) {
|
||||
controller.is_connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::ConnectAllDisconnectedControllers() {
|
||||
std::for_each(connected_controllers.begin(), connected_controllers.end(),
|
||||
[](ControllerHolder& controller) {
|
||||
if (controller.type != NPadControllerType::None && !controller.is_connected) {
|
||||
controller.is_connected = false;
|
||||
}
|
||||
});
|
||||
for (ControllerHolder& controller : connected_controllers) {
|
||||
if (controller.type != NPadControllerType::None && !controller.is_connected) {
|
||||
controller.is_connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::ClearAllControllers() {
|
||||
std::for_each(connected_controllers.begin(), connected_controllers.end(),
|
||||
[](ControllerHolder& controller) {
|
||||
controller.type = NPadControllerType::None;
|
||||
controller.is_connected = false;
|
||||
});
|
||||
for (ControllerHolder& controller : connected_controllers) {
|
||||
controller.type = NPadControllerType::None;
|
||||
controller.is_connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Controller_NPad::GetAndResetPressState() {
|
||||
@@ -685,10 +654,10 @@ u32 Controller_NPad::GetAndResetPressState() {
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
|
||||
const bool support_handheld =
|
||||
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) !=
|
||||
supported_npad_id_types.end();
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
const bool support_handheld =
|
||||
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
|
||||
NPAD_HANDHELD) != supported_npad_id_types.end();
|
||||
// Handheld is not even a supported type, lets stop here
|
||||
if (!support_handheld) {
|
||||
return false;
|
||||
@@ -700,6 +669,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
|
||||
[](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
|
||||
switch (controller) {
|
||||
@@ -717,6 +687,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -795,6 +766,7 @@ Controller_NPad::NPadControllerType Controller_NPad::DecideBestController(
|
||||
priority_list.push_back(NPadControllerType::JoyLeft);
|
||||
priority_list.push_back(NPadControllerType::JoyRight);
|
||||
priority_list.push_back(NPadControllerType::JoyDual);
|
||||
break;
|
||||
}
|
||||
|
||||
const auto iter = std::find_if(priority_list.begin(), priority_list.end(),
|
||||
|
||||
@@ -301,6 +301,11 @@ private:
|
||||
bool is_connected;
|
||||
};
|
||||
|
||||
void InitNewlyAddedControler(std::size_t controller_idx);
|
||||
bool IsControllerSupported(NPadControllerType controller) const;
|
||||
NPadControllerType DecideBestController(NPadControllerType priority) const;
|
||||
void RequestPadStateUpdate(u32 npad_id);
|
||||
|
||||
u32 press_state{};
|
||||
|
||||
NPadType style{};
|
||||
@@ -321,12 +326,7 @@ private:
|
||||
std::array<ControllerHolder, 10> connected_controllers{};
|
||||
bool can_controllers_vibrate{true};
|
||||
|
||||
void InitNewlyAddedControler(std::size_t controller_idx);
|
||||
bool IsControllerSupported(NPadControllerType controller) const;
|
||||
NPadControllerType DecideBestController(NPadControllerType priority) const;
|
||||
void RequestPadStateUpdate(u32 npad_id);
|
||||
std::array<ControllerPad, 10> npad_pad_states{};
|
||||
bool IsControllerSupported(NPadControllerType controller);
|
||||
bool is_in_lr_assignment_mode{false};
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
@@ -574,7 +574,7 @@ enum class ShuffleOperation : u64 {
|
||||
};
|
||||
|
||||
union Instruction {
|
||||
Instruction& operator=(const Instruction& instr) {
|
||||
constexpr Instruction& operator=(const Instruction& instr) {
|
||||
value = instr.value;
|
||||
return *this;
|
||||
}
|
||||
@@ -1760,22 +1760,22 @@ public:
|
||||
|
||||
class Matcher {
|
||||
public:
|
||||
Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type)
|
||||
constexpr Matcher(const char* const name, u16 mask, u16 expected, Id id, Type type)
|
||||
: name{name}, mask{mask}, expected{expected}, id{id}, type{type} {}
|
||||
|
||||
const char* GetName() const {
|
||||
constexpr const char* GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
u16 GetMask() const {
|
||||
constexpr u16 GetMask() const {
|
||||
return mask;
|
||||
}
|
||||
|
||||
Id GetId() const {
|
||||
constexpr Id GetId() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
Type GetType() const {
|
||||
constexpr Type GetType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -1784,7 +1784,7 @@ public:
|
||||
* @param instruction The instruction to test
|
||||
* @returns true if the given instruction matches.
|
||||
*/
|
||||
bool Matches(u16 instruction) const {
|
||||
constexpr bool Matches(u16 instruction) const {
|
||||
return (instruction & mask) == expected;
|
||||
}
|
||||
|
||||
@@ -1818,7 +1818,7 @@ private:
|
||||
* A '0' in a bitstring indicates that a zero must be present at that bit position.
|
||||
* A '1' in a bitstring indicates that a one must be present at that bit position.
|
||||
*/
|
||||
static auto GetMaskAndExpect(const char* const bitstring) {
|
||||
static constexpr auto GetMaskAndExpect(const char* const bitstring) {
|
||||
u16 mask = 0, expect = 0;
|
||||
for (std::size_t i = 0; i < opcode_bitsize; i++) {
|
||||
const std::size_t bit_position = opcode_bitsize - i - 1;
|
||||
@@ -1835,15 +1835,15 @@ private:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::make_tuple(mask, expect);
|
||||
return std::make_pair(mask, expect);
|
||||
}
|
||||
|
||||
public:
|
||||
/// Creates a matcher that can match and parse instructions based on bitstring.
|
||||
static auto GetMatcher(const char* const bitstring, OpCode::Id op, OpCode::Type type,
|
||||
const char* const name) {
|
||||
const auto mask_expect = GetMaskAndExpect(bitstring);
|
||||
return Matcher(name, std::get<0>(mask_expect), std::get<1>(mask_expect), op, type);
|
||||
static constexpr auto GetMatcher(const char* const bitstring, Id op, Type type,
|
||||
const char* const name) {
|
||||
const auto [mask, expected] = GetMaskAndExpect(bitstring);
|
||||
return Matcher(name, mask, expected, op, type);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2293,10 +2293,13 @@ public:
|
||||
switch (index) {
|
||||
case Tegra::Shader::Pred::NeverExecute:
|
||||
target = "false";
|
||||
break;
|
||||
case Tegra::Shader::Pred::UnusedIndex:
|
||||
target = "true";
|
||||
break;
|
||||
default:
|
||||
target = decomp.GetPredicate(index);
|
||||
break;
|
||||
}
|
||||
} else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
|
||||
target = decomp.GetInternalFlag(flag->GetFlag());
|
||||
|
||||
@@ -1682,10 +1682,13 @@ public:
|
||||
switch (index) {
|
||||
case Tegra::Shader::Pred::NeverExecute:
|
||||
target = decomp.v_false;
|
||||
break;
|
||||
case Tegra::Shader::Pred::UnusedIndex:
|
||||
target = decomp.v_true;
|
||||
break;
|
||||
default:
|
||||
target = decomp.predicates.at(index);
|
||||
break;
|
||||
}
|
||||
} else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
|
||||
target = decomp.internal_flags.at(static_cast<u32>(flag->GetFlag()));
|
||||
|
||||
@@ -144,7 +144,7 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
|
||||
case OpCode::Id::ICMP_IMM: {
|
||||
const Node zero = Immediate(0);
|
||||
|
||||
const auto [op_b, test] = [&]() -> std::pair<Node, Node> {
|
||||
const auto [op_rhs, test] = [&]() -> std::pair<Node, Node> {
|
||||
switch (opcode->get().GetId()) {
|
||||
case OpCode::Id::ICMP_CR:
|
||||
return {GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset),
|
||||
@@ -161,10 +161,10 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
|
||||
return {zero, zero};
|
||||
}
|
||||
}();
|
||||
const Node op_a = GetRegister(instr.gpr8);
|
||||
const Node op_lhs = GetRegister(instr.gpr8);
|
||||
const Node comparison =
|
||||
GetPredicateComparisonInteger(instr.icmp.cond, instr.icmp.is_signed != 0, test, zero);
|
||||
SetRegister(bb, instr.gpr0, Operation(OperationCode::Select, comparison, op_a, op_b));
|
||||
SetRegister(bb, instr.gpr0, Operation(OperationCode::Select, comparison, op_lhs, op_rhs));
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::LOP_C:
|
||||
|
||||
@@ -144,8 +144,8 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
|
||||
|
||||
Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
|
||||
const auto offset{static_cast<std::size_t>(image.index.Value())};
|
||||
if (const auto image = TryUseExistingImage(offset, type)) {
|
||||
return *image;
|
||||
if (const auto existing_image = TryUseExistingImage(offset, type)) {
|
||||
return *existing_image;
|
||||
}
|
||||
|
||||
const std::size_t next_index{used_images.size()};
|
||||
|
||||
@@ -314,7 +314,7 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock&
|
||||
|
||||
const auto [base_address, index, offset] =
|
||||
TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
|
||||
ASSERT_OR_EXECUTE_MSG(base_address,
|
||||
ASSERT_OR_EXECUTE_MSG(base_address != nullptr,
|
||||
{ return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
|
||||
"Global memory tracking failed");
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::MOV_SYS: {
|
||||
const Node value = [&]() {
|
||||
const Node value = [this, instr] {
|
||||
switch (instr.sys20) {
|
||||
case SystemVariable::Ydirection:
|
||||
return Operation(OperationCode::YNegate);
|
||||
|
||||
@@ -18,7 +18,7 @@ u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) {
|
||||
const auto opcode = OpCode::Decode(instr);
|
||||
|
||||
Node op_a = GetRegister(instr.gpr8);
|
||||
Node op_b = [&]() {
|
||||
Node op_b = [this, instr] {
|
||||
if (instr.is_b_imm) {
|
||||
return Immediate(instr.alu.GetSignedImm20_20());
|
||||
} else if (instr.is_b_gpr) {
|
||||
|
||||
@@ -150,7 +150,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
|
||||
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
|
||||
}
|
||||
|
||||
WriteTexsInstructionFloat(bb, instr, values);
|
||||
WriteTexsInstructionFloat(bb, instr, values, true);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::TXQ_B:
|
||||
@@ -380,14 +380,14 @@ void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr,
|
||||
const Node4& components) {
|
||||
void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components,
|
||||
bool ignore_mask) {
|
||||
// TEXS has two destination registers and a swizzle. The first two elements in the swizzle
|
||||
// go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1
|
||||
|
||||
u32 dest_elem = 0;
|
||||
for (u32 component = 0; component < 4; ++component) {
|
||||
if (!instr.texs.IsComponentEnabled(component))
|
||||
if (!instr.texs.IsComponentEnabled(component) && !ignore_mask)
|
||||
continue;
|
||||
SetTemporary(bb, dest_elem++, components[component]);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) {
|
||||
const Node op_a =
|
||||
GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a,
|
||||
instr.video.type_a, instr.video.byte_height_a);
|
||||
const Node op_b = [&]() {
|
||||
const Node op_b = [this, instr] {
|
||||
if (instr.video.use_register_b) {
|
||||
return GetVideoOperand(GetRegister(instr.gpr20), instr.video.is_byte_chunk_b,
|
||||
instr.video.signed_b, instr.video.type_b,
|
||||
|
||||
@@ -46,9 +46,10 @@ u32 ShaderIR::DecodeWarp(NodeBlock& bb, u32 pc) {
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::SHFL: {
|
||||
Node mask = instr.shfl.is_mask_imm ? Immediate(static_cast<u32>(instr.shfl.mask_imm))
|
||||
: GetRegister(instr.gpr39);
|
||||
Node width = [&] {
|
||||
Node width = [this, instr] {
|
||||
Node mask = instr.shfl.is_mask_imm ? Immediate(static_cast<u32>(instr.shfl.mask_imm))
|
||||
: GetRegister(instr.gpr39);
|
||||
|
||||
// Convert the obscure SHFL mask back into GL_NV_shader_thread_shuffle's width. This has
|
||||
// been done reversing Nvidia's math. It won't work on all cases due to SHFL having
|
||||
// different parameters that don't properly map to GLSL's interface, but it should work
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -270,21 +271,24 @@ Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) {
|
||||
}
|
||||
|
||||
Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
|
||||
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
||||
{PredCondition::LessThan, OperationCode::LogicalFLessThan},
|
||||
{PredCondition::Equal, OperationCode::LogicalFEqual},
|
||||
{PredCondition::LessEqual, OperationCode::LogicalFLessEqual},
|
||||
{PredCondition::GreaterThan, OperationCode::LogicalFGreaterThan},
|
||||
{PredCondition::NotEqual, OperationCode::LogicalFNotEqual},
|
||||
{PredCondition::GreaterEqual, OperationCode::LogicalFGreaterEqual},
|
||||
{PredCondition::LessThanWithNan, OperationCode::LogicalFLessThan},
|
||||
{PredCondition::NotEqualWithNan, OperationCode::LogicalFNotEqual},
|
||||
{PredCondition::LessEqualWithNan, OperationCode::LogicalFLessEqual},
|
||||
{PredCondition::GreaterThanWithNan, OperationCode::LogicalFGreaterThan},
|
||||
{PredCondition::GreaterEqualWithNan, OperationCode::LogicalFGreaterEqual}};
|
||||
static constexpr std::array comparison_table{
|
||||
std::pair{PredCondition::LessThan, OperationCode::LogicalFLessThan},
|
||||
std::pair{PredCondition::Equal, OperationCode::LogicalFEqual},
|
||||
std::pair{PredCondition::LessEqual, OperationCode::LogicalFLessEqual},
|
||||
std::pair{PredCondition::GreaterThan, OperationCode::LogicalFGreaterThan},
|
||||
std::pair{PredCondition::NotEqual, OperationCode::LogicalFNotEqual},
|
||||
std::pair{PredCondition::GreaterEqual, OperationCode::LogicalFGreaterEqual},
|
||||
std::pair{PredCondition::LessThanWithNan, OperationCode::LogicalFLessThan},
|
||||
std::pair{PredCondition::NotEqualWithNan, OperationCode::LogicalFNotEqual},
|
||||
std::pair{PredCondition::LessEqualWithNan, OperationCode::LogicalFLessEqual},
|
||||
std::pair{PredCondition::GreaterThanWithNan, OperationCode::LogicalFGreaterThan},
|
||||
std::pair{PredCondition::GreaterEqualWithNan, OperationCode::LogicalFGreaterEqual},
|
||||
};
|
||||
|
||||
const auto comparison{PredicateComparisonTable.find(condition)};
|
||||
UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
|
||||
const auto comparison =
|
||||
std::find_if(comparison_table.cbegin(), comparison_table.cend(),
|
||||
[condition](const auto entry) { return condition == entry.first; });
|
||||
UNIMPLEMENTED_IF_MSG(comparison == comparison_table.cend(),
|
||||
"Unknown predicate comparison operation");
|
||||
|
||||
Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b);
|
||||
@@ -305,21 +309,24 @@ Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, N
|
||||
|
||||
Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_signed, Node op_a,
|
||||
Node op_b) {
|
||||
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
||||
{PredCondition::LessThan, OperationCode::LogicalILessThan},
|
||||
{PredCondition::Equal, OperationCode::LogicalIEqual},
|
||||
{PredCondition::LessEqual, OperationCode::LogicalILessEqual},
|
||||
{PredCondition::GreaterThan, OperationCode::LogicalIGreaterThan},
|
||||
{PredCondition::NotEqual, OperationCode::LogicalINotEqual},
|
||||
{PredCondition::GreaterEqual, OperationCode::LogicalIGreaterEqual},
|
||||
{PredCondition::LessThanWithNan, OperationCode::LogicalILessThan},
|
||||
{PredCondition::NotEqualWithNan, OperationCode::LogicalINotEqual},
|
||||
{PredCondition::LessEqualWithNan, OperationCode::LogicalILessEqual},
|
||||
{PredCondition::GreaterThanWithNan, OperationCode::LogicalIGreaterThan},
|
||||
{PredCondition::GreaterEqualWithNan, OperationCode::LogicalIGreaterEqual}};
|
||||
static constexpr std::array comparison_table{
|
||||
std::pair{PredCondition::LessThan, OperationCode::LogicalILessThan},
|
||||
std::pair{PredCondition::Equal, OperationCode::LogicalIEqual},
|
||||
std::pair{PredCondition::LessEqual, OperationCode::LogicalILessEqual},
|
||||
std::pair{PredCondition::GreaterThan, OperationCode::LogicalIGreaterThan},
|
||||
std::pair{PredCondition::NotEqual, OperationCode::LogicalINotEqual},
|
||||
std::pair{PredCondition::GreaterEqual, OperationCode::LogicalIGreaterEqual},
|
||||
std::pair{PredCondition::LessThanWithNan, OperationCode::LogicalILessThan},
|
||||
std::pair{PredCondition::NotEqualWithNan, OperationCode::LogicalINotEqual},
|
||||
std::pair{PredCondition::LessEqualWithNan, OperationCode::LogicalILessEqual},
|
||||
std::pair{PredCondition::GreaterThanWithNan, OperationCode::LogicalIGreaterThan},
|
||||
std::pair{PredCondition::GreaterEqualWithNan, OperationCode::LogicalIGreaterEqual},
|
||||
};
|
||||
|
||||
const auto comparison{PredicateComparisonTable.find(condition)};
|
||||
UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
|
||||
const auto comparison =
|
||||
std::find_if(comparison_table.cbegin(), comparison_table.cend(),
|
||||
[condition](const auto entry) { return condition == entry.first; });
|
||||
UNIMPLEMENTED_IF_MSG(comparison == comparison_table.cend(),
|
||||
"Unknown predicate comparison operation");
|
||||
|
||||
Node predicate = SignedOperation(comparison->second, is_signed, NO_PRECISE, std::move(op_a),
|
||||
@@ -336,36 +343,43 @@ Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_si
|
||||
|
||||
Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a,
|
||||
Node op_b) {
|
||||
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
||||
{PredCondition::LessThan, OperationCode::Logical2HLessThan},
|
||||
{PredCondition::Equal, OperationCode::Logical2HEqual},
|
||||
{PredCondition::LessEqual, OperationCode::Logical2HLessEqual},
|
||||
{PredCondition::GreaterThan, OperationCode::Logical2HGreaterThan},
|
||||
{PredCondition::NotEqual, OperationCode::Logical2HNotEqual},
|
||||
{PredCondition::GreaterEqual, OperationCode::Logical2HGreaterEqual},
|
||||
{PredCondition::LessThanWithNan, OperationCode::Logical2HLessThanWithNan},
|
||||
{PredCondition::NotEqualWithNan, OperationCode::Logical2HNotEqualWithNan},
|
||||
{PredCondition::LessEqualWithNan, OperationCode::Logical2HLessEqualWithNan},
|
||||
{PredCondition::GreaterThanWithNan, OperationCode::Logical2HGreaterThanWithNan},
|
||||
{PredCondition::GreaterEqualWithNan, OperationCode::Logical2HGreaterEqualWithNan}};
|
||||
static constexpr std::array comparison_table{
|
||||
std::pair{PredCondition::LessThan, OperationCode::Logical2HLessThan},
|
||||
std::pair{PredCondition::Equal, OperationCode::Logical2HEqual},
|
||||
std::pair{PredCondition::LessEqual, OperationCode::Logical2HLessEqual},
|
||||
std::pair{PredCondition::GreaterThan, OperationCode::Logical2HGreaterThan},
|
||||
std::pair{PredCondition::NotEqual, OperationCode::Logical2HNotEqual},
|
||||
std::pair{PredCondition::GreaterEqual, OperationCode::Logical2HGreaterEqual},
|
||||
std::pair{PredCondition::LessThanWithNan, OperationCode::Logical2HLessThanWithNan},
|
||||
std::pair{PredCondition::NotEqualWithNan, OperationCode::Logical2HNotEqualWithNan},
|
||||
std::pair{PredCondition::LessEqualWithNan, OperationCode::Logical2HLessEqualWithNan},
|
||||
std::pair{PredCondition::GreaterThanWithNan, OperationCode::Logical2HGreaterThanWithNan},
|
||||
std::pair{PredCondition::GreaterEqualWithNan, OperationCode::Logical2HGreaterEqualWithNan},
|
||||
};
|
||||
|
||||
const auto comparison{PredicateComparisonTable.find(condition)};
|
||||
UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
|
||||
const auto comparison =
|
||||
std::find_if(comparison_table.cbegin(), comparison_table.cend(),
|
||||
[condition](const auto entry) { return condition == entry.first; });
|
||||
UNIMPLEMENTED_IF_MSG(comparison == comparison_table.cend(),
|
||||
"Unknown predicate comparison operation");
|
||||
|
||||
return Operation(comparison->second, NO_PRECISE, std::move(op_a), std::move(op_b));
|
||||
}
|
||||
|
||||
OperationCode ShaderIR::GetPredicateCombiner(PredOperation operation) {
|
||||
const std::unordered_map<PredOperation, OperationCode> PredicateOperationTable = {
|
||||
{PredOperation::And, OperationCode::LogicalAnd},
|
||||
{PredOperation::Or, OperationCode::LogicalOr},
|
||||
{PredOperation::Xor, OperationCode::LogicalXor},
|
||||
static constexpr std::array operation_table{
|
||||
OperationCode::LogicalAnd,
|
||||
OperationCode::LogicalOr,
|
||||
OperationCode::LogicalXor,
|
||||
};
|
||||
|
||||
const auto op = PredicateOperationTable.find(operation);
|
||||
UNIMPLEMENTED_IF_MSG(op == PredicateOperationTable.end(), "Unknown predicate operation");
|
||||
return op->second;
|
||||
const auto index = static_cast<std::size_t>(operation);
|
||||
if (index >= operation_table.size()) {
|
||||
UNIMPLEMENTED_MSG("Unknown predicate operation.");
|
||||
return {};
|
||||
}
|
||||
|
||||
return operation_table[index];
|
||||
}
|
||||
|
||||
Node ShaderIR::GetConditionCode(Tegra::Shader::ConditionCode cc) const {
|
||||
|
||||
@@ -329,7 +329,7 @@ private:
|
||||
const Node4& components);
|
||||
|
||||
void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
|
||||
const Node4& components);
|
||||
const Node4& components, bool ignore_mask = false);
|
||||
void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
|
||||
const Node4& components);
|
||||
|
||||
|
||||
Reference in new issue
Block a user