diff options
| author | 2018-07-21 16:04:01 -0400 | |
|---|---|---|
| committer | 2018-07-21 21:51:06 -0400 | |
| commit | 63fbf9a7d3e24c684cf6f0868f30021a8ddf7256 (patch) | |
| tree | 741aaf7b4a46bbcce5a25192d8df0c3f3d2c88fd /src | |
| parent | gl_rasterizer_cache: Use GPUVAddr as cache key, not parameter set. (diff) | |
| download | yuzu-63fbf9a7d3e24c684cf6f0868f30021a8ddf7256.tar.gz yuzu-63fbf9a7d3e24c684cf6f0868f30021a8ddf7256.tar.xz yuzu-63fbf9a7d3e24c684cf6f0868f30021a8ddf7256.zip | |
gl_rasterizer_cache: Blit surfaces on recreation instead of flush and load.
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 85 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 3 |
2 files changed, 86 insertions, 2 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index bb53a2821..28f0bc379 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -254,6 +254,60 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup | |||
| 254 | cur_state.Apply(); | 254 | cur_state.Apply(); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, | ||
| 258 | const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, | ||
| 259 | GLuint read_fb_handle, GLuint draw_fb_handle) { | ||
| 260 | OpenGLState prev_state{OpenGLState::GetCurState()}; | ||
| 261 | SCOPE_EXIT({ prev_state.Apply(); }); | ||
| 262 | |||
| 263 | OpenGLState state; | ||
| 264 | state.draw.read_framebuffer = read_fb_handle; | ||
| 265 | state.draw.draw_framebuffer = draw_fb_handle; | ||
| 266 | state.Apply(); | ||
| 267 | |||
| 268 | u32 buffers{}; | ||
| 269 | |||
| 270 | if (type == SurfaceType::ColorTexture) { | ||
| 271 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, | ||
| 272 | 0); | ||
| 273 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 274 | 0); | ||
| 275 | |||
| 276 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, | ||
| 277 | 0); | ||
| 278 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 279 | 0); | ||
| 280 | |||
| 281 | buffers = GL_COLOR_BUFFER_BIT; | ||
| 282 | } else if (type == SurfaceType::Depth) { | ||
| 283 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 284 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, src_tex, 0); | ||
| 285 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 286 | |||
| 287 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 288 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dst_tex, 0); | ||
| 289 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 290 | |||
| 291 | buffers = GL_DEPTH_BUFFER_BIT; | ||
| 292 | } else if (type == SurfaceType::DepthStencil) { | ||
| 293 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 294 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 295 | src_tex, 0); | ||
| 296 | |||
| 297 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | ||
| 298 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 299 | dst_tex, 0); | ||
| 300 | |||
| 301 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | ||
| 302 | } | ||
| 303 | |||
| 304 | glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left, | ||
| 305 | dst_rect.bottom, dst_rect.right, dst_rect.top, buffers, | ||
| 306 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | ||
| 307 | |||
| 308 | return true; | ||
| 309 | } | ||
| 310 | |||
| 257 | CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { | 311 | CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { |
| 258 | texture.Create(); | 312 | texture.Create(); |
| 259 | const auto& rect{params.GetRect()}; | 313 | const auto& rect{params.GetRect()}; |
| @@ -580,19 +634,25 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | |||
| 580 | if (gpu.memory_manager->GpuToCpuAddress(params.addr) == boost::none) | 634 | if (gpu.memory_manager->GpuToCpuAddress(params.addr) == boost::none) |
| 581 | return {}; | 635 | return {}; |
| 582 | 636 | ||
| 583 | // Check for an exact match in existing surfaces | 637 | // Look up surface in the cache based on address |
| 584 | const auto& search{surface_cache.find(params.addr)}; | 638 | const auto& search{surface_cache.find(params.addr)}; |
| 585 | Surface surface; | 639 | Surface surface; |
| 586 | if (search != surface_cache.end()) { | 640 | if (search != surface_cache.end()) { |
| 587 | surface = search->second; | 641 | surface = search->second; |
| 588 | if (surface->GetSurfaceParams() != params || Settings::values.use_accurate_framebuffers) { | 642 | if (Settings::values.use_accurate_framebuffers) { |
| 643 | // If use_accurate_framebuffers is enabled, always load from memory | ||
| 589 | FlushSurface(surface); | 644 | FlushSurface(surface); |
| 590 | UnregisterSurface(surface); | 645 | UnregisterSurface(surface); |
| 646 | } else if (surface->GetSurfaceParams() != params) { | ||
| 647 | // If surface parameters changed, recreate the surface from the old one | ||
| 648 | return RecreateSurface(surface, params); | ||
| 591 | } else { | 649 | } else { |
| 650 | // Use the cached surface as-is | ||
| 592 | return surface; | 651 | return surface; |
| 593 | } | 652 | } |
| 594 | } | 653 | } |
| 595 | 654 | ||
| 655 | // No surface found - create a new one | ||
| 596 | surface = std::make_shared<CachedSurface>(params); | 656 | surface = std::make_shared<CachedSurface>(params); |
| 597 | RegisterSurface(surface); | 657 | RegisterSurface(surface); |
| 598 | LoadSurface(surface); | 658 | LoadSurface(surface); |
| @@ -600,6 +660,27 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { | |||
| 600 | return surface; | 660 | return surface; |
| 601 | } | 661 | } |
| 602 | 662 | ||
| 663 | Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface, | ||
| 664 | const SurfaceParams& new_params) { | ||
| 665 | // Verify surface is compatible for blitting | ||
| 666 | const auto& params{surface->GetSurfaceParams()}; | ||
| 667 | ASSERT(params.type == new_params.type); | ||
| 668 | ASSERT(params.pixel_format == new_params.pixel_format); | ||
| 669 | ASSERT(params.component_type == new_params.component_type); | ||
| 670 | |||
| 671 | // Create a new surface with the new parameters, and blit the previous surface to it | ||
| 672 | Surface new_surface{std::make_shared<CachedSurface>(new_params)}; | ||
| 673 | BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle, | ||
| 674 | new_surface->GetSurfaceParams().GetRect(), params.type, read_framebuffer.handle, | ||
| 675 | draw_framebuffer.handle); | ||
| 676 | |||
| 677 | // Update cache accordingly | ||
| 678 | UnregisterSurface(surface); | ||
| 679 | RegisterSurface(new_surface); | ||
| 680 | |||
| 681 | return new_surface; | ||
| 682 | } | ||
| 683 | |||
| 603 | Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { | 684 | Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { |
| 604 | // Tries to find the GPU address of a framebuffer based on the CPU address. This is because | 685 | // Tries to find the GPU address of a framebuffer based on the CPU address. This is because |
| 605 | // final output framebuffers are specified by CPU address, but internally our GPU cache uses | 686 | // final output framebuffers are specified by CPU address, but internally our GPU cache uses |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 5124199b2..b084c4db4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -454,6 +454,9 @@ private: | |||
| 454 | void LoadSurface(const Surface& surface); | 454 | void LoadSurface(const Surface& surface); |
| 455 | Surface GetSurface(const SurfaceParams& params); | 455 | Surface GetSurface(const SurfaceParams& params); |
| 456 | 456 | ||
| 457 | /// Recreates a surface with new parameters | ||
| 458 | Surface RecreateSurface(const Surface& surface, const SurfaceParams& new_params); | ||
| 459 | |||
| 457 | /// Register surface into the cache | 460 | /// Register surface into the cache |
| 458 | void RegisterSurface(const Surface& surface); | 461 | void RegisterSurface(const Surface& surface); |
| 459 | 462 | ||