mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 23:55:40 +12:00
Merge pull request #73 from skylersaleh/SurfaceCacheRing
[GPU] Add texture surface cache eviction
This commit is contained in:
commit
0647fb5b85
3 changed files with 43 additions and 23 deletions
|
@ -45,7 +45,7 @@ class Renderer {
|
||||||
|
|
||||||
SurfaceCache<DepthBuffer, 10> depthBufferCache;
|
SurfaceCache<DepthBuffer, 10> depthBufferCache;
|
||||||
SurfaceCache<ColourBuffer, 10> colourBufferCache;
|
SurfaceCache<ColourBuffer, 10> colourBufferCache;
|
||||||
SurfaceCache<Texture, 256> textureCache;
|
SurfaceCache<Texture, 256, true> textureCache;
|
||||||
|
|
||||||
OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)'
|
OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)'
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
#include "textures.hpp"
|
#include "textures.hpp"
|
||||||
|
|
||||||
// Surface cache class that can fit "capacity" instances of the "SurfaceType" class of surfaces
|
// Surface cache class that can fit "capacity" instances of the "SurfaceType" class of surfaces
|
||||||
// SurfaceType *must* have all of the following
|
// SurfaceType *must* have all of the following.
|
||||||
// - An "allocate" function that allocates GL resources for the surfaces
|
// - An "allocate" function that allocates GL resources for the surfaces. On overflow it will panic
|
||||||
|
// if evictOnOverflow is false, or kick out the oldest item if it is true (like a ring buffer)
|
||||||
// - A "free" function that frees up all resources the surface is taking up
|
// - A "free" function that frees up all resources the surface is taking up
|
||||||
// - A "matches" function that, when provided with a SurfaceType object reference
|
// - A "matches" function that, when provided with a SurfaceType object reference
|
||||||
// Will tell us if the 2 surfaces match (Only as far as location in VRAM, format, dimensions, etc)
|
// Will tell us if the 2 surfaces match (Only as far as location in VRAM, format, dimensions, etc)
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
// Including equality of the allocated OpenGL resources, which we don't want
|
// Including equality of the allocated OpenGL resources, which we don't want
|
||||||
// - A "valid" member that tells us whether the function is still valid or not
|
// - A "valid" member that tells us whether the function is still valid or not
|
||||||
// - A "location" member which tells us which location in 3DS memory this surface occupies
|
// - A "location" member which tells us which location in 3DS memory this surface occupies
|
||||||
template <typename SurfaceType, size_t capacity>
|
template <typename SurfaceType, size_t capacity, bool evictOnOverflow = false>
|
||||||
class SurfaceCache {
|
class SurfaceCache {
|
||||||
// Vanilla std::optional can't hold actual references
|
// Vanilla std::optional can't hold actual references
|
||||||
using OptionalRef = std::optional<std::reference_wrapper<SurfaceType>>;
|
using OptionalRef = std::optional<std::reference_wrapper<SurfaceType>>;
|
||||||
|
@ -22,11 +23,13 @@ class SurfaceCache {
|
||||||
std::is_same<SurfaceType, Texture>(), "Invalid surface type");
|
std::is_same<SurfaceType, Texture>(), "Invalid surface type");
|
||||||
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
size_t evictionIndex;
|
||||||
std::array<SurfaceType, capacity> buffer;
|
std::array<SurfaceType, capacity> buffer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void reset() {
|
void reset() {
|
||||||
size = 0;
|
size = 0;
|
||||||
|
evictionIndex = 0;
|
||||||
for (auto& e : buffer) { // Free the VRAM of all surfaces
|
for (auto& e : buffer) { // Free the VRAM of all surfaces
|
||||||
e.free();
|
e.free();
|
||||||
}
|
}
|
||||||
|
@ -51,26 +54,42 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a surface object to the cache and returns it
|
// Adds a surface object to the cache and returns it
|
||||||
SurfaceType& add(const SurfaceType& surface) {
|
SurfaceType& add(const SurfaceType& surface) {
|
||||||
if (size >= capacity) {
|
if (size >= capacity) {
|
||||||
Helpers::panic("Surface cache full! Add emptying!");
|
if (evictOnOverflow) { // Do a ring buffer if evictOnOverflow is true
|
||||||
}
|
auto& e = buffer[evictionIndex];
|
||||||
size++;
|
evictionIndex = (evictionIndex + 1) % capacity;
|
||||||
|
|
||||||
// Find an invalid entry in the cache and overwrite it with the new surface
|
e.valid = false;
|
||||||
for (auto& e : buffer) {
|
e.free();
|
||||||
if (!e.valid) {
|
e = surface;
|
||||||
e = surface;
|
e.allocate();
|
||||||
e.allocate();
|
return e;
|
||||||
return e;
|
} else {
|
||||||
}
|
Helpers::panic("Surface cache full! Add emptying!");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This should be unreachable but helps to panic anyways
|
size++;
|
||||||
Helpers::panic("Couldn't add surface to cache\n");
|
|
||||||
}
|
// Find an invalid entry in the cache and overwrite it with the new surface
|
||||||
|
for (auto& e : buffer) {
|
||||||
|
if (!e.valid) {
|
||||||
|
e = surface;
|
||||||
|
e.allocate();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should be unreachable but helps to panic anyways
|
||||||
|
Helpers::panic("Couldn't add surface to cache\n");
|
||||||
|
}
|
||||||
|
|
||||||
SurfaceType& operator[](size_t i) {
|
SurfaceType& operator[](size_t i) {
|
||||||
return buffer[i];
|
return buffer[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SurfaceType& operator[](size_t i) const {
|
||||||
|
return buffer[i];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,10 +33,11 @@ void Texture::setNewConfig(u32 cfg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::free() {
|
void Texture::free() {
|
||||||
valid = false;
|
valid = false;
|
||||||
|
|
||||||
if (texture.exists())
|
if (texture.exists()) {
|
||||||
Helpers::panic("Make this texture free itself");
|
texture.free();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Texture::sizeInBytes() {
|
u64 Texture::sizeInBytes() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue