Compare commits

..

3 Commits

Author SHA1 Message Date
ReinUsesLisp
0d1d755086 shader/track: Search inside of conditional nodes
Some games search conditionally use global memory instructions. This
allows the heuristic to search inside conditional nodes for the source
constant buffer.
2019-02-03 17:21:20 -03:00
ReinUsesLisp
42b75e8be8 shader_ir: Rename BasicBlock to NodeBlock
It's not always used as a basic block. Rename it for consistency.
2019-02-03 17:21:20 -03:00
ReinUsesLisp
6a6fabea58 shader_ir: Pass decoded nodes as a whole instead of per basic blocks
Some games call LDG at the top of a basic block, making the tracking
heuristic to fail. This commit lets the heuristic the decoded nodes as a
whole instead of per basic blocks.

This may lead to some false positives but allows it the heuristic to
track cases it previously couldn't.
2019-02-03 17:21:20 -03:00
41 changed files with 231 additions and 361 deletions

View File

@@ -322,15 +322,14 @@ void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& c
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
// TODO(Subv): Find out how AM determines the display to use, for now just
// create the layer in the Default display.
const auto display_id = nvflinger->OpenDisplay("Default");
const auto layer_id = nvflinger->CreateLayer(*display_id);
u64 display_id = nvflinger->OpenDisplay("Default");
u64 layer_id = nvflinger->CreateLayer(display_id);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(*layer_id);
rb.Push(layer_id);
}
void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {

View File

@@ -46,7 +46,7 @@ void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
nvdrv = std::move(instance);
}
std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
u64 NVFlinger::OpenDisplay(std::string_view name) {
LOG_DEBUG(Service, "Opening \"{}\" display", name);
// TODO(Subv): Currently we only support the Default display.
@@ -54,48 +54,32 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
const auto itr = std::find_if(displays.begin(), displays.end(),
[&](const Display& display) { return display.name == name; });
if (itr == displays.end()) {
return {};
}
ASSERT(itr != displays.end());
return itr->id;
}
std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
auto* const display = FindDisplay(display_id);
u64 NVFlinger::CreateLayer(u64 display_id) {
auto& display = FindDisplay(display_id);
if (display == nullptr) {
return {};
}
ASSERT_MSG(display->layers.empty(), "Only one layer is supported per display at the moment");
ASSERT_MSG(display.layers.empty(), "Only one layer is supported per display at the moment");
const u64 layer_id = next_layer_id++;
const u32 buffer_queue_id = next_buffer_queue_id++;
auto buffer_queue = std::make_shared<BufferQueue>(buffer_queue_id, layer_id);
display->layers.emplace_back(layer_id, buffer_queue);
display.layers.emplace_back(layer_id, buffer_queue);
buffer_queues.emplace_back(std::move(buffer_queue));
return layer_id;
}
std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const {
const auto* const layer = FindLayer(display_id, layer_id);
if (layer == nullptr) {
return {};
}
return layer->buffer_queue->GetId();
u32 NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const {
const auto& layer = FindLayer(display_id, layer_id);
return layer.buffer_queue->GetId();
}
Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
auto* const display = FindDisplay(display_id);
if (display == nullptr) {
return nullptr;
}
return display->vsync_event.readable;
Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) {
return FindDisplay(display_id).vsync_event.readable;
}
std::shared_ptr<BufferQueue> NVFlinger::FindBufferQueue(u32 id) const {
@@ -106,60 +90,40 @@ std::shared_ptr<BufferQueue> NVFlinger::FindBufferQueue(u32 id) const {
return *itr;
}
Display* NVFlinger::FindDisplay(u64 display_id) {
Display& NVFlinger::FindDisplay(u64 display_id) {
const auto itr = std::find_if(displays.begin(), displays.end(),
[&](const Display& display) { return display.id == display_id; });
if (itr == displays.end()) {
return nullptr;
}
return &*itr;
ASSERT(itr != displays.end());
return *itr;
}
const Display* NVFlinger::FindDisplay(u64 display_id) const {
const Display& NVFlinger::FindDisplay(u64 display_id) const {
const auto itr = std::find_if(displays.begin(), displays.end(),
[&](const Display& display) { return display.id == display_id; });
if (itr == displays.end()) {
return nullptr;
}
return &*itr;
ASSERT(itr != displays.end());
return *itr;
}
Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) {
auto* const display = FindDisplay(display_id);
Layer& NVFlinger::FindLayer(u64 display_id, u64 layer_id) {
auto& display = FindDisplay(display_id);
if (display == nullptr) {
return nullptr;
}
const auto itr = std::find_if(display->layers.begin(), display->layers.end(),
const auto itr = std::find_if(display.layers.begin(), display.layers.end(),
[&](const Layer& layer) { return layer.id == layer_id; });
if (itr == display->layers.end()) {
return nullptr;
}
return &*itr;
ASSERT(itr != display.layers.end());
return *itr;
}
const Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const {
const auto* const display = FindDisplay(display_id);
const Layer& NVFlinger::FindLayer(u64 display_id, u64 layer_id) const {
const auto& display = FindDisplay(display_id);
if (display == nullptr) {
return nullptr;
}
const auto itr = std::find_if(display->layers.begin(), display->layers.end(),
const auto itr = std::find_if(display.layers.begin(), display.layers.end(),
[&](const Layer& layer) { return layer.id == layer_id; });
if (itr == display->layers.end()) {
return nullptr;
}
return &*itr;
ASSERT(itr != display.layers.end());
return *itr;
}
void NVFlinger::Compose() {

View File

@@ -6,7 +6,6 @@
#include <array>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
@@ -59,24 +58,16 @@ public:
void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
/// Opens the specified display and returns the ID.
///
/// If an invalid display name is provided, then an empty optional is returned.
std::optional<u64> OpenDisplay(std::string_view name);
u64 OpenDisplay(std::string_view name);
/// Creates a layer on the specified display and returns the layer ID.
///
/// If an invalid display ID is specified, then an empty optional is returned.
std::optional<u64> CreateLayer(u64 display_id);
u64 CreateLayer(u64 display_id);
/// Finds the buffer queue ID of the specified layer in the specified display.
///
/// If an invalid display ID or layer ID is provided, then an empty optional is returned.
std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id) const;
u32 FindBufferQueueId(u64 display_id, u64 layer_id) const;
/// Gets the vsync event for the specified display.
///
/// If an invalid display ID is provided, then nullptr is returned.
Kernel::SharedPtr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const;
Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id);
/// Obtains a buffer queue identified by the ID.
std::shared_ptr<BufferQueue> FindBufferQueue(u32 id) const;
@@ -87,16 +78,16 @@ public:
private:
/// Finds the display identified by the specified ID.
Display* FindDisplay(u64 display_id);
Display& FindDisplay(u64 display_id);
/// Finds the display identified by the specified ID.
const Display* FindDisplay(u64 display_id) const;
const Display& FindDisplay(u64 display_id) const;
/// Finds the layer identified by the specified ID in the desired display.
Layer* FindLayer(u64 display_id, u64 layer_id);
Layer& FindLayer(u64 display_id, u64 layer_id);
/// Finds the layer identified by the specified ID in the desired display.
const Layer* FindLayer(u64 display_id, u64 layer_id) const;
const Layer& FindLayer(u64 display_id, u64 layer_id) const;
std::shared_ptr<Nvidia::Module> nvdrv;

View File

@@ -34,7 +34,6 @@ namespace Service::VI {
constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::VI, 1};
constexpr ResultCode ERR_UNSUPPORTED{ErrorModule::VI, 6};
constexpr ResultCode ERR_NOT_FOUND{ErrorModule::VI, 7};
struct DisplayInfo {
/// The name of this particular display.
@@ -839,16 +838,11 @@ private:
"(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
unknown, display, aruid);
const auto layer_id = nv_flinger->CreateLayer(display);
if (!layer_id) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
const u64 layer_id = nv_flinger->CreateLayer(display);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(*layer_id);
rb.Push(layer_id);
}
void AddToLayerStack(Kernel::HLERequestContext& ctx) {
@@ -956,16 +950,9 @@ private:
ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
const auto display_id = nv_flinger->OpenDisplay(name);
if (!display_id) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(*display_id);
rb.Push<u64>(nv_flinger->OpenDisplay(name));
}
void CloseDisplay(Kernel::HLERequestContext& ctx) {
@@ -1056,21 +1043,10 @@ private:
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
const auto display_id = nv_flinger->OpenDisplay(display_name);
if (!display_id) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
const u64 display_id = nv_flinger->OpenDisplay(display_name);
const u32 buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, layer_id);
const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id);
if (!buffer_queue_id) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
NativeWindow native_window{*buffer_queue_id};
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
@@ -1086,24 +1062,13 @@ private:
// TODO(Subv): What's the difference between a Stray and a Managed layer?
const auto layer_id = nv_flinger->CreateLayer(display_id);
if (!layer_id) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
const u64 layer_id = nv_flinger->CreateLayer(display_id);
const u32 buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, layer_id);
const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id);
if (!buffer_queue_id) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
NativeWindow native_window{*buffer_queue_id};
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push(*layer_id);
rb.Push(layer_id);
rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
}
@@ -1123,12 +1088,7 @@ private:
LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
const auto vsync_event = nv_flinger->FindVsyncEvent(display_id);
if (!vsync_event) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND);
return;
}
const auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);

View File

@@ -71,20 +71,15 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa
FlushMode::FlushAndInvalidate);
VAddr end = base + size;
ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
base + page_table.pointers.size());
while (base != end) {
ASSERT_MSG(base < page_table.pointers.size(), "out of range mapping at {:016X}", base);
std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type);
page_table.attributes[base] = type;
page_table.pointers[base] = memory;
if (memory == nullptr) {
std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end, memory);
} else {
while (base != end) {
page_table.pointers[base] = memory;
base += 1;
base += 1;
if (memory != nullptr)
memory += PAGE_SIZE;
}
}
}

View File

@@ -217,9 +217,9 @@ enum class StoreType : u64 {
Signed8 = 1,
Unsigned16 = 2,
Signed16 = 3,
Bits32 = 4,
Bits64 = 5,
Bits128 = 6,
Bytes32 = 4,
Bytes64 = 5,
Bytes128 = 6,
};
enum class IMinMaxExchange : u64 {
@@ -981,10 +981,6 @@ union Instruction {
}
return false;
}
bool IsComponentEnabled(std::size_t component) const {
return ((1ULL << component) & component_mask) != 0;
}
} txq;
union {

View File

@@ -171,7 +171,7 @@ public:
code.AddLine(fmt::format("case 0x{:x}u: {{", address));
++code.scope;
VisitBasicBlock(bb);
VisitBlock(bb);
--code.scope;
code.AddLine('}');
@@ -424,7 +424,7 @@ private:
code.AddNewLine();
}
void VisitBasicBlock(const BasicBlock& bb) {
void VisitBlock(const NodeBlock& bb) {
for (const Node node : bb) {
if (const std::string expr = Visit(node); !expr.empty()) {
code.AddLine(expr);
@@ -576,7 +576,7 @@ private:
code.AddLine("if (" + Visit(conditional->GetCondition()) + ") {");
++code.scope;
VisitBasicBlock(conditional->GetCode());
VisitBlock(conditional->GetCode());
--code.scope;
code.AddLine('}');

View File

@@ -121,15 +121,15 @@ ExitMethod ShaderIR::Scan(u32 begin, u32 end, std::set<u32>& labels) {
return exit_method = ExitMethod::AlwaysReturn;
}
BasicBlock ShaderIR::DecodeRange(u32 begin, u32 end) {
BasicBlock basic_block;
NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) {
NodeBlock basic_block;
for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) {
pc = DecodeInstr(basic_block, pc);
}
return basic_block;
}
u32 ShaderIR::DecodeInstr(BasicBlock& bb, u32 pc) {
u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) {
// Ignore sched instructions when generating code.
if (IsSchedInstruction(pc, main_offset)) {
return pc + 1;
@@ -151,39 +151,38 @@ u32 ShaderIR::DecodeInstr(BasicBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG(instr.pred.full_pred == Pred::NeverExecute,
"NeverExecute predicate not implemented");
static const std::map<OpCode::Type, u32 (ShaderIR::*)(BasicBlock&, const BasicBlock&, u32)>
decoders = {
{OpCode::Type::Arithmetic, &ShaderIR::DecodeArithmetic},
{OpCode::Type::ArithmeticImmediate, &ShaderIR::DecodeArithmeticImmediate},
{OpCode::Type::Bfe, &ShaderIR::DecodeBfe},
{OpCode::Type::Bfi, &ShaderIR::DecodeBfi},
{OpCode::Type::Shift, &ShaderIR::DecodeShift},
{OpCode::Type::ArithmeticInteger, &ShaderIR::DecodeArithmeticInteger},
{OpCode::Type::ArithmeticIntegerImmediate, &ShaderIR::DecodeArithmeticIntegerImmediate},
{OpCode::Type::ArithmeticHalf, &ShaderIR::DecodeArithmeticHalf},
{OpCode::Type::ArithmeticHalfImmediate, &ShaderIR::DecodeArithmeticHalfImmediate},
{OpCode::Type::Ffma, &ShaderIR::DecodeFfma},
{OpCode::Type::Hfma2, &ShaderIR::DecodeHfma2},
{OpCode::Type::Conversion, &ShaderIR::DecodeConversion},
{OpCode::Type::Memory, &ShaderIR::DecodeMemory},
{OpCode::Type::FloatSetPredicate, &ShaderIR::DecodeFloatSetPredicate},
{OpCode::Type::IntegerSetPredicate, &ShaderIR::DecodeIntegerSetPredicate},
{OpCode::Type::HalfSetPredicate, &ShaderIR::DecodeHalfSetPredicate},
{OpCode::Type::PredicateSetRegister, &ShaderIR::DecodePredicateSetRegister},
{OpCode::Type::PredicateSetPredicate, &ShaderIR::DecodePredicateSetPredicate},
{OpCode::Type::RegisterSetPredicate, &ShaderIR::DecodeRegisterSetPredicate},
{OpCode::Type::FloatSet, &ShaderIR::DecodeFloatSet},
{OpCode::Type::IntegerSet, &ShaderIR::DecodeIntegerSet},
{OpCode::Type::HalfSet, &ShaderIR::DecodeHalfSet},
{OpCode::Type::Video, &ShaderIR::DecodeVideo},
{OpCode::Type::Xmad, &ShaderIR::DecodeXmad},
};
static const std::map<OpCode::Type, u32 (ShaderIR::*)(NodeBlock&, u32)> decoders = {
{OpCode::Type::Arithmetic, &ShaderIR::DecodeArithmetic},
{OpCode::Type::ArithmeticImmediate, &ShaderIR::DecodeArithmeticImmediate},
{OpCode::Type::Bfe, &ShaderIR::DecodeBfe},
{OpCode::Type::Bfi, &ShaderIR::DecodeBfi},
{OpCode::Type::Shift, &ShaderIR::DecodeShift},
{OpCode::Type::ArithmeticInteger, &ShaderIR::DecodeArithmeticInteger},
{OpCode::Type::ArithmeticIntegerImmediate, &ShaderIR::DecodeArithmeticIntegerImmediate},
{OpCode::Type::ArithmeticHalf, &ShaderIR::DecodeArithmeticHalf},
{OpCode::Type::ArithmeticHalfImmediate, &ShaderIR::DecodeArithmeticHalfImmediate},
{OpCode::Type::Ffma, &ShaderIR::DecodeFfma},
{OpCode::Type::Hfma2, &ShaderIR::DecodeHfma2},
{OpCode::Type::Conversion, &ShaderIR::DecodeConversion},
{OpCode::Type::Memory, &ShaderIR::DecodeMemory},
{OpCode::Type::FloatSetPredicate, &ShaderIR::DecodeFloatSetPredicate},
{OpCode::Type::IntegerSetPredicate, &ShaderIR::DecodeIntegerSetPredicate},
{OpCode::Type::HalfSetPredicate, &ShaderIR::DecodeHalfSetPredicate},
{OpCode::Type::PredicateSetRegister, &ShaderIR::DecodePredicateSetRegister},
{OpCode::Type::PredicateSetPredicate, &ShaderIR::DecodePredicateSetPredicate},
{OpCode::Type::RegisterSetPredicate, &ShaderIR::DecodeRegisterSetPredicate},
{OpCode::Type::FloatSet, &ShaderIR::DecodeFloatSet},
{OpCode::Type::IntegerSet, &ShaderIR::DecodeIntegerSet},
{OpCode::Type::HalfSet, &ShaderIR::DecodeHalfSet},
{OpCode::Type::Video, &ShaderIR::DecodeVideo},
{OpCode::Type::Xmad, &ShaderIR::DecodeXmad},
};
std::vector<Node> tmp_block;
if (const auto decoder = decoders.find(opcode->get().GetType()); decoder != decoders.end()) {
pc = (this->*decoder->second)(tmp_block, bb, pc);
pc = (this->*decoder->second)(tmp_block, pc);
} else {
pc = DecodeOther(tmp_block, bb, pc);
pc = DecodeOther(tmp_block, pc);
}
// Some instructions (like SSY) don't have a predicate field, they are always unconditionally
@@ -192,11 +191,14 @@ u32 ShaderIR::DecodeInstr(BasicBlock& bb, u32 pc) {
const auto pred_index = static_cast<u32>(instr.pred.pred_index);
if (can_be_predicated && pred_index != static_cast<u32>(Pred::UnusedIndex)) {
bb.push_back(
Conditional(GetPredicate(pred_index, instr.negate_pred != 0), std::move(tmp_block)));
const Node conditional =
Conditional(GetPredicate(pred_index, instr.negate_pred != 0), std::move(tmp_block));
global_code.push_back(conditional);
bb.push_back(conditional);
} else {
for (auto& node : tmp_block) {
bb.push_back(std::move(node));
global_code.push_back(node);
bb.push_back(node);
}
}

View File

@@ -13,7 +13,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::SubOp;
u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeArithmeticHalf(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeArithmeticHalfImmediate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeArithmeticImmediate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeArithmeticImmediate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -15,7 +15,7 @@ using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
using Tegra::Shader::Register;
u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
@@ -242,7 +242,7 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, const BasicBlock& code, u3
return pc;
}
void ShaderIR::WriteLop3Instruction(BasicBlock& bb, Register dest, Node op_a, Node op_b, Node op_c,
void ShaderIR::WriteLop3Instruction(NodeBlock& bb, Register dest, Node op_a, Node op_b, Node op_c,
Node imm_lut, bool sets_cc) {
constexpr u32 lop_iterations = 32;
const Node one = Immediate(1);

View File

@@ -16,7 +16,7 @@ using Tegra::Shader::Pred;
using Tegra::Shader::PredicateResultMode;
using Tegra::Shader::Register;
u32 ShaderIR::DecodeArithmeticIntegerImmediate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeArithmeticIntegerImmediate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
@@ -54,9 +54,9 @@ u32 ShaderIR::DecodeArithmeticIntegerImmediate(BasicBlock& bb, const BasicBlock&
return pc;
}
void ShaderIR::WriteLogicOperation(BasicBlock& bb, Register dest, LogicOperation logic_op,
Node op_a, Node op_b, PredicateResultMode predicate_mode,
Pred predicate, bool sets_cc) {
void ShaderIR::WriteLogicOperation(NodeBlock& bb, Register dest, LogicOperation logic_op, Node op_a,
Node op_b, PredicateResultMode predicate_mode, Pred predicate,
bool sets_cc) {
const Node result = [&]() {
switch (logic_op) {
case LogicOperation::And:

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeBfe(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeBfe(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeBfi(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeBfi(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -13,7 +13,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Register;
u32 ShaderIR::DecodeConversion(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeFfma(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeFfma(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeFloatSet(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeFloatSet(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -13,7 +13,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
u32 ShaderIR::DecodeFloatSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeFloatSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -14,7 +14,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeHalfSet(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -13,7 +13,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
u32 ShaderIR::DecodeHalfSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -16,7 +16,7 @@ using Tegra::Shader::HalfType;
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeHfma2(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeHfma2(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeIntegerSet(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeIntegerSet(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -13,7 +13,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
u32 ShaderIR::DecodeIntegerSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeIntegerSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -36,7 +36,7 @@ static std::size_t GetCoordCount(TextureType texture_type) {
}
}
u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
@@ -104,42 +104,19 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) {
}
case OpCode::Id::LD_L: {
UNIMPLEMENTED_IF_MSG(instr.ld_l.unknown == 1, "LD_L Unhandled mode: {}",
static_cast<u32>(instr.ld_l.unknown.Value()));
static_cast<unsigned>(instr.ld_l.unknown.Value()));
const auto GetLmem = [&](s32 offset) {
ASSERT(offset % 4 == 0);
const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset);
const Node address = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8),
immediate_offset);
return GetLocalMemory(address);
};
const Node index = Operation(OperationCode::IAdd, GetRegister(instr.gpr8),
Immediate(static_cast<s32>(instr.smem_imm)));
const Node lmem = GetLocalMemory(index);
switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bits32:
case Tegra::Shader::StoreType::Bits64:
case Tegra::Shader::StoreType::Bits128: {
const u32 count = [&]() {
switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bits32:
return 1;
case Tegra::Shader::StoreType::Bits64:
return 2;
case Tegra::Shader::StoreType::Bits128:
return 4;
default:
UNREACHABLE();
return 0;
}
}();
for (u32 i = 0; i < count; ++i)
SetTemporal(bb, i, GetLmem(i * 4));
for (u32 i = 0; i < count; ++i)
SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i));
case Tegra::Shader::StoreType::Bytes32:
SetRegister(bb, instr.gpr0, lmem);
break;
}
default:
UNIMPLEMENTED_MSG("LD_L Unhandled type: {}",
static_cast<u32>(instr.ldst_sl.type.Value()));
static_cast<unsigned>(instr.ldst_sl.type.Value()));
}
break;
}
@@ -160,7 +137,8 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) {
}();
const Node addr_register = GetRegister(instr.gpr8);
const Node base_address = TrackCbuf(addr_register, code, static_cast<s64>(code.size()));
const Node base_address =
TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
const auto cbuf = std::get_if<CbufNode>(base_address);
ASSERT(cbuf != nullptr);
const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset());
@@ -225,20 +203,12 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) {
UNIMPLEMENTED_IF_MSG(instr.st_l.unknown == 0, "ST_L Unhandled mode: {}",
static_cast<u32>(instr.st_l.unknown.Value()));
const auto GetLmemAddr = [&](s32 offset) {
ASSERT(offset % 4 == 0);
const Node immediate = Immediate(static_cast<s32>(instr.smem_imm) + offset);
return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate);
};
const Node index = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8),
Immediate(static_cast<s32>(instr.smem_imm)));
switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bits128:
SetLocalMemory(bb, GetLmemAddr(12), GetRegister(instr.gpr0.Value() + 3));
SetLocalMemory(bb, GetLmemAddr(8), GetRegister(instr.gpr0.Value() + 2));
case Tegra::Shader::StoreType::Bits64:
SetLocalMemory(bb, GetLmemAddr(4), GetRegister(instr.gpr0.Value() + 1));
case Tegra::Shader::StoreType::Bits32:
SetLocalMemory(bb, GetLmemAddr(0), GetRegister(instr.gpr0));
case Tegra::Shader::StoreType::Bytes32:
SetLocalMemory(bb, index, GetRegister(instr.gpr0));
break;
default:
UNIMPLEMENTED_MSG("ST_L Unhandled type: {}",
@@ -355,18 +325,15 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) {
const auto& sampler =
GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false, false);
u32 indexer = 0;
switch (instr.txq.query_type) {
case Tegra::Shader::TextureQueryType::Dimension: {
for (u32 element = 0; element < 4; ++element) {
if (instr.txq.IsComponentEnabled(element)) {
MetaTexture meta{sampler, element};
const Node value = Operation(OperationCode::F4TextureQueryDimensions,
std::move(meta), GetRegister(instr.gpr8));
SetTemporal(bb, indexer++, value);
}
MetaTexture meta{sampler, element};
const Node value = Operation(OperationCode::F4TextureQueryDimensions,
std::move(meta), GetRegister(instr.gpr8));
SetTemporal(bb, element, value);
}
for (u32 i = 0; i < indexer; ++i) {
for (u32 i = 0; i < 4; ++i) {
SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i));
}
break;
@@ -464,8 +431,7 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu
return *used_samplers.emplace(entry).first;
}
void ShaderIR::WriteTexInstructionFloat(BasicBlock& bb, Instruction instr,
const Node4& components) {
void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
u32 dest_elem = 0;
for (u32 elem = 0; elem < 4; ++elem) {
if (!instr.tex.IsComponentEnabled(elem)) {
@@ -480,7 +446,7 @@ void ShaderIR::WriteTexInstructionFloat(BasicBlock& bb, Instruction instr,
}
}
void ShaderIR::WriteTexsInstructionFloat(BasicBlock& bb, Instruction instr,
void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr,
const Node4& components) {
// 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
@@ -504,7 +470,7 @@ void ShaderIR::WriteTexsInstructionFloat(BasicBlock& bb, Instruction instr,
}
}
void ShaderIR::WriteTexsInstructionHalfFloat(BasicBlock& bb, Instruction instr,
void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr,
const Node4& components) {
// TEXS.F16 destionation registers are packed in two registers in pairs (just like any half
// float instruction).
@@ -768,4 +734,4 @@ std::tuple<std::size_t, std::size_t> ShaderIR::ValidateAndGetCoordinateElement(
return {coord_count, total_coord_count};
}
} // namespace VideoCommon::Shader
} // namespace VideoCommon::Shader

View File

@@ -14,7 +14,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Register;
u32 ShaderIR::DecodeOther(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -13,7 +13,7 @@ using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
u32 ShaderIR::DecodePredicateSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodePredicateSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodePredicateSetRegister(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodePredicateSetRegister(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeRegisterSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeRegisterSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeShift(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -15,7 +15,7 @@ using Tegra::Shader::Pred;
using Tegra::Shader::VideoType;
using Tegra::Shader::VmadShr;
u32 ShaderIR::DecodeVideo(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -12,7 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
u32 ShaderIR::DecodeXmad(BasicBlock& bb, const BasicBlock& code, u32 pc) {
u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);

View File

@@ -337,27 +337,27 @@ Node ShaderIR::GetConditionCode(Tegra::Shader::ConditionCode cc) {
}
}
void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) {
void ShaderIR::SetRegister(NodeBlock& bb, Register dest, Node src) {
bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src));
}
void ShaderIR::SetPredicate(BasicBlock& bb, u64 dest, Node src) {
void ShaderIR::SetPredicate(NodeBlock& bb, u64 dest, Node src) {
bb.push_back(Operation(OperationCode::LogicalAssign, GetPredicate(dest), src));
}
void ShaderIR::SetInternalFlag(BasicBlock& bb, InternalFlag flag, Node value) {
void ShaderIR::SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value) {
bb.push_back(Operation(OperationCode::LogicalAssign, GetInternalFlag(flag), value));
}
void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) {
void ShaderIR::SetLocalMemory(NodeBlock& bb, Node address, Node value) {
bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value));
}
void ShaderIR::SetTemporal(BasicBlock& bb, u32 id, Node value) {
void ShaderIR::SetTemporal(NodeBlock& bb, u32 id, Node value) {
SetRegister(bb, Register::ZeroIndex + 1 + id, value);
}
void ShaderIR::SetInternalFlagsFromFloat(BasicBlock& bb, Node value, bool sets_cc) {
void ShaderIR::SetInternalFlagsFromFloat(NodeBlock& bb, Node value, bool sets_cc) {
if (!sets_cc) {
return;
}
@@ -366,7 +366,7 @@ void ShaderIR::SetInternalFlagsFromFloat(BasicBlock& bb, Node value, bool sets_c
LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete");
}
void ShaderIR::SetInternalFlagsFromInteger(BasicBlock& bb, Node value, bool sets_cc) {
void ShaderIR::SetInternalFlagsFromInteger(NodeBlock& bb, Node value, bool sets_cc) {
if (!sets_cc) {
return;
}

View File

@@ -39,7 +39,7 @@ using NodeData =
PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>;
using Node = const NodeData*;
using Node4 = std::array<Node, 4>;
using BasicBlock = std::vector<Node>;
using NodeBlock = std::vector<Node>;
constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
@@ -530,7 +530,7 @@ public:
Decode();
}
const std::map<u32, BasicBlock>& GetBasicBlocks() const {
const std::map<u32, NodeBlock>& GetBasicBlocks() const {
return basic_blocks;
}
@@ -581,7 +581,7 @@ private:
ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels);
BasicBlock DecodeRange(u32 begin, u32 end);
NodeBlock DecodeRange(u32 begin, u32 end);
/**
* Decodes a single instruction from Tegra to IR.
@@ -589,33 +589,33 @@ private:
* @param pc Program counter. Offset to decode.
* @return Next address to decode.
*/
u32 DecodeInstr(BasicBlock& bb, u32 pc);
u32 DecodeInstr(NodeBlock& bb, u32 pc);
u32 DecodeArithmetic(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeArithmeticImmediate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeBfe(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeBfi(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeShift(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeArithmeticInteger(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeArithmeticIntegerImmediate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeArithmeticHalf(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeArithmeticHalfImmediate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeFfma(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeHfma2(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeConversion(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeFloatSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeIntegerSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeHalfSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodePredicateSetRegister(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodePredicateSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeRegisterSetPredicate(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeFloatSet(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeIntegerSet(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeHalfSet(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeVideo(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeXmad(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeOther(BasicBlock& bb, const BasicBlock& code, u32 pc);
u32 DecodeArithmetic(NodeBlock& bb, u32 pc);
u32 DecodeArithmeticImmediate(NodeBlock& bb, u32 pc);
u32 DecodeBfe(NodeBlock& bb, u32 pc);
u32 DecodeBfi(NodeBlock& bb, u32 pc);
u32 DecodeShift(NodeBlock& bb, u32 pc);
u32 DecodeArithmeticInteger(NodeBlock& bb, u32 pc);
u32 DecodeArithmeticIntegerImmediate(NodeBlock& bb, u32 pc);
u32 DecodeArithmeticHalf(NodeBlock& bb, u32 pc);
u32 DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc);
u32 DecodeFfma(NodeBlock& bb, u32 pc);
u32 DecodeHfma2(NodeBlock& bb, u32 pc);
u32 DecodeConversion(NodeBlock& bb, u32 pc);
u32 DecodeMemory(NodeBlock& bb, u32 pc);
u32 DecodeFloatSetPredicate(NodeBlock& bb, u32 pc);
u32 DecodeIntegerSetPredicate(NodeBlock& bb, u32 pc);
u32 DecodeHalfSetPredicate(NodeBlock& bb, u32 pc);
u32 DecodePredicateSetRegister(NodeBlock& bb, u32 pc);
u32 DecodePredicateSetPredicate(NodeBlock& bb, u32 pc);
u32 DecodeRegisterSetPredicate(NodeBlock& bb, u32 pc);
u32 DecodeFloatSet(NodeBlock& bb, u32 pc);
u32 DecodeIntegerSet(NodeBlock& bb, u32 pc);
u32 DecodeHalfSet(NodeBlock& bb, u32 pc);
u32 DecodeVideo(NodeBlock& bb, u32 pc);
u32 DecodeXmad(NodeBlock& bb, u32 pc);
u32 DecodeOther(NodeBlock& bb, u32 pc);
/// Internalizes node's data and returns a managed pointer to a clone of that node
Node StoreNode(NodeData&& node_data);
@@ -664,20 +664,20 @@ private:
Node GetTemporal(u32 id);
/// Sets a register. src value must be a number-evaluated node.
void SetRegister(BasicBlock& bb, Tegra::Shader::Register dest, Node src);
void SetRegister(NodeBlock& bb, Tegra::Shader::Register dest, Node src);
/// Sets a predicate. src value must be a bool-evaluated node
void SetPredicate(BasicBlock& bb, u64 dest, Node src);
void SetPredicate(NodeBlock& bb, u64 dest, Node src);
/// Sets an internal flag. src value must be a bool-evaluated node
void SetInternalFlag(BasicBlock& bb, InternalFlag flag, Node value);
void SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value);
/// Sets a local memory address. address and value must be a number-evaluated node
void SetLocalMemory(BasicBlock& bb, Node address, Node value);
void SetLocalMemory(NodeBlock& bb, Node address, Node value);
/// Sets a temporal. Internally it uses a post-RZ register
void SetTemporal(BasicBlock& bb, u32 id, Node value);
void SetTemporal(NodeBlock& bb, u32 id, Node value);
/// Sets internal flags from a float
void SetInternalFlagsFromFloat(BasicBlock& bb, Node value, bool sets_cc = true);
void SetInternalFlagsFromFloat(NodeBlock& bb, Node value, bool sets_cc = true);
/// Sets internal flags from an integer
void SetInternalFlagsFromInteger(BasicBlock& bb, Node value, bool sets_cc = true);
void SetInternalFlagsFromInteger(NodeBlock& bb, Node value, bool sets_cc = true);
/// Conditionally absolute/negated float. Absolute is applied first
Node GetOperandAbsNegFloat(Node value, bool absolute, bool negate);
@@ -718,12 +718,12 @@ private:
/// Extracts a sequence of bits from a node
Node BitfieldExtract(Node value, u32 offset, u32 bits);
void WriteTexInstructionFloat(BasicBlock& bb, Tegra::Shader::Instruction instr,
void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
const Node4& components);
void WriteTexsInstructionFloat(BasicBlock& bb, Tegra::Shader::Instruction instr,
void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
const Node4& components);
void WriteTexsInstructionHalfFloat(BasicBlock& bb, Tegra::Shader::Instruction instr,
void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
const Node4& components);
Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type,
@@ -752,16 +752,16 @@ private:
Node GetVideoOperand(Node op, bool is_chunk, bool is_signed, Tegra::Shader::VideoType type,
u64 byte_height);
void WriteLogicOperation(BasicBlock& bb, Tegra::Shader::Register dest,
void WriteLogicOperation(NodeBlock& bb, Tegra::Shader::Register dest,
Tegra::Shader::LogicOperation logic_op, Node op_a, Node op_b,
Tegra::Shader::PredicateResultMode predicate_mode,
Tegra::Shader::Pred predicate, bool sets_cc);
void WriteLop3Instruction(BasicBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
Node op_c, Node imm_lut, bool sets_cc);
Node TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor);
Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor);
std::pair<Node, s64> TrackRegister(const GprNode* tracked, const BasicBlock& code, s64 cursor);
std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, s64 cursor);
template <typename... T>
Node Operation(OperationCode code, const T*... operands) {
@@ -803,7 +803,8 @@ private:
u32 coverage_end{};
std::map<std::pair<u32, u32>, ExitMethod> exit_method_map;
std::map<u32, BasicBlock> basic_blocks;
std::map<u32, NodeBlock> basic_blocks;
NodeBlock global_code;
std::vector<std::unique_ptr<NodeData>> stored_nodes;

View File

@@ -11,7 +11,7 @@
namespace VideoCommon::Shader {
namespace {
std::pair<Node, s64> FindOperation(const BasicBlock& code, s64 cursor,
std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
OperationCode operation_code) {
for (; cursor >= 0; --cursor) {
const Node node = code[cursor];
@@ -19,12 +19,19 @@ std::pair<Node, s64> FindOperation(const BasicBlock& code, s64 cursor,
if (operation->GetCode() == operation_code)
return {node, cursor};
}
if (const auto conditional = std::get_if<ConditionalNode>(node)) {
const auto& code = conditional->GetCode();
const auto [found, internal_cursor] =
FindOperation(code, static_cast<s64>(code.size() - 1), operation_code);
if (found)
return {found, cursor};
}
}
return {};
}
} // namespace
Node ShaderIR::TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor) {
Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) {
if (const auto cbuf = std::get_if<CbufNode>(tracked)) {
// Cbuf found, but it has to be immediate
return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
@@ -50,10 +57,14 @@ Node ShaderIR::TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor) {
}
return nullptr;
}
if (const auto conditional = std::get_if<ConditionalNode>(tracked)) {
const auto& code = conditional->GetCode();
return TrackCbuf(tracked, code, static_cast<s64>(code.size()));
}
return nullptr;
}
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const BasicBlock& code,
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeBlock& code,
s64 cursor) {
for (; cursor >= 0; --cursor) {
const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign);

View File

@@ -182,7 +182,7 @@ struct TICEntry {
};
union {
BitField<0, 16, u32> height_minus_1;
BitField<16, 14, u32> depth_minus_1;
BitField<16, 15, u32> depth_minus_1;
};
union {
BitField<6, 13, u32> mip_lod_bias;

View File

@@ -62,7 +62,9 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
const QColor new_bg_color = QColorDialog::getColor(bg_color);
if (!new_bg_color.isValid())
return;
UpdateBackgroundColorButton(new_bg_color);
bg_color = new_bg_color;
ui->bg_button->setStyleSheet(
QString("QPushButton { background-color: %1 }").arg(bg_color.name()));
});
}
@@ -74,8 +76,10 @@ void ConfigureGraphics::setConfiguration() {
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
ui->frame_limit->setValue(Settings::values.frame_limit);
ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation);
UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
Settings::values.bg_blue));
bg_color = QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
Settings::values.bg_blue);
ui->bg_button->setStyleSheet(
QString("QPushButton { background-color: %1 }").arg(bg_color.name()));
}
void ConfigureGraphics::applyConfiguration() {
@@ -88,13 +92,3 @@ void ConfigureGraphics::applyConfiguration() {
Settings::values.bg_green = static_cast<float>(bg_color.greenF());
Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
}
void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) {
bg_color = color;
QPixmap pixmap(ui->bg_button->size());
pixmap.fill(bg_color);
const QIcon color_icon(pixmap);
ui->bg_button->setIcon(color_icon);
}

View File

@@ -23,8 +23,6 @@ public:
private:
void setConfiguration();
void UpdateBackgroundColorButton(QColor color);
std::unique_ptr<Ui::ConfigureGraphics> ui;
QColor bg_color;
};

View File

@@ -132,7 +132,7 @@ border-radius: 15px;
font: 75 15pt &quot;Arial&quot;;</string>
</property>
<property name="text">
<string>Estimated Time 5m 4s</string>
<string>Stage 1 of 2. Estimate Time 5m 4s</string>
</property>
</widget>
</item>
@@ -146,9 +146,6 @@ font: 75 15pt &quot;Arial&quot;;</string>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="margin">
<number>30</number>
</property>

View File

@@ -1682,16 +1682,12 @@ void GMainWindow::OnToggleFilterBar() {
void GMainWindow::OnCaptureScreenshot() {
OnPauseGame();
QFileDialog png_dialog(this, tr("Capture Screenshot"), UISettings::values.screenshot_path,
tr("PNG Image (*.png)"));
png_dialog.setAcceptMode(QFileDialog::AcceptSave);
png_dialog.setDefaultSuffix("png");
if (png_dialog.exec()) {
const QString path = png_dialog.selectedFiles().first();
if (!path.isEmpty()) {
UISettings::values.screenshot_path = QFileInfo(path).path();
render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path);
}
const QString path =
QFileDialog::getSaveFileName(this, tr("Capture Screenshot"),
UISettings::values.screenshot_path, tr("PNG Image (*.png)"));
if (!path.isEmpty()) {
UISettings::values.screenshot_path = QFileInfo(path).path();
render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path);
}
OnStartGame();
}