early-access version 1690
This commit is contained in:
parent
57e7aafeca
commit
23d1664dc2
@ -1,7 +1,7 @@
|
|||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1689.
|
This is the source code for early-access 1690.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
@ -289,7 +289,8 @@ struct System::Impl {
|
|||||||
|
|
||||||
telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
|
telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
|
||||||
perf_results.emulation_speed * 100.0);
|
perf_results.emulation_speed * 100.0);
|
||||||
telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps);
|
telemetry_session->AddField(performance, "Shutdown_Framerate",
|
||||||
|
perf_results.average_game_fps);
|
||||||
telemetry_session->AddField(performance, "Shutdown_Frametime",
|
telemetry_session->AddField(performance, "Shutdown_Frametime",
|
||||||
perf_results.frametime * 1000.0);
|
perf_results.frametime * 1000.0);
|
||||||
telemetry_session->AddField(performance, "Mean_Frametime_MS",
|
telemetry_session->AddField(performance, "Mean_Frametime_MS",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "core/file_sys/card_image.h"
|
#include "core/file_sys/card_image.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "core/file_sys/nca_metadata.h"
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "core/file_sys/registered_cache.h"
|
||||||
@ -592,6 +593,12 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
|
|||||||
const CNMT cnmt(cnmt_file);
|
const CNMT cnmt(cnmt_file);
|
||||||
|
|
||||||
const auto title_id = cnmt.GetTitleID();
|
const auto title_id = cnmt.GetTitleID();
|
||||||
|
const auto version = cnmt.GetTitleVersion();
|
||||||
|
|
||||||
|
if (title_id == GetBaseTitleID(title_id) && version == 0) {
|
||||||
|
return InstallResult::ErrorBaseInstall;
|
||||||
|
}
|
||||||
|
|
||||||
const auto result = RemoveExistingEntry(title_id);
|
const auto result = RemoveExistingEntry(title_id);
|
||||||
|
|
||||||
// Install Metadata File
|
// Install Metadata File
|
||||||
|
@ -38,6 +38,7 @@ enum class InstallResult {
|
|||||||
ErrorAlreadyExists,
|
ErrorAlreadyExists,
|
||||||
ErrorCopyFailed,
|
ErrorCopyFailed,
|
||||||
ErrorMetaFailed,
|
ErrorMetaFailed,
|
||||||
|
ErrorBaseInstall,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContentProviderEntry {
|
struct ContentProviderEntry {
|
||||||
|
@ -52,7 +52,6 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
|
|||||||
addr, offset, width, height, stride, static_cast<PixelFormat>(format),
|
addr, offset, width, height, stride, static_cast<PixelFormat>(format),
|
||||||
transform, crop_rect};
|
transform, crop_rect};
|
||||||
|
|
||||||
system.GetPerfStats().EndGameFrame();
|
|
||||||
system.GetPerfStats().EndSystemFrame();
|
system.GetPerfStats().EndSystemFrame();
|
||||||
system.GPU().SwapBuffers(&framebuffer);
|
system.GPU().SwapBuffers(&framebuffer);
|
||||||
system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());
|
system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());
|
||||||
|
@ -76,9 +76,7 @@ void PerfStats::EndSystemFrame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PerfStats::EndGameFrame() {
|
void PerfStats::EndGameFrame() {
|
||||||
std::lock_guard lock{object_mutex};
|
game_frames.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
game_frames += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double PerfStats::GetMeanFrametime() const {
|
double PerfStats::GetMeanFrametime() const {
|
||||||
@ -101,10 +99,11 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us
|
|||||||
const auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
|
const auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
|
||||||
|
|
||||||
const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval;
|
const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval;
|
||||||
|
const auto current_frames = static_cast<double>(game_frames.load(std::memory_order_relaxed));
|
||||||
|
const auto current_fps = current_frames / interval;
|
||||||
const PerfStatsResults results{
|
const PerfStatsResults results{
|
||||||
.system_fps = static_cast<double>(system_frames) / interval,
|
.system_fps = static_cast<double>(system_frames) / interval,
|
||||||
.game_fps = static_cast<double>(game_frames) / interval,
|
.average_game_fps = (current_fps + previous_fps) / 2.0,
|
||||||
.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
|
.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
|
||||||
static_cast<double>(system_frames),
|
static_cast<double>(system_frames),
|
||||||
.emulation_speed = system_us_per_second.count() / 1'000'000.0,
|
.emulation_speed = system_us_per_second.count() / 1'000'000.0,
|
||||||
@ -115,7 +114,8 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us
|
|||||||
reset_point_system_us = current_system_time_us;
|
reset_point_system_us = current_system_time_us;
|
||||||
accumulated_frametime = Clock::duration::zero();
|
accumulated_frametime = Clock::duration::zero();
|
||||||
system_frames = 0;
|
system_frames = 0;
|
||||||
game_frames = 0;
|
game_frames.store(0, std::memory_order_relaxed);
|
||||||
|
previous_fps = current_fps;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -15,8 +16,8 @@ namespace Core {
|
|||||||
struct PerfStatsResults {
|
struct PerfStatsResults {
|
||||||
/// System FPS (LCD VBlanks) in Hz
|
/// System FPS (LCD VBlanks) in Hz
|
||||||
double system_fps;
|
double system_fps;
|
||||||
/// Game FPS (GSP frame submissions) in Hz
|
/// Average game FPS (GPU frame renders) in Hz
|
||||||
double game_fps;
|
double average_game_fps;
|
||||||
/// Walltime per system frame, in seconds, excluding any waits
|
/// Walltime per system frame, in seconds, excluding any waits
|
||||||
double frametime;
|
double frametime;
|
||||||
/// Ratio of walltime / emulated time elapsed
|
/// Ratio of walltime / emulated time elapsed
|
||||||
@ -72,7 +73,7 @@ private:
|
|||||||
/// Cumulative number of system frames (LCD VBlanks) presented since last reset
|
/// Cumulative number of system frames (LCD VBlanks) presented since last reset
|
||||||
u32 system_frames = 0;
|
u32 system_frames = 0;
|
||||||
/// Cumulative number of game frames (GSP frame submissions) since last reset
|
/// Cumulative number of game frames (GSP frame submissions) since last reset
|
||||||
u32 game_frames = 0;
|
std::atomic<u32> game_frames = 0;
|
||||||
|
|
||||||
/// Point when the previous system frame ended
|
/// Point when the previous system frame ended
|
||||||
Clock::time_point previous_frame_end = reset_point;
|
Clock::time_point previous_frame_end = reset_point;
|
||||||
@ -80,6 +81,8 @@ private:
|
|||||||
Clock::time_point frame_begin = reset_point;
|
Clock::time_point frame_begin = reset_point;
|
||||||
/// Total visible duration (including frame-limiting, etc.) of the previous system frame
|
/// Total visible duration (including frame-limiting, etc.) of the previous system frame
|
||||||
Clock::duration previous_frame_length = Clock::duration::zero();
|
Clock::duration previous_frame_length = Clock::duration::zero();
|
||||||
|
/// Previously computed fps
|
||||||
|
double previous_fps = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameLimiter {
|
class FrameLimiter {
|
||||||
|
@ -690,7 +690,10 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||||||
const VAddr cpu_addr = binding.cpu_addr;
|
const VAddr cpu_addr = binding.cpu_addr;
|
||||||
const u32 size = binding.size;
|
const u32 size = binding.size;
|
||||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
if (size <= uniform_buffer_skip_cache_size && !buffer.IsRegionGpuModified(cpu_addr, size)) {
|
const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID &&
|
||||||
|
size <= uniform_buffer_skip_cache_size &&
|
||||||
|
!buffer.IsRegionGpuModified(cpu_addr, size);
|
||||||
|
if (use_fast_buffer) {
|
||||||
if constexpr (IS_OPENGL) {
|
if constexpr (IS_OPENGL) {
|
||||||
if (runtime.HasFastBufferSubData()) {
|
if (runtime.HasFastBufferSubData()) {
|
||||||
// Fast path for Nvidia
|
// Fast path for Nvidia
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "core/hardware_interrupt_manager.h"
|
#include "core/hardware_interrupt_manager.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
#include "core/perf_stats.h"
|
||||||
#include "video_core/engines/fermi_2d.h"
|
#include "video_core/engines/fermi_2d.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/kepler_memory.h"
|
#include "video_core/engines/kepler_memory.h"
|
||||||
@ -191,6 +192,10 @@ u64 GPU::GetTicks() const {
|
|||||||
return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den;
|
return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU::RendererFrameEndNotify() {
|
||||||
|
system.GetPerfStats().EndGameFrame();
|
||||||
|
}
|
||||||
|
|
||||||
void GPU::FlushCommands() {
|
void GPU::FlushCommands() {
|
||||||
rasterizer->FlushCommands();
|
rasterizer->FlushCommands();
|
||||||
}
|
}
|
||||||
|
@ -247,6 +247,8 @@ public:
|
|||||||
return use_nvdec;
|
return use_nvdec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererFrameEndNotify();
|
||||||
|
|
||||||
enum class FenceOperation : u32 {
|
enum class FenceOperation : u32 {
|
||||||
Acquire = 0,
|
Acquire = 0,
|
||||||
Increment = 1,
|
Increment = 1,
|
||||||
|
@ -155,6 +155,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
|||||||
|
|
||||||
++m_current_frame;
|
++m_current_frame;
|
||||||
|
|
||||||
|
gpu.RendererFrameEndNotify();
|
||||||
rasterizer.TickFrame();
|
rasterizer.TickFrame();
|
||||||
|
|
||||||
context->SwapBuffers();
|
context->SwapBuffers();
|
||||||
|
@ -154,6 +154,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
|||||||
if (swapchain.Present(render_semaphore)) {
|
if (swapchain.Present(render_semaphore)) {
|
||||||
blit_screen.Recreate();
|
blit_screen.Recreate();
|
||||||
}
|
}
|
||||||
|
gpu.RendererFrameEndNotify();
|
||||||
rasterizer.TickFrame();
|
rasterizer.TickFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,7 +1367,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
|
|||||||
game_list->hide();
|
game_list->hide();
|
||||||
game_list_placeholder->hide();
|
game_list_placeholder->hide();
|
||||||
}
|
}
|
||||||
status_bar_update_timer.start(2000);
|
status_bar_update_timer.start(500);
|
||||||
async_status_button->setDisabled(true);
|
async_status_button->setDisabled(true);
|
||||||
multicore_status_button->setDisabled(true);
|
multicore_status_button->setDisabled(true);
|
||||||
renderer_status_button->setDisabled(true);
|
renderer_status_button->setDisabled(true);
|
||||||
@ -2098,6 +2098,7 @@ void GMainWindow::OnMenuInstallToNAND() {
|
|||||||
QStringList new_files{}; // Newly installed files that do not yet exist in the NAND
|
QStringList new_files{}; // Newly installed files that do not yet exist in the NAND
|
||||||
QStringList overwritten_files{}; // Files that overwrote those existing in the NAND
|
QStringList overwritten_files{}; // Files that overwrote those existing in the NAND
|
||||||
QStringList failed_files{}; // Files that failed to install due to errors
|
QStringList failed_files{}; // Files that failed to install due to errors
|
||||||
|
bool detected_base_install{}; // Whether a base game was attempted to be installed
|
||||||
|
|
||||||
ui.action_Install_File_NAND->setEnabled(false);
|
ui.action_Install_File_NAND->setEnabled(false);
|
||||||
|
|
||||||
@ -2123,6 +2124,7 @@ void GMainWindow::OnMenuInstallToNAND() {
|
|||||||
|
|
||||||
while (!future.isFinished()) {
|
while (!future.isFinished()) {
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = future.result();
|
result = future.result();
|
||||||
@ -2143,6 +2145,10 @@ void GMainWindow::OnMenuInstallToNAND() {
|
|||||||
case InstallResult::Failure:
|
case InstallResult::Failure:
|
||||||
failed_files.append(QFileInfo(file).fileName());
|
failed_files.append(QFileInfo(file).fileName());
|
||||||
break;
|
break;
|
||||||
|
case InstallResult::BaseInstallAttempted:
|
||||||
|
failed_files.append(QFileInfo(file).fileName());
|
||||||
|
detected_base_install = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
--remaining;
|
--remaining;
|
||||||
@ -2150,6 +2156,13 @@ void GMainWindow::OnMenuInstallToNAND() {
|
|||||||
|
|
||||||
install_progress->close();
|
install_progress->close();
|
||||||
|
|
||||||
|
if (detected_base_install) {
|
||||||
|
QMessageBox::warning(
|
||||||
|
this, tr("Install Results"),
|
||||||
|
tr("To avoid possible conflicts, we discourage users from installing base games to the "
|
||||||
|
"NAND.\nPlease, only use this feature to install updates and DLC."));
|
||||||
|
}
|
||||||
|
|
||||||
const QString install_results =
|
const QString install_results =
|
||||||
(new_files.isEmpty() ? QString{}
|
(new_files.isEmpty() ? QString{}
|
||||||
: tr("%n file(s) were newly installed\n", "", new_files.size())) +
|
: tr("%n file(s) were newly installed\n", "", new_files.size())) +
|
||||||
@ -2211,11 +2224,14 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) {
|
|||||||
const auto res =
|
const auto res =
|
||||||
Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry(
|
Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry(
|
||||||
*nsp, true, qt_raw_copy);
|
*nsp, true, qt_raw_copy);
|
||||||
if (res == FileSys::InstallResult::Success) {
|
switch (res) {
|
||||||
|
case FileSys::InstallResult::Success:
|
||||||
return InstallResult::Success;
|
return InstallResult::Success;
|
||||||
} else if (res == FileSys::InstallResult::OverwriteExisting) {
|
case FileSys::InstallResult::OverwriteExisting:
|
||||||
return InstallResult::Overwrite;
|
return InstallResult::Overwrite;
|
||||||
} else {
|
case FileSys::InstallResult::ErrorBaseInstall:
|
||||||
|
return InstallResult::BaseInstallAttempted;
|
||||||
|
default:
|
||||||
return InstallResult::Failure;
|
return InstallResult::Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2792,7 +2808,7 @@ void GMainWindow::UpdateStatusBar() {
|
|||||||
} else {
|
} else {
|
||||||
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
||||||
}
|
}
|
||||||
game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0));
|
game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0));
|
||||||
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
|
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
|
||||||
|
|
||||||
emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
|
emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
|
||||||
|
@ -76,6 +76,7 @@ enum class InstallResult {
|
|||||||
Success,
|
Success,
|
||||||
Overwrite,
|
Overwrite,
|
||||||
Failure,
|
Failure,
|
||||||
|
BaseInstallAttempted,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ReinitializeKeyBehavior {
|
enum class ReinitializeKeyBehavior {
|
||||||
|
@ -215,7 +215,7 @@ void EmuWindow_SDL2::WaitEvent() {
|
|||||||
const auto results = Core::System::GetInstance().GetAndResetPerfStats();
|
const auto results = Core::System::GetInstance().GetAndResetPerfStats();
|
||||||
const auto title =
|
const auto title =
|
||||||
fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname,
|
fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname,
|
||||||
Common::g_scm_branch, Common::g_scm_desc, results.game_fps,
|
Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps,
|
||||||
results.emulation_speed * 100.0);
|
results.emulation_speed * 100.0);
|
||||||
SDL_SetWindowTitle(render_window, title.c_str());
|
SDL_SetWindowTitle(render_window, title.c_str());
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
|
Loading…
Reference in New Issue
Block a user