mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	gl_rasterizer_cache: Detect and ignore unnecessary texture flushes.
This commit is contained in:
		@@ -231,8 +231,8 @@ void RasterizerOpenGL::DrawTriangles() {
 | 
			
		||||
    u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
 | 
			
		||||
                            * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
 | 
			
		||||
 | 
			
		||||
    res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size);
 | 
			
		||||
    res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size);
 | 
			
		||||
    res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size, true);
 | 
			
		||||
    res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::CommitFramebuffer() {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "common/hash.h"
 | 
			
		||||
#include "common/make_unique.h"
 | 
			
		||||
#include "common/math_util.h"
 | 
			
		||||
#include "common/microprofile.h"
 | 
			
		||||
@@ -21,7 +22,6 @@ MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128
 | 
			
		||||
 | 
			
		||||
void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) {
 | 
			
		||||
    PAddr texture_addr = config.config.GetPhysicalAddress();
 | 
			
		||||
 | 
			
		||||
    const auto cached_texture = texture_cache.find(texture_addr);
 | 
			
		||||
 | 
			
		||||
    if (cached_texture != texture_cache.end()) {
 | 
			
		||||
@@ -51,12 +51,14 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format);
 | 
			
		||||
        u8* texture_src_data = Memory::GetPhysicalPointer(texture_addr);
 | 
			
		||||
 | 
			
		||||
        new_texture->width = info.width;
 | 
			
		||||
        new_texture->height = info.height;
 | 
			
		||||
        new_texture->size = info.width * info.height * Pica::Regs::NibblesPerPixel(info.format);
 | 
			
		||||
        new_texture->size = info.stride * info.height;
 | 
			
		||||
        new_texture->addr = texture_addr;
 | 
			
		||||
        new_texture->hash = Common::ComputeHash64(texture_src_data, new_texture->size);
 | 
			
		||||
 | 
			
		||||
        u8* texture_src_data = Memory::GetPhysicalPointer(texture_addr);
 | 
			
		||||
        std::unique_ptr<Math::Vec4<u8>[]> temp_texture_buffer_rgba(new Math::Vec4<u8>[info.width * info.height]);
 | 
			
		||||
 | 
			
		||||
        for (int y = 0; y < info.height; ++y) {
 | 
			
		||||
@@ -71,12 +73,18 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size) {
 | 
			
		||||
void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size, bool ignore_hash) {
 | 
			
		||||
    // Flush any texture that falls in the flushed region
 | 
			
		||||
    // TODO: Optimize by also inserting upper bound (addr + size) of each texture into the same map and also narrow using lower_bound
 | 
			
		||||
    auto cache_upper_bound = texture_cache.upper_bound(addr + size);
 | 
			
		||||
 | 
			
		||||
    for (auto it = texture_cache.begin(); it != cache_upper_bound;) {
 | 
			
		||||
        if (MathUtil::IntervalsIntersect(addr, size, it->first, it->second->size)) {
 | 
			
		||||
        const auto& info = *it->second;
 | 
			
		||||
 | 
			
		||||
        // Flush the texture only if the memory region intersects and a change is detected
 | 
			
		||||
        if (MathUtil::IntervalsIntersect(addr, size, info.addr, info.size) &&
 | 
			
		||||
            (ignore_hash || info.hash != Common::ComputeHash64(Memory::GetPhysicalPointer(info.addr), info.size))) {
 | 
			
		||||
 | 
			
		||||
            it = texture_cache.erase(it);
 | 
			
		||||
        } else {
 | 
			
		||||
            ++it;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ public:
 | 
			
		||||
    void LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config);
 | 
			
		||||
 | 
			
		||||
    /// Flush any cached resource that touches the flushed region
 | 
			
		||||
    void NotifyFlush(PAddr addr, u32 size);
 | 
			
		||||
    void NotifyFlush(PAddr addr, u32 size, bool ignore_hash = false);
 | 
			
		||||
 | 
			
		||||
    /// Flush all cached OpenGL resources tracked by this cache manager
 | 
			
		||||
    void FullFlush();
 | 
			
		||||
@@ -30,6 +30,8 @@ private:
 | 
			
		||||
        GLuint width;
 | 
			
		||||
        GLuint height;
 | 
			
		||||
        u32 size;
 | 
			
		||||
        u64 hash;
 | 
			
		||||
        PAddr addr;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::map<PAddr, std::unique_ptr<CachedTexture>> texture_cache;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user