diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index bc936887719d4772174f386fac17de6a0b884175..b457b1fbe127506a84f3ac34e6e22bf638bf59af 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -560,6 +560,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu
 
     SurfaceParams src_params;
     src_params.cpu_addr = framebuffer_addr;
+    src_params.addr = res_cache.TryFindFramebufferGpuAddress(framebuffer_addr).get_value_or(0);
     src_params.width = std::min(framebuffer.width, pixel_stride);
     src_params.height = framebuffer.height;
     src_params.stride = pixel_stride;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index e1ad00feb8cb39a3b4a86366a2cb072a0d0339ba..b924f1b8e4b3673b9412e21c358dfddc18f7bef8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -954,6 +954,33 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
     return surface;
 }
 
+boost::optional<Tegra::GPUVAddr> RasterizerCacheOpenGL::TryFindFramebufferGpuAddress(
+    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<Tegra::GPUVAddr> gpu_addresses;
+    for (const auto& pair : surface_cache) {
+        for (const auto& surface : pair.second) {
+            const VAddr surface_cpu_addr = surface->GetCpuAddr();
+            if (cpu_addr >= surface_cpu_addr && cpu_addr < (surface_cpu_addr + surface->size)) {
+                ASSERT_MSG(cpu_addr == surface_cpu_addr, "overlapping surfaces are unsupported");
+                gpu_addresses.push_back(surface->addr);
+            }
+        }
+    }
+
+    if (gpu_addresses.empty()) {
+        return {};
+    }
+
+    ASSERT_MSG(gpu_addresses.size() == 1, ">1 surface is unsupported");
+    return gpu_addresses[0];
+}
+
 SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params,
                                                            ScaleMatch match_res_scale,
                                                            bool load_if_create) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 08858bab433d47311429924efd72722ef38de4dd..dfddcce90932f631c6a6faed7825b9bc0168d445 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -411,6 +411,9 @@ public:
     Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
                        bool load_if_create);
 
+    /// Tries to find a framebuffer GPU address based on the provided CPU address
+    boost::optional<Tegra::GPUVAddr> TryFindFramebufferGpuAddress(VAddr cpu_addr) const;
+
     /// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
     /// Switch memory to OpenGL and caches it (if not already cached)
     SurfaceRect_Tuple GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale,