citra/src/video_core/rasterizer_cache/surface_base.h
GPUCode 5b52849f90
rasterizer_cache: Allow custom recycle (#6851)
* surface_params: Allow custom surface recycling

* rasterizer_cache: Cleanup
2023-08-06 22:59:54 +03:00

95 lines
3.2 KiB
C++

// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <boost/icl/interval_set.hpp>
#include "video_core/rasterizer_cache/surface_params.h"
#include "video_core/rasterizer_cache/utils.h"
namespace VideoCore {
using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterval>;
struct Material;
enum class SurfaceFlagBits : u32 {
Registered = 1 << 0, ///< Surface is registed in the rasterizer cache.
Picked = 1 << 1, ///< Surface has been picked when searching for a match.
Tracked = 1 << 2, ///< Surface is part of a texture cube and should be tracked.
Custom = 1 << 3, ///< Surface texture has been replaced with a custom texture.
ShadowMap = 1 << 4, ///< Surface is used during shadow rendering.
};
DECLARE_ENUM_FLAG_OPERATORS(SurfaceFlagBits);
class SurfaceBase : public SurfaceParams {
public:
SurfaceBase(const SurfaceParams& params);
~SurfaceBase();
/// Returns true when this surface can be used to fill the fill_interval of dest_surface
bool CanFill(const SurfaceParams& dest_surface, SurfaceInterval fill_interval) const;
/// Returns true when surface can validate copy_interval of dest_surface
bool CanCopy(const SurfaceParams& dest_surface, SurfaceInterval copy_interval) const;
/// Returns the region of the biggest valid rectange within interval
SurfaceInterval GetCopyableInterval(const SurfaceParams& params) const;
/// Returns the clear value used to validate another surface from this fill surface
ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format);
/// Returns the internal surface extent.
Extent RealExtent(bool scaled = true) const;
/// Returns true if the surface contains a custom material with a normal map.
bool HasNormalMap() const noexcept;
bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
return addr < overlap_end && overlap_addr < end;
}
u64 ModificationTick() const noexcept {
return modification_tick;
}
bool IsCustom() const noexcept {
return True(flags & SurfaceFlagBits::Custom) && custom_format != CustomPixelFormat::Invalid;
}
bool IsRegionValid(SurfaceInterval interval) const {
return invalid_regions.find(interval) == invalid_regions.end();
}
void MarkValid(SurfaceInterval interval) {
invalid_regions.erase(interval);
modification_tick++;
}
void MarkInvalid(SurfaceInterval interval) {
invalid_regions.insert(interval);
modification_tick++;
}
bool IsFullyInvalid() const {
auto interval = GetInterval();
return *invalid_regions.equal_range(interval).first == interval;
}
private:
/// Returns the fill buffer value starting from copy_addr
std::array<u8, 4> MakeFillBuffer(PAddr copy_addr);
public:
SurfaceFlagBits flags{};
const Material* material = nullptr;
SurfaceRegions invalid_regions;
u32 fill_size = 0;
std::array<u8, 4> fill_data;
u64 modification_tick = 1;
};
} // namespace VideoCore