texture_cache: Implement texception detection and texture barriers.
This commit is contained in:
		
							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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user