Compare commits
13 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2a6dde438 | ||
|
|
b1d61cd025 | ||
|
|
aae208d07f | ||
|
|
01bb5d5c4d | ||
|
|
30515b3b27 | ||
|
|
167d948ce1 | ||
|
|
b210efefb0 | ||
|
|
e2123b27e8 | ||
|
|
795ccc058d | ||
|
|
8c933beb48 | ||
|
|
6523854dd6 | ||
|
|
d657ea69c9 | ||
|
|
30e8876ea4 |
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 91d1f944e3...2d4602a651
2
externals/vcpkg
vendored
2
externals/vcpkg
vendored
Submodule externals/vcpkg updated: cef0b3ec76...9b22b40c6c
@@ -6,8 +6,6 @@ add_library(core STATIC
|
||||
announce_multiplayer_session.h
|
||||
arm/arm_interface.h
|
||||
arm/arm_interface.cpp
|
||||
arm/cpu_interrupt_handler.cpp
|
||||
arm/cpu_interrupt_handler.h
|
||||
arm/dynarmic/arm_dynarmic_32.cpp
|
||||
arm/dynarmic/arm_dynarmic_32.h
|
||||
arm/dynarmic/arm_dynarmic_64.cpp
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace Core {
|
||||
class System;
|
||||
class CPUInterruptHandler;
|
||||
|
||||
using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>;
|
||||
using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>;
|
||||
|
||||
/// Generic ARMv8 CPU interface
|
||||
@@ -36,10 +35,8 @@ public:
|
||||
YUZU_NON_COPYABLE(ARM_Interface);
|
||||
YUZU_NON_MOVEABLE(ARM_Interface);
|
||||
|
||||
explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers_,
|
||||
bool uses_wall_clock_)
|
||||
: system{system_}, interrupt_handlers{interrupt_handlers_}, uses_wall_clock{
|
||||
uses_wall_clock_} {}
|
||||
explicit ARM_Interface(System& system_, bool uses_wall_clock_)
|
||||
: system{system_}, uses_wall_clock{uses_wall_clock_} {}
|
||||
virtual ~ARM_Interface() = default;
|
||||
|
||||
struct ThreadContext32 {
|
||||
@@ -181,6 +178,9 @@ public:
|
||||
/// Signal an interrupt and ask the core to halt as soon as possible.
|
||||
virtual void SignalInterrupt() = 0;
|
||||
|
||||
/// Clear a previous interrupt.
|
||||
virtual void ClearInterrupt() = 0;
|
||||
|
||||
struct BacktraceEntry {
|
||||
std::string module;
|
||||
u64 address;
|
||||
@@ -208,7 +208,6 @@ public:
|
||||
protected:
|
||||
/// System context that this ARM interface is running under.
|
||||
System& system;
|
||||
CPUInterrupts& interrupt_handlers;
|
||||
const WatchpointArray* watchpoints;
|
||||
bool uses_wall_clock;
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/thread.h"
|
||||
#include "core/arm/cpu_interrupt_handler.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {}
|
||||
|
||||
CPUInterruptHandler::~CPUInterruptHandler() = default;
|
||||
|
||||
void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) {
|
||||
if (is_interrupted_) {
|
||||
interrupt_event->Set();
|
||||
}
|
||||
is_interrupted = is_interrupted_;
|
||||
}
|
||||
|
||||
void CPUInterruptHandler::AwaitInterrupt() {
|
||||
interrupt_event->Wait();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
@@ -1,39 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
namespace Common {
|
||||
class Event;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class CPUInterruptHandler {
|
||||
public:
|
||||
CPUInterruptHandler();
|
||||
~CPUInterruptHandler();
|
||||
|
||||
CPUInterruptHandler(const CPUInterruptHandler&) = delete;
|
||||
CPUInterruptHandler& operator=(const CPUInterruptHandler&) = delete;
|
||||
|
||||
CPUInterruptHandler(CPUInterruptHandler&&) = delete;
|
||||
CPUInterruptHandler& operator=(CPUInterruptHandler&&) = delete;
|
||||
|
||||
bool IsInterrupted() const {
|
||||
return is_interrupted;
|
||||
}
|
||||
|
||||
void SetInterrupt(bool is_interrupted);
|
||||
|
||||
void AwaitInterrupt();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Common::Event> interrupt_event;
|
||||
std::atomic_bool is_interrupted{false};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/page_table.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/arm/cpu_interrupt_handler.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
|
||||
#include "core/arm/dynarmic/arm_exclusive_monitor.h"
|
||||
@@ -125,7 +124,9 @@ public:
|
||||
}
|
||||
|
||||
void AddTicks(u64 ticks) override {
|
||||
ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
|
||||
if (parent.uses_wall_clock) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
|
||||
// rough approximation of the amount of executed ticks in the system, it may be thrown off
|
||||
@@ -142,7 +143,12 @@ public:
|
||||
}
|
||||
|
||||
u64 GetTicksRemaining() override {
|
||||
ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
|
||||
if (parent.uses_wall_clock) {
|
||||
if (!IsInterrupted()) {
|
||||
return minimum_run_cycles;
|
||||
}
|
||||
return 0U;
|
||||
}
|
||||
|
||||
return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
|
||||
}
|
||||
@@ -168,11 +174,15 @@ public:
|
||||
parent.jit.load()->HaltExecution(hr);
|
||||
}
|
||||
|
||||
bool IsInterrupted() {
|
||||
return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
|
||||
}
|
||||
|
||||
ARM_Dynarmic_32& parent;
|
||||
Core::Memory::Memory& memory;
|
||||
std::size_t num_interpreted_instructions{};
|
||||
bool debugger_enabled{};
|
||||
static constexpr u64 minimum_run_cycles = 1000U;
|
||||
static constexpr u64 minimum_run_cycles = 10000U;
|
||||
};
|
||||
|
||||
std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* page_table) const {
|
||||
@@ -200,7 +210,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
|
||||
// Timing
|
||||
config.wall_clock_cntpct = uses_wall_clock;
|
||||
config.enable_cycle_counting = !uses_wall_clock;
|
||||
config.enable_cycle_counting = true;
|
||||
|
||||
// Code cache size
|
||||
config.code_cache_size = 512_MiB;
|
||||
@@ -311,11 +321,9 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() {
|
||||
LoadContext(breakpoint_context);
|
||||
}
|
||||
|
||||
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_,
|
||||
bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
|
||||
std::size_t core_index_)
|
||||
: ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
|
||||
cb(std::make_unique<DynarmicCallbacks32>(*this)),
|
||||
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
|
||||
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
|
||||
: ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
|
||||
cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
|
||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
|
||||
null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
|
||||
@@ -394,6 +402,10 @@ void ARM_Dynarmic_32::SignalInterrupt() {
|
||||
jit.load()->HaltExecution(break_loop);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::ClearInterrupt() {
|
||||
jit.load()->ClearHalt(break_loop);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::ClearInstructionCache() {
|
||||
jit.load()->ClearCache();
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ class System;
|
||||
|
||||
class ARM_Dynarmic_32 final : public ARM_Interface {
|
||||
public:
|
||||
ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_,
|
||||
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
|
||||
ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
|
||||
std::size_t core_index_);
|
||||
~ARM_Dynarmic_32() override;
|
||||
|
||||
void SetPC(u64 pc) override;
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
void LoadContext(const ThreadContext64& ctx) override {}
|
||||
|
||||
void SignalInterrupt() override;
|
||||
void ClearInterrupt() override;
|
||||
void ClearExclusiveState() override;
|
||||
|
||||
void ClearInstructionCache() override;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/page_table.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/arm/cpu_interrupt_handler.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#include "core/arm/dynarmic/arm_exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
@@ -166,7 +165,9 @@ public:
|
||||
}
|
||||
|
||||
void AddTicks(u64 ticks) override {
|
||||
ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
|
||||
if (parent.uses_wall_clock) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
|
||||
// rough approximation of the amount of executed ticks in the system, it may be thrown off
|
||||
@@ -181,7 +182,12 @@ public:
|
||||
}
|
||||
|
||||
u64 GetTicksRemaining() override {
|
||||
ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
|
||||
if (parent.uses_wall_clock) {
|
||||
if (!IsInterrupted()) {
|
||||
return minimum_run_cycles;
|
||||
}
|
||||
return 0U;
|
||||
}
|
||||
|
||||
return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
|
||||
}
|
||||
@@ -211,12 +217,16 @@ public:
|
||||
parent.jit.load()->HaltExecution(hr);
|
||||
}
|
||||
|
||||
bool IsInterrupted() {
|
||||
return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
|
||||
}
|
||||
|
||||
ARM_Dynarmic_64& parent;
|
||||
Core::Memory::Memory& memory;
|
||||
u64 tpidrro_el0 = 0;
|
||||
u64 tpidr_el0 = 0;
|
||||
bool debugger_enabled{};
|
||||
static constexpr u64 minimum_run_cycles = 1000U;
|
||||
static constexpr u64 minimum_run_cycles = 10000U;
|
||||
};
|
||||
|
||||
std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* page_table,
|
||||
@@ -260,7 +270,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
|
||||
// Timing
|
||||
config.wall_clock_cntpct = uses_wall_clock;
|
||||
config.enable_cycle_counting = !uses_wall_clock;
|
||||
config.enable_cycle_counting = true;
|
||||
|
||||
// Code cache size
|
||||
config.code_cache_size = 512_MiB;
|
||||
@@ -371,10 +381,9 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() {
|
||||
LoadContext(breakpoint_context);
|
||||
}
|
||||
|
||||
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_,
|
||||
bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
|
||||
std::size_t core_index_)
|
||||
: ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
|
||||
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
|
||||
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
|
||||
: ARM_Interface{system_, uses_wall_clock_},
|
||||
cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
|
||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
|
||||
null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
|
||||
@@ -461,6 +470,10 @@ void ARM_Dynarmic_64::SignalInterrupt() {
|
||||
jit.load()->HaltExecution(break_loop);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_64::ClearInterrupt() {
|
||||
jit.load()->ClearHalt(break_loop);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_64::ClearInstructionCache() {
|
||||
jit.load()->ClearCache();
|
||||
}
|
||||
|
||||
@@ -20,14 +20,13 @@ class Memory;
|
||||
namespace Core {
|
||||
|
||||
class DynarmicCallbacks64;
|
||||
class CPUInterruptHandler;
|
||||
class DynarmicExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class ARM_Dynarmic_64 final : public ARM_Interface {
|
||||
public:
|
||||
ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_,
|
||||
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
|
||||
ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
|
||||
std::size_t core_index_);
|
||||
~ARM_Dynarmic_64() override;
|
||||
|
||||
void SetPC(u64 pc) override;
|
||||
@@ -50,6 +49,7 @@ public:
|
||||
void LoadContext(const ThreadContext64& ctx) override;
|
||||
|
||||
void SignalInterrupt() override;
|
||||
void ClearInterrupt() override;
|
||||
void ClearExclusiveState() override;
|
||||
|
||||
void ClearInstructionCache() override;
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
using Callback = Dynarmic::A32::Coprocessor::Callback;
|
||||
using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
|
||||
using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
|
||||
@@ -51,31 +47,12 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1
|
||||
switch (opc2) {
|
||||
case 4:
|
||||
// CP15_DATA_SYNC_BARRIER
|
||||
return Callback{
|
||||
[](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t {
|
||||
#ifdef _MSC_VER
|
||||
_mm_mfence();
|
||||
_mm_lfence();
|
||||
#else
|
||||
asm volatile("mfence\n\tlfence\n\t" : : : "memory");
|
||||
#endif
|
||||
return 0;
|
||||
},
|
||||
std::nullopt,
|
||||
};
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &dummy_value;
|
||||
case 5:
|
||||
// CP15_DATA_MEMORY_BARRIER
|
||||
return Callback{
|
||||
[](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t {
|
||||
#ifdef _MSC_VER
|
||||
_mm_mfence();
|
||||
#else
|
||||
asm volatile("mfence\n\t" : : : "memory");
|
||||
#endif
|
||||
return 0;
|
||||
},
|
||||
std::nullopt,
|
||||
};
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &dummy_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@ public:
|
||||
ARM_Dynarmic_32& parent;
|
||||
u32 uprw = 0;
|
||||
u32 uro = 0;
|
||||
|
||||
friend class ARM_Dynarmic_32;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "core/debugger/debugger_interface.h"
|
||||
#include "core/debugger/gdbstub.h"
|
||||
#include "core/hle/kernel/global_scheduler_context.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
|
||||
template <typename Readable, typename Buffer, typename Callback>
|
||||
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) {
|
||||
@@ -230,13 +231,12 @@ private:
|
||||
}
|
||||
|
||||
void PauseEmulation() {
|
||||
Kernel::KScopedSchedulerLock sl{system.Kernel()};
|
||||
|
||||
// Put all threads to sleep on next scheduler round.
|
||||
for (auto* thread : ThreadList()) {
|
||||
thread->RequestSuspend(Kernel::SuspendType::Debug);
|
||||
}
|
||||
|
||||
// Signal an interrupt so that scheduler will fire.
|
||||
system.Kernel().InterruptAllPhysicalCores();
|
||||
}
|
||||
|
||||
void ResumeEmulation(Kernel::KThread* except = nullptr) {
|
||||
@@ -253,7 +253,8 @@ private:
|
||||
|
||||
template <typename Callback>
|
||||
void MarkResumed(Callback&& cb) {
|
||||
std::scoped_lock lk{connection_lock};
|
||||
Kernel::KScopedSchedulerLock sl{system.Kernel()};
|
||||
std::scoped_lock cl{connection_lock};
|
||||
stopped = false;
|
||||
cb();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "common/thread.h"
|
||||
#include "common/thread_worker.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/cpu_interrupt_handler.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
@@ -82,7 +81,7 @@ struct KernelCore::Impl {
|
||||
|
||||
void InitializeCores() {
|
||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||
cores[core_id].Initialize((*current_process).Is64BitProcess());
|
||||
cores[core_id]->Initialize((*current_process).Is64BitProcess());
|
||||
system.Memory().SetCurrentPageTable(*current_process, core_id);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +99,9 @@ struct KernelCore::Impl {
|
||||
next_user_process_id = KProcess::ProcessIDMin;
|
||||
next_thread_id = 1;
|
||||
|
||||
cores.clear();
|
||||
for (auto& core : cores) {
|
||||
core = nullptr;
|
||||
}
|
||||
|
||||
global_handle_table->Finalize();
|
||||
global_handle_table.reset();
|
||||
@@ -199,7 +200,7 @@ struct KernelCore::Impl {
|
||||
const s32 core{static_cast<s32>(i)};
|
||||
|
||||
schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel());
|
||||
cores.emplace_back(i, system, *schedulers[i], interrupts);
|
||||
cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]);
|
||||
|
||||
auto* main_thread{Kernel::KThread::Create(system.Kernel())};
|
||||
main_thread->SetName(fmt::format("MainThread:{}", core));
|
||||
@@ -761,7 +762,7 @@ struct KernelCore::Impl {
|
||||
std::unordered_set<KAutoObject*> registered_in_use_objects;
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
|
||||
std::vector<Kernel::PhysicalCore> cores;
|
||||
std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores;
|
||||
|
||||
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
|
||||
std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
|
||||
@@ -785,7 +786,6 @@ struct KernelCore::Impl {
|
||||
Common::ThreadWorker service_threads_manager;
|
||||
|
||||
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
|
||||
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
|
||||
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
||||
|
||||
bool is_multicore{};
|
||||
@@ -874,11 +874,11 @@ const Kernel::KScheduler& KernelCore::Scheduler(std::size_t id) const {
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
|
||||
return impl->cores[id];
|
||||
return *impl->cores[id];
|
||||
}
|
||||
|
||||
const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
|
||||
return impl->cores[id];
|
||||
return *impl->cores[id];
|
||||
}
|
||||
|
||||
size_t KernelCore::CurrentPhysicalCoreIndex() const {
|
||||
@@ -890,11 +890,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const {
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
|
||||
return impl->cores[CurrentPhysicalCoreIndex()];
|
||||
return *impl->cores[CurrentPhysicalCoreIndex()];
|
||||
}
|
||||
|
||||
const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
|
||||
return impl->cores[CurrentPhysicalCoreIndex()];
|
||||
return *impl->cores[CurrentPhysicalCoreIndex()];
|
||||
}
|
||||
|
||||
Kernel::KScheduler* KernelCore::CurrentScheduler() {
|
||||
@@ -906,15 +906,6 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
|
||||
return impl->schedulers[core_id].get();
|
||||
}
|
||||
|
||||
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() {
|
||||
return impl->interrupts;
|
||||
}
|
||||
|
||||
const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts()
|
||||
const {
|
||||
return impl->interrupts;
|
||||
}
|
||||
|
||||
Kernel::TimeManager& KernelCore::TimeManager() {
|
||||
return impl->time_manager;
|
||||
}
|
||||
@@ -939,24 +930,18 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
|
||||
return *impl->global_object_list_container;
|
||||
}
|
||||
|
||||
void KernelCore::InterruptAllPhysicalCores() {
|
||||
for (auto& physical_core : impl->cores) {
|
||||
physical_core.Interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void KernelCore::InvalidateAllInstructionCaches() {
|
||||
for (auto& physical_core : impl->cores) {
|
||||
physical_core.ArmInterface().ClearInstructionCache();
|
||||
physical_core->ArmInterface().ClearInstructionCache();
|
||||
}
|
||||
}
|
||||
|
||||
void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
|
||||
for (auto& physical_core : impl->cores) {
|
||||
if (!physical_core.IsInitialized()) {
|
||||
if (!physical_core->IsInitialized()) {
|
||||
continue;
|
||||
}
|
||||
physical_core.ArmInterface().InvalidateCacheRange(addr, size);
|
||||
physical_core->ArmInterface().InvalidateCacheRange(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,12 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "core/arm/cpu_interrupt_handler.h"
|
||||
#include "core/hardware_properties.h"
|
||||
#include "core/hle/kernel/k_auto_object.h"
|
||||
#include "core/hle/kernel/k_slab_heap.h"
|
||||
#include "core/hle/kernel/svc_common.h"
|
||||
|
||||
namespace Core {
|
||||
class CPUInterruptHandler;
|
||||
class ExclusiveMonitor;
|
||||
class System;
|
||||
} // namespace Core
|
||||
@@ -183,12 +181,6 @@ public:
|
||||
|
||||
const KAutoObjectWithListContainer& ObjectListContainer() const;
|
||||
|
||||
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts();
|
||||
|
||||
const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const;
|
||||
|
||||
void InterruptAllPhysicalCores();
|
||||
|
||||
void InvalidateAllInstructionCaches();
|
||||
|
||||
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/arm/cpu_interrupt_handler.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#include "core/core.h"
|
||||
@@ -11,16 +10,14 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_,
|
||||
Core::CPUInterrupts& interrupts_)
|
||||
: core_index{core_index_}, system{system_}, scheduler{scheduler_},
|
||||
interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} {
|
||||
PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_)
|
||||
: core_index{core_index_}, system{system_}, scheduler{scheduler_} {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
// TODO(bunnei): Initialization relies on a core being available. We may later replace this with
|
||||
// a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
|
||||
auto& kernel = system.Kernel();
|
||||
arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
|
||||
system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
|
||||
system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
|
||||
#else
|
||||
#error Platform not supported yet.
|
||||
#endif
|
||||
@@ -34,7 +31,7 @@ void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) {
|
||||
if (!is_64_bit) {
|
||||
// We already initialized a 64-bit core, replace with a 32-bit one.
|
||||
arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
|
||||
system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
|
||||
system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
|
||||
}
|
||||
#else
|
||||
#error Platform not supported yet.
|
||||
@@ -47,24 +44,26 @@ void PhysicalCore::Run() {
|
||||
}
|
||||
|
||||
void PhysicalCore::Idle() {
|
||||
interrupts[core_index].AwaitInterrupt();
|
||||
std::unique_lock lk{guard};
|
||||
on_interrupt.wait(lk, [this] { return is_interrupted; });
|
||||
}
|
||||
|
||||
bool PhysicalCore::IsInterrupted() const {
|
||||
return interrupts[core_index].IsInterrupted();
|
||||
return is_interrupted;
|
||||
}
|
||||
|
||||
void PhysicalCore::Interrupt() {
|
||||
guard->lock();
|
||||
interrupts[core_index].SetInterrupt(true);
|
||||
std::unique_lock lk{guard};
|
||||
is_interrupted = true;
|
||||
arm_interface->SignalInterrupt();
|
||||
guard->unlock();
|
||||
on_interrupt.notify_all();
|
||||
}
|
||||
|
||||
void PhysicalCore::ClearInterrupt() {
|
||||
guard->lock();
|
||||
interrupts[core_index].SetInterrupt(false);
|
||||
guard->unlock();
|
||||
std::unique_lock lk{guard};
|
||||
is_interrupted = false;
|
||||
arm_interface->ClearInterrupt();
|
||||
on_interrupt.notify_all();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -14,7 +14,6 @@ class KScheduler;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Core {
|
||||
class CPUInterruptHandler;
|
||||
class ExclusiveMonitor;
|
||||
class System;
|
||||
} // namespace Core
|
||||
@@ -23,15 +22,11 @@ namespace Kernel {
|
||||
|
||||
class PhysicalCore {
|
||||
public:
|
||||
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_,
|
||||
Core::CPUInterrupts& interrupts_);
|
||||
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_);
|
||||
~PhysicalCore();
|
||||
|
||||
PhysicalCore(const PhysicalCore&) = delete;
|
||||
PhysicalCore& operator=(const PhysicalCore&) = delete;
|
||||
|
||||
PhysicalCore(PhysicalCore&&) = default;
|
||||
PhysicalCore& operator=(PhysicalCore&&) = delete;
|
||||
YUZU_NON_COPYABLE(PhysicalCore);
|
||||
YUZU_NON_MOVEABLE(PhysicalCore);
|
||||
|
||||
/// Initialize the core for the specified parameters.
|
||||
void Initialize(bool is_64_bit);
|
||||
@@ -86,9 +81,11 @@ private:
|
||||
const std::size_t core_index;
|
||||
Core::System& system;
|
||||
Kernel::KScheduler& scheduler;
|
||||
Core::CPUInterrupts& interrupts;
|
||||
std::unique_ptr<std::mutex> guard;
|
||||
|
||||
std::mutex guard;
|
||||
std::condition_variable on_interrupt;
|
||||
std::unique_ptr<Core::ARM_Interface> arm_interface;
|
||||
bool is_interrupted;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -67,6 +67,7 @@ std::string_view TextureType(IR::TextureInstInfo info) {
|
||||
case TextureType::ColorArray1D:
|
||||
return "SHADOWARRAY1D";
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
return "SHADOW2D";
|
||||
case TextureType::ColorArray2D:
|
||||
return "SHADOWARRAY2D";
|
||||
@@ -86,6 +87,7 @@ std::string_view TextureType(IR::TextureInstInfo info) {
|
||||
case TextureType::ColorArray1D:
|
||||
return "ARRAY1D";
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
return "2D";
|
||||
case TextureType::ColorArray2D:
|
||||
return "ARRAY2D";
|
||||
|
||||
@@ -466,6 +466,7 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value&
|
||||
case TextureType::ColorArray1D:
|
||||
case TextureType::Color2D:
|
||||
case TextureType::ColorCube:
|
||||
case TextureType::Color2DRect:
|
||||
return ctx.AddU32x4(
|
||||
"{}=uvec4(uvec2(textureSize({},int({}))),0u,uint(textureQueryLevels({})));", inst,
|
||||
texture, lod, texture);
|
||||
|
||||
@@ -86,6 +86,7 @@ std::string_view SamplerType(TextureType type, bool is_depth) {
|
||||
case TextureType::ColorArray1D:
|
||||
return "sampler1DArray";
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
return "sampler2D";
|
||||
case TextureType::ColorArray2D:
|
||||
return "sampler2DArray";
|
||||
|
||||
@@ -453,6 +453,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
|
||||
case TextureType::ColorArray1D:
|
||||
case TextureType::Color2D:
|
||||
case TextureType::ColorCube:
|
||||
case TextureType::Color2DRect:
|
||||
return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod),
|
||||
zero, mips());
|
||||
case TextureType::ColorArray2D:
|
||||
|
||||
@@ -41,6 +41,7 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
|
||||
case TextureType::ColorArray1D:
|
||||
return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format);
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, false, 1, format);
|
||||
case TextureType::ColorArray2D:
|
||||
return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, false, 1, format);
|
||||
|
||||
@@ -1832,6 +1832,11 @@ Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod) {
|
||||
return Inst(op, handle, lod);
|
||||
}
|
||||
|
||||
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
||||
TextureInstInfo info) {
|
||||
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod);
|
||||
}
|
||||
|
||||
Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) {
|
||||
const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryLod
|
||||
: Opcode::BindlessImageQueryLod};
|
||||
|
||||
@@ -315,6 +315,8 @@ public:
|
||||
const F32& dref, const F32& lod,
|
||||
const Value& offset, TextureInstInfo info);
|
||||
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod);
|
||||
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
||||
TextureInstInfo info);
|
||||
|
||||
[[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords,
|
||||
TextureInstInfo info);
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace {
|
||||
switch (type) {
|
||||
case TextureType::Color2D:
|
||||
case TextureType::ColorArray2D:
|
||||
case TextureType::Color2DRect:
|
||||
return true;
|
||||
case TextureType::Color1D:
|
||||
case TextureType::ColorArray1D:
|
||||
@@ -132,7 +133,8 @@ void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) {
|
||||
const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))};
|
||||
switch (info.type) {
|
||||
case TextureType::Color2D:
|
||||
case TextureType::ColorArray2D: {
|
||||
case TextureType::ColorArray2D:
|
||||
case TextureType::Color2DRect: {
|
||||
const IR::Value new_inst{&*block.PrependNewInst(it, inst)};
|
||||
const IR::U32 width{DownScale(ir, is_scaled, IR::U32{ir.CompositeExtract(new_inst, 0)})};
|
||||
const IR::U32 height{DownScale(ir, is_scaled, IR::U32{ir.CompositeExtract(new_inst, 1)})};
|
||||
@@ -163,6 +165,7 @@ void ScaleIntegerComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_s
|
||||
const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(composite, 1)})};
|
||||
switch (info.type) {
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
inst.SetArg(index, ir.CompositeConstruct(x, y));
|
||||
break;
|
||||
case TextureType::ColorArray2D: {
|
||||
@@ -193,6 +196,7 @@ void ScaleIntegerOffsetComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1
|
||||
switch (info.type) {
|
||||
case TextureType::ColorArray2D:
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
inst.SetArg(index, ir.CompositeConstruct(x, y));
|
||||
break;
|
||||
case TextureType::Color1D:
|
||||
@@ -216,6 +220,7 @@ void SubScaleCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) {
|
||||
const IR::U32 scaled_y{SubScale(ir, is_scaled, coord_y, IR::Attribute::PositionY)};
|
||||
switch (info.type) {
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
inst.SetArg(1, ir.CompositeConstruct(scaled_x, scaled_y));
|
||||
break;
|
||||
case TextureType::ColorArray2D: {
|
||||
|
||||
@@ -362,6 +362,21 @@ private:
|
||||
TextureDescriptors& texture_descriptors;
|
||||
ImageDescriptors& image_descriptors;
|
||||
};
|
||||
|
||||
void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
||||
const IR::Value coord(inst.Arg(1));
|
||||
const IR::Value handle(ir.Imm32(0));
|
||||
const IR::U32 lod{ir.Imm32(0)};
|
||||
const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, info);
|
||||
inst.SetArg(
|
||||
1, ir.CompositeConstruct(
|
||||
ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)),
|
||||
ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 0)))),
|
||||
ir.FPMul(IR::F32(ir.CompositeExtract(coord, 1)),
|
||||
ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void TexturePass(Environment& env, IR::Program& program) {
|
||||
@@ -399,6 +414,14 @@ void TexturePass(Environment& env, IR::Program& program) {
|
||||
flags.type.Assign(ReadTextureType(env, cbuf));
|
||||
inst->SetFlags(flags);
|
||||
break;
|
||||
case IR::Opcode::ImageSampleImplicitLod:
|
||||
if (flags.type == TextureType::Color2D) {
|
||||
auto texture_type = ReadTextureType(env, cbuf);
|
||||
if (texture_type == TextureType::Color2DRect) {
|
||||
PatchImageSampleImplicitLod(*texture_inst.block, *texture_inst.inst);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::ImageFetch:
|
||||
if (flags.type != TextureType::Color1D) {
|
||||
break;
|
||||
|
||||
@@ -24,8 +24,9 @@ enum class TextureType : u32 {
|
||||
ColorCube,
|
||||
ColorArrayCube,
|
||||
Buffer,
|
||||
Color2DRect,
|
||||
};
|
||||
constexpr u32 NUM_TEXTURE_TYPES = 8;
|
||||
constexpr u32 NUM_TEXTURE_TYPES = 9;
|
||||
|
||||
enum class ImageFormat : u32 {
|
||||
Typeless,
|
||||
|
||||
@@ -93,6 +93,7 @@ GLenum ImageTarget(Shader::TextureType type, int num_samples = 1) {
|
||||
case Shader::TextureType::Color1D:
|
||||
return GL_TEXTURE_1D;
|
||||
case Shader::TextureType::Color2D:
|
||||
case Shader::TextureType::Color2DRect:
|
||||
return is_multisampled ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
|
||||
case Shader::TextureType::ColorCube:
|
||||
return GL_TEXTURE_CUBE_MAP;
|
||||
@@ -502,6 +503,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager&
|
||||
set_view(Shader::TextureType::ColorArray1D, null_image_1d_array.handle);
|
||||
set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle);
|
||||
set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle);
|
||||
set_view(Shader::TextureType::Color2DRect, null_image_view_2d.handle);
|
||||
|
||||
if (resolution.active) {
|
||||
for (size_t i = 0; i < rescale_draw_fbos.size(); ++i) {
|
||||
@@ -1110,6 +1112,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
flat_range.extent.layers = 1;
|
||||
[[fallthrough]];
|
||||
case ImageViewType::e2D:
|
||||
case ImageViewType::Rect:
|
||||
if (True(flags & VideoCommon::ImageViewFlagBits::Slice)) {
|
||||
// 2D and 2D array views on a 3D textures are used exclusively for render targets
|
||||
ASSERT(info.range.extent.levels == 1);
|
||||
@@ -1135,9 +1138,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
SetupView(Shader::TextureType::ColorCube);
|
||||
SetupView(Shader::TextureType::ColorArrayCube);
|
||||
break;
|
||||
case ImageViewType::Rect:
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
case ImageViewType::Buffer:
|
||||
ASSERT(false);
|
||||
break;
|
||||
@@ -1150,6 +1150,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
default_handle = Handle(Shader::TextureType::ColorArray1D);
|
||||
break;
|
||||
case ImageViewType::e2D:
|
||||
case ImageViewType::Rect:
|
||||
default_handle = Handle(Shader::TextureType::Color2D);
|
||||
break;
|
||||
case ImageViewType::e2DArray:
|
||||
@@ -1210,6 +1211,7 @@ GLuint ImageView::MakeView(Shader::TextureType view_type, GLenum view_format) {
|
||||
case Shader::TextureType::Color1D:
|
||||
case Shader::TextureType::Color2D:
|
||||
case Shader::TextureType::ColorCube:
|
||||
case Shader::TextureType::Color2DRect:
|
||||
view_range = flat_range;
|
||||
break;
|
||||
case Shader::TextureType::ColorArray1D:
|
||||
@@ -1250,7 +1252,6 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) {
|
||||
const GLint seamless = config.cubemap_interface_filtering ? GL_TRUE : GL_FALSE;
|
||||
|
||||
UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1);
|
||||
UNIMPLEMENTED_IF(config.float_coord_normalization != 0);
|
||||
|
||||
sampler.Create();
|
||||
const GLuint handle = sampler.handle;
|
||||
|
||||
@@ -434,7 +434,9 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
|
||||
state.statistics.get(), false)};
|
||||
|
||||
std::scoped_lock lock{state.mutex};
|
||||
graphics_cache.emplace(key, std::move(pipeline));
|
||||
if (pipeline) {
|
||||
graphics_cache.emplace(key, std::move(pipeline));
|
||||
}
|
||||
++state.built;
|
||||
if (state.has_loaded) {
|
||||
callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
|
||||
|
||||
@@ -230,6 +230,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
case Shader::TextureType::Color1D:
|
||||
return VK_IMAGE_VIEW_TYPE_1D;
|
||||
case Shader::TextureType::Color2D:
|
||||
case Shader::TextureType::Color2DRect:
|
||||
return VK_IMAGE_VIEW_TYPE_2D;
|
||||
case Shader::TextureType::ColorCube:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
@@ -254,6 +255,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
case VideoCommon::ImageViewType::e1D:
|
||||
return VK_IMAGE_VIEW_TYPE_1D;
|
||||
case VideoCommon::ImageViewType::e2D:
|
||||
case VideoCommon::ImageViewType::Rect:
|
||||
return VK_IMAGE_VIEW_TYPE_2D;
|
||||
case VideoCommon::ImageViewType::Cube:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
@@ -265,9 +267,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
case VideoCommon::ImageViewType::CubeArray:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
||||
case VideoCommon::ImageViewType::Rect:
|
||||
UNIMPLEMENTED_MSG("Rect image view");
|
||||
return VK_IMAGE_VIEW_TYPE_2D;
|
||||
case VideoCommon::ImageViewType::Buffer:
|
||||
ASSERT_MSG(false, "Texture buffers can't be image views");
|
||||
return VK_IMAGE_VIEW_TYPE_1D;
|
||||
@@ -1579,6 +1578,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
break;
|
||||
case VideoCommon::ImageViewType::e2D:
|
||||
case VideoCommon::ImageViewType::e2DArray:
|
||||
case VideoCommon::ImageViewType::Rect:
|
||||
create(TextureType::Color2D, 1);
|
||||
create(TextureType::ColorArray2D, std::nullopt);
|
||||
render_target = Handle(Shader::TextureType::ColorArray2D);
|
||||
@@ -1592,9 +1592,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
create(TextureType::ColorCube, 6);
|
||||
create(TextureType::ColorArrayCube, std::nullopt);
|
||||
break;
|
||||
case VideoCommon::ImageViewType::Rect:
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
case VideoCommon::ImageViewType::Buffer:
|
||||
ASSERT(false);
|
||||
break;
|
||||
|
||||
@@ -39,7 +39,11 @@ static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) {
|
||||
return Shader::TextureType::Color1D;
|
||||
case Tegra::Texture::TextureType::Texture2D:
|
||||
case Tegra::Texture::TextureType::Texture2DNoMipmap:
|
||||
return Shader::TextureType::Color2D;
|
||||
if (entry.normalized_coords) {
|
||||
return Shader::TextureType::Color2D;
|
||||
} else {
|
||||
return Shader::TextureType::Color2DRect;
|
||||
}
|
||||
case Tegra::Texture::TextureType::Texture3D:
|
||||
return Shader::TextureType::Color3D;
|
||||
case Tegra::Texture::TextureType::TextureCubemap:
|
||||
@@ -53,7 +57,8 @@ static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) {
|
||||
case Tegra::Texture::TextureType::TextureCubeArray:
|
||||
return Shader::TextureType::ColorArrayCube;
|
||||
default:
|
||||
throw Shader::NotImplementedException("Unknown texture type");
|
||||
UNIMPLEMENTED();
|
||||
return Shader::TextureType::Color2D;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1089,8 +1089,8 @@ QStringList GRenderWindow::GetUnsupportedGLExtensions() const {
|
||||
}
|
||||
|
||||
if (!unsupported_ext.empty()) {
|
||||
LOG_ERROR(Frontend, "GPU does not support all required extensions: {}",
|
||||
glGetString(GL_RENDERER));
|
||||
const std::string gl_renderer{reinterpret_cast<const char*>(glGetString(GL_RENDERER))};
|
||||
LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", gl_renderer);
|
||||
}
|
||||
for (const QString& ext : unsupported_ext) {
|
||||
LOG_ERROR(Frontend, "Unsupported GL extension: {}", ext.toStdString());
|
||||
|
||||
@@ -3338,7 +3338,8 @@ void GMainWindow::MigrateConfigFiles() {
|
||||
}
|
||||
const auto origin = config_dir_fs_path / filename;
|
||||
const auto destination = config_dir_fs_path / "custom" / filename;
|
||||
LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination);
|
||||
LOG_INFO(Frontend, "Migrating config file from {} to {}", origin.string(),
|
||||
destination.string());
|
||||
if (!Common::FS::RenameFile(origin, destination)) {
|
||||
// Delete the old config file if one already exists in the new location.
|
||||
Common::FS::RemoveFile(origin);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
|
||||
"name": "yuzu",
|
||||
"builtin-baseline": "cef0b3ec767df6e83806899fe9525f6cf8d7bc91",
|
||||
"builtin-baseline": "9b22b40c6c61bf0da2d46346dd44a11e90972cc9",
|
||||
"version": "1.0",
|
||||
"dependencies": [
|
||||
"boost-algorithm",
|
||||
@@ -37,6 +37,10 @@
|
||||
{
|
||||
"name": "catch2",
|
||||
"version": "2.13.9"
|
||||
},
|
||||
{
|
||||
"name": "fmt",
|
||||
"version": "9.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user