texture_cache: Implement texception detection and texture barriers.
This commit is contained in:
		 Fernando Sahmkow
					Fernando Sahmkow
				
			
				
					committed by
					
						 ReinUsesLisp
						ReinUsesLisp
					
				
			
			
				
	
			
			
			 ReinUsesLisp
						ReinUsesLisp
					
				
			
						parent
						
							198a0395bb
						
					
				
				
					commit
					d7587842eb
				
			| @@ -422,7 +422,7 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers( | ||||
|     } | ||||
|     current_framebuffer_config_state = fb_config_state; | ||||
|  | ||||
|     texture_cache.Guard(true); | ||||
|     texture_cache.GuardRenderTargets(true); | ||||
|  | ||||
|     View depth_surface{}; | ||||
|     if (using_depth_fb) { | ||||
| @@ -500,7 +500,7 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers( | ||||
|                                depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil; | ||||
|     } | ||||
|  | ||||
|     texture_cache.Guard(false); | ||||
|     texture_cache.GuardRenderTargets(false); | ||||
|  | ||||
|     current_state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey); | ||||
|     SyncViewport(current_state); | ||||
| @@ -651,7 +651,9 @@ void RasterizerOpenGL::DrawArrays() { | ||||
|     SetupVertexBuffer(vao); | ||||
|  | ||||
|     DrawParameters params = SetupDraw(); | ||||
|     texture_cache.GuardSamplers(true); | ||||
|     SetupShaders(params.primitive_mode); | ||||
|     texture_cache.GuardSamplers(false); | ||||
|  | ||||
|     ConfigureFramebuffers(state); | ||||
|  | ||||
| @@ -660,6 +662,10 @@ void RasterizerOpenGL::DrawArrays() { | ||||
|     shader_program_manager->ApplyTo(state); | ||||
|     state.Apply(); | ||||
|  | ||||
|     if (texture_cache.TextureBarrier()) { | ||||
|         glTextureBarrier(); | ||||
|     } | ||||
|  | ||||
|     params.DispatchDraw(); | ||||
|  | ||||
|     accelerate_draw = AccelDraw::Disabled; | ||||
|   | ||||
| @@ -70,8 +70,12 @@ public: | ||||
|      * `Guard` guarantees that rendertargets don't unregister themselves if the | ||||
|      * collide. Protection is currently only done on 3D slices. | ||||
|      **/ | ||||
|     void Guard(bool new_guard) { | ||||
|         guard_cache = new_guard; | ||||
|     void GuardRenderTargets(bool new_guard) { | ||||
|         guard_render_targets = new_guard; | ||||
|     } | ||||
|  | ||||
|     void GuardSamplers(bool new_guard) { | ||||
|         guard_samplers = new_guard; | ||||
|     } | ||||
|  | ||||
|     void FlushRegion(CacheAddr addr, std::size_t size) { | ||||
| @@ -98,7 +102,25 @@ public: | ||||
|             return {}; | ||||
|         } | ||||
|         const auto params{SurfaceParams::CreateForTexture(system, config, entry)}; | ||||
|         return GetSurface(gpu_addr, params, true, false).second; | ||||
|         auto pair = GetSurface(gpu_addr, params, true, false); | ||||
|         if (guard_samplers) { | ||||
|             if (sampled_textures_stack_pointer == sampled_textures_stack.size()) { | ||||
|                 sampled_textures_stack.resize(sampled_textures_stack.size() * 2); | ||||
|             } | ||||
|             sampled_textures_stack[sampled_textures_stack_pointer] = pair.first; | ||||
|             sampled_textures_stack_pointer++; | ||||
|         } | ||||
|         return pair.second; | ||||
|     } | ||||
|  | ||||
|     bool TextureBarrier() { | ||||
|         bool must_do = false; | ||||
|         for (u32 i = 0; i < sampled_textures_stack_pointer; i++) { | ||||
|             must_do |= sampled_textures_stack[i]->IsRenderTarget(); | ||||
|             sampled_textures_stack[i] = nullptr; | ||||
|         } | ||||
|         sampled_textures_stack_pointer = 0; | ||||
|         return must_do; | ||||
|     } | ||||
|  | ||||
|     TView GetDepthBufferSurface(bool preserve_contents) { | ||||
| @@ -239,6 +261,7 @@ protected: | ||||
|         make_siblings(PixelFormat::Z16, PixelFormat::R16F); | ||||
|         make_siblings(PixelFormat::Z32F, PixelFormat::R32F); | ||||
|         make_siblings(PixelFormat::Z32FS8, PixelFormat::RG32F); | ||||
|         sampled_textures_stack.resize(64); | ||||
|     } | ||||
|  | ||||
|     ~TextureCache() = default; | ||||
| @@ -275,7 +298,7 @@ protected: | ||||
|     } | ||||
|  | ||||
|     void Unregister(TSurface surface) { | ||||
|         if (guard_cache && surface->IsProtected()) { | ||||
|         if (guard_render_targets && surface->IsProtected()) { | ||||
|             return; | ||||
|         } | ||||
|         const GPUVAddr gpu_addr = surface->GetGpuAddr(); | ||||
| @@ -766,7 +789,8 @@ private: | ||||
|     u64 ticks{}; | ||||
|  | ||||
|     // Guards the cache for protection conflicts. | ||||
|     bool guard_cache{}; | ||||
|     bool guard_render_targets{}; | ||||
|     bool guard_samplers{}; | ||||
|  | ||||
|     // The siblings table is for formats that can inter exchange with one another | ||||
|     // without causing issues. This is only valid when a conflict occurs on a non | ||||
| @@ -792,6 +816,9 @@ private: | ||||
|         render_targets; | ||||
|     FramebufferTargetInfo depth_buffer; | ||||
|  | ||||
|     std::vector<TSurface> sampled_textures_stack{}; | ||||
|     u32 sampled_textures_stack_pointer{}; | ||||
|  | ||||
|     StagingCache staging_cache; | ||||
|     std::recursive_mutex mutex; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user