diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 7 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 17 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 26 |
4 files changed, 51 insertions, 14 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 63ee83391..3baf1522d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -461,15 +461,15 @@ void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, | |||
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers( | 463 | std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers( |
| 464 | OpenGLState& current_state, bool using_color_fb, bool using_depth_fb, bool preserve_contents, | 464 | OpenGLState& current_state, bool must_reconfigure, bool using_color_fb, bool using_depth_fb, |
| 465 | std::optional<std::size_t> single_color_target) { | 465 | bool preserve_contents, std::optional<std::size_t> single_color_target) { |
| 466 | MICROPROFILE_SCOPE(OpenGL_Framebuffer); | 466 | MICROPROFILE_SCOPE(OpenGL_Framebuffer); |
| 467 | auto& gpu = system.GPU().Maxwell3D(); | 467 | auto& gpu = system.GPU().Maxwell3D(); |
| 468 | const auto& regs = gpu.regs; | 468 | const auto& regs = gpu.regs; |
| 469 | 469 | ||
| 470 | const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents, | 470 | const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents, |
| 471 | single_color_target}; | 471 | single_color_target}; |
| 472 | if (fb_config_state == current_framebuffer_config_state && | 472 | if (!must_reconfigure && fb_config_state == current_framebuffer_config_state && |
| 473 | gpu.dirty_flags.color_buffer.none() && !gpu.dirty_flags.zeta_buffer) { | 473 | gpu.dirty_flags.color_buffer.none() && !gpu.dirty_flags.zeta_buffer) { |
| 474 | // Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or | 474 | // Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or |
| 475 | // single color targets). This is done because the guest registers may not change but the | 475 | // single color targets). This is done because the guest registers may not change but the |
| @@ -622,8 +622,9 @@ void RasterizerOpenGL::Clear() { | |||
| 622 | return; | 622 | return; |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | const auto [clear_depth, clear_stencil] = ConfigureFramebuffers( | 625 | const auto [clear_depth, clear_stencil] = |
| 626 | clear_state, use_color, use_depth || use_stencil, false, regs.clear_buffers.RT.Value()); | 626 | ConfigureFramebuffers(clear_state, false, use_color, use_depth || use_stencil, false, |
| 627 | regs.clear_buffers.RT.Value()); | ||
| 627 | if (regs.clear_flags.scissor) { | 628 | if (regs.clear_flags.scissor) { |
| 628 | SyncScissorTest(clear_state); | 629 | SyncScissorTest(clear_state); |
| 629 | } | 630 | } |
| @@ -705,6 +706,10 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 705 | DrawParameters params = SetupDraw(); | 706 | DrawParameters params = SetupDraw(); |
| 706 | SetupShaders(params.primitive_mode); | 707 | SetupShaders(params.primitive_mode); |
| 707 | 708 | ||
| 709 | if (texture_cache.ConsumeReconfigurationFlag()) { | ||
| 710 | ConfigureFramebuffers(state, true); | ||
| 711 | } | ||
| 712 | |||
| 708 | buffer_cache.Unmap(); | 713 | buffer_cache.Unmap(); |
| 709 | 714 | ||
| 710 | shader_program_manager->ApplyTo(state); | 715 | shader_program_manager->ApplyTo(state); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index d872e5110..970637efa 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -101,6 +101,8 @@ private: | |||
| 101 | 101 | ||
| 102 | /** | 102 | /** |
| 103 | * Configures the color and depth framebuffer states. | 103 | * Configures the color and depth framebuffer states. |
| 104 | * @param must_reconfigure If true, tells the framebuffer to skip the cache and reconfigure | ||
| 105 | * again. Used by the texture cache to solve texception conflicts | ||
| 104 | * @param use_color_fb If true, configure color framebuffers. | 106 | * @param use_color_fb If true, configure color framebuffers. |
| 105 | * @param using_depth_fb If true, configure the depth/stencil framebuffer. | 107 | * @param using_depth_fb If true, configure the depth/stencil framebuffer. |
| 106 | * @param preserve_contents If true, tries to preserve data from a previously used framebuffer. | 108 | * @param preserve_contents If true, tries to preserve data from a previously used framebuffer. |
| @@ -109,8 +111,9 @@ private: | |||
| 109 | * (requires using_depth_fb to be true) | 111 | * (requires using_depth_fb to be true) |
| 110 | */ | 112 | */ |
| 111 | std::pair<bool, bool> ConfigureFramebuffers( | 113 | std::pair<bool, bool> ConfigureFramebuffers( |
| 112 | OpenGLState& current_state, bool use_color_fb = true, bool using_depth_fb = true, | 114 | OpenGLState& current_state, bool must_reconfigure = false, bool use_color_fb = true, |
| 113 | bool preserve_contents = true, std::optional<std::size_t> single_color_target = {}); | 115 | bool using_depth_fb = true, bool preserve_contents = true, |
| 116 | std::optional<std::size_t> single_color_target = {}); | ||
| 114 | 117 | ||
| 115 | /// Configures the current constbuffers to use for the draw command. | 118 | /// Configures the current constbuffers to use for the draw command. |
| 116 | void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, | 119 | void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 017ee999e..179e80ddb 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -55,6 +55,11 @@ public: | |||
| 55 | return (cache_addr < end) && (cache_addr_end > start); | 55 | return (cache_addr < end) && (cache_addr_end > start); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) { | ||
| 59 | const GPUVAddr gpu_addr_end = gpu_addr + guest_memory_size; | ||
| 60 | return (gpu_addr <= other_start && other_end <= gpu_addr_end); | ||
| 61 | } | ||
| 62 | |||
| 58 | // Use only when recycling a surface | 63 | // Use only when recycling a surface |
| 59 | void SetGpuAddr(const GPUVAddr new_addr) { | 64 | void SetGpuAddr(const GPUVAddr new_addr) { |
| 60 | gpu_addr = new_addr; | 65 | gpu_addr = new_addr; |
| @@ -105,6 +110,12 @@ public: | |||
| 105 | return params.target == target; | 110 | return params.target == target; |
| 106 | } | 111 | } |
| 107 | 112 | ||
| 113 | bool MatchesSubTexture(const SurfaceParams& rhs, const GPUVAddr other_gpu_addr) const { | ||
| 114 | return std::tie(gpu_addr, params.target, params.num_levels) == | ||
| 115 | std::tie(other_gpu_addr, rhs.target, rhs.num_levels) && | ||
| 116 | params.target == SurfaceTarget::Texture2D && params.num_levels == 1; | ||
| 117 | } | ||
| 118 | |||
| 108 | bool MatchesTopology(const SurfaceParams& rhs) const { | 119 | bool MatchesTopology(const SurfaceParams& rhs) const { |
| 109 | const u32 src_bpp{params.GetBytesPerPixel()}; | 120 | const u32 src_bpp{params.GetBytesPerPixel()}; |
| 110 | const u32 dst_bpp{rhs.GetBytesPerPixel()}; | 121 | const u32 dst_bpp{rhs.GetBytesPerPixel()}; |
| @@ -121,9 +132,9 @@ public: | |||
| 121 | } | 132 | } |
| 122 | // Tiled surface | 133 | // Tiled surface |
| 123 | if (std::tie(params.height, params.depth, params.block_width, params.block_height, | 134 | if (std::tie(params.height, params.depth, params.block_width, params.block_height, |
| 124 | params.block_depth, params.tile_width_spacing) == | 135 | params.block_depth, params.tile_width_spacing, params.num_levels) == |
| 125 | std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, | 136 | std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, |
| 126 | rhs.tile_width_spacing)) { | 137 | rhs.tile_width_spacing, rhs.num_levels)) { |
| 127 | if (params.width == rhs.width) { | 138 | if (params.width == rhs.width) { |
| 128 | return MatchStructureResult::FullMatch; | 139 | return MatchStructureResult::FullMatch; |
| 129 | } | 140 | } |
| @@ -259,7 +270,7 @@ public: | |||
| 259 | 270 | ||
| 260 | std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { | 271 | std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { |
| 261 | if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D || | 272 | if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D || |
| 262 | view_params.target == SurfaceTarget::Texture3D) { | 273 | params.num_levels == 1 || view_params.target == SurfaceTarget::Texture3D) { |
| 263 | return {}; | 274 | return {}; |
| 264 | } | 275 | } |
| 265 | const auto layer_mipmap{GetLayerMipmap(view_addr)}; | 276 | const auto layer_mipmap{GetLayerMipmap(view_addr)}; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 422bf3e58..96d108147 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -120,6 +120,10 @@ public: | |||
| 120 | return {}; | 120 | return {}; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | if (regs.color_mask[index].raw == 0) { | ||
| 124 | return {}; | ||
| 125 | } | ||
| 126 | |||
| 123 | auto surface_view = GetSurface(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index), | 127 | auto surface_view = GetSurface(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index), |
| 124 | preserve_contents); | 128 | preserve_contents); |
| 125 | if (render_targets[index].target) | 129 | if (render_targets[index].target) |
| @@ -183,6 +187,12 @@ public: | |||
| 183 | return ++ticks; | 187 | return ++ticks; |
| 184 | } | 188 | } |
| 185 | 189 | ||
| 190 | bool ConsumeReconfigurationFlag() { | ||
| 191 | const bool result = force_reconfiguration; | ||
| 192 | force_reconfiguration = false; | ||
| 193 | return result; | ||
| 194 | } | ||
| 195 | |||
| 186 | protected: | 196 | protected: |
| 187 | TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer) | 197 | TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer) |
| 188 | : system{system}, rasterizer{rasterizer} { | 198 | : system{system}, rasterizer{rasterizer} { |
| @@ -219,9 +229,10 @@ protected: | |||
| 219 | rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); | 229 | rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); |
| 220 | } | 230 | } |
| 221 | 231 | ||
| 222 | void Unregister(TSurface surface) { | 232 | void Unregister(TSurface surface, const bool force_unregister = false) { |
| 223 | if (surface->IsProtected()) | 233 | if (surface->IsProtected() && !force_unregister) { |
| 224 | return; | 234 | return; |
| 235 | } | ||
| 225 | const GPUVAddr gpu_addr = surface->GetGpuAddr(); | 236 | const GPUVAddr gpu_addr = surface->GetGpuAddr(); |
| 226 | const CacheAddr cache_ptr = surface->GetCacheAddr(); | 237 | const CacheAddr cache_ptr = surface->GetCacheAddr(); |
| 227 | const std::size_t size = surface->GetSizeInBytes(); | 238 | const std::size_t size = surface->GetSizeInBytes(); |
| @@ -365,8 +376,10 @@ private: | |||
| 365 | std::min(src_params.height, dst_height), 1); | 376 | std::min(src_params.height, dst_height), 1); |
| 366 | ImageCopy(surface, new_surface, copy_params); | 377 | ImageCopy(surface, new_surface, copy_params); |
| 367 | } | 378 | } |
| 379 | force_reconfiguration = false; | ||
| 368 | for (auto surface : overlaps) { | 380 | for (auto surface : overlaps) { |
| 369 | Unregister(surface); | 381 | force_reconfiguration |= surface->IsProtected(); |
| 382 | Unregister(surface, true); | ||
| 370 | } | 383 | } |
| 371 | Register(new_surface); | 384 | Register(new_surface); |
| 372 | return {{new_surface, new_surface->GetMainView()}}; | 385 | return {{new_surface, new_surface->GetMainView()}}; |
| @@ -379,6 +392,7 @@ private: | |||
| 379 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 392 | const auto cache_addr{ToCacheAddr(host_ptr)}; |
| 380 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); | 393 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); |
| 381 | auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; | 394 | auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; |
| 395 | |||
| 382 | if (overlaps.empty()) { | 396 | if (overlaps.empty()) { |
| 383 | return InitializeSurface(gpu_addr, params, preserve_contents); | 397 | return InitializeSurface(gpu_addr, params, preserve_contents); |
| 384 | } | 398 | } |
| @@ -403,7 +417,7 @@ private: | |||
| 403 | return RebuildSurface(current_surface, params); | 417 | return RebuildSurface(current_surface, params); |
| 404 | } | 418 | } |
| 405 | } | 419 | } |
| 406 | if (current_surface->GetSizeInBytes() <= candidate_size) { | 420 | if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) { |
| 407 | return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, | 421 | return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, |
| 408 | false); | 422 | false); |
| 409 | } | 423 | } |
| @@ -530,6 +544,10 @@ private: | |||
| 530 | 544 | ||
| 531 | u64 ticks{}; | 545 | u64 ticks{}; |
| 532 | 546 | ||
| 547 | // Sometimes Setup Textures can hit a surface that's on the render target, when this happens | ||
| 548 | // we force a reconfiguration of the frame buffer after setup. | ||
| 549 | bool force_reconfiguration; | ||
| 550 | |||
| 533 | // The internal Cache is different for the Texture Cache. It's based on buckets | 551 | // The internal Cache is different for the Texture Cache. It's based on buckets |
| 534 | // of 1MB. This fits better for the purpose of this cache as textures are normaly | 552 | // of 1MB. This fits better for the purpose of this cache as textures are normaly |
| 535 | // large in size. | 553 | // large in size. |