summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/ptm/psm.cpp71
-rw-r--r--src/core/hle/service/ptm/psm.h15
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/video_core/engines/shader_bytecode.h14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp75
-rw-r--r--src/yuzu/CMakeLists.txt2
8 files changed, 150 insertions, 32 deletions
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index abbd056ee..c9161155a 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -91,6 +91,7 @@ enum class Class : ClassType {
91 Service_PM, ///< The PM service 91 Service_PM, ///< The PM service
92 Service_PREPO, ///< The PREPO (Play report) service 92 Service_PREPO, ///< The PREPO (Play report) service
93 Service_PSC, ///< The PSC service 93 Service_PSC, ///< The PSC service
94 Service_PSM, ///< The PSM service
94 Service_SET, ///< The SET (Settings) service 95 Service_SET, ///< The SET (Settings) service
95 Service_SM, ///< The SM (Service manager) service 96 Service_SM, ///< The SM (Service manager) service
96 Service_SPL, ///< The SPL service 97 Service_SPL, ///< The SPL service
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9b1cfae42..64fdf38cd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -331,6 +331,8 @@ add_library(core STATIC
331 hle/service/prepo/prepo.h 331 hle/service/prepo/prepo.h
332 hle/service/psc/psc.cpp 332 hle/service/psc/psc.cpp
333 hle/service/psc/psc.h 333 hle/service/psc/psc.h
334 hle/service/ptm/psm.cpp
335 hle/service/ptm/psm.h
334 hle/service/service.cpp 336 hle/service/service.cpp
335 hle/service/service.h 337 hle/service/service.h
336 hle/service/set/set.cpp 338 hle/service/set/set.cpp
diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp
new file mode 100644
index 000000000..c2d5fda94
--- /dev/null
+++ b/src/core/hle/service/ptm/psm.cpp
@@ -0,0 +1,71 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6
7#include "common/logging/log.h"
8#include "core/hle/ipc_helpers.h"
9#include "core/hle/service/ptm/psm.h"
10#include "core/hle/service/service.h"
11#include "core/hle/service/sm/sm.h"
12
13namespace Service::PSM {
14
15constexpr u32 BATTERY_FULLY_CHARGED = 100; // 100% Full
16constexpr u32 BATTERY_CURRENTLY_CHARGING = 1; // Plugged into an official dock
17
18class PSM final : public ServiceFramework<PSM> {
19public:
20 explicit PSM() : ServiceFramework{"psm"} {
21 // clang-format off
22 static const FunctionInfo functions[] = {
23 {0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"},
24 {1, &PSM::GetChargerType, "GetChargerType"},
25 {2, nullptr, "EnableBatteryCharging"},
26 {3, nullptr, "DisableBatteryCharging"},
27 {4, nullptr, "IsBatteryChargingEnabled"},
28 {5, nullptr, "AcquireControllerPowerSupply"},
29 {6, nullptr, "ReleaseControllerPowerSupply"},
30 {7, nullptr, "OpenSession"},
31 {8, nullptr, "EnableEnoughPowerChargeEmulation"},
32 {9, nullptr, "DisableEnoughPowerChargeEmulation"},
33 {10, nullptr, "EnableFastBatteryCharging"},
34 {11, nullptr, "DisableFastBatteryCharging"},
35 {12, nullptr, "GetBatteryVoltageState"},
36 {13, nullptr, "GetRawBatteryChargePercentage"},
37 {14, nullptr, "IsEnoughPowerSupplied"},
38 {15, nullptr, "GetBatteryAgePercentage"},
39 {16, nullptr, "GetBatteryChargeInfoEvent"},
40 {17, nullptr, "GetBatteryChargeInfoFields"},
41 };
42 // clang-format on
43
44 RegisterHandlers(functions);
45 }
46
47 ~PSM() override = default;
48
49private:
50 void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) {
51 LOG_WARNING(Service_PSM, "(STUBBED) called");
52
53 IPC::ResponseBuilder rb{ctx, 3};
54 rb.Push(RESULT_SUCCESS);
55 rb.Push<u32>(BATTERY_FULLY_CHARGED);
56 }
57
58 void GetChargerType(Kernel::HLERequestContext& ctx) {
59 LOG_WARNING(Service_PSM, "(STUBBED) called");
60
61 IPC::ResponseBuilder rb{ctx, 3};
62 rb.Push(RESULT_SUCCESS);
63 rb.Push<u32>(BATTERY_CURRENTLY_CHARGING);
64 }
65};
66
67void InstallInterfaces(SM::ServiceManager& sm) {
68 std::make_shared<PSM>()->InstallAsService(sm);
69}
70
71} // namespace Service::PSM
diff --git a/src/core/hle/service/ptm/psm.h b/src/core/hle/service/ptm/psm.h
new file mode 100644
index 000000000..a286793ae
--- /dev/null
+++ b/src/core/hle/service/ptm/psm.h
@@ -0,0 +1,15 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::PSM {
12
13void InstallInterfaces(SM::ServiceManager& sm);
14
15} // namespace Service::PSM
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index dd6c6d3b3..a4cf45267 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -58,6 +58,7 @@
58#include "core/hle/service/pm/pm.h" 58#include "core/hle/service/pm/pm.h"
59#include "core/hle/service/prepo/prepo.h" 59#include "core/hle/service/prepo/prepo.h"
60#include "core/hle/service/psc/psc.h" 60#include "core/hle/service/psc/psc.h"
61#include "core/hle/service/ptm/psm.h"
61#include "core/hle/service/service.h" 62#include "core/hle/service/service.h"
62#include "core/hle/service/set/settings.h" 63#include "core/hle/service/set/settings.h"
63#include "core/hle/service/sm/sm.h" 64#include "core/hle/service/sm/sm.h"
@@ -246,6 +247,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs)
246 PlayReport::InstallInterfaces(*sm); 247 PlayReport::InstallInterfaces(*sm);
247 PM::InstallInterfaces(*sm); 248 PM::InstallInterfaces(*sm);
248 PSC::InstallInterfaces(*sm); 249 PSC::InstallInterfaces(*sm);
250 PSM::InstallInterfaces(*sm);
249 Set::InstallInterfaces(*sm); 251 Set::InstallInterfaces(*sm);
250 Sockets::InstallInterfaces(*sm); 252 Sockets::InstallInterfaces(*sm);
251 SPL::InstallInterfaces(*sm); 253 SPL::InstallInterfaces(*sm);
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 67501cf0a..ac50bb622 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -564,6 +564,10 @@ union Instruction {
564 } fmul; 564 } fmul;
565 565
566 union { 566 union {
567 BitField<55, 1, u64> saturate;
568 } fmul32;
569
570 union {
567 BitField<48, 1, u64> is_signed; 571 BitField<48, 1, u64> is_signed;
568 } shift; 572 } shift;
569 573
@@ -1209,11 +1213,13 @@ public:
1209 KIL, 1213 KIL,
1210 SSY, 1214 SSY,
1211 SYNC, 1215 SYNC,
1216 BRK,
1212 DEPBAR, 1217 DEPBAR,
1213 BFE_C, 1218 BFE_C,
1214 BFE_R, 1219 BFE_R,
1215 BFE_IMM, 1220 BFE_IMM,
1216 BRA, 1221 BRA,
1222 PBK,
1217 LD_A, 1223 LD_A,
1218 LD_C, 1224 LD_C,
1219 ST_A, 1225 ST_A,
@@ -1370,7 +1376,7 @@ public:
1370 /// conditionally executed). 1376 /// conditionally executed).
1371 static bool IsPredicatedInstruction(Id opcode) { 1377 static bool IsPredicatedInstruction(Id opcode) {
1372 // TODO(Subv): Add the rest of unpredicated instructions. 1378 // TODO(Subv): Add the rest of unpredicated instructions.
1373 return opcode != Id::SSY; 1379 return opcode != Id::SSY && opcode != Id::PBK;
1374 } 1380 }
1375 1381
1376 class Matcher { 1382 class Matcher {
@@ -1466,9 +1472,11 @@ private:
1466#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) 1472#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
1467 INST("111000110011----", Id::KIL, Type::Flow, "KIL"), 1473 INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
1468 INST("111000101001----", Id::SSY, Type::Flow, "SSY"), 1474 INST("111000101001----", Id::SSY, Type::Flow, "SSY"),
1475 INST("111000101010----", Id::PBK, Type::Flow, "PBK"),
1469 INST("111000100100----", Id::BRA, Type::Flow, "BRA"), 1476 INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
1477 INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"),
1478 INST("111000110100---", Id::BRK, Type::Flow, "BRK"),
1470 INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), 1479 INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"),
1471 INST("1111000011111---", Id::SYNC, Type::Synch, "SYNC"),
1472 INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), 1480 INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
1473 INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), 1481 INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
1474 INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), 1482 INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
@@ -1606,4 +1614,4 @@ private:
1606 } 1614 }
1607}; 1615};
1608 1616
1609} // namespace Tegra::Shader 1617} // namespace Tegra::Shader \ No newline at end of file
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index f224cb5b2..7a019fc86 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -163,10 +163,11 @@ private:
163 const ExitMethod jmp = Scan(target, end, labels); 163 const ExitMethod jmp = Scan(target, end, labels);
164 return exit_method = ParallelExit(no_jmp, jmp); 164 return exit_method = ParallelExit(no_jmp, jmp);
165 } 165 }
166 case OpCode::Id::SSY: { 166 case OpCode::Id::SSY:
167 // The SSY instruction uses a similar encoding as the BRA instruction. 167 case OpCode::Id::PBK: {
168 // The SSY and PBK use a similar encoding as the BRA instruction.
168 ASSERT_MSG(instr.bra.constant_buffer == 0, 169 ASSERT_MSG(instr.bra.constant_buffer == 0,
169 "Constant buffer SSY is not supported"); 170 "Constant buffer branching is not supported");
170 const u32 target = offset + instr.bra.GetBranchTarget(); 171 const u32 target = offset + instr.bra.GetBranchTarget();
171 labels.insert(target); 172 labels.insert(target);
172 // Continue scanning for an exit method. 173 // Continue scanning for an exit method.
@@ -378,8 +379,8 @@ public:
378 * @param reg The destination register to use. 379 * @param reg The destination register to use.
379 * @param elem The element to use for the operation. 380 * @param elem The element to use for the operation.
380 * @param value The code representing the value to assign. Type has to be half float. 381 * @param value The code representing the value to assign. Type has to be half float.
381 * @param type Half float kind of assignment. 382 * @param merge Half float kind of assignment.
382 * @param dest_num_components Number of components in the destionation. 383 * @param dest_num_components Number of components in the destination.
383 * @param value_num_components Number of components in the value. 384 * @param value_num_components Number of components in the value.
384 * @param is_saturated Optional, when True, saturates the provided value. 385 * @param is_saturated Optional, when True, saturates the provided value.
385 * @param dest_elem Optional, the destination element to use for the operation. 386 * @param dest_elem Optional, the destination element to use for the operation.
@@ -422,6 +423,7 @@ public:
422 * @param reg The destination register to use. 423 * @param reg The destination register to use.
423 * @param elem The element to use for the operation. 424 * @param elem The element to use for the operation.
424 * @param attribute The input attribute to use as the source value. 425 * @param attribute The input attribute to use as the source value.
426 * @param input_mode The input mode.
425 * @param vertex The register that decides which vertex to read from (used in GS). 427 * @param vertex The register that decides which vertex to read from (used in GS).
426 */ 428 */
427 void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute, 429 void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
@@ -951,7 +953,7 @@ private:
951 // Can't assign to the constant predicate. 953 // Can't assign to the constant predicate.
952 ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); 954 ASSERT(pred != static_cast<u64>(Pred::UnusedIndex));
953 955
954 const std::string variable = 'p' + std::to_string(pred) + '_' + suffix; 956 std::string variable = 'p' + std::to_string(pred) + '_' + suffix;
955 shader.AddLine(variable + " = " + value + ';'); 957 shader.AddLine(variable + " = " + value + ';');
956 declr_predicates.insert(std::move(variable)); 958 declr_predicates.insert(std::move(variable));
957 } 959 }
@@ -1058,7 +1060,7 @@ private:
1058 /* 1060 /*
1059 * Transforms the input string GLSL operand into an unpacked half float pair. 1061 * Transforms the input string GLSL operand into an unpacked half float pair.
1060 * @note This function returns a float type pair instead of a half float pair. This is because 1062 * @note This function returns a float type pair instead of a half float pair. This is because
1061 * real half floats are not standarized in GLSL but unpackHalf2x16 (which returns a vec2) is. 1063 * real half floats are not standardized in GLSL but unpackHalf2x16 (which returns a vec2) is.
1062 * @param operand Input operand. It has to be an unsigned integer. 1064 * @param operand Input operand. It has to be an unsigned integer.
1063 * @param type How to unpack the unsigned integer to a half float pair. 1065 * @param type How to unpack the unsigned integer to a half float pair.
1064 * @param abs Get the absolute value of unpacked half floats. 1066 * @param abs Get the absolute value of unpacked half floats.
@@ -1232,27 +1234,27 @@ private:
1232 } 1234 }
1233 1235
1234 /* 1236 /*
1235 * Emits code to push the input target address to the SSY address stack, incrementing the stack 1237 * Emits code to push the input target address to the flow address stack, incrementing the stack
1236 * top. 1238 * top.
1237 */ 1239 */
1238 void EmitPushToSSYStack(u32 target) { 1240 void EmitPushToFlowStack(u32 target) {
1239 shader.AddLine('{'); 1241 shader.AddLine('{');
1240 ++shader.scope; 1242 ++shader.scope;
1241 shader.AddLine("ssy_stack[ssy_stack_top] = " + std::to_string(target) + "u;"); 1243 shader.AddLine("flow_stack[flow_stack_top] = " + std::to_string(target) + "u;");
1242 shader.AddLine("ssy_stack_top++;"); 1244 shader.AddLine("flow_stack_top++;");
1243 --shader.scope; 1245 --shader.scope;
1244 shader.AddLine('}'); 1246 shader.AddLine('}');
1245 } 1247 }
1246 1248
1247 /* 1249 /*
1248 * Emits code to pop an address from the SSY address stack, setting the jump address to the 1250 * Emits code to pop an address from the flow address stack, setting the jump address to the
1249 * popped address and decrementing the stack top. 1251 * popped address and decrementing the stack top.
1250 */ 1252 */
1251 void EmitPopFromSSYStack() { 1253 void EmitPopFromFlowStack() {
1252 shader.AddLine('{'); 1254 shader.AddLine('{');
1253 ++shader.scope; 1255 ++shader.scope;
1254 shader.AddLine("ssy_stack_top--;"); 1256 shader.AddLine("flow_stack_top--;");
1255 shader.AddLine("jmp_to = ssy_stack[ssy_stack_top];"); 1257 shader.AddLine("jmp_to = flow_stack[flow_stack_top];");
1256 shader.AddLine("break;"); 1258 shader.AddLine("break;");
1257 --shader.scope; 1259 --shader.scope;
1258 shader.AddLine('}'); 1260 shader.AddLine('}');
@@ -1479,9 +1481,10 @@ private:
1479 break; 1481 break;
1480 } 1482 }
1481 case OpCode::Id::FMUL32_IMM: { 1483 case OpCode::Id::FMUL32_IMM: {
1482 regs.SetRegisterToFloat( 1484 regs.SetRegisterToFloat(instr.gpr0, 0,
1483 instr.gpr0, 0, 1485 regs.GetRegisterAsFloat(instr.gpr8) + " * " +
1484 regs.GetRegisterAsFloat(instr.gpr8) + " * " + GetImmediate32(instr), 1, 1); 1486 GetImmediate32(instr),
1487 1, 1, instr.fmul32.saturate);
1485 break; 1488 break;
1486 } 1489 }
1487 case OpCode::Id::FADD32I: { 1490 case OpCode::Id::FADD32I: {
@@ -3283,16 +3286,32 @@ private:
3283 // The SSY opcode tells the GPU where to re-converge divergent execution paths, it 3286 // The SSY opcode tells the GPU where to re-converge divergent execution paths, it
3284 // sets the target of the jump that the SYNC instruction will make. The SSY opcode 3287 // sets the target of the jump that the SYNC instruction will make. The SSY opcode
3285 // has a similar structure to the BRA opcode. 3288 // has a similar structure to the BRA opcode.
3286 ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported"); 3289 ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer flow is not supported");
3287 3290
3288 const u32 target = offset + instr.bra.GetBranchTarget(); 3291 const u32 target = offset + instr.bra.GetBranchTarget();
3289 EmitPushToSSYStack(target); 3292 EmitPushToFlowStack(target);
3293 break;
3294 }
3295 case OpCode::Id::PBK: {
3296 // PBK pushes to a stack the address where BRK will jump to. This shares stack with
3297 // SSY but using SYNC on a PBK address will kill the shader execution. We don't
3298 // emulate this because it's very unlikely a driver will emit such invalid shader.
3299 ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer PBK is not supported");
3300
3301 const u32 target = offset + instr.bra.GetBranchTarget();
3302 EmitPushToFlowStack(target);
3290 break; 3303 break;
3291 } 3304 }
3292 case OpCode::Id::SYNC: { 3305 case OpCode::Id::SYNC: {
3293 // The SYNC opcode jumps to the address previously set by the SSY opcode 3306 // The SYNC opcode jumps to the address previously set by the SSY opcode
3294 ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); 3307 ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
3295 EmitPopFromSSYStack(); 3308 EmitPopFromFlowStack();
3309 break;
3310 }
3311 case OpCode::Id::BRK: {
3312 // The BRK opcode jumps to the address previously set by the PBK opcode
3313 ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
3314 EmitPopFromFlowStack();
3296 break; 3315 break;
3297 } 3316 }
3298 case OpCode::Id::DEPBAR: { 3317 case OpCode::Id::DEPBAR: {
@@ -3311,8 +3330,8 @@ private:
3311 Tegra::Shader::VmadType type, u64 byte_height) { 3330 Tegra::Shader::VmadType type, u64 byte_height) {
3312 const std::string value = [&]() { 3331 const std::string value = [&]() {
3313 if (!is_chunk) { 3332 if (!is_chunk) {
3314 const auto offset = static_cast<u32>(byte_height * 8); 3333 const auto shift = static_cast<u32>(byte_height * 8);
3315 return "((" + op + " >> " + std::to_string(offset) + ") & 0xff)"; 3334 return "((" + op + " >> " + std::to_string(shift) + ") & 0xff)";
3316 } 3335 }
3317 const std::string zero = "0"; 3336 const std::string zero = "0";
3318 3337
@@ -3446,11 +3465,11 @@ private:
3446 labels.insert(subroutine.begin); 3465 labels.insert(subroutine.begin);
3447 shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;"); 3466 shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
3448 3467
3449 // TODO(Subv): Figure out the actual depth of the SSY stack, for now it seems 3468 // TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
3450 // unlikely that shaders will use 20 nested SSYs. 3469 // unlikely that shaders will use 20 nested SSYs and PBKs.
3451 constexpr u32 SSY_STACK_SIZE = 20; 3470 constexpr u32 FLOW_STACK_SIZE = 20;
3452 shader.AddLine("uint ssy_stack[" + std::to_string(SSY_STACK_SIZE) + "];"); 3471 shader.AddLine("uint flow_stack[" + std::to_string(FLOW_STACK_SIZE) + "];");
3453 shader.AddLine("uint ssy_stack_top = 0u;"); 3472 shader.AddLine("uint flow_stack_top = 0u;");
3454 3473
3455 shader.AddLine("while (true) {"); 3474 shader.AddLine("while (true) {");
3456 ++shader.scope; 3475 ++shader.scope;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 04464ad5e..b901c29d2 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -121,7 +121,7 @@ target_link_libraries(yuzu PRIVATE Boost::boost glad Qt5::OpenGL Qt5::Widgets)
121target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) 121target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
122 122
123if (YUZU_ENABLE_COMPATIBILITY_REPORTING) 123if (YUZU_ENABLE_COMPATIBILITY_REPORTING)
124 add_definitions(-DYUZU_ENABLE_COMPATIBILITY_REPORTING) 124 target_compile_definitions(yuzu PRIVATE -DYUZU_ENABLE_COMPATIBILITY_REPORTING)
125endif() 125endif()
126 126
127if (USE_DISCORD_PRESENCE) 127if (USE_DISCORD_PRESENCE)