summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h7
-rw-r--r--src/video_core/texture_cache/surface_base.h17
-rw-r--r--src/video_core/texture_cache/texture_cache.h26
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
463std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers( 463std::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
186protected: 196protected:
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.