diff options
| author | bunnei <bunneidev@gmail.com> | 2018-06-24 17:42:29 -0400 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2018-06-27 00:08:03 -0400 | 
| commit | 3f9f047375dd9aae7eadcb957747fa8db01544bf (patch) | |
| tree | 4a5ce82d2726e5f723a3a7a0e72d973f6d6d0573 | |
| parent | ff6785f3e8547878d26c2571513a5596e5c9ddd5 (diff) | |
gl_rasterizer: Implement AccelerateDisplay to forward textures to framebuffers.
| -rw-r--r-- | src/video_core/rasterizer_interface.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 2 | 
6 files changed, 62 insertions, 8 deletions
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index f0e48a802..145e58334 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -51,9 +51,8 @@ public:      }      /// Attempt to use a faster method to display the framebuffer to screen -    virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer, -                                   VAddr framebuffer_addr, u32 pixel_stride, -                                   ScreenInfo& screen_info) { +    virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, +                                   u32 pixel_stride, ScreenInfo& screen_info) {          return false;      } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index bc463fc30..f9b0ce434 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -468,11 +468,30 @@ bool RasterizerOpenGL::AccelerateFill(const void* config) {      return true;  } -bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer, +bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,                                           VAddr framebuffer_addr, u32 pixel_stride,                                           ScreenInfo& screen_info) { -    // TODO(bunnei): ImplementMe -    return false; +    if (!framebuffer_addr) { +        return {}; +    } + +    MICROPROFILE_SCOPE(OpenGL_CacheManagement); + +    const auto& surface{res_cache.TryFindFramebufferSurface(framebuffer_addr)}; +    if (!surface) { +        return {}; +    } + +    // Verify that the cached surface is the same size and format as the requested framebuffer +    const auto& params{surface->GetSurfaceParams()}; +    const auto& pixel_format{SurfaceParams::PixelFormatFromGPUPixelFormat(config.pixel_format)}; +    ASSERT_MSG(params.width == config.width, "Framebuffer width is different"); +    ASSERT_MSG(params.height == config.height, "Framebuffer height is different"); +    ASSERT_MSG(params.pixel_format == pixel_format, "Framebuffer pixel_format is different"); + +    screen_info.display_texture = surface->Texture().handle; + +    return true;  }  void RasterizerOpenGL::SamplerInfo::Create() { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 882490f47..919931d64 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -436,3 +436,29 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {      return surface;  } + +Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { +    // Tries to find the GPU address of a framebuffer based on the CPU address. This is because +    // final output framebuffers are specified by CPU address, but internally our GPU cache uses GPU +    // addresses. We iterate through all cached framebuffers, and compare their starting CPU address +    // to the one provided. This is obviously not great, and won't work if the framebuffer overlaps +    // surfaces. + +    std::vector<Surface> surfaces; +    for (const auto& surface : surface_cache) { +        const auto& params = surface.second->GetSurfaceParams(); +        const VAddr surface_cpu_addr = params.GetCpuAddr(); +        if (cpu_addr >= surface_cpu_addr && cpu_addr < (surface_cpu_addr + params.size_in_bytes)) { +            ASSERT_MSG(cpu_addr == surface_cpu_addr, "overlapping surfaces are unsupported"); +            surfaces.push_back(surface.second); +        } +    } + +    if (surfaces.empty()) { +        return {}; +    } + +    ASSERT_MSG(surfaces.size() == 1, ">1 surface is unsupported"); + +    return surfaces[0]; +} diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 9f1209b0f..53ff2722d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -220,6 +220,16 @@ struct SurfaceParams {          }      } +    static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { +        switch (format) { +        case Tegra::FramebufferConfig::PixelFormat::ABGR8: +            return PixelFormat::ABGR8; +        default: +            NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); +            UNREACHABLE(); +        } +    } +      static SurfaceType GetFormatType(PixelFormat pixel_format) {          if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {              return SurfaceType::ColorTexture; @@ -302,6 +312,7 @@ public:                                                      const MathUtil::Rectangle<s32>& viewport);      void LoadSurface(const Surface& surface);      void FlushSurface(const Surface& surface); +    Surface TryFindFramebufferSurface(VAddr cpu_addr) const;  private:      Surface GetSurface(const SurfaceParams& params); diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index f33766bfd..e3bb2cbb8 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -150,7 +150,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf                                           screen_info)) {          // Reset the screen info's display texture to its own permanent texture          screen_info.display_texture = screen_info.texture.resource.handle; -        screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f);          Memory::RasterizerFlushVirtualRegion(framebuffer_addr, size_in_bytes,                                               Memory::FlushMode::Flush); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 2cc6d9a00..21f0d298c 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -27,7 +27,7 @@ struct TextureInfo {  /// Structure used for storing information about the display target for the Switch screen  struct ScreenInfo {      GLuint display_texture; -    MathUtil::Rectangle<float> display_texcoords; +    const MathUtil::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};      TextureInfo texture;  };  | 
