diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 97 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 11 | 
2 files changed, 104 insertions, 4 deletions
| diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 78fa7c051..81b4a64a7 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -21,10 +21,13 @@  #include "common/microprofile.h"  #include "common/scope_exit.h"  #include "common/vector_math.h" +#include "core/core.h"  #include "core/frontend/emu_window.h" +#include "core/hle/kernel/process.h"  #include "core/hle/kernel/vm_manager.h"  #include "core/memory.h"  #include "core/settings.h" +#include "video_core/engines/maxwell_3d.h"  #include "video_core/renderer_opengl/gl_rasterizer_cache.h"  #include "video_core/renderer_opengl/gl_state.h"  #include "video_core/utils.h" @@ -1098,9 +1101,97 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const void* config) {  }  SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( -    bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport_rect) { -    UNIMPLEMENTED(); -    return {}; +    bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport) { +    const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; +    const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; +    const auto& config = regs.rt[0]; + +    // TODO(bunnei): This is hard corded to use just the first render buffer +    LOG_WARNING(Render_OpenGL, "hard-coded for render target 0!"); + +    // update resolution_scale_factor and reset cache if changed +    // TODO (bunnei): This code was ported as-is from Citra, and is technically not thread-safe. We +    // need to fix this before making the renderer multi-threaded. +    static u16 resolution_scale_factor = GetResolutionScaleFactor(); +    if (resolution_scale_factor != GetResolutionScaleFactor()) { +        resolution_scale_factor = GetResolutionScaleFactor(); +        FlushAll(); +        while (!surface_cache.empty()) +            UnregisterSurface(*surface_cache.begin()->second.begin()); +    } + +    MathUtil::Rectangle<u32> viewport_clamped{ +        static_cast<u32>(MathUtil::Clamp(viewport.left, 0, static_cast<s32>(config.width))), +        static_cast<u32>(MathUtil::Clamp(viewport.top, 0, static_cast<s32>(config.height))), +        static_cast<u32>(MathUtil::Clamp(viewport.right, 0, static_cast<s32>(config.width))), +        static_cast<u32>(MathUtil::Clamp(viewport.bottom, 0, static_cast<s32>(config.height)))}; + +    // get color and depth surfaces +    SurfaceParams color_params; +    color_params.is_tiled = true; +    color_params.res_scale = resolution_scale_factor; +    color_params.width = config.width; +    color_params.height = config.height; +    SurfaceParams depth_params = color_params; + +    color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); +    color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); +    color_params.UpdateParams(); + +    ASSERT(!using_depth_fb, "depth buffer is unimplemented"); +    // depth_params.addr = config.GetDepthBufferPhysicalAddress(); +    // depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(config.depth_format); +    // depth_params.UpdateParams(); + +    auto color_vp_interval = color_params.GetSubRectInterval(viewport_clamped); +    auto depth_vp_interval = depth_params.GetSubRectInterval(viewport_clamped); + +    // Make sure that framebuffers don't overlap if both color and depth are being used +    if (using_color_fb && using_depth_fb && +        boost::icl::length(color_vp_interval & depth_vp_interval)) { +        LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " +                                    "overlapping framebuffers not supported!"); +        using_depth_fb = false; +    } + +    MathUtil::Rectangle<u32> color_rect{}; +    Surface color_surface = nullptr; +    if (using_color_fb) +        std::tie(color_surface, color_rect) = +            GetSurfaceSubRect(color_params, ScaleMatch::Exact, false); + +    MathUtil::Rectangle<u32> depth_rect{}; +    Surface depth_surface = nullptr; +    if (using_depth_fb) +        std::tie(depth_surface, depth_rect) = +            GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false); + +    MathUtil::Rectangle<u32> fb_rect{}; +    if (color_surface != nullptr && depth_surface != nullptr) { +        fb_rect = color_rect; +        // Color and Depth surfaces must have the same dimensions and offsets +        if (color_rect.bottom != depth_rect.bottom || color_rect.top != depth_rect.top || +            color_rect.left != depth_rect.left || color_rect.right != depth_rect.right) { +            color_surface = GetSurface(color_params, ScaleMatch::Exact, false); +            depth_surface = GetSurface(depth_params, ScaleMatch::Exact, false); +            fb_rect = color_surface->GetScaledRect(); +        } +    } else if (color_surface != nullptr) { +        fb_rect = color_rect; +    } else if (depth_surface != nullptr) { +        fb_rect = depth_rect; +    } + +    if (color_surface != nullptr) { +        ValidateSurface(color_surface, boost::icl::first(color_vp_interval), +                        boost::icl::length(color_vp_interval)); +    } +    if (depth_surface != nullptr) { +        ValidateSurface(depth_surface, boost::icl::first(depth_vp_interval), +                        boost::icl::length(depth_vp_interval)); +    } + +    return std::make_tuple(color_surface, depth_surface, fb_rect);  }  Surface RasterizerCacheOpenGL::GetFillSurface(const void* config) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 14f3cdc38..0e1c481d7 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -116,6 +116,15 @@ struct SurfaceParams {          return GetFormatBpp(pixel_format);      } +    static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { +        switch (format) { +        case Tegra::RenderTargetFormat::RGBA8_UNORM: +            return PixelFormat::RGBA8; +        default: +            UNREACHABLE(); +        } +    } +      static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {          switch (format) {          case Tegra::FramebufferConfig::PixelFormat::ABGR8: @@ -308,7 +317,7 @@ public:      /// Get the color and depth surfaces based on the framebuffer configuration      SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, -                                                    const MathUtil::Rectangle<s32>& viewport_rect); +                                                    const MathUtil::Rectangle<s32>& viewport);      /// Get a surface that matches the fill config      Surface GetFillSurface(const void* config); | 
