diff --git a/externals/dynarmic/src/dynarmic/backend/x64/abi.cpp b/externals/dynarmic/src/dynarmic/backend/x64/abi.cpp index 7cbe92aaf3..c97d98d9ae 100644 --- a/externals/dynarmic/src/dynarmic/backend/x64/abi.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/abi.cpp @@ -116,18 +116,13 @@ void ABI_PopCallerSaveRegistersAndAdjustStack(BlockOfCode& code, const std::size ABI_PopRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLER_SAVE); } -static consteval size_t ABI_AllCallerSaveSize() noexcept { - return ABI_ALL_CALLER_SAVE.max_size(); -} -static consteval std::array ABI_AllCallerSaveExcept(const std::size_t except) noexcept { - std::array arr; - for(std::size_t i = 0; i < arr.size(); ++i) { - arr[i] = static_cast(i + (i >= except ? 1 : 0)); - } +static std::vector ABI_AllCallerSaveExcept(const std::size_t except) noexcept { + std::vector arr; + std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(arr), static_cast(except)); return arr; } -alignas(64) static constinit std::array ABI_CALLER_SAVED_EXCEPT_TABLE[32] = { +alignas(64) static std::vector ABI_CALLER_SAVED_EXCEPT_TABLE[32] = { ABI_AllCallerSaveExcept(0), ABI_AllCallerSaveExcept(1), ABI_AllCallerSaveExcept(2), @@ -163,24 +158,12 @@ alignas(64) static constinit std::array AB }; void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) { -#ifdef _MSC_VER - std::vector regs; - std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); - ABI_PushRegistersAndAdjustStack(code, 0, regs); -#else ASSUME(size_t(exception) < 32); ABI_PushRegistersAndAdjustStack(code, 0, ABI_CALLER_SAVED_EXCEPT_TABLE[size_t(exception)]); -#endif } void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) { -#ifdef _MSC_VER - std::vector regs; - std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); - ABI_PopRegistersAndAdjustStack(code, 0, regs); -#else ASSUME(size_t(exception) < 32); ABI_PopRegistersAndAdjustStack(code, 0, ABI_CALLER_SAVED_EXCEPT_TABLE[size_t(exception)]); -#endif } } // namespace Dynarmic::Backend::X64 diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index 90891e241d..e63cf82cc5 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -224,7 +224,7 @@ HaltReason ArmNce::RunThread(Kernel::KThread* thread) { if (auto it = post_handlers.find(m_guest_ctx.pc); it != post_handlers.end()) { hr = ReturnToRunCodeByTrampoline(thread_params, &m_guest_ctx, it->second); } else { - hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params); + hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params); // Android: Use "process handle SIGUSR2 -n true -p true -s false" (and SIGURG) in LLDB when debugging } // Critical section for thread cleanup diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index c657c4efd8..034a4b013c 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -151,7 +151,12 @@ static std::pair GetHostByNameRequestImpl(HLERequestConte // For now, ignore options, which are in input buffer 1 for GetHostByNameRequestWithOptions. // Prevent resolution of Nintendo servers - if (host.find("srv.nintendo.net") != std::string::npos) { + if (host.find("srv.nintendo.net") != std::string::npos || + host.find("battle.net") != std::string::npos || + host.find("microsoft.com") != std::string::npos || + host.find("mojang.com") != std::string::npos || + host.find("xboxlive.com") != std::string::npos || + host.find("minecraftservices.com") != std::string::npos) { LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host); return {0, GetAddrInfoError::AGAIN}; } @@ -268,7 +273,12 @@ static std::pair GetAddrInfoRequestImpl(HLERequestContext const std::string host = Common::StringFromBuffer(host_buffer); // Prevent resolution of Nintendo servers - if (host.find("srv.nintendo.net") != std::string::npos) { + if (host.find("srv.nintendo.net") != std::string::npos || + host.find("battle.net") != std::string::npos || + host.find("microsoft.com") != std::string::npos || + host.find("mojang.com") != std::string::npos || + host.find("xboxlive.com") != std::string::npos || + host.find("minecraftservices.com") != std::string::npos) { LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host); return {0, GetAddrInfoError::AGAIN}; } diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp index f0436994b2..da2e31c012 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp @@ -4,6 +4,7 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" +#include namespace Shader::Maxwell { namespace { @@ -33,6 +34,17 @@ enum class ShuffleMode : u64 { } } +bool IsKONA() { + std::ifstream machineFile("/sys/devices/soc0/machine"); + if (machineFile.is_open()) { + std::string line; + std::getline(machineFile, line); + if (line == "KONA") + return true; + } + return false; +} + void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32& mask) { union { u64 insn; @@ -44,7 +56,10 @@ void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32 const IR::U32 result{ShuffleOperation(v.ir, v.X(shfl.src_reg), index, mask, shfl.mode)}; v.ir.SetPred(shfl.pred, v.ir.GetInBoundsFromOp(result)); - v.X(shfl.dest_reg, result); + if (IsKONA()) + v.X(shfl.dest_reg, v.ir.Imm32(0xffffffff)); // This fixes the freeze for Retroid / Snapdragon SD865 + else + v.X(shfl.dest_reg, result); } } // Anonymous namespace diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index ef1ef63500..44ffa2b578 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -327,30 +327,14 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme }; } -// TODO:xbzk: shall be dropped when Track method cover all bindless stuff -static ConstBufferAddr last_valid_addr = ConstBufferAddr{ - .index = 0, - .offset = 0, - .shift_left = 0, - .secondary_index = 0, - .secondary_offset = 0, - .secondary_shift_left = 0, - .dynamic_offset = {}, - .count = 1, - .has_secondary = false, -}; - TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { - ConstBufferAddr addr; + ConstBufferAddr addr{}; if (IsBindless(inst)) { const std::optional track_addr{Track(inst.Arg(0), env)}; - if (!track_addr) { - //throw NotImplementedException("Failed to track bindless texture constant buffer"); - addr = last_valid_addr; // TODO:xbzk: shall be dropped when Track method cover all bindless stuff + LOG_WARNING(Shader, "Failed to track bindless texture constant buffer"); } else { addr = *track_addr; - last_valid_addr = addr; // TODO:xbzk: shall be dropped when Track method cover all bindless stuff } } else { addr = ConstBufferAddr{ diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index af237703d5..c7e287553e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -50,7 +50,7 @@ BufferCache

::~BufferCache() = default; template void BufferCache

::RunGarbageCollector() { const bool aggressive_gc = total_used_memory >= critical_memory; - const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; + const u64 ticks_to_destroy = aggressive_gc ? 60 : 150; int num_iterations = aggressive_gc ? 64 : 32; const auto clean_up = [this, &num_iterations](BufferId buffer_id) { if (num_iterations == 0) { @@ -1380,6 +1380,9 @@ void BufferCache

::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, }); new_buffer.MarkUsage(copies[0].dst_offset, copies[0].size); runtime.CopyBuffer(new_buffer, overlap, copies, true); +#ifdef ANDROID + runtime.Finish(); +#endif DeleteBuffer(overlap_id, true); } @@ -1671,7 +1674,12 @@ void BufferCache

::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { } Unregister(buffer_id); + +#ifdef ANDROID + if (!do_not_mark) +#endif delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id])); + slot_buffers.erase(buffer_id); if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 240e9f0150..3a40bbad19 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -156,7 +156,11 @@ template class BufferCache : public VideoCommon::ChannelSetupCaches { // Page size for caching purposes. // This is unrelated to the CPU page size and it can be changed as it seems optimal. +#ifdef ANDROID + static constexpr u32 CACHING_PAGEBITS = 12; +#else static constexpr u32 CACHING_PAGEBITS = 16; +#endif static constexpr u64 CACHING_PAGESIZE = u64{1} << CACHING_PAGEBITS; static constexpr bool IS_OPENGL = P::IS_OPENGL; @@ -170,9 +174,15 @@ class BufferCache : public VideoCommon::ChannelSetupCaches slot_buffers; - DelayedDestructionRing delayed_destruction_ring; +#ifdef ANDROID + static constexpr size_t TICKS_TO_DESTROY = 2; +#else + static constexpr size_t TICKS_TO_DESTROY = 8; +#endif + DelayedDestructionRing delayed_destruction_ring; const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{}; diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp index 3bcf1b0664..aa501ae51b 100644 --- a/src/video_core/cdma_pusher.cpp +++ b/src/video_core/cdma_pusher.cpp @@ -20,6 +20,9 @@ CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_, s32 id) : host1x{host1x_}, memory_manager{host1x.GMMU()}, host_processor{std::make_unique(host1x_)}, current_class{ static_cast(id)} { +#ifdef ANDROID + std::this_thread::sleep_for(std::chrono::milliseconds{500}); // HACK: Fix for Astroneer - doesn't always start without this delay. Happens on Windows too (but rarer) +#endif thread = std::jthread([this](std::stop_token stop_token) { ProcessEntries(stop_token); }); } diff --git a/src/video_core/delayed_destruction_ring.h b/src/video_core/delayed_destruction_ring.h index d13ee622b2..49d7842f8e 100644 --- a/src/video_core/delayed_destruction_ring.h +++ b/src/video_core/delayed_destruction_ring.h @@ -22,7 +22,6 @@ public: void Push(T&& object) { elements[index].push_back(std::move(object)); } - private: size_t index = 0; std::array, TICKS_TO_DESTROY> elements; diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp index ffde231aee..4bca9ab7b1 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp +++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp @@ -237,16 +237,23 @@ std::shared_ptr DecoderContext::ReceiveFrame() { if (m_codec_context->hw_device_ctx) { // If we have a hardware context, make a separate frame here to receive the // hardware result before sending it to the output. - Frame intermediate_frame; + std::shared_ptr intermediate_frame = std::make_shared(); - if (!receive(intermediate_frame.GetFrame())) { + if (!receive(intermediate_frame->GetFrame())) { return {}; } - m_temp_frame->SetFormat(PreferredGpuFormat); - if (int ret = av_hwframe_transfer_data(m_temp_frame->GetFrame(), intermediate_frame.GetFrame(), 0); ret < 0) { - LOG_ERROR(HW_GPU, "av_hwframe_transfer_data error: {}", AVError(ret)); - return {}; + const auto fmt = intermediate_frame->GetPixelFormat(); + const auto desc = av_pix_fmt_desc_get(fmt); + if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { + m_temp_frame->SetFormat(PreferredGpuFormat); + if (int ret = av_hwframe_transfer_data(m_temp_frame->GetFrame(), intermediate_frame->GetFrame(), 0); ret < 0) { + LOG_ERROR(HW_GPU, "av_hwframe_transfer_data error: {}", AVError(ret)); + return {}; + } + } + else { + m_temp_frame = std::move(intermediate_frame); } } else { // Otherwise, decode the frame as normal. diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.h b/src/video_core/host1x/ffmpeg/ffmpeg.h index 28f1742b7e..9fe0b1532a 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.h +++ b/src/video_core/host1x/ffmpeg/ffmpeg.h @@ -21,6 +21,7 @@ extern "C" { #include #include +#include #include #if defined(__GNUC__) || defined(__clang__) diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 4e41afe5b4..984466f687 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -137,6 +137,7 @@ void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { .pQueueFamilyIndices = nullptr, }; + buffer.reset(); buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload); } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index feb1c575eb..3178866128 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -78,6 +78,9 @@ void TextureCache

::RunGarbageCollector() { size_t num_iterations = 0; const auto Configure = [&](bool allow_aggressive) { +#ifdef ANDROID + high_priority_mode = true; +#endif high_priority_mode = total_used_memory >= expected_memory; aggressive_mode = allow_aggressive && total_used_memory >= critical_memory; ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index da98a634b5..ba38182169 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -107,10 +107,17 @@ class TextureCache : public VideoCommon::ChannelSetupCaches::max()}; + #ifdef ANDROID + static constexpr s64 TARGET_THRESHOLD = 3_GiB; + static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; + static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB; + static constexpr size_t GC_EMERGENCY_COUNTS = 2; + #else static constexpr s64 TARGET_THRESHOLD = 4_GiB; static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB; static constexpr size_t GC_EMERGENCY_COUNTS = 2; + #endif using Runtime = typename P::Runtime; using Image = typename P::Image; @@ -476,7 +483,11 @@ private: }; Common::LeastRecentlyUsedCache lru_cache; + #ifdef ANDROID + static constexpr size_t TICKS_TO_DESTROY = 2; + #else static constexpr size_t TICKS_TO_DESTROY = 8; +#endif DelayedDestructionRing sentenced_images; DelayedDestructionRing sentenced_image_view; DelayedDestructionRing sentenced_framebuffers; diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 54331688e3..e35dea90d6 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -268,7 +268,10 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsa VmaAllocation allocation{}; VkMemoryPropertyFlags property_flags{}; - vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info)); + VkResult result = vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info); + if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) { + LOG_ERROR(Render_Vulkan, "Out of memory creating buffer (size: {})", ci.size); + } vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags); u8* data = reinterpret_cast(alloc_info.pMappedData);