Compare commits

...

12 Commits

Author SHA1 Message Date
8e75b72d33 Android #44 2023-08-19 00:57:22 +00:00
ae1421265a Merge pull request #11278 from Kelebek1/dma_sync
Mark accelerated DMA destination buffers and images as GPU-modified
2023-08-18 09:12:27 -04:00
314d3858a1 Merge pull request #11288 from liamwhite/svc-tick
kernel: remove relative task registration
2023-08-18 09:12:19 -04:00
0383ae1dbf Merge pull request #11310 from vonchenplus/vulkan_format
video_core: Fix vulkan format assert error
2023-08-18 09:12:11 -04:00
1dcb0c2232 video_core: Fix vulkan assert error 2023-08-18 14:40:11 +08:00
ddedaa8875 Merge pull request #10989 from comex/epipe
sockets: Improve behavior when sending to closed connection
2023-08-17 11:59:47 -04:00
0e3a995bf4 cmake: mark warning disable for gcc 11 (#11301) 2023-08-17 16:03:34 +02:00
755bcc459b Improve behavior when sending to closed connection
- On Unix, this would previously kill the Yuzu process with SIGPIPE.
  Send MSG_NOSIGNAL to opt out of this.

- Add support for the proper error code in this situation, EPIPE.

- Windows has nonstandard behavior in this situation; translate it to
  the standard behavior.  Kind of pointless, but isn't it nice to be
  correct?
2023-08-15 20:59:57 -04:00
a8c4f01f6c Merge pull request #11287 from liamwhite/replaced-bytes
gdbstub: fixup replaced instruction bytes in memory reads
2023-08-15 15:36:14 +02:00
0bd9a4456c kernel: remove relative task registration 2023-08-14 18:12:06 -04:00
fbda084acb gdbstub: fixup replaced instruction bytes in memory reads 2023-08-14 16:33:27 -04:00
5a37b8f2c1 Mark accelerted DMA destination buffers and images as GPU-modified 2023-08-13 02:22:39 +01:00
23 changed files with 153 additions and 47 deletions

View File

@ -1,3 +1,11 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
End of merge log. You can find the original README.md below the break.
-----
<!-- <!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later SPDX-License-Identifier: GPL-2.0-or-later

View File

@ -134,7 +134,7 @@ else()
endif() endif()
# GCC bugs # GCC bugs
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# These diagnostics would be great if they worked, but are just completely broken # These diagnostics would be great if they worked, but are just completely broken
# and produce bogus errors on external libraries like fmt. # and produce bogus errors on external libraries like fmt.
add_compile_options( add_compile_options(

View File

@ -263,6 +263,23 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
std::vector<u8> mem(size); std::vector<u8> mem(size);
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) { if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
// Restore any bytes belonging to replaced instructions.
auto it = replaced_instructions.lower_bound(addr);
for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
// Get the bytes of the instruction we previously replaced.
const u32 original_bytes = it->second;
// Calculate where to start writing to the output buffer.
const size_t output_offset = it->first - addr;
// Calculate how many bytes to write.
// The loop condition ensures output_offset < size.
const size_t n = std::min<size_t>(size - output_offset, sizeof(u32));
// Write the bytes to the output buffer.
std::memcpy(mem.data() + output_offset, &original_bytes, n);
}
SendReply(Common::HexToString(mem)); SendReply(Common::HexToString(mem));
} else { } else {
SendReply(GDB_STUB_REPLY_ERR); SendReply(GDB_STUB_REPLY_ERR);

View File

@ -19,13 +19,7 @@ public:
void Initialize(); void Initialize();
void Finalize(); void Finalize();
s64 GetCount() const { s64 GetTick() const;
return GetTick();
}
void RegisterTask(KTimerTask* task, s64 time_from_now) {
this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
}
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) { void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
KScopedDisableDispatch dd{m_kernel}; KScopedDisableDispatch dd{m_kernel};
@ -42,7 +36,6 @@ private:
void EnableInterrupt(s64 wakeup_time); void EnableInterrupt(s64 wakeup_time);
void DisableInterrupt(); void DisableInterrupt();
bool GetInterruptEnabled(); bool GetInterruptEnabled();
s64 GetTick() const;
void DoTask(); void DoTask();
private: private:

View File

@ -5,6 +5,7 @@
#include "common/overflow.h" #include "common/overflow.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_results.h"
@ -15,9 +16,7 @@ KResourceLimit::KResourceLimit(KernelCore& kernel)
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {} : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {}
KResourceLimit::~KResourceLimit() = default; KResourceLimit::~KResourceLimit() = default;
void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing) { void KResourceLimit::Initialize() {}
m_core_timing = core_timing;
}
void KResourceLimit::Finalize() {} void KResourceLimit::Finalize() {}
@ -86,7 +85,7 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
} }
bool KResourceLimit::Reserve(LimitableResource which, s64 value) { bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
return Reserve(which, value, m_core_timing->GetGlobalTimeNs().count() + DefaultTimeout); return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout);
} }
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
@ -117,7 +116,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
} }
if (m_current_hints[index] + value <= m_limit_values[index] && if (m_current_hints[index] + value <= m_limit_values[index] &&
(timeout < 0 || m_core_timing->GetGlobalTimeNs().count() < timeout)) { (timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) {
m_waiter_count++; m_waiter_count++;
m_cond_var.Wait(std::addressof(m_lock), timeout, false); m_cond_var.Wait(std::addressof(m_lock), timeout, false);
m_waiter_count--; m_waiter_count--;
@ -154,7 +153,7 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) { KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) {
auto* resource_limit = KResourceLimit::Create(system.Kernel()); auto* resource_limit = KResourceLimit::Create(system.Kernel());
resource_limit->Initialize(std::addressof(system.CoreTiming())); resource_limit->Initialize();
// Initialize default resource limit values. // Initialize default resource limit values.
// TODO(bunnei): These values are the system defaults, the limits for service processes are // TODO(bunnei): These values are the system defaults, the limits for service processes are

View File

@ -31,7 +31,7 @@ public:
explicit KResourceLimit(KernelCore& kernel); explicit KResourceLimit(KernelCore& kernel);
~KResourceLimit() override; ~KResourceLimit() override;
void Initialize(const Core::Timing::CoreTiming* core_timing); void Initialize();
void Finalize() override; void Finalize() override;
s64 GetLimitValue(LimitableResource which) const; s64 GetLimitValue(LimitableResource which) const;
@ -57,7 +57,6 @@ private:
mutable KLightLock m_lock; mutable KLightLock m_lock;
s32 m_waiter_count{}; s32 m_waiter_count{};
KLightConditionVariable m_cond_var; KLightConditionVariable m_cond_var;
const Core::Timing::CoreTiming* m_core_timing{};
}; };
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size); KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);

View File

@ -28,7 +28,7 @@ public:
~KScopedSchedulerLockAndSleep() { ~KScopedSchedulerLockAndSleep() {
// Register the sleep. // Register the sleep.
if (m_timeout_tick > 0) { if (m_timeout_tick > 0) {
m_timer->RegisterTask(m_thread, m_timeout_tick); m_timer->RegisterAbsoluteTask(m_thread, m_timeout_tick);
} }
// Unlock the scheduler. // Unlock the scheduler.

View File

@ -231,7 +231,7 @@ struct KernelCore::Impl {
void InitializeSystemResourceLimit(KernelCore& kernel, void InitializeSystemResourceLimit(KernelCore& kernel,
const Core::Timing::CoreTiming& core_timing) { const Core::Timing::CoreTiming& core_timing) {
system_resource_limit = KResourceLimit::Create(system.Kernel()); system_resource_limit = KResourceLimit::Create(system.Kernel());
system_resource_limit->Initialize(&core_timing); system_resource_limit->Initialize();
KResourceLimit::Register(kernel, system_resource_limit); KResourceLimit::Register(kernel, system_resource_limit);
const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()}; const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()};

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
@ -52,7 +53,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ
if (timeout_ns > 0) { if (timeout_ns > 0) {
const s64 offset_tick(timeout_ns); const s64 offset_tick(timeout_ns);
if (offset_tick > 0) { if (offset_tick > 0) {
timeout = offset_tick + 2; timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
if (timeout <= 0) { if (timeout <= 0) {
timeout = std::numeric_limits<s64>::max(); timeout = std::numeric_limits<s64>::max();
} }

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
@ -25,7 +26,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u
if (timeout_ns > 0) { if (timeout_ns > 0) {
const s64 offset_tick(timeout_ns); const s64 offset_tick(timeout_ns);
if (offset_tick > 0) { if (offset_tick > 0) {
timeout = offset_tick + 2; timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
if (timeout <= 0) { if (timeout <= 0) {
timeout = std::numeric_limits<s64>::max(); timeout = std::numeric_limits<s64>::max();
} }

View File

@ -5,6 +5,7 @@
#include "common/scratch_buffer.h" #include "common/scratch_buffer.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_client_session.h" #include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_server_session.h"
#include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc.h"
@ -82,12 +83,29 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
R_TRY(session->SendReply()); R_TRY(session->SendReply());
} }
// Convert the timeout from nanoseconds to ticks.
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
s64 timeout;
if (timeout_ns > 0) {
const s64 offset_tick(timeout_ns);
if (offset_tick > 0) {
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
if (timeout <= 0) {
timeout = std::numeric_limits<s64>::max();
}
} else {
timeout = std::numeric_limits<s64>::max();
}
} else {
timeout = timeout_ns;
}
// Wait for a message. // Wait for a message.
while (true) { while (true) {
// Wait for an object. // Wait for an object.
s32 index; s32 index;
Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(), Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
num_handles, timeout_ns); num_handles, timeout);
if (result == ResultTimedOut) { if (result == ResultTimedOut) {
R_RETURN(result); R_RETURN(result);
} }

View File

@ -21,7 +21,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
SCOPE_EXIT({ resource_limit->Close(); }); SCOPE_EXIT({ resource_limit->Close(); });
// Initialize the resource limit. // Initialize the resource limit.
resource_limit->Initialize(std::addressof(system.CoreTiming())); resource_limit->Initialize();
// Register the limit. // Register the limit.
KResourceLimit::Register(kernel, resource_limit); KResourceLimit::Register(kernel, resource_limit);

View File

@ -4,6 +4,7 @@
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/scratch_buffer.h" #include "common/scratch_buffer.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc.h"
@ -83,9 +84,20 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
} }
}); });
// Convert the timeout from nanoseconds to ticks.
s64 timeout;
if (timeout_ns > 0) {
u64 ticks = kernel.HardwareTimer().GetTick();
ticks += timeout_ns;
ticks += 2;
timeout = ticks;
} else {
timeout = timeout_ns;
}
// Wait on the objects. // Wait on the objects.
Result res = Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout);
KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns);
R_SUCCEED_IF(res == ResultSessionClosed); R_SUCCEED_IF(res == ResultSessionClosed);
R_RETURN(res); R_RETURN(res);

View File

@ -4,6 +4,7 @@
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
@ -42,9 +43,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
// Reserve a new thread from the process resource limit (waiting up to 100ms). // Reserve a new thread from the process resource limit (waiting up to 100ms).
KScopedResourceReservation thread_reservation( KScopedResourceReservation thread_reservation(std::addressof(process),
std::addressof(process), LimitableResource::ThreadCountMax, 1, LimitableResource::ThreadCountMax, 1,
system.CoreTiming().GetGlobalTimeNs().count() + 100000000); kernel.HardwareTimer().GetTick() + 100000000);
R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
// Create the thread. // Create the thread.
@ -102,20 +103,31 @@ void ExitThread(Core::System& system) {
} }
/// Sleep the current thread /// Sleep the current thread
void SleepThread(Core::System& system, s64 nanoseconds) { void SleepThread(Core::System& system, s64 ns) {
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
const auto yield_type = static_cast<Svc::YieldType>(nanoseconds); const auto yield_type = static_cast<Svc::YieldType>(ns);
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); LOG_TRACE(Kernel_SVC, "called nanoseconds={}", ns);
// When the input tick is positive, sleep. // When the input tick is positive, sleep.
if (nanoseconds > 0) { if (ns > 0) {
// Convert the timeout from nanoseconds to ticks. // Convert the timeout from nanoseconds to ticks.
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization... // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
s64 timeout;
const s64 offset_tick(ns);
if (offset_tick > 0) {
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
if (timeout <= 0) {
timeout = std::numeric_limits<s64>::max();
}
} else {
timeout = std::numeric_limits<s64>::max();
}
// Sleep. // Sleep.
// NOTE: Nintendo does not check the result of this sleep. // NOTE: Nintendo does not check the result of this sleep.
static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds)); static_cast<void>(GetCurrentThread(kernel).Sleep(timeout));
} else if (yield_type == Svc::YieldType::WithoutCoreMigration) { } else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
KScheduler::YieldWithoutCoreMigration(kernel); KScheduler::YieldWithoutCoreMigration(kernel);
} else if (yield_type == Svc::YieldType::WithCoreMigration) { } else if (yield_type == Svc::YieldType::WithCoreMigration) {
@ -124,7 +136,6 @@ void SleepThread(Core::System& system, s64 nanoseconds) {
KScheduler::YieldToAnyThread(kernel); KScheduler::YieldToAnyThread(kernel);
} else { } else {
// Nintendo does nothing at all if an otherwise invalid value is passed. // Nintendo does nothing at all if an otherwise invalid value is passed.
ASSERT_MSG(false, "Unimplemented sleep yield type '{:016X}'!", nanoseconds);
} }
} }

View File

@ -18,7 +18,9 @@ enum class Errno : u32 {
AGAIN = 11, AGAIN = 11,
INVAL = 22, INVAL = 22,
MFILE = 24, MFILE = 24,
PIPE = 32,
MSGSIZE = 90, MSGSIZE = 90,
CONNABORTED = 103,
CONNRESET = 104, CONNRESET = 104,
NOTCONN = 107, NOTCONN = 107,
TIMEDOUT = 110, TIMEDOUT = 110,

View File

@ -23,10 +23,14 @@ Errno Translate(Network::Errno value) {
return Errno::INVAL; return Errno::INVAL;
case Network::Errno::MFILE: case Network::Errno::MFILE:
return Errno::MFILE; return Errno::MFILE;
case Network::Errno::PIPE:
return Errno::PIPE;
case Network::Errno::NOTCONN: case Network::Errno::NOTCONN:
return Errno::NOTCONN; return Errno::NOTCONN;
case Network::Errno::TIMEDOUT: case Network::Errno::TIMEDOUT:
return Errno::TIMEDOUT; return Errno::TIMEDOUT;
case Network::Errno::CONNABORTED:
return Errno::CONNABORTED;
case Network::Errno::CONNRESET: case Network::Errno::CONNRESET:
return Errno::CONNRESET; return Errno::CONNRESET;
case Network::Errno::INPROGRESS: case Network::Errno::INPROGRESS:

View File

@ -39,6 +39,11 @@ namespace Network {
namespace { namespace {
enum class CallType {
Send,
Other,
};
#ifdef _WIN32 #ifdef _WIN32
using socklen_t = int; using socklen_t = int;
@ -96,7 +101,7 @@ bool EnableNonBlock(SOCKET fd, bool enable) {
return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR; return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
} }
Errno TranslateNativeError(int e) { Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
switch (e) { switch (e) {
case 0: case 0:
return Errno::SUCCESS; return Errno::SUCCESS;
@ -112,6 +117,14 @@ Errno TranslateNativeError(int e) {
return Errno::AGAIN; return Errno::AGAIN;
case WSAECONNREFUSED: case WSAECONNREFUSED:
return Errno::CONNREFUSED; return Errno::CONNREFUSED;
case WSAECONNABORTED:
if (call_type == CallType::Send) {
// Winsock yields WSAECONNABORTED from `send` in situations where Unix
// systems, and actual Switches, yield EPIPE.
return Errno::PIPE;
} else {
return Errno::CONNABORTED;
}
case WSAECONNRESET: case WSAECONNRESET:
return Errno::CONNRESET; return Errno::CONNRESET;
case WSAEHOSTUNREACH: case WSAEHOSTUNREACH:
@ -198,7 +211,7 @@ bool EnableNonBlock(int fd, bool enable) {
return fcntl(fd, F_SETFL, flags) == 0; return fcntl(fd, F_SETFL, flags) == 0;
} }
Errno TranslateNativeError(int e) { Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
switch (e) { switch (e) {
case 0: case 0:
return Errno::SUCCESS; return Errno::SUCCESS;
@ -208,6 +221,10 @@ Errno TranslateNativeError(int e) {
return Errno::INVAL; return Errno::INVAL;
case EMFILE: case EMFILE:
return Errno::MFILE; return Errno::MFILE;
case EPIPE:
return Errno::PIPE;
case ECONNABORTED:
return Errno::CONNABORTED;
case ENOTCONN: case ENOTCONN:
return Errno::NOTCONN; return Errno::NOTCONN;
case EAGAIN: case EAGAIN:
@ -236,13 +253,13 @@ Errno TranslateNativeError(int e) {
#endif #endif
Errno GetAndLogLastError() { Errno GetAndLogLastError(CallType call_type = CallType::Other) {
#ifdef _WIN32 #ifdef _WIN32
int e = WSAGetLastError(); int e = WSAGetLastError();
#else #else
int e = errno; int e = errno;
#endif #endif
const Errno err = TranslateNativeError(e); const Errno err = TranslateNativeError(e, call_type);
if (err == Errno::AGAIN || err == Errno::TIMEDOUT || err == Errno::INPROGRESS) { if (err == Errno::AGAIN || err == Errno::TIMEDOUT || err == Errno::INPROGRESS) {
// These happen during normal operation, so only log them at debug level. // These happen during normal operation, so only log them at debug level.
LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e));
@ -731,13 +748,17 @@ std::pair<s32, Errno> Socket::Send(std::span<const u8> message, int flags) {
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
ASSERT(flags == 0); ASSERT(flags == 0);
int native_flags = 0;
#if YUZU_UNIX
native_flags |= MSG_NOSIGNAL; // do not send us SIGPIPE
#endif
const auto result = send(fd, reinterpret_cast<const char*>(message.data()), const auto result = send(fd, reinterpret_cast<const char*>(message.data()),
static_cast<int>(message.size()), 0); static_cast<int>(message.size()), native_flags);
if (result != SOCKET_ERROR) { if (result != SOCKET_ERROR) {
return {static_cast<s32>(result), Errno::SUCCESS}; return {static_cast<s32>(result), Errno::SUCCESS};
} }
return {-1, GetAndLogLastError()}; return {-1, GetAndLogLastError(CallType::Send)};
} }
std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message, std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
@ -759,7 +780,7 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
return {static_cast<s32>(result), Errno::SUCCESS}; return {static_cast<s32>(result), Errno::SUCCESS};
} }
return {-1, GetAndLogLastError()}; return {-1, GetAndLogLastError(CallType::Send)};
} }
Errno Socket::Close() { Errno Socket::Close() {

View File

@ -33,10 +33,12 @@ enum class Errno {
BADF, BADF,
INVAL, INVAL,
MFILE, MFILE,
PIPE,
NOTCONN, NOTCONN,
AGAIN, AGAIN,
CONNREFUSED, CONNREFUSED,
CONNRESET, CONNRESET,
CONNABORTED,
HOSTUNREACH, HOSTUNREACH,
NETDOWN, NETDOWN,
NETUNREACH, NETUNREACH,

View File

@ -1335,7 +1335,8 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
} }
const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height); const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height);
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize; static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing; const auto post_op = IS_IMAGE_UPLOAD ? VideoCommon::ObtainBufferOperation::DoNothing
: VideoCommon::ObtainBufferOperation::MarkAsWritten;
const auto [buffer, offset] = const auto [buffer, offset] =
buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op); buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op);
@ -1344,8 +1345,12 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
const std::span copy_span{&copy, 1}; const std::span copy_span{&copy, 1};
if constexpr (IS_IMAGE_UPLOAD) { if constexpr (IS_IMAGE_UPLOAD) {
texture_cache.PrepareImage(image_id, true, false);
image->UploadMemory(buffer->Handle(), offset, copy_span); image->UploadMemory(buffer->Handle(), offset, copy_span);
} else { } else {
if (offset % BytesPerBlock(image->info.format)) {
return false;
}
texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span, texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span,
buffer_operand.address, buffer_size); buffer_operand.address, buffer_size);
} }

View File

@ -126,7 +126,7 @@ struct FormatTuple {
{VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1R5G5B5_UNORM {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1R5G5B5_UNORM
{VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10_UNORM {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10_UNORM
{VK_FORMAT_A2B10G10R10_UINT_PACK32, Attachable | Storage}, // A2B10G10R10_UINT {VK_FORMAT_A2B10G10R10_UINT_PACK32, Attachable | Storage}, // A2B10G10R10_UINT
{VK_FORMAT_A2R10G10B10_UNORM_PACK32, Attachable | Storage}, // A2R10G10B10_UNORM {VK_FORMAT_A2R10G10B10_UNORM_PACK32, Attachable}, // A2R10G10B10_UNORM
{VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5_UNORM (flipped with swizzle) {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5_UNORM (flipped with swizzle)
{VK_FORMAT_R5G5B5A1_UNORM_PACK16}, // A5B5G5R1_UNORM (specially swizzled) {VK_FORMAT_R5G5B5A1_UNORM_PACK16}, // A5B5G5R1_UNORM (specially swizzled)
{VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8_UNORM {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8_UNORM

View File

@ -830,7 +830,8 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
} }
const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height); const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height);
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize; static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing; const auto post_op = IS_IMAGE_UPLOAD ? VideoCommon::ObtainBufferOperation::DoNothing
: VideoCommon::ObtainBufferOperation::MarkAsWritten;
const auto [buffer, offset] = const auto [buffer, offset] =
buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op); buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op);
@ -839,8 +840,12 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
const std::span copy_span{&copy, 1}; const std::span copy_span{&copy, 1};
if constexpr (IS_IMAGE_UPLOAD) { if constexpr (IS_IMAGE_UPLOAD) {
texture_cache.PrepareImage(image_id, true, false);
image->UploadMemory(buffer->Handle(), offset, copy_span); image->UploadMemory(buffer->Handle(), offset, copy_span);
} else { } else {
if (offset % BytesPerBlock(image->info.format)) {
return false;
}
texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span, texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span,
buffer_operand.address, buffer_size); buffer_operand.address, buffer_size);
} }

View File

@ -243,6 +243,9 @@ public:
/// Create channel state. /// Create channel state.
void CreateChannel(Tegra::Control::ChannelState& channel) final override; void CreateChannel(Tegra::Control::ChannelState& channel) final override;
/// Prepare an image to be used
void PrepareImage(ImageId image_id, bool is_modification, bool invalidate);
std::recursive_mutex mutex; std::recursive_mutex mutex;
private: private:
@ -387,9 +390,6 @@ private:
/// Synchronize image aliases, copying data if needed /// Synchronize image aliases, copying data if needed
void SynchronizeAliases(ImageId image_id); void SynchronizeAliases(ImageId image_id);
/// Prepare an image to be used
void PrepareImage(ImageId image_id, bool is_modification, bool invalidate);
/// Prepare an image view to be used /// Prepare an image view to be used
void PrepareImageView(ImageViewId image_view_id, bool is_modification, bool invalidate); void PrepareImageView(ImageViewId image_view_id, bool is_modification, bool invalidate);

View File

@ -71,6 +71,11 @@ constexpr std::array R8G8B8_SSCALED{
VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED,
}; };
constexpr std::array VK_FORMAT_R32G32B32_SFLOAT{
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_FORMAT_UNDEFINED,
};
} // namespace Alternatives } // namespace Alternatives
enum class NvidiaArchitecture { enum class NvidiaArchitecture {
@ -103,6 +108,8 @@ constexpr const VkFormat* GetFormatAlternatives(VkFormat format) {
return Alternatives::R16G16B16_SSCALED.data(); return Alternatives::R16G16B16_SSCALED.data();
case VK_FORMAT_R8G8B8_SSCALED: case VK_FORMAT_R8G8B8_SSCALED:
return Alternatives::R8G8B8_SSCALED.data(); return Alternatives::R8G8B8_SSCALED.data();
case VK_FORMAT_R32G32B32_SFLOAT:
return Alternatives::VK_FORMAT_R32G32B32_SFLOAT.data();
default: default:
return nullptr; return nullptr;
} }
@ -130,6 +137,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica
VK_FORMAT_A2B10G10R10_UINT_PACK32, VK_FORMAT_A2B10G10R10_UINT_PACK32,
VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_FORMAT_A2B10G10R10_UNORM_PACK32,
VK_FORMAT_A2B10G10R10_USCALED_PACK32, VK_FORMAT_A2B10G10R10_USCALED_PACK32,
VK_FORMAT_A2R10G10B10_UNORM_PACK32,
VK_FORMAT_A8B8G8R8_SINT_PACK32, VK_FORMAT_A8B8G8R8_SINT_PACK32,
VK_FORMAT_A8B8G8R8_SNORM_PACK32, VK_FORMAT_A8B8G8R8_SNORM_PACK32,
VK_FORMAT_A8B8G8R8_SRGB_PACK32, VK_FORMAT_A8B8G8R8_SRGB_PACK32,