mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	texture_cache: Port original code management for 2D vs 3D textures
Handle blits to images as 2D, even when they have block depth. - Fixes rendering issues on Luigi's Mansion 3
This commit is contained in:
		@@ -247,7 +247,7 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
 | 
			
		||||
    params.height = config.height;
 | 
			
		||||
    params.pitch = config.pitch;
 | 
			
		||||
    // TODO(Rodrigo): Try to guess texture arrays from parameters
 | 
			
		||||
    params.target = params.block_depth > 0 ? SurfaceTarget::Texture3D : SurfaceTarget::Texture2D;
 | 
			
		||||
    params.target = SurfaceTarget::Texture2D;
 | 
			
		||||
    params.depth = 1;
 | 
			
		||||
    params.num_levels = 1;
 | 
			
		||||
    params.emulated_levels = 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -724,10 +724,35 @@ private:
 | 
			
		||||
     * @param params    The parameters on the new surface.
 | 
			
		||||
     * @param gpu_addr  The starting address of the new surface.
 | 
			
		||||
     * @param cpu_addr  The starting address of the new surface on physical memory.
 | 
			
		||||
     * @param preserve_contents Indicates that the new surface should be loaded from memory or
 | 
			
		||||
     *                          left blank.
 | 
			
		||||
     */
 | 
			
		||||
    std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(VectorSurface& overlaps,
 | 
			
		||||
                                                               const SurfaceParams& params,
 | 
			
		||||
                                                               GPUVAddr gpu_addr, VAddr cpu_addr) {
 | 
			
		||||
                                                               GPUVAddr gpu_addr, VAddr cpu_addr,
 | 
			
		||||
                                                               bool preserve_contents) {
 | 
			
		||||
        if (params.target != SurfaceTarget::Texture3D) {
 | 
			
		||||
            for (const auto& surface : overlaps) {
 | 
			
		||||
                if (!surface->MatchTarget(params.target)) {
 | 
			
		||||
                    if (overlaps.size() == 1 && surface->GetCpuAddr() == cpu_addr) {
 | 
			
		||||
                        if (Settings::IsGPULevelExtreme()) {
 | 
			
		||||
                            return std::nullopt;
 | 
			
		||||
                        }
 | 
			
		||||
                        Unregister(surface);
 | 
			
		||||
                        return InitializeSurface(gpu_addr, params, preserve_contents);
 | 
			
		||||
                    }
 | 
			
		||||
                    return std::nullopt;
 | 
			
		||||
                }
 | 
			
		||||
                if (surface->GetCpuAddr() != cpu_addr) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                if (surface->MatchesStructure(params) == MatchStructureResult::FullMatch) {
 | 
			
		||||
                    return std::make_pair(surface, surface->GetMainView());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return InitializeSurface(gpu_addr, params, preserve_contents);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.num_levels > 1) {
 | 
			
		||||
            // We can't handle mipmaps in 3D textures yet, better fallback to LLE approach
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
@@ -748,25 +773,18 @@ private:
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.depth == 1) {
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        TSurface new_surface = GetUncachedSurface(gpu_addr, params);
 | 
			
		||||
        LoadSurface(new_surface);
 | 
			
		||||
 | 
			
		||||
        bool modified = false;
 | 
			
		||||
 | 
			
		||||
        for (auto& surface : overlaps) {
 | 
			
		||||
            const SurfaceParams& src_params = surface->GetSurfaceParams();
 | 
			
		||||
            if (src_params.height != params.height ||
 | 
			
		||||
            if (src_params.target != SurfaceTarget::Texture2D ||
 | 
			
		||||
                src_params.height != params.height ||
 | 
			
		||||
                src_params.block_depth != params.block_depth ||
 | 
			
		||||
                src_params.block_height != params.block_height) {
 | 
			
		||||
                return std::nullopt;
 | 
			
		||||
            }
 | 
			
		||||
            if (!surface->IsModified()) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            modified = true;
 | 
			
		||||
            modified |= surface->IsModified();
 | 
			
		||||
 | 
			
		||||
            const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr);
 | 
			
		||||
            const u32 slice = std::get<2>(params.GetBlockOffsetXYZ(offset));
 | 
			
		||||
@@ -781,7 +799,7 @@ private:
 | 
			
		||||
        new_surface->MarkAsModified(modified, Tick());
 | 
			
		||||
        Register(new_surface);
 | 
			
		||||
 | 
			
		||||
        auto view = new_surface->GetMainView();
 | 
			
		||||
        TView view = new_surface->GetMainView();
 | 
			
		||||
        return std::make_pair(std::move(new_surface), std::move(view));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -861,8 +879,9 @@ private:
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Manage 3D textures
 | 
			
		||||
        if (params.target == SurfaceTarget::Texture3D) {
 | 
			
		||||
            auto surface = Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr);
 | 
			
		||||
        if (params.block_depth > 0) {
 | 
			
		||||
            auto surface =
 | 
			
		||||
                Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents);
 | 
			
		||||
            if (surface) {
 | 
			
		||||
                return *surface;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user