summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp38
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h4
-rw-r--r--src/core/gdbstub/gdbstub.cpp170
-rw-r--r--src/core/gdbstub/gdbstub.h9
-rw-r--r--src/video_core/gpu.cpp4
-rw-r--r--src/video_core/gpu.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp19
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h20
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h2
-rw-r--r--src/video_core/textures/decoders.cpp3
10 files changed, 232 insertions, 39 deletions
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index c0cc62f03..ce6c5616d 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -35,6 +35,17 @@ LoadDll LoadDll::g_load_dll;
35 } \ 35 } \
36 } while (0) 36 } while (0)
37 37
38static void CodeHook(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) {
39 GDBStub::BreakpointAddress bkpt =
40 GDBStub::GetNextBreakpointFromAddress(address, GDBStub::BreakpointType::Execute);
41 if (GDBStub::IsMemoryBreak() ||
42 (bkpt.type != GDBStub::BreakpointType::None && address == bkpt.address)) {
43 auto core = static_cast<ARM_Unicorn*>(user_data);
44 core->RecordBreak(bkpt);
45 uc_emu_stop(uc);
46 }
47}
48
38static void InterruptHook(uc_engine* uc, u32 intNo, void* user_data) { 49static void InterruptHook(uc_engine* uc, u32 intNo, void* user_data) {
39 u32 esr{}; 50 u32 esr{};
40 CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR, &esr)); 51 CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR, &esr));
@@ -67,6 +78,10 @@ ARM_Unicorn::ARM_Unicorn() {
67 uc_hook hook{}; 78 uc_hook hook{};
68 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)InterruptHook, this, 0, -1)); 79 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)InterruptHook, this, 0, -1));
69 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, this, 0, -1)); 80 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, this, 0, -1));
81 if (GDBStub::IsServerEnabled()) {
82 CHECKED(uc_hook_add(uc, &hook, UC_HOOK_CODE, (void*)CodeHook, this, 0, -1));
83 last_bkpt_hit = false;
84 }
70} 85}
71 86
72ARM_Unicorn::~ARM_Unicorn() { 87ARM_Unicorn::~ARM_Unicorn() {
@@ -155,7 +170,11 @@ void ARM_Unicorn::SetTlsAddress(VAddr base) {
155} 170}
156 171
157void ARM_Unicorn::Run() { 172void ARM_Unicorn::Run() {
158 ExecuteInstructions(std::max(CoreTiming::GetDowncount(), 0)); 173 if (GDBStub::IsServerEnabled()) {
174 ExecuteInstructions(std::max(4000000, 0));
175 } else {
176 ExecuteInstructions(std::max(CoreTiming::GetDowncount(), 0));
177 }
159} 178}
160 179
161void ARM_Unicorn::Step() { 180void ARM_Unicorn::Step() {
@@ -168,6 +187,18 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
168 MICROPROFILE_SCOPE(ARM_Jit); 187 MICROPROFILE_SCOPE(ARM_Jit);
169 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions)); 188 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
170 CoreTiming::AddTicks(num_instructions); 189 CoreTiming::AddTicks(num_instructions);
190 if (GDBStub::IsServerEnabled()) {
191 if (last_bkpt_hit) {
192 uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);
193 }
194 Kernel::Thread* thread = Kernel::GetCurrentThread();
195 SaveContext(thread->context);
196 if (last_bkpt_hit) {
197 last_bkpt_hit = false;
198 GDBStub::Break();
199 }
200 GDBStub::SendTrap(thread, 5);
201 }
171} 202}
172 203
173void ARM_Unicorn::SaveContext(ARM_Interface::ThreadContext& ctx) { 204void ARM_Unicorn::SaveContext(ARM_Interface::ThreadContext& ctx) {
@@ -233,3 +264,8 @@ void ARM_Unicorn::PrepareReschedule() {
233} 264}
234 265
235void ARM_Unicorn::ClearInstructionCache() {} 266void ARM_Unicorn::ClearInstructionCache() {}
267
268void ARM_Unicorn::RecordBreak(GDBStub::BreakpointAddress bkpt) {
269 last_bkpt = bkpt;
270 last_bkpt_hit = true;
271}
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index b99b58e4c..a482a2aa3 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -7,6 +7,7 @@
7#include <unicorn/unicorn.h> 7#include <unicorn/unicorn.h>
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
10#include "core/gdbstub/gdbstub.h"
10 11
11class ARM_Unicorn final : public ARM_Interface { 12class ARM_Unicorn final : public ARM_Interface {
12public: 13public:
@@ -35,7 +36,10 @@ public:
35 void Step() override; 36 void Step() override;
36 void ClearInstructionCache() override; 37 void ClearInstructionCache() override;
37 void PageTableChanged() override{}; 38 void PageTableChanged() override{};
39 void RecordBreak(GDBStub::BreakpointAddress bkpt);
38 40
39private: 41private:
40 uc_engine* uc{}; 42 uc_engine* uc{};
43 GDBStub::BreakpointAddress last_bkpt{};
44 bool last_bkpt_hit;
41}; 45};
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 6c5a40ba8..2603192fe 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -32,9 +32,13 @@
32 32
33#include "common/logging/log.h" 33#include "common/logging/log.h"
34#include "common/string_util.h" 34#include "common/string_util.h"
35#include "common/swap.h"
35#include "core/arm/arm_interface.h" 36#include "core/arm/arm_interface.h"
36#include "core/core.h" 37#include "core/core.h"
38#include "core/core_cpu.h"
37#include "core/gdbstub/gdbstub.h" 39#include "core/gdbstub/gdbstub.h"
40#include "core/hle/kernel/kernel.h"
41#include "core/hle/kernel/scheduler.h"
38#include "core/loader/loader.h" 42#include "core/loader/loader.h"
39#include "core/memory.h" 43#include "core/memory.h"
40 44
@@ -137,15 +141,17 @@ static u8 command_buffer[GDB_BUFFER_SIZE];
137static u32 command_length; 141static u32 command_length;
138 142
139static u32 latest_signal = 0; 143static u32 latest_signal = 0;
140static bool step_break = false;
141static bool memory_break = false; 144static bool memory_break = false;
142 145
146static Kernel::Thread* current_thread = nullptr;
147
143// Binding to a port within the reserved ports range (0-1023) requires root permissions, 148// Binding to a port within the reserved ports range (0-1023) requires root permissions,
144// so default to a port outside of that range. 149// so default to a port outside of that range.
145static u16 gdbstub_port = 24689; 150static u16 gdbstub_port = 24689;
146 151
147static bool halt_loop = true; 152static bool halt_loop = true;
148static bool step_loop = false; 153static bool step_loop = false;
154static bool send_trap = false;
149 155
150// If set to false, the server will never be started and no 156// If set to false, the server will never be started and no
151// gdbstub-related functions will be executed. 157// gdbstub-related functions will be executed.
@@ -165,6 +171,53 @@ static std::map<u64, Breakpoint> breakpoints_execute;
165static std::map<u64, Breakpoint> breakpoints_read; 171static std::map<u64, Breakpoint> breakpoints_read;
166static std::map<u64, Breakpoint> breakpoints_write; 172static std::map<u64, Breakpoint> breakpoints_write;
167 173
174static Kernel::Thread* FindThreadById(int id) {
175 for (int core = 0; core < Core::NUM_CPU_CORES; core++) {
176 auto threads = Core::System::GetInstance().Scheduler(core)->GetThreadList();
177 for (auto thread : threads) {
178 if (thread->GetThreadId() == id) {
179 current_thread = thread.get();
180 return current_thread;
181 }
182 }
183 }
184 return nullptr;
185}
186
187static u64 RegRead(int id, Kernel::Thread* thread = nullptr) {
188 if (!thread) {
189 return 0;
190 }
191
192 if (id < SP_REGISTER) {
193 return thread->context.cpu_registers[id];
194 } else if (id == SP_REGISTER) {
195 return thread->context.sp;
196 } else if (id == PC_REGISTER) {
197 return thread->context.pc;
198 } else if (id == CPSR_REGISTER) {
199 return thread->context.cpsr;
200 } else {
201 return 0;
202 }
203}
204
205static void RegWrite(int id, u64 val, Kernel::Thread* thread = nullptr) {
206 if (!thread) {
207 return;
208 }
209
210 if (id < SP_REGISTER) {
211 thread->context.cpu_registers[id] = val;
212 } else if (id == SP_REGISTER) {
213 thread->context.sp = val;
214 } else if (id == PC_REGISTER) {
215 thread->context.pc = val;
216 } else if (id == CPSR_REGISTER) {
217 thread->context.cpsr = val;
218 }
219}
220
168/** 221/**
169 * Turns hex string character into the equivalent byte. 222 * Turns hex string character into the equivalent byte.
170 * 223 *
@@ -193,7 +246,7 @@ static u8 NibbleToHex(u8 n) {
193 if (n < 0xA) { 246 if (n < 0xA) {
194 return '0' + n; 247 return '0' + n;
195 } else { 248 } else {
196 return 'A' + n - 0xA; 249 return 'a' + n - 0xA;
197 } 250 }
198} 251}
199 252
@@ -439,6 +492,8 @@ static void SendReply(const char* reply) {
439 return; 492 return;
440 } 493 }
441 494
495 NGLOG_DEBUG(Debug_GDBStub, "Reply: {}", reply);
496
442 memset(command_buffer, 0, sizeof(command_buffer)); 497 memset(command_buffer, 0, sizeof(command_buffer));
443 498
444 command_length = static_cast<u32>(strlen(reply)); 499 command_length = static_cast<u32>(strlen(reply));
@@ -483,6 +538,22 @@ static void HandleQuery() {
483 } else if (strncmp(query, "Xfer:features:read:target.xml:", 538 } else if (strncmp(query, "Xfer:features:read:target.xml:",
484 strlen("Xfer:features:read:target.xml:")) == 0) { 539 strlen("Xfer:features:read:target.xml:")) == 0) {
485 SendReply(target_xml); 540 SendReply(target_xml);
541 } else if (strncmp(query, "Offsets", strlen("Offsets")) == 0) {
542 std::string buffer = fmt::format("TextSeg={:0x}", Memory::PROCESS_IMAGE_VADDR);
543 SendReply(buffer.c_str());
544 } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) {
545 std::string val = "m";
546 for (int core = 0; core < Core::NUM_CPU_CORES; core++) {
547 auto threads = Core::System::GetInstance().Scheduler(core)->GetThreadList();
548 for (auto thread : threads) {
549 val += fmt::format("{:x}", thread->GetThreadId());
550 val += ",";
551 }
552 }
553 val.pop_back();
554 SendReply(val.c_str());
555 } else if (strncmp(query, "sThreadInfo", strlen("sThreadInfo")) == 0) {
556 SendReply("l");
486 } else { 557 } else {
487 SendReply(""); 558 SendReply("");
488 } 559 }
@@ -490,11 +561,40 @@ static void HandleQuery() {
490 561
491/// Handle set thread command from gdb client. 562/// Handle set thread command from gdb client.
492static void HandleSetThread() { 563static void HandleSetThread() {
493 if (memcmp(command_buffer, "Hg0", 3) == 0 || memcmp(command_buffer, "Hc-1", 4) == 0 || 564 if (memcmp(command_buffer, "Hc", 2) == 0 || memcmp(command_buffer, "Hg", 2) == 0) {
494 memcmp(command_buffer, "Hc0", 4) == 0 || memcmp(command_buffer, "Hc1", 4) == 0) { 565 int thread_id = -1;
495 return SendReply("OK"); 566 if (command_buffer[2] != '-') {
567 thread_id = static_cast<int>(HexToInt(
568 command_buffer + 2,
569 command_length - 2 /*strlen(reinterpret_cast<char*>(command_buffer) + 2)*/));
570 }
571 if (thread_id >= 1) {
572 current_thread = FindThreadById(thread_id);
573 }
574 if (!current_thread) {
575 thread_id = 1;
576 current_thread = FindThreadById(thread_id);
577 }
578 if (current_thread) {
579 SendReply("OK");
580 return;
581 }
496 } 582 }
583 SendReply("E01");
584}
497 585
586/// Handle thread alive command from gdb client.
587static void HandleThreadAlive() {
588 int thread_id = static_cast<int>(
589 HexToInt(command_buffer + 1,
590 command_length - 1 /*strlen(reinterpret_cast<char*>(command_buffer) + 1)*/));
591 if (thread_id == 0) {
592 thread_id = 1;
593 }
594 if (FindThreadById(thread_id)) {
595 SendReply("OK");
596 return;
597 }
498 SendReply("E01"); 598 SendReply("E01");
499} 599}
500 600
@@ -503,15 +603,24 @@ static void HandleSetThread() {
503 * 603 *
504 * @param signal Signal to be sent to client. 604 * @param signal Signal to be sent to client.
505 */ 605 */
506static void SendSignal(u32 signal) { 606static void SendSignal(Kernel::Thread* thread, u32 signal, bool full = true) {
507 if (gdbserver_socket == -1) { 607 if (gdbserver_socket == -1) {
508 return; 608 return;
509 } 609 }
510 610
511 latest_signal = signal; 611 latest_signal = signal;
512 612
513 std::string buffer = fmt::format("T{:02x}", latest_signal); 613 std::string buffer;
514 NGLOG_DEBUG(Debug_GDBStub, "Response: {}", buffer); 614 if (full) {
615 buffer = fmt::format("T{:02x}{:02x}:{:016x};{:02x}:{:016x};", latest_signal, PC_REGISTER,
616 Common::swap64(RegRead(PC_REGISTER, thread)), SP_REGISTER,
617 Common::swap64(RegRead(SP_REGISTER, thread)));
618 } else {
619 buffer = fmt::format("T{:02x};", latest_signal);
620 }
621
622 buffer += fmt::format("thread:{:x};", thread->GetThreadId());
623
515 SendReply(buffer.c_str()); 624 SendReply(buffer.c_str());
516} 625}
517 626
@@ -527,7 +636,7 @@ static void ReadCommand() {
527 } else if (c == 0x03) { 636 } else if (c == 0x03) {
528 NGLOG_INFO(Debug_GDBStub, "gdb: found break command"); 637 NGLOG_INFO(Debug_GDBStub, "gdb: found break command");
529 halt_loop = true; 638 halt_loop = true;
530 SendSignal(SIGTRAP); 639 SendSignal(current_thread, SIGTRAP);
531 return; 640 return;
532 } else if (c != GDB_STUB_START) { 641 } else if (c != GDB_STUB_START) {
533 NGLOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte {:02X}", c); 642 NGLOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte {:02X}", c);
@@ -598,11 +707,11 @@ static void ReadRegister() {
598 } 707 }
599 708
600 if (id <= SP_REGISTER) { 709 if (id <= SP_REGISTER) {
601 LongToGdbHex(reply, Core::CurrentArmInterface().GetReg(static_cast<int>(id))); 710 LongToGdbHex(reply, RegRead(id, current_thread));
602 } else if (id == PC_REGISTER) { 711 } else if (id == PC_REGISTER) {
603 LongToGdbHex(reply, Core::CurrentArmInterface().GetPC()); 712 LongToGdbHex(reply, RegRead(id, current_thread));
604 } else if (id == CPSR_REGISTER) { 713 } else if (id == CPSR_REGISTER) {
605 IntToGdbHex(reply, Core::CurrentArmInterface().GetCPSR()); 714 IntToGdbHex(reply, (u32)RegRead(id, current_thread));
606 } else { 715 } else {
607 return SendReply("E01"); 716 return SendReply("E01");
608 } 717 }
@@ -618,16 +727,16 @@ static void ReadRegisters() {
618 u8* bufptr = buffer; 727 u8* bufptr = buffer;
619 728
620 for (int reg = 0; reg <= SP_REGISTER; reg++) { 729 for (int reg = 0; reg <= SP_REGISTER; reg++) {
621 LongToGdbHex(bufptr + reg * 16, Core::CurrentArmInterface().GetReg(reg)); 730 LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread));
622 } 731 }
623 732
624 bufptr += (32 * 16); 733 bufptr += (32 * 16);
625 734
626 LongToGdbHex(bufptr, Core::CurrentArmInterface().GetPC()); 735 LongToGdbHex(bufptr, RegRead(PC_REGISTER, current_thread));
627 736
628 bufptr += 16; 737 bufptr += 16;
629 738
630 IntToGdbHex(bufptr, Core::CurrentArmInterface().GetCPSR()); 739 IntToGdbHex(bufptr, (u32)RegRead(CPSR_REGISTER, current_thread));
631 740
632 bufptr += 8; 741 bufptr += 8;
633 742
@@ -646,11 +755,11 @@ static void WriteRegister() {
646 } 755 }
647 756
648 if (id <= SP_REGISTER) { 757 if (id <= SP_REGISTER) {
649 Core::CurrentArmInterface().SetReg(id, GdbHexToLong(buffer_ptr)); 758 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
650 } else if (id == PC_REGISTER) { 759 } else if (id == PC_REGISTER) {
651 Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr)); 760 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
652 } else if (id == CPSR_REGISTER) { 761 } else if (id == CPSR_REGISTER) {
653 Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr)); 762 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
654 } else { 763 } else {
655 return SendReply("E01"); 764 return SendReply("E01");
656 } 765 }
@@ -667,11 +776,11 @@ static void WriteRegisters() {
667 776
668 for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) { 777 for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) {
669 if (reg <= SP_REGISTER) { 778 if (reg <= SP_REGISTER) {
670 Core::CurrentArmInterface().SetReg(reg, GdbHexToLong(buffer_ptr + i * 16)); 779 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
671 } else if (reg == PC_REGISTER) { 780 } else if (reg == PC_REGISTER) {
672 Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr + i * 16)); 781 RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
673 } else if (reg == CPSR_REGISTER) { 782 } else if (reg == CPSR_REGISTER) {
674 Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr + i * 16)); 783 RegWrite(CPSR_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread);
675 } else { 784 } else {
676 UNIMPLEMENTED(); 785 UNIMPLEMENTED();
677 } 786 }
@@ -734,7 +843,7 @@ static void WriteMemory() {
734void Break(bool is_memory_break) { 843void Break(bool is_memory_break) {
735 if (!halt_loop) { 844 if (!halt_loop) {
736 halt_loop = true; 845 halt_loop = true;
737 SendSignal(SIGTRAP); 846 send_trap = true;
738 } 847 }
739 848
740 memory_break = is_memory_break; 849 memory_break = is_memory_break;
@@ -744,10 +853,10 @@ void Break(bool is_memory_break) {
744static void Step() { 853static void Step() {
745 step_loop = true; 854 step_loop = true;
746 halt_loop = true; 855 halt_loop = true;
747 step_break = true; 856 send_trap = true;
748 SendSignal(SIGTRAP);
749} 857}
750 858
859/// Tell the CPU if we hit a memory breakpoint.
751bool IsMemoryBreak() { 860bool IsMemoryBreak() {
752 if (IsConnected()) { 861 if (IsConnected()) {
753 return false; 862 return false;
@@ -759,7 +868,6 @@ bool IsMemoryBreak() {
759/// Tell the CPU to continue executing. 868/// Tell the CPU to continue executing.
760static void Continue() { 869static void Continue() {
761 memory_break = false; 870 memory_break = false;
762 step_break = false;
763 step_loop = false; 871 step_loop = false;
764 halt_loop = false; 872 halt_loop = false;
765} 873}
@@ -898,7 +1006,7 @@ void HandlePacket() {
898 HandleSetThread(); 1006 HandleSetThread();
899 break; 1007 break;
900 case '?': 1008 case '?':
901 SendSignal(latest_signal); 1009 SendSignal(current_thread, latest_signal);
902 break; 1010 break;
903 case 'k': 1011 case 'k':
904 Shutdown(); 1012 Shutdown();
@@ -935,6 +1043,9 @@ void HandlePacket() {
935 case 'Z': 1043 case 'Z':
936 AddBreakpoint(); 1044 AddBreakpoint();
937 break; 1045 break;
1046 case 'T':
1047 HandleThreadAlive();
1048 break;
938 default: 1049 default:
939 SendReply(""); 1050 SendReply("");
940 break; 1051 break;
@@ -1079,4 +1190,11 @@ bool GetCpuStepFlag() {
1079void SetCpuStepFlag(bool is_step) { 1190void SetCpuStepFlag(bool is_step) {
1080 step_loop = is_step; 1191 step_loop = is_step;
1081} 1192}
1193
1194void SendTrap(Kernel::Thread* thread, int trap) {
1195 if (send_trap) {
1196 send_trap = false;
1197 SendSignal(thread, trap);
1198 }
1199}
1082}; // namespace GDBStub 1200}; // namespace GDBStub
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h
index 201fca095..f2418c9e4 100644
--- a/src/core/gdbstub/gdbstub.h
+++ b/src/core/gdbstub/gdbstub.h
@@ -7,6 +7,7 @@
7#pragma once 7#pragma once
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/kernel/thread.h"
10 11
11namespace GDBStub { 12namespace GDBStub {
12 13
@@ -91,4 +92,12 @@ bool GetCpuStepFlag();
91 * @param is_step 92 * @param is_step
92 */ 93 */
93void SetCpuStepFlag(bool is_step); 94void SetCpuStepFlag(bool is_step);
95
96/**
97 * Send trap signal from thread back to the gdbstub server.
98 *
99 * @param thread Sending thread.
100 * @param trap Trap no.
101 */
102void SendTrap(Kernel::Thread* thread, int trap);
94} // namespace GDBStub 103} // namespace GDBStub
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 756518ee7..66351fe6e 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -26,6 +26,10 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
26 ASSERT(format != RenderTargetFormat::NONE); 26 ASSERT(format != RenderTargetFormat::NONE);
27 27
28 switch (format) { 28 switch (format) {
29 case RenderTargetFormat::RGBA32_FLOAT:
30 return 16;
31 case RenderTargetFormat::RGBA16_FLOAT:
32 return 8;
29 case RenderTargetFormat::RGBA8_UNORM: 33 case RenderTargetFormat::RGBA8_UNORM:
30 case RenderTargetFormat::RGB10_A2_UNORM: 34 case RenderTargetFormat::RGB10_A2_UNORM:
31 return 4; 35 return 4;
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index f168a5171..5852b9619 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -15,10 +15,12 @@ namespace Tegra {
15 15
16enum class RenderTargetFormat : u32 { 16enum class RenderTargetFormat : u32 {
17 NONE = 0x0, 17 NONE = 0x0,
18 RGBA32_FLOAT = 0xC0,
18 RGBA16_FLOAT = 0xCA, 19 RGBA16_FLOAT = 0xCA,
19 RGB10_A2_UNORM = 0xD1, 20 RGB10_A2_UNORM = 0xD1,
20 RGBA8_UNORM = 0xD5, 21 RGBA8_UNORM = 0xD5,
21 RGBA8_SRGB = 0xD6, 22 RGBA8_SRGB = 0xD6,
23 R11G11B10_FLOAT = 0xE0,
22}; 24};
23 25
24/// Returns the number of bytes per pixel of each rendertarget format. 26/// Returns the number of bytes per pixel of each rendertarget format.
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index d6048f639..9164d7f34 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -50,6 +50,7 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
50 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false}, // A1B5G5R5 50 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false}, // A1B5G5R5
51 {GL_R8, GL_RED, GL_UNSIGNED_BYTE, false}, // R8 51 {GL_R8, GL_RED, GL_UNSIGNED_BYTE, false}, // R8
52 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false}, // RGBA16F 52 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false}, // RGBA16F
53 {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false}, // R11FG11FB10F
53 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1 54 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1
54 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23 55 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23
55 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45 56 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45
@@ -60,8 +61,10 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType
60 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); 61 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
61 if (type == SurfaceType::ColorTexture) { 62 if (type == SurfaceType::ColorTexture) {
62 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); 63 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
63 // For now only UNORM components are supported, or RGBA16F which is type FLOAT 64 // For now only UNORM components are supported, or either R11FG11FB10F or RGBA16F which are
64 ASSERT(component_type == ComponentType::UNorm || pixel_format == PixelFormat::RGBA16F); 65 // type FLOAT
66 ASSERT(component_type == ComponentType::UNorm || pixel_format == PixelFormat::RGBA16F ||
67 pixel_format == PixelFormat::R11FG11FB10F);
65 return tex_format_tuples[static_cast<unsigned int>(pixel_format)]; 68 return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
66 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { 69 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
67 // TODO(Subv): Implement depth formats 70 // TODO(Subv): Implement depth formats
@@ -110,11 +113,12 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra:
110 Tegra::GPUVAddr), 113 Tegra::GPUVAddr),
111 SurfaceParams::MaxPixelFormat> 114 SurfaceParams::MaxPixelFormat>
112 morton_to_gl_fns = { 115 morton_to_gl_fns = {
113 MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>, 116 MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
114 MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::A1B5G5R5>, 117 MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::A1B5G5R5>,
115 MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::RGBA16F>, 118 MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::RGBA16F>,
116 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, 119 MortonCopy<true, PixelFormat::R11FG11FB10F>, MortonCopy<true, PixelFormat::DXT1>,
117 MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, 120 MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>,
121 MortonCopy<true, PixelFormat::DXN1>,
118}; 122};
119 123
120static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr, 124static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr,
@@ -127,6 +131,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra:
127 MortonCopy<false, PixelFormat::A1B5G5R5>, 131 MortonCopy<false, PixelFormat::A1B5G5R5>,
128 MortonCopy<false, PixelFormat::R8>, 132 MortonCopy<false, PixelFormat::R8>,
129 MortonCopy<false, PixelFormat::RGBA16F>, 133 MortonCopy<false, PixelFormat::RGBA16F>,
134 MortonCopy<false, PixelFormat::R11FG11FB10F>,
130 // TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1 formats is not yet supported 135 // TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1 formats is not yet supported
131 nullptr, 136 nullptr,
132 nullptr, 137 nullptr,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 6f08678ab..0f43e863d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -60,10 +60,11 @@ struct SurfaceParams {
60 A1B5G5R5 = 3, 60 A1B5G5R5 = 3,
61 R8 = 4, 61 R8 = 4,
62 RGBA16F = 5, 62 RGBA16F = 5,
63 DXT1 = 6, 63 R11FG11FB10F = 6,
64 DXT23 = 7, 64 DXT1 = 7,
65 DXT45 = 8, 65 DXT23 = 8,
66 DXN1 = 9, // This is also known as BC4 66 DXT45 = 9,
67 DXN1 = 10, // This is also known as BC4
67 68
68 Max, 69 Max,
69 Invalid = 255, 70 Invalid = 255,
@@ -104,7 +105,8 @@ struct SurfaceParams {
104 1, // A2B10G10R10 105 1, // A2B10G10R10
105 1, // A1B5G5R5 106 1, // A1B5G5R5
106 1, // R8 107 1, // R8
107 2, // RGBA16F 108 1, // RGBA16F
109 1, // R11FG11FB10F
108 4, // DXT1 110 4, // DXT1
109 4, // DXT23 111 4, // DXT23
110 4, // DXT45 112 4, // DXT45
@@ -129,6 +131,7 @@ struct SurfaceParams {
129 16, // A1B5G5R5 131 16, // A1B5G5R5
130 8, // R8 132 8, // R8
131 64, // RGBA16F 133 64, // RGBA16F
134 32, // R11FG11FB10F
132 64, // DXT1 135 64, // DXT1
133 128, // DXT23 136 128, // DXT23
134 128, // DXT45 137 128, // DXT45
@@ -151,6 +154,8 @@ struct SurfaceParams {
151 return PixelFormat::A2B10G10R10; 154 return PixelFormat::A2B10G10R10;
152 case Tegra::RenderTargetFormat::RGBA16_FLOAT: 155 case Tegra::RenderTargetFormat::RGBA16_FLOAT:
153 return PixelFormat::RGBA16F; 156 return PixelFormat::RGBA16F;
157 case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
158 return PixelFormat::R11FG11FB10F;
154 default: 159 default:
155 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 160 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
156 UNREACHABLE(); 161 UNREACHABLE();
@@ -182,6 +187,8 @@ struct SurfaceParams {
182 return PixelFormat::R8; 187 return PixelFormat::R8;
183 case Tegra::Texture::TextureFormat::R16_G16_B16_A16: 188 case Tegra::Texture::TextureFormat::R16_G16_B16_A16:
184 return PixelFormat::RGBA16F; 189 return PixelFormat::RGBA16F;
190 case Tegra::Texture::TextureFormat::BF10GF11RF11:
191 return PixelFormat::R11FG11FB10F;
185 case Tegra::Texture::TextureFormat::DXT1: 192 case Tegra::Texture::TextureFormat::DXT1:
186 return PixelFormat::DXT1; 193 return PixelFormat::DXT1;
187 case Tegra::Texture::TextureFormat::DXT23: 194 case Tegra::Texture::TextureFormat::DXT23:
@@ -211,6 +218,8 @@ struct SurfaceParams {
211 return Tegra::Texture::TextureFormat::R8; 218 return Tegra::Texture::TextureFormat::R8;
212 case PixelFormat::RGBA16F: 219 case PixelFormat::RGBA16F:
213 return Tegra::Texture::TextureFormat::R16_G16_B16_A16; 220 return Tegra::Texture::TextureFormat::R16_G16_B16_A16;
221 case PixelFormat::R11FG11FB10F:
222 return Tegra::Texture::TextureFormat::BF10GF11RF11;
214 case PixelFormat::DXT1: 223 case PixelFormat::DXT1:
215 return Tegra::Texture::TextureFormat::DXT1; 224 return Tegra::Texture::TextureFormat::DXT1;
216 case PixelFormat::DXT23: 225 case PixelFormat::DXT23:
@@ -243,6 +252,7 @@ struct SurfaceParams {
243 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 252 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
244 return ComponentType::UNorm; 253 return ComponentType::UNorm;
245 case Tegra::RenderTargetFormat::RGBA16_FLOAT: 254 case Tegra::RenderTargetFormat::RGBA16_FLOAT:
255 case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
246 return ComponentType::Float; 256 return ComponentType::Float;
247 default: 257 default:
248 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 258 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index a630610d8..cf11983cf 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -100,6 +100,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
100 switch (wrap_mode) { 100 switch (wrap_mode) {
101 case Tegra::Texture::WrapMode::Wrap: 101 case Tegra::Texture::WrapMode::Wrap:
102 return GL_REPEAT; 102 return GL_REPEAT;
103 case Tegra::Texture::WrapMode::Mirror:
104 return GL_MIRRORED_REPEAT;
103 case Tegra::Texture::WrapMode::ClampToEdge: 105 case Tegra::Texture::WrapMode::ClampToEdge:
104 return GL_CLAMP_TO_EDGE; 106 return GL_CLAMP_TO_EDGE;
105 case Tegra::Texture::WrapMode::ClampOGL: 107 case Tegra::Texture::WrapMode::ClampOGL:
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 2d2af5554..7bf9c4c4b 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -55,6 +55,7 @@ u32 BytesPerPixel(TextureFormat format) {
55 return 16; 55 return 16;
56 case TextureFormat::A8R8G8B8: 56 case TextureFormat::A8R8G8B8:
57 case TextureFormat::A2B10G10R10: 57 case TextureFormat::A2B10G10R10:
58 case TextureFormat::BF10GF11RF11:
58 return 4; 59 return 4;
59 case TextureFormat::A1B5G5R5: 60 case TextureFormat::A1B5G5R5:
60 case TextureFormat::B5G6R5: 61 case TextureFormat::B5G6R5:
@@ -92,6 +93,7 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
92 case TextureFormat::B5G6R5: 93 case TextureFormat::B5G6R5:
93 case TextureFormat::R8: 94 case TextureFormat::R8:
94 case TextureFormat::R16_G16_B16_A16: 95 case TextureFormat::R16_G16_B16_A16:
96 case TextureFormat::BF10GF11RF11:
95 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, 97 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
96 unswizzled_data.data(), true, block_height); 98 unswizzled_data.data(), true, block_height);
97 break; 99 break;
@@ -118,6 +120,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
118 case TextureFormat::A1B5G5R5: 120 case TextureFormat::A1B5G5R5:
119 case TextureFormat::B5G6R5: 121 case TextureFormat::B5G6R5:
120 case TextureFormat::R8: 122 case TextureFormat::R8:
123 case TextureFormat::BF10GF11RF11:
121 // TODO(Subv): For the time being just forward the same data without any decoding. 124 // TODO(Subv): For the time being just forward the same data without any decoding.
122 rgba_data = texture_data; 125 rgba_data = texture_data;
123 break; 126 break;