Corrections and redesign.
This commit is contained in:
		
							parent
							
								
									d6b9b51606
								
							
						
					
					
						commit
						5a9204dbd7
					
				@ -3,6 +3,7 @@
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <glad/glad.h>
 | 
			
		||||
 | 
			
		||||
#include "common/alignment.h"
 | 
			
		||||
@ -1000,7 +1001,7 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres
 | 
			
		||||
    Surface surface{TryGet(params.addr)};
 | 
			
		||||
    if (surface) {
 | 
			
		||||
        if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
 | 
			
		||||
            // Use the cached surface as-is
 | 
			
		||||
            // Use the cached surface as-is unless it's not synced with memory
 | 
			
		||||
            if (surface->MustReload())
 | 
			
		||||
                LoadSurface(surface);
 | 
			
		||||
            return surface;
 | 
			
		||||
@ -1298,44 +1299,47 @@ Surface RasterizerCacheOpenGL::TryGetReservedSurface(const SurfaceParams& params
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FindBestMipMap(std::size_t memory, const SurfaceParams params, u32 height, u32& mipmap) {
 | 
			
		||||
    for (u32 i = 0; i < params.max_mip_level; i++)
 | 
			
		||||
static std::optional<u32> TryFindBestMipMap(std::size_t memory, const SurfaceParams params,
 | 
			
		||||
                                            u32 height) {
 | 
			
		||||
    for (u32 i = 0; i < params.max_mip_level; i++) {
 | 
			
		||||
        if (memory == params.GetMipmapSingleSize(i) && params.MipHeight(i) == height) {
 | 
			
		||||
            mipmap = i;
 | 
			
		||||
            return true;
 | 
			
		||||
            return {i};
 | 
			
		||||
        }
 | 
			
		||||
    return false;
 | 
			
		||||
    }
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FindBestLayer(VAddr addr, const SurfaceParams params, u32 mipmap, u32& layer) {
 | 
			
		||||
    std::size_t size = params.LayerMemorySize();
 | 
			
		||||
static std::optional<u32> TryFindBestLayer(VAddr addr, const SurfaceParams params, u32 mipmap) {
 | 
			
		||||
    const std::size_t size = params.LayerMemorySize();
 | 
			
		||||
    VAddr start = params.addr + params.GetMipmapLevelOffset(mipmap);
 | 
			
		||||
    for (u32 i = 0; i < params.depth; i++) {
 | 
			
		||||
        if (start == addr) {
 | 
			
		||||
            layer = i;
 | 
			
		||||
            return true;
 | 
			
		||||
            return {i};
 | 
			
		||||
        }
 | 
			
		||||
        start += size;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayerFitReinterpretSurface(RasterizerCacheOpenGL& cache, const Surface render_surface,
 | 
			
		||||
                                const Surface blitted_surface) {
 | 
			
		||||
    const auto dst_params = blitted_surface->GetSurfaceParams();
 | 
			
		||||
    const auto src_params = render_surface->GetSurfaceParams();
 | 
			
		||||
    u32 level = 0;
 | 
			
		||||
    std::size_t src_memory_size = src_params.size_in_bytes;
 | 
			
		||||
    if (FindBestMipMap(src_memory_size, dst_params, src_params.height, level)) {
 | 
			
		||||
        if (src_params.width == dst_params.MipWidthGobAligned(level) &&
 | 
			
		||||
            src_params.height == dst_params.MipHeight(level) &&
 | 
			
		||||
            src_params.block_height >= dst_params.MipBlockHeight(level)) {
 | 
			
		||||
            u32 slot = 0;
 | 
			
		||||
            if (FindBestLayer(render_surface->GetAddr(), dst_params, level, slot)) {
 | 
			
		||||
                glCopyImageSubData(
 | 
			
		||||
                    render_surface->Texture().handle, SurfaceTargetToGL(src_params.target), 0, 0, 0,
 | 
			
		||||
                    0, blitted_surface->Texture().handle, SurfaceTargetToGL(dst_params.target),
 | 
			
		||||
                    level, 0, 0, slot, dst_params.MipWidth(level), dst_params.MipHeight(level), 1);
 | 
			
		||||
static bool LayerFitReinterpretSurface(RasterizerCacheOpenGL& cache, const Surface render_surface,
 | 
			
		||||
                                       const Surface blitted_surface) {
 | 
			
		||||
    const auto& dst_params = blitted_surface->GetSurfaceParams();
 | 
			
		||||
    const auto& src_params = render_surface->GetSurfaceParams();
 | 
			
		||||
    const std::size_t src_memory_size = src_params.size_in_bytes;
 | 
			
		||||
    const std::optional<u32> level =
 | 
			
		||||
        TryFindBestMipMap(src_memory_size, dst_params, src_params.height);
 | 
			
		||||
    if (level.has_value()) {
 | 
			
		||||
        if (src_params.width == dst_params.MipWidthGobAligned(*level) &&
 | 
			
		||||
            src_params.height == dst_params.MipHeight(*level) &&
 | 
			
		||||
            src_params.block_height >= dst_params.MipBlockHeight(*level)) {
 | 
			
		||||
            const std::optional<u32> slot =
 | 
			
		||||
                TryFindBestLayer(render_surface->GetAddr(), dst_params, *level);
 | 
			
		||||
            if (slot.has_value()) {
 | 
			
		||||
                glCopyImageSubData(render_surface->Texture().handle,
 | 
			
		||||
                                   SurfaceTargetToGL(src_params.target), 0, 0, 0, 0,
 | 
			
		||||
                                   blitted_surface->Texture().handle,
 | 
			
		||||
                                   SurfaceTargetToGL(dst_params.target), *level, 0, 0, *slot,
 | 
			
		||||
                                   dst_params.MipWidth(*level), dst_params.MipHeight(*level), 1);
 | 
			
		||||
                blitted_surface->MarkAsModified(true, cache);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
@ -1344,24 +1348,21 @@ bool LayerFitReinterpretSurface(RasterizerCacheOpenGL& cache, const Surface rend
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsReinterpretInvalid(const Surface render_surface, const Surface blitted_surface) {
 | 
			
		||||
    VAddr bound1 = blitted_surface->GetAddr() + blitted_surface->GetMemorySize();
 | 
			
		||||
    VAddr bound2 = render_surface->GetAddr() + render_surface->GetMemorySize();
 | 
			
		||||
static bool IsReinterpretInvalid(const Surface render_surface, const Surface blitted_surface) {
 | 
			
		||||
    const VAddr bound1 = blitted_surface->GetAddr() + blitted_surface->GetMemorySize();
 | 
			
		||||
    const VAddr bound2 = render_surface->GetAddr() + render_surface->GetMemorySize();
 | 
			
		||||
    if (bound2 > bound1)
 | 
			
		||||
        return true;
 | 
			
		||||
    const auto dst_params = blitted_surface->GetSurfaceParams();
 | 
			
		||||
    const auto src_params = render_surface->GetSurfaceParams();
 | 
			
		||||
    if (dst_params.component_type != src_params.component_type)
 | 
			
		||||
        return true;
 | 
			
		||||
    return false;
 | 
			
		||||
    const auto& dst_params = blitted_surface->GetSurfaceParams();
 | 
			
		||||
    const auto& src_params = render_surface->GetSurfaceParams();
 | 
			
		||||
    return (dst_params.component_type != src_params.component_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsReinterpretInvalidSecond(const Surface render_surface, const Surface blitted_surface) {
 | 
			
		||||
    const auto dst_params = blitted_surface->GetSurfaceParams();
 | 
			
		||||
    const auto src_params = render_surface->GetSurfaceParams();
 | 
			
		||||
    if (dst_params.height > src_params.height && dst_params.width > src_params.width)
 | 
			
		||||
        return false;
 | 
			
		||||
    return true;
 | 
			
		||||
static bool IsReinterpretInvalidSecond(const Surface render_surface,
 | 
			
		||||
                                       const Surface blitted_surface) {
 | 
			
		||||
    const auto& dst_params = blitted_surface->GetSurfaceParams();
 | 
			
		||||
    const auto& src_params = render_surface->GetSurfaceParams();
 | 
			
		||||
    return (dst_params.height > src_params.height && dst_params.width > src_params.width);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerCacheOpenGL::PartialReinterpretSurface(Surface triggering_surface,
 | 
			
		||||
@ -1383,7 +1384,7 @@ bool RasterizerCacheOpenGL::PartialReinterpretSurface(Surface triggering_surface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerCacheOpenGL::SignalPreDrawCall() {
 | 
			
		||||
    if (texception) {
 | 
			
		||||
    if (texception && GLAD_GL_ARB_texture_barrier) {
 | 
			
		||||
        glTextureBarrier();
 | 
			
		||||
    }
 | 
			
		||||
    texception = false;
 | 
			
		||||
 | 
			
		||||
@ -412,7 +412,7 @@ public:
 | 
			
		||||
        reinterpreted = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsReinterpreted() {
 | 
			
		||||
    bool IsReinterpreted() const {
 | 
			
		||||
        return reinterpreted;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -420,11 +420,11 @@ public:
 | 
			
		||||
        must_reload = reload;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool MustReload() {
 | 
			
		||||
    bool MustReload() const {
 | 
			
		||||
        return must_reload;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsUploaded() {
 | 
			
		||||
    bool IsUploaded() const {
 | 
			
		||||
        return params.identity == SurfaceParams::SurfaceClass::Uploaded;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -489,6 +489,7 @@ private:
 | 
			
		||||
    Surface TryGetReservedSurface(const SurfaceParams& params);
 | 
			
		||||
 | 
			
		||||
    // Partialy reinterpret a surface based on a triggering_surface that collides with it.
 | 
			
		||||
    // returns true if the reinterpret was successful, false in case it was not.
 | 
			
		||||
    bool PartialReinterpretSurface(Surface triggering_surface, Surface intersect);
 | 
			
		||||
 | 
			
		||||
    /// Performs a slow but accurate surface copy, flushing to RAM and reinterpreting the data
 | 
			
		||||
@ -528,10 +529,10 @@ private:
 | 
			
		||||
    // Reinterpreted surfaces are very fragil as the game may keep rendering into them.
 | 
			
		||||
    SurfaceIntervalCache reinterpreted_surfaces;
 | 
			
		||||
 | 
			
		||||
    void RegisterReinterpretSurface(Surface r_surface) {
 | 
			
		||||
        auto interval = GetReinterpretInterval(r_surface);
 | 
			
		||||
        reinterpreted_surfaces.insert({interval, r_surface});
 | 
			
		||||
        r_surface->MarkReinterpreted();
 | 
			
		||||
    void RegisterReinterpretSurface(Surface reinterpret_surface) {
 | 
			
		||||
        auto interval = GetReinterpretInterval(reinterpret_surface);
 | 
			
		||||
        reinterpreted_surfaces.insert({interval, reinterpret_surface});
 | 
			
		||||
        reinterpret_surface->MarkReinterpreted();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Surface CollideOnReinterpretedSurface(VAddr addr) const {
 | 
			
		||||
@ -543,14 +544,12 @@ private:
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void Register(const Surface& object) {
 | 
			
		||||
        RasterizerCache<Surface>::Register(object);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Unregisters an object from the cache
 | 
			
		||||
    void Unregister(const Surface& object) {
 | 
			
		||||
        const auto& params = object->GetSurfaceParams();
 | 
			
		||||
        if (object->IsReinterpreted()) {
 | 
			
		||||
            auto interval = GetReinterpretInterval(object);
 | 
			
		||||
            reinterpreted_surfaces.erase(interval);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user