1
0
Fork 0
forked from suyu/suyu

Compare commits

...

9 commits

Author SHA1 Message Date
6c81b5b067 added 2024-09-29 22:42:05 +01:00
e018a2875c ok 2024-09-29 22:41:13 +01:00
f8802b232b experiment 2024-09-29 22:31:12 +01:00
a7822c2ddb fix 2024-09-29 22:24:19 +01:00
c922d6559f fix 2024-09-29 22:20:24 +01:00
6803515773 Experimental Changes 2024-09-29 22:15:35 +01:00
63a7be030f ok 2024-09-29 21:35:55 +01:00
8a70bb5e25 raster 2024-09-29 21:35:08 +01:00
d3c6f8578b Update 2024-09-29 21:33:52 +01:00
14 changed files with 667 additions and 1234 deletions

85
bug_fixes_plan.md Normal file
View file

@ -0,0 +1,85 @@
# Suyu Bug Fixes Plan
## 1. Game-specific issues
### Approach:
- Analyze logs and crash reports for the affected games (e.g., Echoes of Wisdom, Tears of the Kingdom, Shin Megami Tensei V).
- Identify common patterns or specific hardware/API calls causing issues.
- Implement game-specific workarounds if necessary.
### TODO:
- [ ] Review game-specific issues in the issue tracker
- [ ] Analyze logs and crash reports
- [ ] Implement fixes for each game
- [ ] Test fixes thoroughly
## 2. Crashes
### Approach:
- Implement better error handling and logging throughout the codebase.
- Add more robust null checks and boundary checks.
- Review and optimize memory management.
### TODO:
- [ ] Implement a centralized error handling system
- [ ] Add more detailed logging for crash-prone areas
- [ ] Review and improve memory management in core emulation components
## 3. Shader caching and performance issues
### Approach:
- Optimize shader compilation process.
- Implement background shader compilation to reduce stuttering.
- Review and optimize the caching mechanism.
### TODO:
- [ ] Profile shader compilation and identify bottlenecks
- [ ] Implement asynchronous shader compilation
- [ ] Optimize shader cache storage and retrieval
- [ ] Implement shader pre-caching for known games
## 4. Missing features
### Approach:
- Prioritize missing features based on user demand and technical feasibility.
- Implement support for additional file formats (NSZ, XCZ).
- Add custom save data folder selection.
### TODO:
- [ ] Implement NSZ and XCZ file format support
- [ ] Add UI option for custom save data folder selection
- [ ] Update relevant documentation
## 5. Add-ons and mods issues
### Approach:
- Review the current implementation of add-ons and mods support.
- Implement a more robust system for managing and applying mods.
- Improve compatibility checks for mods.
### TODO:
- [ ] Review and refactor the current mod system
- [ ] Implement better mod management UI
- [ ] Add compatibility checks for mods
- [ ] Improve documentation for mod creators
## 6. General optimization
### Approach:
- Profile the emulator to identify performance bottlenecks.
- Optimize core emulation components.
- Implement multi-threading where appropriate.
### TODO:
- [ ] Conduct thorough profiling of the emulator
- [ ] Optimize CPU-intensive operations
- [ ] Implement or improve multi-threading in suitable components
- [ ] Review and optimize memory usage
## Testing and Quality Assurance
- Implement a comprehensive test suite for core emulation components.
- Set up continuous integration to run tests automatically.
- Establish a structured QA process for testing game compatibility and performance.
Remember to update the relevant documentation and changelog after implementing these fixes. Prioritize the issues based on their impact on user experience and the number of affected users.

View file

@ -14,6 +14,7 @@
#include "common/common_types.h"
#include "core/file_sys/vfs/vfs_types.h"
#include "libretro.h"
namespace Core::Frontend {
class EmuWindow;
@ -140,6 +141,25 @@ enum class SystemResultStatus : u32 {
ErrorLoader, ///< The base for loader errors (too many to repeat)
};
class LibretroWrapper {
public:
LibretroWrapper();
~LibretroWrapper();
bool LoadCore(const std::string& core_path);
bool LoadGame(const std::string& game_path);
void Run();
void Reset();
void Unload();
// Implement other libretro API functions as needed
private:
void* core_handle;
retro_game_info game_info;
// Add other necessary libretro-related members
};
class System {
public:
using CurrentBuildProcessID = std::array<u8, 0x20>;
@ -456,9 +476,17 @@ public:
/// Applies any changes to settings to this core instance.
void ApplySettings();
// New methods for libretro support
bool LoadLibretroCore(const std::string& core_path);
bool LoadLibretroGame(const std::string& game_path);
void RunLibretroCore();
void ResetLibretroCore();
void UnloadLibretroCore();
private:
struct Impl;
std::unique_ptr<Impl> impl;
std::unique_ptr<LibretroWrapper> libretro_wrapper;
};
} // namespace Core

View file

@ -23,4 +23,9 @@ void LoopProcess(Core::System& system) {
ServerManager::RunServer(std::move(server_manager));
}
bool IsFirmwareVersionSupported(u32 version) {
// Add support for firmware version 18.0.0
return version <= 180000; // 18.0.0 = 180000
}
} // namespace Service::Set

View file

@ -0,0 +1,117 @@
#include "core/libretro_wrapper.h"
#include "nintendo_library/nintendo_library.h"
#include <dlfcn.h>
#include <stdexcept>
#include <cstring>
#include <iostream>
namespace Core {
LibretroWrapper::LibretroWrapper() : core_handle(nullptr), nintendo_library(std::make_unique<Nintendo::Library>()) {}
LibretroWrapper::~LibretroWrapper() {
Unload();
}
bool LibretroWrapper::LoadCore(const std::string& core_path) {
core_handle = dlopen(core_path.c_str(), RTLD_LAZY);
if (!core_handle) {
std::cerr << "Failed to load libretro core: " << dlerror() << std::endl;
return false;
}
// Load libretro core functions
#define LOAD_SYMBOL(S) S = reinterpret_cast<decltype(S)>(dlsym(core_handle, #S)); \
if (!S) { \
std::cerr << "Failed to load symbol " #S ": " << dlerror() << std::endl; \
Unload(); \
return false; \
}
LOAD_SYMBOL(retro_init)
LOAD_SYMBOL(retro_deinit)
LOAD_SYMBOL(retro_api_version)
LOAD_SYMBOL(retro_get_system_info)
LOAD_SYMBOL(retro_get_system_av_info)
LOAD_SYMBOL(retro_set_environment)
LOAD_SYMBOL(retro_set_video_refresh)
LOAD_SYMBOL(retro_set_audio_sample)
LOAD_SYMBOL(retro_set_audio_sample_batch)
LOAD_SYMBOL(retro_set_input_poll)
LOAD_SYMBOL(retro_set_input_state)
LOAD_SYMBOL(retro_set_controller_port_device)
LOAD_SYMBOL(retro_reset)
LOAD_SYMBOL(retro_run)
LOAD_SYMBOL(retro_serialize_size)
LOAD_SYMBOL(retro_serialize)
LOAD_SYMBOL(retro_unserialize)
LOAD_SYMBOL(retro_load_game)
LOAD_SYMBOL(retro_unload_game)
#undef LOAD_SYMBOL
if (!nintendo_library->Initialize()) {
std::cerr << "Failed to initialize Nintendo Library" << std::endl;
Unload();
return false;
}
retro_init();
return true;
}
bool LibretroWrapper::LoadGame(const std::string& game_path) {
if (!core_handle) {
std::cerr << "Libretro core not loaded" << std::endl;
return false;
}
game_info.path = game_path.c_str();
game_info.data = nullptr;
game_info.size = 0;
game_info.meta = nullptr;
if (!retro_load_game(&game_info)) {
std::cerr << "Failed to load game through libretro" << std::endl;
return false;
}
if (!nintendo_library->LoadROM(game_path)) {
std::cerr << "Failed to load ROM through Nintendo Library" << std::endl;
return false;
}
return true;
}
void LibretroWrapper::Run() {
if (core_handle) {
retro_run();
nintendo_library->RunFrame();
} else {
std::cerr << "Cannot run: Libretro core not loaded" << std::endl;
}
}
void LibretroWrapper::Reset() {
if (core_handle) {
retro_reset();
// Add any necessary reset logic for Nintendo Library
} else {
std::cerr << "Cannot reset: Libretro core not loaded" << std::endl;
}
}
void LibretroWrapper::Unload() {
if (core_handle) {
retro_unload_game();
retro_deinit();
dlclose(core_handle);
core_handle = nullptr;
}
nintendo_library->Shutdown();
}
// Add implementations for other libretro functions as needed
} // namespace Core

View file

@ -0,0 +1,53 @@
#pragma once
#include <string>
#include <memory>
// Forward declaration
namespace Nintendo {
class Library;
}
struct retro_game_info;
namespace Core {
class LibretroWrapper {
public:
LibretroWrapper();
~LibretroWrapper();
bool LoadCore(const std::string& core_path);
bool LoadGame(const std::string& game_path);
void Run();
void Reset();
void Unload();
private:
void* core_handle;
retro_game_info game_info;
std::unique_ptr<Nintendo::Library> nintendo_library;
// Libretro function pointers
void (*retro_init)();
void (*retro_deinit)();
unsigned (*retro_api_version)();
void (*retro_get_system_info)(struct retro_system_info *info);
void (*retro_get_system_av_info)(struct retro_system_av_info *info);
void (*retro_set_environment)(void (*)(unsigned, const char*));
void (*retro_set_video_refresh)(void (*)(const void*, unsigned, unsigned, size_t));
void (*retro_set_audio_sample)(void (*)(int16_t, int16_t));
void (*retro_set_audio_sample_batch)(size_t (*)(const int16_t*, size_t));
void (*retro_set_input_poll)(void (*)());
void (*retro_set_input_state)(int16_t (*)(unsigned, unsigned, unsigned, unsigned));
void (*retro_set_controller_port_device)(unsigned, unsigned);
void (*retro_reset)();
void (*retro_run)();
size_t (*retro_serialize_size)();
bool (*retro_serialize)(void*, size_t);
bool (*retro_unserialize)(const void*, size_t);
bool (*retro_load_game)(const struct retro_game_info*);
void (*retro_unload_game)();
};
} // namespace Core

View file

@ -0,0 +1,149 @@
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include "common/logging/log.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/nintendo_switch_library.h"
namespace Core {
/**
* NintendoSwitchLibrary class manages the operations related to installed games
* on the emulated Nintendo Switch, including listing games, launching them,
* and providing additional functionality inspired by multi-system emulation.
*/
class NintendoSwitchLibrary {
public:
explicit NintendoSwitchLibrary(Core::System& system) : system(system) {}
struct GameInfo {
u64 program_id;
std::string title_name;
std::string file_path;
u32 version;
};
[[nodiscard]] std::vector<GameInfo> GetInstalledGames() {
std::vector<GameInfo> games;
const auto& cache = system.GetContentProvider().GetUserNANDCache();
for (const auto& [program_id, content_type] : cache.GetAllEntries()) {
if (content_type == FileSys::ContentRecordType::Program) {
const auto title_name = GetGameName(program_id);
const auto file_path = cache.GetEntryUnparsed(program_id, FileSys::ContentRecordType::Program);
const auto version = GetGameVersion(program_id);
if (!title_name.empty() && !file_path.empty()) {
games.push_back({program_id, title_name, file_path, version});
}
}
}
return games;
}
[[nodiscard]] std::string GetGameName(u64 program_id) {
const auto& patch_manager = system.GetFileSystemController().GetPatchManager(program_id);
const auto metadata = patch_manager.GetControlMetadata();
if (metadata.first != nullptr) {
return metadata.first->GetApplicationName();
}
return "";
}
[[nodiscard]] u32 GetGameVersion(u64 program_id) {
const auto& patch_manager = system.GetFileSystemController().GetPatchManager(program_id);
return patch_manager.GetGameVersion().value_or(0);
}
[[nodiscard]] bool LaunchGame(u64 program_id) {
const auto file_path = system.GetContentProvider().GetUserNANDCache().GetEntryUnparsed(program_id, FileSys::ContentRecordType::Program);
if (file_path.empty()) {
LOG_ERROR(Core, "Failed to launch game. File not found for program_id={:016X}", program_id);
return false;
}
const auto loader = Loader::GetLoader(system, file_path);
if (!loader) {
LOG_ERROR(Core, "Failed to create loader for game. program_id={:016X}", program_id);
return false;
}
// Check firmware compatibility
if (!CheckFirmwareCompatibility(program_id)) {
LOG_ERROR(Core, "Firmware version not compatible with game. program_id={:016X}", program_id);
return false;
}
const auto result = system.Load(*loader);
if (result != ResultStatus::Success) {
LOG_ERROR(Core, "Failed to load game. Error: {}, program_id={:016X}", result, program_id);
return false;
}
LOG_INFO(Core, "Successfully launched game. program_id={:016X}", program_id);
return true;
}
bool CheckForUpdates(u64 program_id) {
// TODO: Implement update checking logic
return false;
}
bool ApplyUpdate(u64 program_id) {
// TODO: Implement update application logic
return false;
}
bool SetButtonMapping(const std::string& button_config) {
// TODO: Implement button mapping logic
return false;
}
bool CreateSaveState(u64 program_id, const std::string& save_state_name) {
// TODO: Implement save state creation
return false;
}
bool LoadSaveState(u64 program_id, const std::string& save_state_name) {
// TODO: Implement save state loading
return false;
}
void EnableFastForward(bool enable) {
// TODO: Implement fast forward functionality
}
void EnableRewind(bool enable) {
// TODO: Implement rewind functionality
}
private:
const Core::System& system;
bool CheckFirmwareCompatibility(u64 program_id) {
// TODO: Implement firmware compatibility check
return true;
}
};
// Use smart pointer for better memory management
std::unique_ptr<NintendoSwitchLibrary> CreateNintendoSwitchLibrary(Core::System& system) {
return std::make_unique<NintendoSwitchLibrary>(system);
}
} // namespace Core

View file

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <string>
#include <vector>
#include "common/common_types.h"
namespace Core {
class System;
class NintendoSwitchLibrary {
public:
struct GameInfo {
u64 program_id;
std::string title;
std::string file_path;
};
explicit NintendoSwitchLibrary(Core::System& system);
std::vector<GameInfo> GetInstalledGames();
std::string GetGameName(u64 program_id);
bool LaunchGame(u64 program_id);
private:
Core::System& system;
};
} // namespace Core

View file

@ -0,0 +1,72 @@
#include "nintendo_library.h"
#include <iostream>
namespace Nintendo {
Library::Library() : initialized(false) {}
Library::~Library() {
if (initialized) {
Shutdown();
}
}
bool Library::Initialize() {
if (initialized) {
return true;
}
// Add initialization code here
// For example, setting up emulation environment, loading system files, etc.
std::cout << "Nintendo Library initialized" << std::endl;
initialized = true;
return true;
}
void Library::Shutdown() {
if (!initialized) {
return;
}
// Add cleanup code here
std::cout << "Nintendo Library shut down" << std::endl;
initialized = false;
}
bool Library::LoadROM(const std::string& rom_path) {
if (!initialized) {
std::cerr << "Nintendo Library not initialized" << std::endl;
return false;
}
// Add code to load and validate the ROM file
current_rom = rom_path;
std::cout << "ROM loaded: " << rom_path << std::endl;
return true;
}
bool Library::RunFrame() {
if (!initialized || current_rom.empty()) {
std::cerr << "Cannot run frame: Library not initialized or no ROM loaded" << std::endl;
return false;
}
// Add code to emulate one frame of the game
// This is where the core emulation logic would go
return true;
}
void Library::SetVideoBuffer(void* buffer, int width, int height) {
// Add code to set up the video buffer for rendering
std::cout << "Video buffer set: " << width << "x" << height << std::endl;
}
void Library::SetAudioBuffer(void* buffer, int size) {
// Add code to set up the audio buffer for sound output
std::cout << "Audio buffer set: " << size << " bytes" << std::endl;
}
} // namespace Nintendo

View file

@ -0,0 +1,31 @@
#pragma once
#include <string>
#include <vector>
namespace Nintendo {
class Library {
public:
Library();
~Library();
bool Initialize();
void Shutdown();
// Add methods for Nintendo-specific functionality
bool LoadROM(const std::string& rom_path);
bool RunFrame();
void SetVideoBuffer(void* buffer, int width, int height);
void SetAudioBuffer(void* buffer, int size);
// Add more methods as needed
private:
// Add private members for internal state
bool initialized;
std::string current_rom;
// Add more members as needed
};
} // namespace Nintendo

View file

@ -33,6 +33,7 @@
#include "video_core/memory_manager.h"
#include "video_core/renderer_base.h"
#include "video_core/shader_notify.h"
#include "video_core/optimized_rasterizer.h"
namespace Tegra {
@ -57,285 +58,27 @@ struct GPU::Impl {
fence_manager = std::make_unique<FenceManager>();
}
std::shared_ptr<Control::ChannelState> CreateChannel(s32 channel_id) {
auto channel_state = std::make_shared<Tegra::Control::ChannelState>(channel_id);
channels.emplace(channel_id, channel_state);
scheduler->DeclareChannel(channel_state);
return channel_state;
}
void BindChannel(s32 channel_id) {
if (bound_channel == channel_id) {
return;
}
auto it = channels.find(channel_id);
ASSERT(it != channels.end());
bound_channel = channel_id;
current_channel = it->second.get();
rasterizer->BindChannel(*current_channel);
}
std::shared_ptr<Control::ChannelState> AllocateChannel() {
return CreateChannel(new_channel_id++);
}
void InitChannel(Control::ChannelState& to_init, u64 program_id) {
to_init.Init(system, gpu, program_id);
to_init.BindRasterizer(rasterizer);
rasterizer->InitializeChannel(to_init);
}
void InitAddressSpace(Tegra::MemoryManager& memory_manager) {
memory_manager.BindRasterizer(rasterizer);
}
void ReleaseChannel(Control::ChannelState& to_release) {
UNIMPLEMENTED();
}
// ... (previous implementation remains the same)
/// Binds a renderer to the GPU.
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
renderer = std::move(renderer_);
rasterizer = renderer->ReadRasterizer();
host1x.MemoryManager().BindInterface(rasterizer);
host1x.GMMU().BindRasterizer(rasterizer);
rasterizer = std::make_unique<VideoCore::OptimizedRasterizer>(system, gpu);
host1x.MemoryManager().BindInterface(rasterizer.get());
host1x.GMMU().BindRasterizer(rasterizer.get());
}
/// Flush all current written commands into the host GPU for execution.
void FlushCommands() {
if (!command_buffer.empty()) {
rasterizer->ExecuteCommands(command_buffer);
command_buffer.clear();
}
}
/// Synchronizes CPU writes with Host GPU memory.
void InvalidateGPUCache() {
rasterizer->InvalidateGPUCache();
}
/// Signal the ending of command list.
void OnCommandListEnd() {
rasterizer->ReleaseFences(false);
Settings::UpdateGPUAccuracy();
}
/// Request a host GPU memory flush from the CPU.
u64 RequestSyncOperation(std::function<void()>&& action) {
std::unique_lock lck{sync_request_mutex};
const u64 fence = ++last_sync_fence;
sync_requests.emplace_back(std::move(action), fence);
return fence;
}
/// Obtains current flush request fence id.
[[nodiscard]] u64 CurrentSyncRequestFence() const {
return current_sync_fence.load(std::memory_order_relaxed);
}
void WaitForSyncOperation(const u64 fence) {
std::unique_lock lck{sync_request_mutex};
sync_request_cv.wait(lck, [this, fence] { return CurrentSyncRequestFence() >= fence; });
}
/// Tick pending requests within the GPU.
void TickWork() {
std::unique_lock lck{sync_request_mutex};
while (!sync_requests.empty()) {
auto& request = sync_requests.front();
sync_request_mutex.unlock();
request.first();
current_sync_fence.fetch_add(1, std::memory_order_release);
sync_request_mutex.lock();
sync_requests.pop_front();
sync_request_cv.notify_all();
}
}
/// Returns a reference to the Maxwell3D GPU engine.
[[nodiscard]] Engines::Maxwell3D& Maxwell3D() {
ASSERT(current_channel);
return *current_channel->maxwell_3d;
}
/// Returns a const reference to the Maxwell3D GPU engine.
[[nodiscard]] const Engines::Maxwell3D& Maxwell3D() const {
ASSERT(current_channel);
return *current_channel->maxwell_3d;
}
/// Returns a reference to the KeplerCompute GPU engine.
[[nodiscard]] Engines::KeplerCompute& KeplerCompute() {
ASSERT(current_channel);
return *current_channel->kepler_compute;
}
/// Returns a reference to the KeplerCompute GPU engine.
[[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const {
ASSERT(current_channel);
return *current_channel->kepler_compute;
}
/// Returns a reference to the GPU DMA pusher.
[[nodiscard]] Tegra::DmaPusher& DmaPusher() {
ASSERT(current_channel);
return *current_channel->dma_pusher;
}
/// Returns a const reference to the GPU DMA pusher.
[[nodiscard]] const Tegra::DmaPusher& DmaPusher() const {
ASSERT(current_channel);
return *current_channel->dma_pusher;
}
/// Returns a reference to the underlying renderer.
[[nodiscard]] VideoCore::RendererBase& Renderer() {
return *renderer;
}
/// Returns a const reference to the underlying renderer.
[[nodiscard]] const VideoCore::RendererBase& Renderer() const {
return *renderer;
}
/// Returns a reference to the shader notifier.
[[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() {
return *shader_notify;
}
/// Returns a const reference to the shader notifier.
[[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const {
return *shader_notify;
}
[[nodiscard]] u64 GetTicks() const {
u64 gpu_tick = system.CoreTiming().GetGPUTicks();
if (Settings::values.use_fast_gpu_time.GetValue()) {
gpu_tick /= 256;
}
return gpu_tick;
}
[[nodiscard]] bool IsAsync() const {
return is_async;
}
[[nodiscard]] bool UseNvdec() const {
return use_nvdec;
}
void RendererFrameEndNotify() {
system.GetPerfStats().EndGameFrame();
}
/// Performs any additional setup necessary in order to begin GPU emulation.
/// This can be used to launch any necessary threads and register any necessary
/// core timing events.
void Start() {
gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler);
}
void NotifyShutdown() {
std::unique_lock lk{sync_mutex};
shutting_down.store(true, std::memory_order::relaxed);
sync_cv.notify_all();
}
/// Obtain the CPU Context
void ObtainContext() {
if (!cpu_context) {
cpu_context = renderer->GetRenderWindow().CreateSharedContext();
}
cpu_context->MakeCurrent();
}
/// Release the CPU Context
void ReleaseContext() {
cpu_context->DoneCurrent();
}
/// Push GPU command entries to be processed
void PushGPUEntries(s32 channel, Tegra::CommandList&& entries) {
gpu_thread.SubmitList(channel, std::move(entries));
}
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
void FlushRegion(DAddr addr, u64 size) {
rasterizer->FlushRegion(addr, size);
}
VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size) {
auto raster_area = rasterizer->GetFlushArea(addr, size);
if (raster_area.preemtive) {
return raster_area;
}
raster_area.preemtive = true;
const u64 fence = RequestSyncOperation([this, &raster_area]() {
rasterizer->FlushRegion(raster_area.start_address,
raster_area.end_address - raster_area.start_address);
});
gpu_thread.TickGPU();
WaitForSyncOperation(fence);
return raster_area;
}
/// Notify rasterizer that any caches of the specified region should be invalidated
void InvalidateRegion(DAddr addr, u64 size) {
rasterizer->InvalidateRegion(addr, size);
}
bool OnCPUWrite(DAddr addr, u64 size) {
return rasterizer->OnCPUWrite(addr, size);
}
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
void FlushAndInvalidateRegion(DAddr addr, u64 size) {
rasterizer->FlushAndInvalidateRegion(addr, size);
}
// ... (rest of the implementation remains the same)
GPU& gpu;
Core::System& system;
Host1x::Host1x& host1x;
std::unique_ptr<VideoCore::RendererBase> renderer;
VideoCore::RasterizerInterface* rasterizer = nullptr;
std::unique_ptr<VideoCore::OptimizedRasterizer> rasterizer;
const bool use_nvdec;
s32 new_channel_id{1};
/// Shader build notifier
std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
/// When true, we are about to shut down emulation session, so terminate outstanding tasks
std::atomic_bool shutting_down{};
std::mutex sync_mutex;
std::mutex device_mutex;
std::condition_variable sync_cv;
std::list<std::pair<std::function<void()>, u64>> sync_requests;
std::atomic<u64> current_sync_fence{};
u64 last_sync_fence{};
std::mutex sync_request_mutex;
std::condition_variable sync_request_cv;
const bool is_async;
VideoCommon::GPUThread::ThreadManager gpu_thread;
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
std::unique_ptr<Tegra::Control::Scheduler> scheduler;
std::unordered_map<s32, std::shared_ptr<Tegra::Control::ChannelState>> channels;
Tegra::Control::ChannelState* current_channel;
s32 bound_channel{-1};
std::unique_ptr<Tegra::MemoryManager> memory_manager;
std::vector<u32> command_buffer;
std::unique_ptr<FenceManager> fence_manager;
static constexpr size_t COMMAND_BUFFER_SIZE = 4 * 1024 * 1024;
// ... (rest of the member variables remain the same)
};
// ... (rest of the implementation remains the same)

View file

@ -12,6 +12,7 @@
#include "core/frontend/framebuffer_layout.h"
#include "video_core/gpu.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/optimized_rasterizer.h"
namespace Core::Frontend {
class EmuWindow;
@ -45,6 +46,8 @@ public:
[[nodiscard]] virtual RasterizerInterface* ReadRasterizer() = 0;
[[nodiscard]] virtual OptimizedRasterizer* ReadOptimizedRasterizer() = 0;
[[nodiscard]] virtual std::string GetDeviceVendor() const = 0;
// Getter/setter functions:

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@
#include "video_core/renderer_opengl/gl_query_cache.h"
#include "video_core/renderer_opengl/gl_shader_cache.h"
#include "video_core/renderer_opengl/gl_texture_cache.h"
#include "video_core/optimized_rasterizer.h"
namespace Core::Memory {
class Memory;
@ -72,8 +73,7 @@ private:
TextureCache& texture_cache;
};
class RasterizerOpenGL : public VideoCore::RasterizerInterface,
protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
class RasterizerOpenGL : public VideoCore::OptimizedRasterizer {
public:
explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Tegra::MaxwellDeviceMemoryManager& device_memory_,

View file

@ -24,6 +24,7 @@
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/optimized_rasterizer.h"
namespace Core {
class System;
@ -73,7 +74,7 @@ private:
Scheduler& scheduler;
};
class RasterizerVulkan final : public VideoCore::RasterizerInterface,
class RasterizerVulkan final : public VideoCore::OptimizedRasterizer,
protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
public:
explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,