mirror of
https://github.com/azahar-emu/azahar.git
synced 2025-04-28 13:47:59 +03:00
Allow shader cache to switch to different titles at runtime (#978)
This commit is contained in:
parent
975ad17442
commit
939a6e0f7a
19 changed files with 205 additions and 67 deletions
|
@ -215,7 +215,8 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
|||
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||
|
||||
std::unique_ptr<Frontend::GraphicsContext> cpu_context;
|
||||
system.GPU().Renderer().Rasterizer()->LoadDiskResources(stop_run, &LoadDiskCacheProgress);
|
||||
system.GPU().Renderer().Rasterizer()->LoadDefaultDiskResources(stop_run,
|
||||
&LoadDiskCacheProgress);
|
||||
|
||||
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
|
||||
|
||||
|
|
|
@ -72,9 +72,14 @@ void EmuThread::run() {
|
|||
std::size_t total) { emit LoadProgress(stage, value, total); });
|
||||
}
|
||||
|
||||
system.GPU().Renderer().Rasterizer()->SetSwitchDiskResourcesCallback(
|
||||
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
||||
emit SwitchDiskResources(stage, value, total);
|
||||
});
|
||||
|
||||
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||
|
||||
system.GPU().Renderer().Rasterizer()->LoadDiskResources(
|
||||
system.GPU().Renderer().Rasterizer()->LoadDefaultDiskResources(
|
||||
stop_run, [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
||||
emit LoadProgress(stage, value, total);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -110,6 +110,9 @@ signals:
|
|||
|
||||
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
|
||||
|
||||
void SwitchDiskResources(VideoCore::LoadCallbackStage stage, std::size_t value,
|
||||
std::size_t total);
|
||||
|
||||
void HideLoadingScreen();
|
||||
};
|
||||
|
||||
|
|
|
@ -500,6 +500,8 @@ void GMainWindow::InitializeWidgets() {
|
|||
progress_bar->hide();
|
||||
statusBar()->addPermanentWidget(progress_bar);
|
||||
|
||||
loading_shaders_label = new QLabel();
|
||||
|
||||
artic_traffic_label = new QLabel();
|
||||
artic_traffic_label->setToolTip(
|
||||
tr("Current Artic traffic speed. Higher values indicate bigger transfer loads."));
|
||||
|
@ -515,8 +517,8 @@ void GMainWindow::InitializeWidgets() {
|
|||
tr("Time taken to emulate a 3DS frame, not counting framelimiting or v-sync. For "
|
||||
"full-speed emulation this should be at most 16.67 ms."));
|
||||
|
||||
for (auto& label :
|
||||
{artic_traffic_label, emu_speed_label, game_fps_label, emu_frametime_label}) {
|
||||
for (auto& label : {loading_shaders_label, artic_traffic_label, emu_speed_label, game_fps_label,
|
||||
emu_frametime_label}) {
|
||||
label->setVisible(false);
|
||||
label->setFrameStyle(QFrame::NoFrame);
|
||||
label->setContentsMargins(4, 0, 4, 0);
|
||||
|
@ -1430,6 +1432,8 @@ void GMainWindow::BootGame(const QString& filename) {
|
|||
|
||||
connect(emu_thread.get(), &EmuThread::LoadProgress, loading_screen,
|
||||
&LoadingScreen::OnLoadProgress, Qt::QueuedConnection);
|
||||
connect(emu_thread.get(), &EmuThread::SwitchDiskResources, this,
|
||||
&GMainWindow::OnSwitchDiskResources, Qt::QueuedConnection);
|
||||
connect(emu_thread.get(), &EmuThread::HideLoadingScreen, loading_screen,
|
||||
&LoadingScreen::OnLoadComplete);
|
||||
|
||||
|
@ -1529,6 +1533,7 @@ void GMainWindow::ShutdownGame() {
|
|||
status_bar_update_timer.stop();
|
||||
message_label_used_for_movie = false;
|
||||
show_artic_label = false;
|
||||
loading_shaders_label->setVisible(false);
|
||||
artic_traffic_label->setVisible(false);
|
||||
emu_speed_label->setVisible(false);
|
||||
game_fps_label->setVisible(false);
|
||||
|
@ -3711,6 +3716,18 @@ void GMainWindow::OnEmulatorUpdateAvailable() {
|
|||
}
|
||||
#endif
|
||||
|
||||
void GMainWindow::OnSwitchDiskResources(VideoCore::LoadCallbackStage stage, std::size_t value,
|
||||
std::size_t total) {
|
||||
if (stage == VideoCore::LoadCallbackStage::Prepare) {
|
||||
loading_shaders_label->setText(QString());
|
||||
loading_shaders_label->setVisible(true);
|
||||
} else if (stage == VideoCore::LoadCallbackStage::Complete) {
|
||||
loading_shaders_label->setVisible(false);
|
||||
} else {
|
||||
loading_shaders_label->setText(loading_screen->GetStageTranslation(stage, value, total));
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateWindowTitle() {
|
||||
const QString full_name = QString::fromUtf8(Common::g_build_fullname);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "citra_qt/user_data_migration.h"
|
||||
#include "core/core.h"
|
||||
#include "core/savestate.h"
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
|
||||
// Needs to be included at the end due to https://bugreports.qt.io/browse/QTBUG-73263
|
||||
#include <filesystem>
|
||||
|
@ -299,6 +300,8 @@ private slots:
|
|||
#ifdef ENABLE_QT_UPDATE_CHECKER
|
||||
void OnEmulatorUpdateAvailable();
|
||||
#endif
|
||||
void OnSwitchDiskResources(VideoCore::LoadCallbackStage stage, std::size_t value,
|
||||
std::size_t total);
|
||||
|
||||
private:
|
||||
Q_INVOKABLE void OnMoviePlaybackCompleted();
|
||||
|
@ -334,6 +337,7 @@ private:
|
|||
QProgressBar* progress_bar = nullptr;
|
||||
QLabel* message_label = nullptr;
|
||||
bool show_artic_label = false;
|
||||
QLabel* loading_shaders_label = nullptr;
|
||||
QLabel* artic_traffic_label = nullptr;
|
||||
QLabel* emu_speed_label = nullptr;
|
||||
QLabel* game_fps_label = nullptr;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -184,14 +184,7 @@ void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size
|
|||
}
|
||||
|
||||
// update labels and progress bar
|
||||
const auto& stg = tr(stage_translations.at(stage));
|
||||
if (stage == VideoCore::LoadCallbackStage::Decompile ||
|
||||
stage == VideoCore::LoadCallbackStage::Build ||
|
||||
stage == VideoCore::LoadCallbackStage::Preload) {
|
||||
ui->stage->setText(stg.arg(value).arg(total));
|
||||
} else {
|
||||
ui->stage->setText(stg);
|
||||
}
|
||||
ui->stage->setText(GetStageTranslation(stage, value, total));
|
||||
ui->value->setText(estimate);
|
||||
ui->progress_bar->setValue(static_cast<int>(value));
|
||||
previous_time = now;
|
||||
|
@ -205,4 +198,16 @@ void LoadingScreen::paintEvent(QPaintEvent* event) {
|
|||
QWidget::paintEvent(event);
|
||||
}
|
||||
|
||||
QString LoadingScreen::GetStageTranslation(VideoCore::LoadCallbackStage stage, std::size_t value,
|
||||
std::size_t total) {
|
||||
const auto& stg = tr(stage_translations.at(stage));
|
||||
if (stage == VideoCore::LoadCallbackStage::Decompile ||
|
||||
stage == VideoCore::LoadCallbackStage::Build ||
|
||||
stage == VideoCore::LoadCallbackStage::Preload) {
|
||||
return stg.arg(value).arg(total);
|
||||
} else {
|
||||
return stg;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadingScreen::Clear() {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -49,6 +49,9 @@ public:
|
|||
// See https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
QString GetStageTranslation(VideoCore::LoadCallbackStage stage, std::size_t value,
|
||||
std::size_t total);
|
||||
|
||||
signals:
|
||||
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
|
||||
/// Signals that this widget is completely hidden now and should be replaced with the other
|
||||
|
|
|
@ -509,9 +509,7 @@ Result CIAFile::WriteTitleMetadata(std::span<const u8> tmd_data, std::size_t off
|
|||
return FileSys::ResultFileNotFound;
|
||||
}
|
||||
|
||||
PrepareToImportContent(tmd);
|
||||
|
||||
return ResultSuccess;
|
||||
return PrepareToImportContent(tmd);
|
||||
}
|
||||
|
||||
ResultVal<std::size_t> CIAFile::WriteContentData(u64 offset, std::size_t length, const u8* buffer) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "video_core/gpu.h"
|
||||
#include "video_core/gpu_debugger.h"
|
||||
#include "video_core/pica/regs_lcd.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/right_eye_disabler.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::GSP::SessionData)
|
||||
|
@ -613,6 +614,8 @@ Result GSP_GPU::AcquireGpuRight(const Kernel::HLERequestContext& ctx,
|
|||
ErrorLevel::Success};
|
||||
}
|
||||
|
||||
gpu.Renderer().Rasterizer()->SwitchDiskResources(process->codeset->program_id);
|
||||
|
||||
if (blocking) {
|
||||
// TODO: The thread should be put to sleep until acquired.
|
||||
ASSERT_MSG(active_thread_id == std::numeric_limits<u32>::max(),
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
namespace VideoCore {
|
||||
|
||||
DiskResourceLoadCallback RasterizerInterface::switch_disk_resources_callback{};
|
||||
|
||||
using Pica::f24;
|
||||
|
||||
static Common::Vec4f ColorRGBA8(const u32 color) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -78,8 +78,15 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual void LoadDiskResources([[maybe_unused]] const std::atomic_bool& stop_loading,
|
||||
[[maybe_unused]] const DiskResourceLoadCallback& callback) {}
|
||||
virtual void LoadDefaultDiskResources(
|
||||
[[maybe_unused]] const std::atomic_bool& stop_loading,
|
||||
[[maybe_unused]] const DiskResourceLoadCallback& callback) {}
|
||||
|
||||
virtual void SwitchDiskResources([[maybe_unused]] u64 title_id) {}
|
||||
|
||||
static void SetSwitchDiskResourcesCallback(const DiskResourceLoadCallback& callback) {
|
||||
switch_disk_resources_callback = callback;
|
||||
}
|
||||
|
||||
virtual void SyncEntireState() {}
|
||||
|
||||
|
@ -89,5 +96,9 @@ public:
|
|||
|
||||
protected:
|
||||
bool accurate_mul = false;
|
||||
|
||||
// Rasterizer gets destroyed on reboot, so make the callback
|
||||
// static until a better solution is found.
|
||||
static DiskResourceLoadCallback switch_disk_resources_callback;
|
||||
};
|
||||
} // namespace VideoCore
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "common/logging/log.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "video_core/pica/pica_core.h"
|
||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||
#include "video_core/renderer_opengl/pica_to_gl.h"
|
||||
|
@ -84,8 +85,8 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, Pica::PicaCore&
|
|||
VideoCore::CustomTexManager& custom_tex_manager,
|
||||
VideoCore::RendererBase& renderer, Driver& driver_)
|
||||
: VideoCore::RasterizerAccelerated{memory, pica}, driver{driver_},
|
||||
shader_manager{renderer.GetRenderWindow(), driver, !driver.IsOpenGLES()},
|
||||
runtime{driver, renderer}, res_cache{memory, custom_tex_manager, runtime, regs, renderer},
|
||||
render_window{renderer.GetRenderWindow()}, runtime{driver, renderer},
|
||||
res_cache{memory, custom_tex_manager, runtime, regs, renderer},
|
||||
vertex_buffer{driver, GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE},
|
||||
uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE},
|
||||
index_buffer{driver, GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE},
|
||||
|
@ -173,9 +174,86 @@ void RasterizerOpenGL::TickFrame() {
|
|||
res_cache.TickFrame();
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) {
|
||||
shader_manager.LoadDiskCache(stop_loading, callback, accurate_mul);
|
||||
void RasterizerOpenGL::LoadDefaultDiskResources(
|
||||
const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) {
|
||||
// First element in vector is the default one and cannot be removed.
|
||||
u64 program_id;
|
||||
if (Core::System::GetInstance().GetAppLoader().ReadProgramId(program_id) !=
|
||||
Loader::ResultStatus::Success) {
|
||||
program_id = 0;
|
||||
}
|
||||
|
||||
shader_managers.clear();
|
||||
curr_shader_manager = shader_managers.emplace_back(std::make_shared<ShaderProgramManager>(
|
||||
render_window, driver, program_id, !driver.IsOpenGLES()));
|
||||
|
||||
curr_shader_manager->LoadDiskCache(stop_loading, callback, accurate_mul);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SwitchDiskResources(u64 title_id) {
|
||||
// NOTE: curr_shader_manager can be null if emulation restarted without calling
|
||||
// LoadDefaultDiskResources
|
||||
|
||||
// Check if the current manager is for the specified TID.
|
||||
if (curr_shader_manager && curr_shader_manager->GetProgramID() == title_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for an existing manager
|
||||
size_t new_pos = 0;
|
||||
for (new_pos = 0; new_pos < shader_managers.size(); new_pos++) {
|
||||
if (shader_managers[new_pos]->GetProgramID() == title_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Manager does not exist, create it and append to the end
|
||||
if (new_pos >= shader_managers.size()) {
|
||||
new_pos = shader_managers.size();
|
||||
auto& new_manager = shader_managers.emplace_back(std::make_shared<ShaderProgramManager>(
|
||||
render_window, driver, title_id, !driver.IsOpenGLES()));
|
||||
|
||||
if (switch_disk_resources_callback) {
|
||||
switch_disk_resources_callback(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||
}
|
||||
|
||||
std::atomic_bool stop_loading;
|
||||
new_manager->LoadDiskCache(stop_loading, switch_disk_resources_callback, accurate_mul);
|
||||
|
||||
if (switch_disk_resources_callback) {
|
||||
switch_disk_resources_callback(VideoCore::LoadCallbackStage::Complete, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
auto is_applet = [](u64 tid) {
|
||||
constexpr u32 APPLET_TID_HIGH = 0x00040030;
|
||||
return static_cast<u32>(tid >> 32) == APPLET_TID_HIGH;
|
||||
};
|
||||
|
||||
bool prev_applet = curr_shader_manager ? is_applet(curr_shader_manager->GetProgramID()) : false;
|
||||
bool new_applet = is_applet(shader_managers[new_pos]->GetProgramID());
|
||||
curr_shader_manager = shader_managers[new_pos];
|
||||
|
||||
if (prev_applet) {
|
||||
// If we came from an applet, clean up all other applets
|
||||
for (auto it = shader_managers.begin(); it != shader_managers.end();) {
|
||||
if (it == shader_managers.begin() || *it == curr_shader_manager ||
|
||||
!is_applet((*it)->GetProgramID())) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
it = shader_managers.erase(it);
|
||||
}
|
||||
}
|
||||
if (!new_applet) {
|
||||
// If we are going into a non-applet, clean up everything
|
||||
for (auto it = shader_managers.begin(); it != shader_managers.end();) {
|
||||
if (it == shader_managers.begin() || *it == curr_shader_manager) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
it = shader_managers.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncFixedState() {
|
||||
|
@ -271,7 +349,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset,
|
|||
|
||||
bool RasterizerOpenGL::SetupVertexShader() {
|
||||
MICROPROFILE_SCOPE(OpenGL_VS);
|
||||
return shader_manager.UseProgrammableVertexShader(regs, pica.vs_setup, accurate_mul);
|
||||
return curr_shader_manager->UseProgrammableVertexShader(regs, pica.vs_setup, accurate_mul);
|
||||
}
|
||||
|
||||
bool RasterizerOpenGL::SetupGeometryShader() {
|
||||
|
@ -286,9 +364,9 @@ bool RasterizerOpenGL::SetupGeometryShader() {
|
|||
// lighting and care about proper quaternions. Otherwise just use standard vertex+fragment
|
||||
// shaders
|
||||
if (regs.lighting.disable) {
|
||||
shader_manager.UseTrivialGeometryShader();
|
||||
curr_shader_manager->UseTrivialGeometryShader();
|
||||
} else {
|
||||
shader_manager.UseFixedGeometryShader(regs);
|
||||
curr_shader_manager->UseFixedGeometryShader(regs);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -333,7 +411,7 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) {
|
|||
SetupVertexArray(buffer_ptr, buffer_offset, vs_input_index_min, vs_input_index_max);
|
||||
vertex_buffer.Unmap(vs_input_size);
|
||||
|
||||
shader_manager.ApplyTo(state, accurate_mul);
|
||||
curr_shader_manager->ApplyTo(state, accurate_mul);
|
||||
state.Apply();
|
||||
|
||||
if (is_indexed) {
|
||||
|
@ -444,7 +522,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
|||
|
||||
// Sync and bind the shader
|
||||
if (shader_dirty) {
|
||||
shader_manager.UseFragmentShader(regs, user_config);
|
||||
curr_shader_manager->UseFragmentShader(regs, user_config);
|
||||
shader_dirty = false;
|
||||
}
|
||||
|
||||
|
@ -462,9 +540,9 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
|||
} else {
|
||||
state.draw.vertex_array = sw_vao.handle;
|
||||
state.draw.vertex_buffer = vertex_buffer.GetHandle();
|
||||
shader_manager.UseTrivialVertexShader();
|
||||
shader_manager.UseTrivialGeometryShader();
|
||||
shader_manager.ApplyTo(state, accurate_mul);
|
||||
curr_shader_manager->UseTrivialVertexShader();
|
||||
curr_shader_manager->UseTrivialGeometryShader();
|
||||
curr_shader_manager->ApplyTo(state, accurate_mul);
|
||||
state.Apply();
|
||||
|
||||
std::size_t max_vertices = 3 * (VERTEX_BUFFER_SIZE / (3 * sizeof(HardwareVertex)));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2022 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -40,8 +40,9 @@ public:
|
|||
~RasterizerOpenGL() override;
|
||||
|
||||
void TickFrame();
|
||||
void LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||
void LoadDefaultDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||
void SwitchDiskResources(u64 title_id) override;
|
||||
|
||||
void DrawTriangles() override;
|
||||
void FlushAll() override;
|
||||
|
@ -137,7 +138,9 @@ private:
|
|||
private:
|
||||
Driver& driver;
|
||||
OpenGLState state;
|
||||
ShaderProgramManager shader_manager;
|
||||
Frontend::EmuWindow& render_window;
|
||||
std::vector<std::shared_ptr<ShaderProgramManager>> shader_managers;
|
||||
std::shared_ptr<ShaderProgramManager> curr_shader_manager{};
|
||||
TextureRuntime runtime;
|
||||
RasterizerCache res_cache;
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
@ -12,8 +16,6 @@
|
|||
#include "common/scm_rev.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/zstd_compression.h"
|
||||
#include "core/core.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
@ -103,8 +105,8 @@ bool ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
ShaderDiskCache::ShaderDiskCache(bool separable)
|
||||
: separable{separable}, transferable_file(AppendTransferableFile()),
|
||||
ShaderDiskCache::ShaderDiskCache(u64 program_id, bool separable)
|
||||
: separable{separable}, program_id{program_id}, transferable_file(AppendTransferableFile()),
|
||||
// seperable shaders use the virtual precompile file, that already has a header.
|
||||
precompiled_file(AppendPrecompiledFile(!separable)) {}
|
||||
|
||||
|
@ -568,15 +570,7 @@ std::string ShaderDiskCache::GetBaseDir() const {
|
|||
return FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir) + DIR_SEP "opengl";
|
||||
}
|
||||
|
||||
u64 ShaderDiskCache::GetProgramID() {
|
||||
// Skip games without title id
|
||||
if (program_id != 0) {
|
||||
return program_id;
|
||||
}
|
||||
if (Core::System::GetInstance().GetAppLoader().ReadProgramId(program_id) !=
|
||||
Loader::ResultStatus::Success) {
|
||||
return 0;
|
||||
}
|
||||
u64 ShaderDiskCache::GetProgramID() const {
|
||||
return program_id;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
@ -83,7 +87,7 @@ struct ShaderDiskCacheDump {
|
|||
|
||||
class ShaderDiskCache {
|
||||
public:
|
||||
explicit ShaderDiskCache(bool separable);
|
||||
explicit ShaderDiskCache(u64 title_id, bool separable);
|
||||
~ShaderDiskCache() = default;
|
||||
|
||||
/// Loads transferable cache. If file has a old version or on failure, it deletes the file.
|
||||
|
@ -113,6 +117,9 @@ public:
|
|||
/// Serializes virtual precompiled shader cache file to real file
|
||||
void SaveVirtualPrecompiledFile();
|
||||
|
||||
/// Get current game's title id as u64
|
||||
u64 GetProgramID() const;
|
||||
|
||||
private:
|
||||
/// Loads the transferable cache. Returns empty on failure.
|
||||
std::optional<std::pair<ShaderDecompiledMap, ShaderDumpsMap>> LoadPrecompiledFile(
|
||||
|
@ -161,9 +168,6 @@ private:
|
|||
/// Get user's shader directory path
|
||||
std::string GetBaseDir() const;
|
||||
|
||||
/// Get current game's title id as u64
|
||||
u64 GetProgramID();
|
||||
|
||||
/// Get current game's title id
|
||||
std::string GetTitleID();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2022 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -259,10 +259,10 @@ using FragmentShaders = ShaderCache<FSConfig, &GLSL::GenerateFragmentShader, GL_
|
|||
|
||||
class ShaderProgramManager::Impl {
|
||||
public:
|
||||
explicit Impl(const Driver& driver, bool separable)
|
||||
explicit Impl(const Driver& driver, u64 title_id, bool separable)
|
||||
: separable(separable), programmable_vertex_shaders(separable),
|
||||
trivial_vertex_shader(driver, separable), fixed_geometry_shaders(separable),
|
||||
fragment_shaders(separable), disk_cache(separable) {
|
||||
fragment_shaders(separable), disk_cache(title_id, separable) {
|
||||
if (separable) {
|
||||
pipeline.Create();
|
||||
}
|
||||
|
@ -329,10 +329,10 @@ public:
|
|||
};
|
||||
|
||||
ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, const Driver& driver_,
|
||||
bool separable)
|
||||
u64 title_id, bool separable)
|
||||
: emu_window{emu_window_}, driver{driver_},
|
||||
strict_context_required{emu_window.StrictContextRequired()},
|
||||
impl{std::make_unique<Impl>(driver_, separable)} {}
|
||||
impl{std::make_unique<Impl>(driver_, title_id, separable)} {}
|
||||
|
||||
ShaderProgramManager::~ShaderProgramManager() = default;
|
||||
|
||||
|
@ -425,6 +425,10 @@ void ShaderProgramManager::ApplyTo(OpenGLState& state, bool accurate_mul) {
|
|||
}
|
||||
}
|
||||
|
||||
u64 ShaderProgramManager::GetProgramID() const {
|
||||
return impl->disk_cache.GetProgramID();
|
||||
}
|
||||
|
||||
void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback,
|
||||
bool accurate_mul) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2022 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -34,7 +34,8 @@ enum UniformBindings {
|
|||
/// A class that manage different shader stages and configures them with given config data.
|
||||
class ShaderProgramManager {
|
||||
public:
|
||||
ShaderProgramManager(Frontend::EmuWindow& emu_window, const Driver& driver, bool separable);
|
||||
ShaderProgramManager(Frontend::EmuWindow& emu_window, const Driver& driver, u64 title_id,
|
||||
bool separable);
|
||||
~ShaderProgramManager();
|
||||
|
||||
void LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||
|
@ -53,6 +54,8 @@ public:
|
|||
|
||||
void ApplyTo(OpenGLState& state, bool accurate_mul);
|
||||
|
||||
u64 GetProgramID() const;
|
||||
|
||||
private:
|
||||
Frontend::EmuWindow& emu_window;
|
||||
const Driver& driver;
|
||||
|
|
|
@ -143,8 +143,8 @@ void RasterizerVulkan::TickFrame() {
|
|||
res_cache.TickFrame();
|
||||
}
|
||||
|
||||
void RasterizerVulkan::LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) {
|
||||
void RasterizerVulkan::LoadDefaultDiskResources(
|
||||
const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) {
|
||||
pipeline_cache.LoadDiskCache();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -45,8 +45,8 @@ public:
|
|||
~RasterizerVulkan() override;
|
||||
|
||||
void TickFrame();
|
||||
void LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||
void LoadDefaultDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||
|
||||
void DrawTriangles() override;
|
||||
void FlushAll() override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue