From 926abc6ddb51b92a7898b1a5457d70209d7ae389 Mon Sep 17 00:00:00 2001 From: Phantom Date: Fri, 6 Oct 2017 17:33:00 +0200 Subject: [PATCH] integer res_scale and cleanup --- src/citra/config.cpp | 2 +- src/citra_qt/configuration/config.cpp | 3 +- .../configuration/configure_graphics.cpp | 74 +--------- src/core/frontend/framebuffer_layout.cpp | 4 +- src/core/frontend/framebuffer_layout.h | 2 +- src/core/settings.h | 2 +- .../renderer_opengl/gl_rasterizer.cpp | 47 +++---- .../renderer_opengl/gl_rasterizer.h | 4 +- .../renderer_opengl/gl_rasterizer_cache.cpp | 128 ++++++++---------- .../renderer_opengl/gl_rasterizer_cache.h | 31 ++--- .../renderer_opengl/gl_shader_gen.cpp | 2 +- 11 files changed, 99 insertions(+), 200 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 45c28ad09..72bda0be0 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -88,7 +88,7 @@ void Config::ReadValues() { Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true); Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true); Settings::values.resolution_factor = - (float)sdl2_config->GetReal("Renderer", "resolution_factor", 1.0); + static_cast(sdl2_config->GetInteger("Renderer", "resolution_factor", 1)); Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false); Settings::values.toggle_framelimit = sdl2_config->GetBoolean("Renderer", "toggle_framelimit", true); diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 5261f4c4c..718f305dc 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -73,7 +73,8 @@ void Config::ReadValues() { qt_config->beginGroup("Renderer"); Settings::values.use_hw_renderer = qt_config->value("use_hw_renderer", true).toBool(); Settings::values.use_shader_jit = qt_config->value("use_shader_jit", true).toBool(); - Settings::values.resolution_factor = qt_config->value("resolution_factor", 1.0).toFloat(); + Settings::values.resolution_factor = + static_cast(qt_config->value("resolution_factor", 1).toInt()); Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool(); Settings::values.toggle_framelimit = qt_config->value("toggle_framelimit", true).toBool(); diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp index b5a5ab1e1..22a8ca8ae 100644 --- a/src/citra_qt/configuration/configure_graphics.cpp +++ b/src/citra_qt/configuration/configure_graphics.cpp @@ -20,81 +20,11 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) ConfigureGraphics::~ConfigureGraphics() {} -enum class Resolution : int { - Auto, - Scale1x, - Scale2x, - Scale3x, - Scale4x, - Scale5x, - Scale6x, - Scale7x, - Scale8x, - Scale9x, - Scale10x, -}; - -float ToResolutionFactor(Resolution option) { - switch (option) { - case Resolution::Auto: - return 0.f; - case Resolution::Scale1x: - return 1.f; - case Resolution::Scale2x: - return 2.f; - case Resolution::Scale3x: - return 3.f; - case Resolution::Scale4x: - return 4.f; - case Resolution::Scale5x: - return 5.f; - case Resolution::Scale6x: - return 6.f; - case Resolution::Scale7x: - return 7.f; - case Resolution::Scale8x: - return 8.f; - case Resolution::Scale9x: - return 9.f; - case Resolution::Scale10x: - return 10.f; - } - return 0.f; -} - -Resolution FromResolutionFactor(float factor) { - if (factor == 0.f) { - return Resolution::Auto; - } else if (factor == 1.f) { - return Resolution::Scale1x; - } else if (factor == 2.f) { - return Resolution::Scale2x; - } else if (factor == 3.f) { - return Resolution::Scale3x; - } else if (factor == 4.f) { - return Resolution::Scale4x; - } else if (factor == 5.f) { - return Resolution::Scale5x; - } else if (factor == 6.f) { - return Resolution::Scale6x; - } else if (factor == 7.f) { - return Resolution::Scale7x; - } else if (factor == 8.f) { - return Resolution::Scale8x; - } else if (factor == 9.f) { - return Resolution::Scale9x; - } else if (factor == 10.f) { - return Resolution::Scale10x; - } - return Resolution::Auto; -} - void ConfigureGraphics::setConfiguration() { ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer); ui->resolution_factor_combobox->setEnabled(Settings::values.use_hw_renderer); ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); - ui->resolution_factor_combobox->setCurrentIndex( - static_cast(FromResolutionFactor(Settings::values.resolution_factor))); + ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor); ui->toggle_vsync->setChecked(Settings::values.use_vsync); ui->toggle_framelimit->setChecked(Settings::values.toggle_framelimit); ui->layout_combobox->setCurrentIndex(static_cast(Settings::values.layout_option)); @@ -105,7 +35,7 @@ void ConfigureGraphics::applyConfiguration() { Settings::values.use_hw_renderer = ui->toggle_hw_renderer->isChecked(); Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); Settings::values.resolution_factor = - ToResolutionFactor(static_cast(ui->resolution_factor_combobox->currentIndex())); + static_cast(ui->resolution_factor_combobox->currentIndex()); Settings::values.use_vsync = ui->toggle_vsync->isChecked(); Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked(); Settings::values.layout_option = diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index e9f778fcb..7af9556b1 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -16,8 +16,8 @@ static const float TOP_SCREEN_ASPECT_RATIO = static const float BOT_SCREEN_ASPECT_RATIO = static_cast(Core::kScreenBottomHeight) / Core::kScreenBottomWidth; -float FramebufferLayout::GetScalingRatio() const { - return static_cast(top_screen.GetWidth()) / Core::kScreenTopWidth; +u16 FramebufferLayout::GetScalingRatio() const { + return static_cast(((top_screen.GetWidth() - 1) / Core::kScreenTopWidth) + 1); } // Finds the largest size subrectangle contained in window area that is confined to the aspect ratio diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 4983cf103..0d826be9e 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -21,7 +21,7 @@ struct FramebufferLayout { * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS * screen. */ - float GetScalingRatio() const; + u16 GetScalingRatio() const; }; /** diff --git a/src/core/settings.h b/src/core/settings.h index 8d78cb424..34e5914c8 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -95,7 +95,7 @@ struct Values { // Renderer bool use_hw_renderer; bool use_shader_jit; - float resolution_factor; + u16 resolution_factor; bool use_vsync; bool toggle_framelimit; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 75fbc70a9..f2677b0e9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -245,7 +245,7 @@ void RasterizerOpenGL::DrawTriangles() { // Sync and bind the framebuffer surfaces Surface color_surface; Surface depth_surface; - MathUtil::Rectangle rect; + MathUtil::Rectangle rect; std::tie(color_surface, depth_surface, rect) = res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb); @@ -279,37 +279,32 @@ void RasterizerOpenGL::DrawTriangles() { const GLsizei viewport_height = static_cast(Pica::float24::FromRaw(regs.rasterizer.viewport_size_y).ToFloat32() * 2); - const float res_scale_width = color_surface != nullptr ? color_surface->res_scale_width : - (depth_surface == nullptr ? 1.0f : depth_surface->res_scale_width); - const float res_scale_height = color_surface != nullptr ? color_surface->res_scale_height : - (depth_surface == nullptr ? 1.0f : depth_surface->res_scale_height); + const u16 res_scale = color_surface != nullptr ? color_surface->res_scale : + (depth_surface == nullptr ? 1u : depth_surface->res_scale); glViewport( - static_cast(rect.left + regs.rasterizer.viewport_corner.x * res_scale_width), - static_cast(rect.bottom + regs.rasterizer.viewport_corner.y * res_scale_height), - static_cast(viewport_width * res_scale_width), - static_cast(viewport_height * res_scale_height)); + static_cast(rect.left + regs.rasterizer.viewport_corner.x * res_scale), + static_cast(rect.bottom + regs.rasterizer.viewport_corner.y * res_scale), + viewport_width * res_scale, + viewport_height * res_scale); - if (uniform_block_data.data.framebuffer_scale[0] != res_scale_width || - uniform_block_data.data.framebuffer_scale[1] != res_scale_height) { - - uniform_block_data.data.framebuffer_scale[0] = res_scale_width; - uniform_block_data.data.framebuffer_scale[1] = res_scale_height; + if (uniform_block_data.data.framebuffer_scale != res_scale) { + uniform_block_data.data.framebuffer_scale = res_scale; uniform_block_data.dirty = true; } // Scissor checks are window-, not viewport-relative, which means that if the cached texture // sub-rect changes, the scissor bounds also need to be updated. GLint scissor_x1 = static_cast( - rect.left + regs.rasterizer.scissor_test.x1 * res_scale_width); + rect.left + regs.rasterizer.scissor_test.x1 * res_scale); GLint scissor_y1 = static_cast( - rect.bottom + regs.rasterizer.scissor_test.y1 * res_scale_height); + rect.bottom + regs.rasterizer.scissor_test.y1 * res_scale); // x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when // scaling or doing multisampling. GLint scissor_x2 = static_cast( - rect.left + (regs.rasterizer.scissor_test.x2 + 1) * res_scale_width); + rect.left + (regs.rasterizer.scissor_test.x2 + 1) * res_scale); GLint scissor_y2 = static_cast( - rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * res_scale_height); + rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * res_scale); if (uniform_block_data.data.scissor_x1 != scissor_x1 || uniform_block_data.data.scissor_x2 != scissor_x2 || @@ -959,16 +954,15 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe dst_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.output_format); dst_params.UpdateParams(); - MathUtil::Rectangle src_rect; + MathUtil::Rectangle src_rect; Surface src_surface; std::tie(src_surface, src_rect) = res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true); if (src_surface == nullptr) return false; - dst_params.res_scale_width = src_surface->res_scale_width; - dst_params.res_scale_height = src_surface->res_scale_height; + dst_params.res_scale = src_surface->res_scale; - MathUtil::Rectangle dst_rect; + MathUtil::Rectangle dst_rect; Surface dst_surface; std::tie(dst_surface, dst_rect) = res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, false); if (dst_surface == nullptr) @@ -1004,7 +998,7 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon src_params.size = ((src_params.height - 1) * src_params.stride) + src_params.width; src_params.end = src_params.addr + src_params.size; - MathUtil::Rectangle src_rect; + MathUtil::Rectangle src_rect; Surface src_surface; std::tie(src_surface, src_rect) = res_cache.GetTexCopySurface(src_params); if (src_surface == nullptr) @@ -1019,12 +1013,11 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon dst_params.stride = (output_width + output_gap) * src_surface->stride / src_params.stride; dst_params.width = output_width * src_surface->stride / src_params.stride; dst_params.height = src_surface->is_tiled ? src_params.height * 8 : src_params.height; - dst_params.res_scale_width = src_surface->res_scale_width; - dst_params.res_scale_height = src_surface->res_scale_height; + dst_params.res_scale = src_surface->res_scale; dst_params.UpdateParams(); const bool load_gap = output_gap != 0; // Since we are going to invalidate the gap if there is one, we will have to load it first - MathUtil::Rectangle dst_rect; + MathUtil::Rectangle dst_rect; Surface dst_surface; std::tie(dst_surface, dst_rect) = res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, load_gap); if (src_surface == nullptr) @@ -1063,7 +1056,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con src_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.color_format); src_params.UpdateParams(); - MathUtil::Rectangle src_rect; + MathUtil::Rectangle src_rect; Surface src_surface; std::tie(src_surface, src_rect) = res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index e83cb48fc..18808b1e4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -136,7 +136,7 @@ private: // the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. // Not following that rule will cause problems on some AMD drivers. struct UniformData { - alignas(8) GLvec2 framebuffer_scale; + GLint framebuffer_scale; GLint alphatest_ref; GLfloat depth_scale; GLfloat depth_offset; @@ -156,7 +156,7 @@ private: }; static_assert( - sizeof(UniformData) == 0x470, + sizeof(UniformData) == 0x460, "The size of the UniformData structure has changed, update the structure in the shader"); static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec"); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 2fdddf2bb..2e9bfbff6 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -179,8 +179,8 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup cur_state.Apply(); } -static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle& src_rect, - GLuint dst_tex, const MathUtil::Rectangle& dst_rect, +static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle& src_rect, + GLuint dst_tex, const MathUtil::Rectangle& dst_rect, SurfaceType type) { OpenGLState cur_state = OpenGLState::GetCurState(); @@ -312,35 +312,23 @@ static bool FillSurface(const Surface& surface, const u8* fill_data) { return true; } -SurfaceParams::SurfaceParams() { - // todo: metroid needs that for now, "breaks" other stuff - // Set the internal resolution, assume the same scaling factor for top and bottom screens - float resolution_scale_factor = Settings::values.resolution_factor; - if (resolution_scale_factor == 0.0f) { - // Auto - scale resolution to the window size - resolution_scale_factor = VideoCore::g_emu_window->GetFramebufferLayout().GetScalingRatio(); - } - res_scale_width = resolution_scale_factor; - res_scale_height = resolution_scale_factor; -} - -MathUtil::Rectangle CachedSurface::GetSubRect(const SurfaceParams& sub_surface) const { +MathUtil::Rectangle CachedSurface::GetSubRect(const SurfaceParams& sub_surface) const { const u32 begin_pixel_index = PixelsInBytes(sub_surface.addr - addr); const int x0 = begin_pixel_index % width; const int y0 = begin_pixel_index / width; if (is_tiled) - return MathUtil::Rectangle(x0, height - y0 - sub_surface.height, x0 + sub_surface.width, height - y0); // Bottom to top + return MathUtil::Rectangle(x0, height - y0 - sub_surface.height, x0 + sub_surface.width, height - y0); // Bottom to top - return MathUtil::Rectangle(x0, y0, x0 + sub_surface.width, y0 + sub_surface.height); // Top to bottom + return MathUtil::Rectangle(x0, y0, x0 + sub_surface.width, y0 + sub_surface.height); // Top to bottom } -MathUtil::Rectangle CachedSurface::GetScaledSubRect(const SurfaceParams& sub_surface) const { +MathUtil::Rectangle CachedSurface::GetScaledSubRect(const SurfaceParams& sub_surface) const { auto rect = GetSubRect(sub_surface); - rect.left = static_cast(rect.left * res_scale_width); - rect.right = static_cast(rect.right * res_scale_width); - rect.top = static_cast(rect.top * res_scale_height); - rect.bottom = static_cast(rect.bottom * res_scale_height); + rect.left = rect.left * res_scale; + rect.right = rect.right * res_scale; + rect.top = rect.top * res_scale; + rect.bottom = rect.bottom * res_scale; return rect; } @@ -577,7 +565,7 @@ void CachedSurface::UploadGLTexture() { cur_state.Apply(); // If not 1x scale, blit 1x texture to a new scaled texture and replace texture in surface - if (res_scale_width != 1.f || res_scale_height != 1.f) { + if (res_scale != 1) { OGLTexture scaled_texture; scaled_texture.Create(); @@ -604,7 +592,7 @@ void CachedSurface::DownloadGLTexture() { // If not 1x scale, blit scaled texture to a new 1x texture and use that to flush OGLTexture unscaled_tex; - if (res_scale_width != 1.f || res_scale_height != 1.f) { + if (res_scale != 1) { unscaled_tex.Create(); AllocateSurfaceTexture(unscaled_tex.handle, tuple, width, height); @@ -626,65 +614,58 @@ void CachedSurface::DownloadGLTexture() { gl_buffer_dirty = false; } -enum MatchType : int { - Exact = (1 << 0), // Surfaces perfectly match - SubRect = (1 << 1), // Surface encompasses params - Invalid = (1 << 2), // Flag that can be applied to other match types, invalid matches require validation before they can be used - Copy = (1 << 3), // Surface we can copy from - //PartialCopy = (1 << 4), // Surface we can partialy copy from - TexCopy = (1 << 5), // Surface that will match a display transfer "texture copy" parameters - All = (1 << 6) - 1, - None = 0, +enum MatchFlags { + Invalid = 1, // Flag that can be applied to other match types, invalid matches require validation before they can be used + Exact = 1 << 1, // Surfaces perfectly match + SubRect = 1 << 2, // Surface encompasses params + Copy = 1 << 3, // Surface we can copy from + TexCopy = 1 << 4 // Surface that will match a display transfer "texture copy" parameters }; -constexpr MatchType operator | (MatchType lhs, MatchType rhs) { - return static_cast(static_cast(lhs) | static_cast(rhs)); +constexpr MatchFlags operator | (MatchFlags lhs, MatchFlags rhs) { + return static_cast(static_cast(lhs) | static_cast(rhs)); } -/// Get the best surface match (and its match type) for the given flags, higher flag value meaning lower priority -/// NEW:: no more match type priority, only region validity matters and then scaling comparison -template -Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, ScaleMatch match_res_scale) { - constexpr float MATCH_GOODNESS_RESET = -1.f; - +/// Get the best surface match (and its match type) for the given flags +template +Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, ScaleMatch match_scale_type) { Surface match_surface = nullptr; bool match_valid = false; - float best_match_goodness = MATCH_GOODNESS_RESET; + u32 match_scale = 0; for (auto& pair : RangeFromInterval(surface_cache, params.GetInterval())) { for (auto& surface : pair.second) { - const bool res_scale_match = match_res_scale == ScaleMatch::Exact ? - (params.res_scale_width == surface->res_scale_width && params.res_scale_height == surface->res_scale_height) : - (params.res_scale_width <= surface->res_scale_width && params.res_scale_height <= surface->res_scale_height); - const float match_goodness = surface->res_scale_width * surface->res_scale_height; + const bool res_scale_matched = match_scale_type == ScaleMatch::Exact ? + (params.res_scale == surface->res_scale) : + (params.res_scale <= surface->res_scale); const bool is_valid = surface->IsRegionValid(params.GetInterval()); - if (!(find_flags & MatchType::Invalid) && !is_valid) + if (!(find_flags & MatchFlags::Invalid) && !is_valid) continue; - const auto IsMatch_Helper = [&](MatchType check_type, auto match_fn) { + const auto IsMatch_Helper = [&](MatchFlags check_type, auto match_fn) { if (!(find_flags & check_type)) return false; if (!match_fn()) return false; - if (match_res_scale == ScaleMatch::Ignore || res_scale_match || surface->type == SurfaceType::Fill) { // Found a match + if (match_scale_type == ScaleMatch::Ignore || res_scale_matched || surface->type == SurfaceType::Fill) { // Found a match if (is_valid && !match_valid) { - best_match_goodness = MATCH_GOODNESS_RESET; + match_scale = 0; match_valid = true; } - if (match_goodness > best_match_goodness) { - best_match_goodness = match_goodness; + if (surface->res_scale > match_scale) { + match_scale = surface->res_scale; match_surface = surface; } } return false; }; - IsMatch_Helper(MatchType::Exact, [&] { return surface->ExactMatch(params); }); - IsMatch_Helper(MatchType::SubRect, [&] { return surface->CanSubRect(params); }); - IsMatch_Helper(MatchType::Copy, [&] { return surface->CanCopy(params); }); - IsMatch_Helper(MatchType::TexCopy, [&] { return surface->CanTexCopy(params); }); + IsMatch_Helper(MatchFlags::Exact, [&] { return surface->ExactMatch(params); }); + IsMatch_Helper(MatchFlags::SubRect, [&] { return surface->CanSubRect(params); }); + IsMatch_Helper(MatchFlags::Copy, [&] { return surface->CanCopy(params); }); + IsMatch_Helper(MatchFlags::TexCopy, [&] { return surface->CanTexCopy(params); }); } } return match_surface; @@ -704,9 +685,9 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() { } bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface, - const MathUtil::Rectangle& src_rect, + const MathUtil::Rectangle& src_rect, const Surface& dst_surface, - const MathUtil::Rectangle& dst_rect) { + const MathUtil::Rectangle& dst_rect) { if (!SurfaceParams::CheckFormatsBlittable(src_surface->pixel_format, dst_surface->pixel_format)) return false; @@ -722,7 +703,7 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc } // Check for an exact or subrect match in existing surfaces - Surface surface_match = FindMatch(surface_cache, params, match_res_scale); + Surface surface_match = FindMatch(surface_cache, params, match_res_scale); if (surface_match != nullptr) { if (load_if_create) { @@ -745,14 +726,14 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale, bool load_if_create) { - MathUtil::Rectangle out_rect{}; + MathUtil::Rectangle out_rect{}; if (params.addr == 0 || params.height * params.width == 0) { return std::make_tuple(nullptr, out_rect); } // Attempt to find encompassing surface - Surface subrect_match = FindMatch(surface_cache, params, match_res_scale); + Surface subrect_match = FindMatch(surface_cache, params, match_res_scale); // Return the best subrect surface if found if (subrect_match != nullptr) { @@ -778,7 +759,7 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& std::swap(out_rect.top, out_rect.bottom); // If stride was bigger than width we need to adjust our output rect - out_rect.right = static_cast(params.width * new_params.res_scale_width); + out_rect.right = static_cast(params.width * new_params.res_scale); Surface new_surface = CreateSurface(new_params); if (load_if_create) @@ -802,8 +783,8 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::TexturingRegs::Full return GetSurface(params, ScaleMatch::Ignore, true); } -constexpr float GetResolutionScaleFactor() { - return Settings::values.resolution_factor == 0.0f ? +constexpr u16 GetResolutionScaleFactor() { + return !Settings::values.resolution_factor ? VideoCore::g_emu_window->GetFramebufferLayout().GetScalingRatio() : Settings::values.resolution_factor; } @@ -834,7 +815,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool usin color_params.is_tiled = depth_params.is_tiled = true; // update resolution_scale_factor and reset cache if changed - static float resolution_scale_factor = GetResolutionScaleFactor(); + static u16 resolution_scale_factor = GetResolutionScaleFactor(); if (resolution_scale_factor != GetResolutionScaleFactor()) { resolution_scale_factor = GetResolutionScaleFactor(); FlushAll(); @@ -845,19 +826,17 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool usin color_params.width = depth_params.width = config.GetWidth(); color_params.height = depth_params.height = config.GetHeight(); color_params.pixel_format = SurfaceParams::PixelFormatFromColorFormat(config.color_format); - color_params.res_scale_height = resolution_scale_factor; - color_params.res_scale_width = resolution_scale_factor; + color_params.res_scale = resolution_scale_factor; color_params.UpdateParams(); - MathUtil::Rectangle rect{}; + MathUtil::Rectangle rect{}; Surface color_surface = nullptr; if (using_color_fb) std::tie(color_surface, rect) = GetSurfaceSubRect(color_params, ScaleMatch::Exact, true); depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(config.depth_format); depth_params.addr = config.GetDepthBufferPhysicalAddress(); - depth_params.res_scale_height = resolution_scale_factor; - depth_params.res_scale_width = resolution_scale_factor; + depth_params.res_scale = resolution_scale_factor; depth_params.UpdateParams(); Surface depth_surface = nullptr; @@ -900,9 +879,9 @@ Surface RasterizerCacheOpenGL::GetFillSurface(const GPU::Regs::MemoryFillConfig& } SurfaceRect_Tuple RasterizerCacheOpenGL::GetTexCopySurface(const SurfaceParams& params) { - MathUtil::Rectangle rect{}; + MathUtil::Rectangle rect{}; - Surface match_surface = FindMatch(surface_cache, params, ScaleMatch::Ignore); + Surface match_surface = FindMatch(surface_cache, params, ScaleMatch::Ignore); if (match_surface != nullptr) { ValidateSurface(match_surface, params.addr, params.size); @@ -964,7 +943,7 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, PAddr addr, } params.UpdateParams(); - Surface match_surface = FindMatch(surface_cache, params, ScaleMatch::Ignore); + Surface match_surface = FindMatch(surface_cache, params, ScaleMatch::Ignore); if (match_surface != nullptr) { if (!match_surface->CanSubRect(params)) { @@ -1046,8 +1025,6 @@ void RasterizerCacheOpenGL::InvalidateRegion(PAddr addr, u32 size, const Surface region_owner->invalid_regions.erase(invalid_interval); } - SurfaceSet remove_surfaces; - for (auto& pair : RangeFromInterval(surface_cache, invalid_interval)) { for (auto& cached_surface : pair.second) { if (cached_surface == region_owner) @@ -1085,6 +1062,7 @@ void RasterizerCacheOpenGL::InvalidateRegion(PAddr addr, u32 size, const Surface for (auto& remove_surface : remove_surfaces) UnregisterSurface(remove_surface); + remove_surfaces.clear(); } Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 1249b6e42..0a524213e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -39,8 +39,8 @@ using SurfaceInterval = SurfaceCache::interval_type; static_assert(std::is_same() && std::is_same(), "incorrect interval types"); -using SurfaceRect_Tuple = std::tuple>; -using SurfaceSurfaceRect_Tuple = std::tuple>; +using SurfaceRect_Tuple = std::tuple>; +using SurfaceSurfaceRect_Tuple = std::tuple>; using PageMap = boost::icl::interval_map; @@ -51,8 +51,6 @@ enum class ScaleMatch { }; struct SurfaceParams { - explicit SurfaceParams(); - enum class PixelFormat { // First 5 formats are shared between textures and color buffers RGBA8 = 0, @@ -200,19 +198,19 @@ struct SurfaceParams { } u32 GetScaledWidth() const { - return static_cast(width * res_scale_width); + return width * res_scale; } u32 GetScaledHeight() const { - return static_cast(height * res_scale_height); + return height * res_scale; } - MathUtil::Rectangle GetRect() const { - return MathUtil::Rectangle(0, 0, width, height); + MathUtil::Rectangle GetRect() const { + return { 0, 0, width, height }; } - MathUtil::Rectangle GetScaledRect() const { - return MathUtil::Rectangle(0, 0, GetScaledWidth(), GetScaledHeight()); + MathUtil::Rectangle GetScaledRect() const { + return { 0, 0, GetScaledWidth(), GetScaledHeight() }; } u32 PixelsInBytes(u32 size) const { @@ -226,8 +224,7 @@ struct SurfaceParams { u32 width = 0; u32 height = 0; u32 stride = 0; - float res_scale_width = 1.f; - float res_scale_height = 1.f; + u16 res_scale = 1; bool is_tiled = false; u32 bytes_per_pixel = 0; @@ -239,11 +236,10 @@ struct CachedSurface : SurfaceParams { bool ExactMatch(const SurfaceParams& other_surface) const; bool CanSubRect(const SurfaceParams& sub_surface) const; bool CanCopy(const SurfaceParams& dest_surface) const; - //bool CanPartialCopy(const SurfaceParams& dest_surface) const; bool CanTexCopy(const SurfaceParams& texcopy_params) const; - MathUtil::Rectangle GetSubRect(const SurfaceParams& sub_surface) const; - MathUtil::Rectangle GetScaledSubRect(const SurfaceParams& sub_surface) const; + MathUtil::Rectangle GetSubRect(const SurfaceParams& sub_surface) const; + MathUtil::Rectangle GetScaledSubRect(const SurfaceParams& sub_surface) const; bool IsRegionValid(const SurfaceInterval& interval) const { return (invalid_regions.find(interval) == invalid_regions.end()); @@ -283,8 +279,8 @@ public: ~RasterizerCacheOpenGL(); /// Blit one surface's texture to another - bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle& src_rect, - const Surface& dst_surface, const MathUtil::Rectangle& dst_rect); + bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle& src_rect, + const Surface& dst_surface, const MathUtil::Rectangle& dst_rect); /// Load a texture from 3DS memory to OpenGL and cache it (if not already cached) Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale, bool load_if_create); @@ -334,4 +330,5 @@ private: SurfaceCache surface_cache; SurfaceMap dirty_regions; PageMap cached_pages; + SurfaceSet remove_surfaces; }; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 9fe183944..62f449a35 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -41,7 +41,7 @@ struct LightSrc { }; layout (std140) uniform shader_data { - vec2 framebuffer_scale; + int framebuffer_scale; int alphatest_ref; float depth_scale; float depth_offset;