Frontend PR fixes (#6378)
* citra_qt: Check if renderer is null * core: Fix dynarmic use-after-free error * bootmanager: Add current context check in DoneCurrent * Loading a save state would destroy the frame dumper class, which contains a shared context. That context would call DoneCurrent without checking if it was actually bound or not, resulting in crashes when calling opengl functions * externals: Correct glad readme * common: Log renderer debug setting * citra: Make lambda lower case * Consistency with review comments on the PR * video_core: Kill more global state * GetResolutionScaleFactor would be called somewhere in the renderer constructor chain but it relies on the yet unitialized g_renderer, resulting in crashes when the resolution scale is set to auto. Rather than adding a workaround, let's kill this global state to fix this for good
This commit is contained in:
parent
5346ca27b5
commit
ffc95eb59b
17 changed files with 102 additions and 93 deletions
2
externals/glad/Readme.md
vendored
2
externals/glad/Readme.md
vendored
|
@ -1,5 +1,5 @@
|
||||||
These files were generated by the [glad](https://github.com/Dav1dde/glad) OpenGL loader generator and have been checked in as-is. You can re-generate them using glad with the following command:
|
These files were generated by the [glad](https://github.com/Dav1dde/glad) OpenGL loader generator and have been checked in as-is. You can re-generate them using glad with the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
python -m glad --profile core --out-path glad/ --api "gl=4.6,gles2=3.2" --generator=c
|
python -m glad --profile core --out-path glad/ --api "gl=4.3,gles2=3.2" --generator=c
|
||||||
```
|
```
|
||||||
|
|
|
@ -364,7 +364,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
EmuWindow_SDL2::InitializeSDL2();
|
EmuWindow_SDL2::InitializeSDL2();
|
||||||
|
|
||||||
const auto CreateEmuWindow = [](bool fullscreen,
|
const auto create_emu_window = [](bool fullscreen,
|
||||||
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
|
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
|
||||||
switch (Settings::values.graphics_api.GetValue()) {
|
switch (Settings::values.graphics_api.GetValue()) {
|
||||||
case Settings::GraphicsAPI::OpenGL:
|
case Settings::GraphicsAPI::OpenGL:
|
||||||
|
@ -374,11 +374,11 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto emu_window{CreateEmuWindow(fullscreen, false)};
|
const auto emu_window{create_emu_window(fullscreen, false)};
|
||||||
const bool use_secondary_window{
|
const bool use_secondary_window{
|
||||||
Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows &&
|
Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows &&
|
||||||
Settings::values.graphics_api.GetValue() != Settings::GraphicsAPI::Software};
|
Settings::values.graphics_api.GetValue() != Settings::GraphicsAPI::Software};
|
||||||
const auto secondary_window = use_secondary_window ? CreateEmuWindow(false, true) : nullptr;
|
const auto secondary_window = use_secondary_window ? create_emu_window(false, true) : nullptr;
|
||||||
|
|
||||||
const auto scope = emu_window->Acquire();
|
const auto scope = emu_window->Acquire();
|
||||||
|
|
||||||
|
@ -448,8 +448,8 @@ int main(int argc, char** argv) {
|
||||||
Core::Movie::GetInstance().StartRecording(movie_record, movie_record_author);
|
Core::Movie::GetInstance().StartRecording(movie_record, movie_record_author);
|
||||||
}
|
}
|
||||||
if (!dump_video.empty()) {
|
if (!dump_video.empty()) {
|
||||||
Layout::FramebufferLayout layout{
|
Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(
|
||||||
Layout::FrameLayoutFromResolutionScale(VideoCore::GetResolutionScaleFactor())};
|
VideoCore::g_renderer->GetResolutionScaleFactor())};
|
||||||
system.VideoDumper().StartDumping(dump_video, layout);
|
system.VideoDumper().StartDumping(dump_video, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
~OpenGLSharedContext() {
|
~OpenGLSharedContext() {
|
||||||
context->doneCurrent();
|
OpenGLSharedContext::DoneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapBuffers() override {
|
void SwapBuffers() override {
|
||||||
|
@ -196,8 +196,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoneCurrent() override {
|
void DoneCurrent() override {
|
||||||
|
if (QOpenGLContext::currentContext() == context.get()) {
|
||||||
context->doneCurrent();
|
context->doneCurrent();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QOpenGLContext* GetShareContext() const {
|
QOpenGLContext* GetShareContext() const {
|
||||||
return context.get();
|
return context.get();
|
||||||
|
@ -257,7 +259,9 @@ public:
|
||||||
}
|
}
|
||||||
context->MakeCurrent();
|
context->MakeCurrent();
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
if (VideoCore::g_renderer) {
|
||||||
VideoCore::g_renderer->TryPresent(100, is_secondary);
|
VideoCore::g_renderer->TryPresent(100, is_secondary);
|
||||||
|
}
|
||||||
context->SwapBuffers();
|
context->SwapBuffers();
|
||||||
glFinish();
|
glFinish();
|
||||||
}
|
}
|
||||||
|
@ -633,7 +637,7 @@ void GRenderWindow::ReleaseRenderTarget() {
|
||||||
|
|
||||||
void GRenderWindow::CaptureScreenshot(u32 res_scale, const QString& screenshot_path) {
|
void GRenderWindow::CaptureScreenshot(u32 res_scale, const QString& screenshot_path) {
|
||||||
if (res_scale == 0) {
|
if (res_scale == 0) {
|
||||||
res_scale = VideoCore::GetResolutionScaleFactor();
|
res_scale = VideoCore::g_renderer->GetResolutionScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto layout{Layout::FrameLayoutFromResolutionScale(res_scale, is_secondary)};
|
const auto layout{Layout::FrameLayoutFromResolutionScale(res_scale, is_secondary)};
|
||||||
|
|
|
@ -1173,8 +1173,8 @@ void GMainWindow::BootGame(const QString& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_dumping_on_start) {
|
if (video_dumping_on_start) {
|
||||||
Layout::FramebufferLayout layout{
|
Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(
|
||||||
Layout::FrameLayoutFromResolutionScale(VideoCore::GetResolutionScaleFactor())};
|
VideoCore::g_renderer->GetResolutionScaleFactor())};
|
||||||
if (!Core::System::GetInstance().VideoDumper().StartDumping(
|
if (!Core::System::GetInstance().VideoDumper().StartDumping(
|
||||||
video_dumping_path.toStdString(), layout)) {
|
video_dumping_path.toStdString(), layout)) {
|
||||||
|
|
||||||
|
@ -2195,8 +2195,8 @@ void GMainWindow::OnStartVideoDumping() {
|
||||||
}
|
}
|
||||||
const auto path = dialog.GetFilePath();
|
const auto path = dialog.GetFilePath();
|
||||||
if (emulation_running) {
|
if (emulation_running) {
|
||||||
Layout::FramebufferLayout layout{
|
Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(
|
||||||
Layout::FrameLayoutFromResolutionScale(VideoCore::GetResolutionScaleFactor())};
|
VideoCore::g_renderer->GetResolutionScaleFactor())};
|
||||||
if (!Core::System::GetInstance().VideoDumper().StartDumping(path.toStdString(), layout)) {
|
if (!Core::System::GetInstance().VideoDumper().StartDumping(path.toStdString(), layout)) {
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
this, tr("Citra"),
|
this, tr("Citra"),
|
||||||
|
|
|
@ -55,7 +55,6 @@ void Apply() {
|
||||||
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
||||||
VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue();
|
VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue();
|
||||||
VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul.GetValue();
|
VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul.GetValue();
|
||||||
VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache.GetValue();
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
if (VideoCore::g_renderer) {
|
if (VideoCore::g_renderer) {
|
||||||
|
@ -63,10 +62,13 @@ void Apply() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VideoCore::g_renderer_bg_color_update_requested = true;
|
if (VideoCore::g_renderer) {
|
||||||
VideoCore::g_renderer_sampler_update_requested = true;
|
auto& settings = VideoCore::g_renderer->Settings();
|
||||||
VideoCore::g_renderer_shader_update_requested = true;
|
settings.bg_color_update_requested = true;
|
||||||
VideoCore::g_texture_filter_update_requested = true;
|
settings.sampler_update_requested = true;
|
||||||
|
settings.shader_update_requested = true;
|
||||||
|
settings.texture_filter_update_requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
if (system.IsPoweredOn()) {
|
if (system.IsPoweredOn()) {
|
||||||
|
@ -114,6 +116,7 @@ void LogSettings() {
|
||||||
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
||||||
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
||||||
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
||||||
|
log_setting("Renderer_Debug", values.renderer_debug.GetValue());
|
||||||
log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue());
|
log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue());
|
||||||
log_setting("Renderer_SeparableShader", values.separable_shader.GetValue());
|
log_setting("Renderer_SeparableShader", values.separable_shader.GetValue());
|
||||||
log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul.GetValue());
|
log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul.GetValue());
|
||||||
|
|
|
@ -429,7 +429,7 @@ struct Values {
|
||||||
SwitchableSetting<bool> shaders_accurate_mul{true, "shaders_accurate_mul"};
|
SwitchableSetting<bool> shaders_accurate_mul{true, "shaders_accurate_mul"};
|
||||||
SwitchableSetting<bool> use_vsync_new{true, "use_vsync_new"};
|
SwitchableSetting<bool> use_vsync_new{true, "use_vsync_new"};
|
||||||
Setting<bool> use_shader_jit{true, "use_shader_jit"};
|
Setting<bool> use_shader_jit{true, "use_shader_jit"};
|
||||||
SwitchableSetting<u16, true> resolution_factor{1, 0, 10, "resolution_factor"};
|
SwitchableSetting<u32, true> resolution_factor{1, 0, 10, "resolution_factor"};
|
||||||
SwitchableSetting<u16, true> frame_limit{100, 0, 1000, "frame_limit"};
|
SwitchableSetting<u16, true> frame_limit{100, 0, 1000, "frame_limit"};
|
||||||
SwitchableSetting<std::string> texture_filter_name{"none", "texture_filter_name"};
|
SwitchableSetting<std::string> texture_filter_name{"none", "texture_filter_name"};
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,7 @@ System::~System() = default;
|
||||||
|
|
||||||
System::ResultStatus System::RunLoop(bool tight_loop) {
|
System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||||
status = ResultStatus::Success;
|
status = ResultStatus::Success;
|
||||||
if (std::any_of(cpu_cores.begin(), cpu_cores.end(),
|
if (!IsPoweredOn()) {
|
||||||
[](std::shared_ptr<ARM_Interface> ptr) { return ptr == nullptr; })) {
|
|
||||||
return ResultStatus::ErrorNotInitialized;
|
return ResultStatus::ErrorNotInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +434,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
|
||||||
|
|
||||||
LOG_DEBUG(Core, "Initialized OK");
|
LOG_DEBUG(Core, "Initialized OK");
|
||||||
|
|
||||||
initalized = true;
|
is_powered_on = true;
|
||||||
|
|
||||||
return ResultStatus::Success;
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
@ -537,6 +536,8 @@ void System::Shutdown(bool is_deserializing) {
|
||||||
perf_stats ? perf_stats->GetMeanFrametime() : 0);
|
perf_stats ? perf_stats->GetMeanFrametime() : 0);
|
||||||
|
|
||||||
// Shutdown emulation session
|
// Shutdown emulation session
|
||||||
|
is_powered_on = false;
|
||||||
|
|
||||||
VideoCore::Shutdown();
|
VideoCore::Shutdown();
|
||||||
HW::Shutdown();
|
HW::Shutdown();
|
||||||
if (!is_deserializing) {
|
if (!is_deserializing) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -151,10 +152,7 @@ public:
|
||||||
* @returns True if the emulated system is powered on, otherwise false.
|
* @returns True if the emulated system is powered on, otherwise false.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool IsPoweredOn() const {
|
[[nodiscard]] bool IsPoweredOn() const {
|
||||||
return cpu_cores.size() > 0 &&
|
return is_powered_on;
|
||||||
std::all_of(cpu_cores.begin(), cpu_cores.end(),
|
|
||||||
[](std::shared_ptr<ARM_Interface> ptr) { return ptr != nullptr; });
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -383,7 +381,7 @@ private:
|
||||||
private:
|
private:
|
||||||
static System s_instance;
|
static System s_instance;
|
||||||
|
|
||||||
bool initalized = false;
|
std::atomic_bool is_powered_on{};
|
||||||
|
|
||||||
ResultStatus status = ResultStatus::Success;
|
ResultStatus status = ResultStatus::Success;
|
||||||
std::string status_details = "";
|
std::string status_details = "";
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "video_core/pica_state.h"
|
#include "video_core/pica_state.h"
|
||||||
#include "video_core/rasterizer_cache/rasterizer_cache.h"
|
#include "video_core/rasterizer_cache/rasterizer_cache.h"
|
||||||
|
#include "video_core/renderer_base.h"
|
||||||
#include "video_core/renderer_opengl/gl_format_reinterpreter.h"
|
#include "video_core/renderer_opengl/gl_format_reinterpreter.h"
|
||||||
#include "video_core/renderer_opengl/texture_downloader_es.h"
|
#include "video_core/renderer_opengl/texture_downloader_es.h"
|
||||||
#include "video_core/renderer_opengl/texture_filters/texture_filterer.h"
|
#include "video_core/renderer_opengl/texture_filters/texture_filterer.h"
|
||||||
|
@ -239,8 +240,9 @@ static Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams&
|
||||||
return match_surface;
|
return match_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerCacheOpenGL::RasterizerCacheOpenGL() {
|
RasterizerCacheOpenGL::RasterizerCacheOpenGL(VideoCore::RendererBase& renderer_)
|
||||||
resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
|
: renderer{renderer_} {
|
||||||
|
resolution_scale_factor = renderer.GetResolutionScaleFactor();
|
||||||
texture_filterer = std::make_unique<TextureFilterer>(
|
texture_filterer = std::make_unique<TextureFilterer>(
|
||||||
Settings::values.texture_filter_name.GetValue(), resolution_scale_factor);
|
Settings::values.texture_filter_name.GetValue(), resolution_scale_factor);
|
||||||
format_reinterpreter = std::make_unique<FormatReinterpreterOpenGL>();
|
format_reinterpreter = std::make_unique<FormatReinterpreterOpenGL>();
|
||||||
|
@ -588,15 +590,14 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
|
||||||
const auto& config = regs.framebuffer.framebuffer;
|
const auto& config = regs.framebuffer.framebuffer;
|
||||||
|
|
||||||
// Update resolution_scale_factor and reset cache if changed
|
// Update resolution_scale_factor and reset cache if changed
|
||||||
const bool resolution_scale_changed =
|
const u32 scale_factor = renderer.GetResolutionScaleFactor();
|
||||||
resolution_scale_factor != VideoCore::GetResolutionScaleFactor();
|
const bool resolution_scale_changed = resolution_scale_factor != scale_factor;
|
||||||
const bool texture_filter_changed =
|
const bool texture_filter_changed =
|
||||||
VideoCore::g_texture_filter_update_requested.exchange(false) &&
|
renderer.Settings().texture_filter_update_requested.exchange(false) &&
|
||||||
texture_filterer->Reset(Settings::values.texture_filter_name.GetValue(),
|
texture_filterer->Reset(Settings::values.texture_filter_name.GetValue(), scale_factor);
|
||||||
VideoCore::GetResolutionScaleFactor());
|
|
||||||
|
|
||||||
if (resolution_scale_changed || texture_filter_changed) {
|
if (resolution_scale_changed || texture_filter_changed) {
|
||||||
resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
|
resolution_scale_factor = scale_factor;
|
||||||
FlushAll();
|
FlushAll();
|
||||||
while (!surface_cache.empty())
|
while (!surface_cache.empty())
|
||||||
UnregisterSurface(*surface_cache.begin()->second.begin());
|
UnregisterSurface(*surface_cache.begin()->second.begin());
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
#include "video_core/rasterizer_cache/surface_params.h"
|
#include "video_core/rasterizer_cache/surface_params.h"
|
||||||
#include "video_core/texture/texture_decode.h"
|
#include "video_core/texture/texture_decode.h"
|
||||||
|
|
||||||
|
namespace VideoCore {
|
||||||
|
class RendererBase;
|
||||||
|
}
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
enum class ScaleMatch {
|
enum class ScaleMatch {
|
||||||
|
@ -23,7 +27,7 @@ class FormatReinterpreterOpenGL;
|
||||||
|
|
||||||
class RasterizerCacheOpenGL : NonCopyable {
|
class RasterizerCacheOpenGL : NonCopyable {
|
||||||
public:
|
public:
|
||||||
RasterizerCacheOpenGL();
|
RasterizerCacheOpenGL(VideoCore::RendererBase& renderer);
|
||||||
~RasterizerCacheOpenGL();
|
~RasterizerCacheOpenGL();
|
||||||
|
|
||||||
/// Blit one surface's texture to another
|
/// Blit one surface's texture to another
|
||||||
|
@ -108,6 +112,7 @@ private:
|
||||||
/// Increase/decrease the number of surface in pages touching the specified region
|
/// Increase/decrease the number of surface in pages touching the specified region
|
||||||
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta);
|
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta);
|
||||||
|
|
||||||
|
VideoCore::RendererBase& renderer;
|
||||||
TextureRuntime runtime;
|
TextureRuntime runtime;
|
||||||
SurfaceCache surface_cache;
|
SurfaceCache surface_cache;
|
||||||
PageMap cached_pages;
|
PageMap cached_pages;
|
||||||
|
|
|
@ -16,6 +16,18 @@ RendererBase::RendererBase(Core::System& system_, Frontend::EmuWindow& window,
|
||||||
|
|
||||||
RendererBase::~RendererBase() = default;
|
RendererBase::~RendererBase() = default;
|
||||||
|
|
||||||
|
u32 RendererBase::GetResolutionScaleFactor() {
|
||||||
|
const auto graphics_api = Settings::values.graphics_api.GetValue();
|
||||||
|
if (graphics_api == Settings::GraphicsAPI::Software) {
|
||||||
|
// Software renderer always render at native resolution
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 scale_factor = Settings::values.resolution_factor.GetValue();
|
||||||
|
return scale_factor != 0 ? scale_factor
|
||||||
|
: render_window.GetFramebufferLayout().GetScalingRatio();
|
||||||
|
}
|
||||||
|
|
||||||
void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) {
|
void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) {
|
||||||
const auto update_layout = [is_portrait_mode](Frontend::EmuWindow& window) {
|
const auto update_layout = [is_portrait_mode](Frontend::EmuWindow& window) {
|
||||||
const Layout::FramebufferLayout& layout = window.GetFramebufferLayout();
|
const Layout::FramebufferLayout& layout = window.GetFramebufferLayout();
|
||||||
|
@ -43,19 +55,19 @@ void RendererBase::EndFrame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RendererBase::IsScreenshotPending() const {
|
bool RendererBase::IsScreenshotPending() const {
|
||||||
return renderer_settings.screenshot_requested;
|
return settings.screenshot_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
|
void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
|
||||||
const Layout::FramebufferLayout& layout) {
|
const Layout::FramebufferLayout& layout) {
|
||||||
if (renderer_settings.screenshot_requested) {
|
if (settings.screenshot_requested) {
|
||||||
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
|
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renderer_settings.screenshot_bits = data;
|
settings.screenshot_bits = data;
|
||||||
renderer_settings.screenshot_complete_callback = callback;
|
settings.screenshot_complete_callback = callback;
|
||||||
renderer_settings.screenshot_framebuffer_layout = layout;
|
settings.screenshot_framebuffer_layout = layout;
|
||||||
renderer_settings.screenshot_requested = true;
|
settings.screenshot_requested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
|
@ -24,6 +24,11 @@ struct RendererSettings {
|
||||||
void* screenshot_bits{};
|
void* screenshot_bits{};
|
||||||
std::function<void()> screenshot_complete_callback;
|
std::function<void()> screenshot_complete_callback;
|
||||||
Layout::FramebufferLayout screenshot_framebuffer_layout;
|
Layout::FramebufferLayout screenshot_framebuffer_layout;
|
||||||
|
// Renderer
|
||||||
|
std::atomic_bool texture_filter_update_requested{false};
|
||||||
|
std::atomic_bool bg_color_update_requested{false};
|
||||||
|
std::atomic_bool sampler_update_requested{false};
|
||||||
|
std::atomic_bool shader_update_requested{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
class RendererBase : NonCopyable {
|
class RendererBase : NonCopyable {
|
||||||
|
@ -54,6 +59,9 @@ public:
|
||||||
/// Synchronizes fixed function renderer state
|
/// Synchronizes fixed function renderer state
|
||||||
virtual void Sync() {}
|
virtual void Sync() {}
|
||||||
|
|
||||||
|
/// Returns the resolution scale factor relative to the native 3DS screen resolution
|
||||||
|
u32 GetResolutionScaleFactor();
|
||||||
|
|
||||||
/// Updates the framebuffer layout of the contained render window handle.
|
/// Updates the framebuffer layout of the contained render window handle.
|
||||||
void UpdateCurrentFramebufferLayout(bool is_portrait_mode = {});
|
void UpdateCurrentFramebufferLayout(bool is_portrait_mode = {});
|
||||||
|
|
||||||
|
@ -80,11 +88,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] RendererSettings& Settings() {
|
[[nodiscard]] RendererSettings& Settings() {
|
||||||
return renderer_settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const RendererSettings& Settings() const {
|
[[nodiscard]] const RendererSettings& Settings() const {
|
||||||
return renderer_settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if a screenshot is being processed
|
/// Returns true if a screenshot is being processed
|
||||||
|
@ -96,7 +104,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
RendererSettings renderer_settings;
|
RendererSettings settings;
|
||||||
Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
||||||
Frontend::EmuWindow* secondary_window; ///< Reference to the secondary render window handle.
|
Frontend::EmuWindow* secondary_window; ///< Reference to the secondary render window handle.
|
||||||
f32 current_fps = 0.0f; ///< Current framerate, should be set by the renderer
|
f32 current_fps = 0.0f; ///< Current framerate, should be set by the renderer
|
||||||
|
|
|
@ -64,11 +64,10 @@ GLenum MakeAttributeType(Pica::PipelineRegs::VertexAttributeFormat format) {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window,
|
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, VideoCore::RendererBase& renderer,
|
||||||
Driver& driver_)
|
Driver& driver_)
|
||||||
: VideoCore::RasterizerAccelerated{memory}, driver{driver_}, vertex_buffer{driver,
|
: VideoCore::RasterizerAccelerated{memory}, driver{driver_}, res_cache{renderer},
|
||||||
GL_ARRAY_BUFFER,
|
vertex_buffer{driver, GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE},
|
||||||
VERTEX_BUFFER_SIZE},
|
|
||||||
uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE},
|
uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE},
|
||||||
index_buffer{driver, GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE},
|
index_buffer{driver, GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE},
|
||||||
texture_buffer{driver, GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE}, texture_lf_buffer{
|
texture_buffer{driver, GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE}, texture_lf_buffer{
|
||||||
|
@ -167,12 +166,14 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWi
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (driver.GetVendor() == Vendor::Intel) {
|
if (driver.GetVendor() == Vendor::Intel) {
|
||||||
shader_program_manager = std::make_unique<ShaderProgramManager>(
|
shader_program_manager = std::make_unique<ShaderProgramManager>(
|
||||||
emu_window, driver, VideoCore::g_separable_shader_enabled);
|
renderer.GetRenderWindow(), driver, VideoCore::g_separable_shader_enabled);
|
||||||
} else {
|
} else {
|
||||||
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, driver, true);
|
shader_program_manager =
|
||||||
|
std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, true);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, driver, !GLES);
|
shader_program_manager =
|
||||||
|
std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, !GLES);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
#include "video_core/renderer_opengl/gl_stream_buffer.h"
|
#include "video_core/renderer_opengl/gl_stream_buffer.h"
|
||||||
#include "video_core/shader/shader.h"
|
#include "video_core/shader/shader.h"
|
||||||
|
|
||||||
namespace Frontend {
|
namespace VideoCore {
|
||||||
class EmuWindow;
|
class RendererBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
@ -25,7 +25,7 @@ class ShaderProgramManager;
|
||||||
|
|
||||||
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
|
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
|
||||||
public:
|
public:
|
||||||
explicit RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window,
|
explicit RasterizerOpenGL(Memory::MemorySystem& memory, VideoCore::RendererBase& renderer,
|
||||||
Driver& driver);
|
Driver& driver);
|
||||||
~RasterizerOpenGL() override;
|
~RasterizerOpenGL() override;
|
||||||
|
|
||||||
|
|
|
@ -360,7 +360,7 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window
|
||||||
}
|
}
|
||||||
frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>();
|
frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>();
|
||||||
InitOpenGLObjects();
|
InitOpenGLObjects();
|
||||||
rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), render_window, driver);
|
rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), *this, driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererOpenGL::~RendererOpenGL() = default;
|
RendererOpenGL::~RendererOpenGL() = default;
|
||||||
|
@ -401,7 +401,7 @@ void RendererOpenGL::SwapBuffers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::RenderScreenshot() {
|
void RendererOpenGL::RenderScreenshot() {
|
||||||
if (renderer_settings.screenshot_requested.exchange(false)) {
|
if (settings.screenshot_requested.exchange(false)) {
|
||||||
// Draw this frame to the screenshot framebuffer
|
// Draw this frame to the screenshot framebuffer
|
||||||
screenshot_framebuffer.Create();
|
screenshot_framebuffer.Create();
|
||||||
GLuint old_read_fb = state.draw.read_framebuffer;
|
GLuint old_read_fb = state.draw.read_framebuffer;
|
||||||
|
@ -409,7 +409,7 @@ void RendererOpenGL::RenderScreenshot() {
|
||||||
state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
|
state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
const auto layout{renderer_settings.screenshot_framebuffer_layout};
|
const Layout::FramebufferLayout layout{settings.screenshot_framebuffer_layout};
|
||||||
|
|
||||||
GLuint renderbuffer;
|
GLuint renderbuffer;
|
||||||
glGenRenderbuffers(1, &renderbuffer);
|
glGenRenderbuffers(1, &renderbuffer);
|
||||||
|
@ -421,7 +421,7 @@ void RendererOpenGL::RenderScreenshot() {
|
||||||
DrawScreens(layout, false);
|
DrawScreens(layout, false);
|
||||||
|
|
||||||
glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||||
renderer_settings.screenshot_bits);
|
settings.screenshot_bits);
|
||||||
|
|
||||||
screenshot_framebuffer.Release();
|
screenshot_framebuffer.Release();
|
||||||
state.draw.read_framebuffer = old_read_fb;
|
state.draw.read_framebuffer = old_read_fb;
|
||||||
|
@ -429,7 +429,7 @@ void RendererOpenGL::RenderScreenshot() {
|
||||||
state.Apply();
|
state.Apply();
|
||||||
glDeleteRenderbuffers(1, &renderbuffer);
|
glDeleteRenderbuffers(1, &renderbuffer);
|
||||||
|
|
||||||
renderer_settings.screenshot_complete_callback();
|
settings.screenshot_complete_callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,7 +808,7 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa
|
||||||
// As this is the "DrawSingleScreenRotated" function, the output resolution dimensions have been
|
// As this is the "DrawSingleScreenRotated" function, the output resolution dimensions have been
|
||||||
// swapped. If a non-rotated draw-screen function were to be added for book-mode games, those
|
// swapped. If a non-rotated draw-screen function were to be added for book-mode games, those
|
||||||
// should probably be set to the standard (w, h, 1.0 / w, 1.0 / h) ordering.
|
// should probably be set to the standard (w, h, 1.0 / w, 1.0 / h) ordering.
|
||||||
const u16 scale_factor = VideoCore::GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor),
|
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor),
|
||||||
static_cast<float>(screen_info.texture.height * scale_factor),
|
static_cast<float>(screen_info.texture.height * scale_factor),
|
||||||
1.0f / static_cast<float>(screen_info.texture.width * scale_factor),
|
1.0f / static_cast<float>(screen_info.texture.width * scale_factor),
|
||||||
|
@ -837,7 +837,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
|
||||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const u16 scale_factor = VideoCore::GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor),
|
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor),
|
||||||
static_cast<float>(screen_info.texture.height * scale_factor),
|
static_cast<float>(screen_info.texture.height * scale_factor),
|
||||||
1.0f / static_cast<float>(screen_info.texture.width * scale_factor),
|
1.0f / static_cast<float>(screen_info.texture.width * scale_factor),
|
||||||
|
@ -871,7 +871,7 @@ void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info
|
||||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right),
|
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right),
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const u16 scale_factor = VideoCore::GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
glUniform4f(uniform_i_resolution,
|
glUniform4f(uniform_i_resolution,
|
||||||
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
||||||
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
||||||
|
@ -906,7 +906,7 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
||||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const u16 scale_factor = VideoCore::GetResolutionScaleFactor();
|
const u32 scale_factor = GetResolutionScaleFactor();
|
||||||
glUniform4f(uniform_i_resolution,
|
glUniform4f(uniform_i_resolution,
|
||||||
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
||||||
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
||||||
|
@ -933,18 +933,18 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
||||||
* Draws the emulated screens to the emulator window.
|
* Draws the emulated screens to the emulator window.
|
||||||
*/
|
*/
|
||||||
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
||||||
if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) {
|
if (settings.bg_color_update_requested.exchange(false)) {
|
||||||
// Update background color before drawing
|
// Update background color before drawing
|
||||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||||
Settings::values.bg_blue.GetValue(), 0.0f);
|
Settings::values.bg_blue.GetValue(), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) {
|
if (settings.sampler_update_requested.exchange(false)) {
|
||||||
// Set the new filtering mode for the sampler
|
// Set the new filtering mode for the sampler
|
||||||
ReloadSampler();
|
ReloadSampler();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VideoCore::g_renderer_shader_update_requested.exchange(false)) {
|
if (settings.shader_update_requested.exchange(false)) {
|
||||||
// Update fragment shader before drawing
|
// Update fragment shader before drawing
|
||||||
shader.Release();
|
shader.Release();
|
||||||
// Link shaders and get variable locations
|
// Link shaders and get variable locations
|
||||||
|
|
|
@ -26,11 +26,6 @@ std::atomic<bool> g_shader_jit_enabled;
|
||||||
std::atomic<bool> g_hw_shader_enabled;
|
std::atomic<bool> g_hw_shader_enabled;
|
||||||
std::atomic<bool> g_separable_shader_enabled;
|
std::atomic<bool> g_separable_shader_enabled;
|
||||||
std::atomic<bool> g_hw_shader_accurate_mul;
|
std::atomic<bool> g_hw_shader_accurate_mul;
|
||||||
std::atomic<bool> g_use_disk_shader_cache;
|
|
||||||
std::atomic<bool> g_renderer_bg_color_update_requested;
|
|
||||||
std::atomic<bool> g_renderer_sampler_update_requested;
|
|
||||||
std::atomic<bool> g_renderer_shader_update_requested;
|
|
||||||
std::atomic<bool> g_texture_filter_update_requested;
|
|
||||||
|
|
||||||
Memory::MemorySystem* g_memory;
|
Memory::MemorySystem* g_memory;
|
||||||
|
|
||||||
|
@ -64,18 +59,6 @@ void Shutdown() {
|
||||||
LOG_DEBUG(Render, "shutdown OK");
|
LOG_DEBUG(Render, "shutdown OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 GetResolutionScaleFactor() {
|
|
||||||
const auto graphics_api = Settings::values.graphics_api.GetValue();
|
|
||||||
if (graphics_api == Settings::GraphicsAPI::Software) {
|
|
||||||
// Software renderer always render at native resolution
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Settings::values.resolution_factor.GetValue()
|
|
||||||
? Settings::values.resolution_factor.GetValue()
|
|
||||||
: g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
ar& Pica::g_state;
|
ar& Pica::g_state;
|
||||||
|
|
|
@ -37,11 +37,6 @@ extern std::atomic<bool> g_shader_jit_enabled;
|
||||||
extern std::atomic<bool> g_hw_shader_enabled;
|
extern std::atomic<bool> g_hw_shader_enabled;
|
||||||
extern std::atomic<bool> g_separable_shader_enabled;
|
extern std::atomic<bool> g_separable_shader_enabled;
|
||||||
extern std::atomic<bool> g_hw_shader_accurate_mul;
|
extern std::atomic<bool> g_hw_shader_accurate_mul;
|
||||||
extern std::atomic<bool> g_use_disk_shader_cache;
|
|
||||||
extern std::atomic<bool> g_renderer_bg_color_update_requested;
|
|
||||||
extern std::atomic<bool> g_renderer_sampler_update_requested;
|
|
||||||
extern std::atomic<bool> g_renderer_shader_update_requested;
|
|
||||||
extern std::atomic<bool> g_texture_filter_update_requested;
|
|
||||||
|
|
||||||
extern Memory::MemorySystem* g_memory;
|
extern Memory::MemorySystem* g_memory;
|
||||||
|
|
||||||
|
@ -52,8 +47,6 @@ void Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window
|
||||||
/// Shutdown the video core
|
/// Shutdown the video core
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
u16 GetResolutionScaleFactor();
|
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int file_version);
|
void serialize(Archive& ar, const unsigned int file_version);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue