gl_framebuffer_cache: Implement framebuffer cache texture invalidation
This commit is contained in:
@@ -27,11 +27,11 @@ bool FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const {
|
||||
rhs.zeta);
|
||||
}
|
||||
|
||||
FramebufferCacheOpenGL::FramebufferCacheOpenGL() = default;
|
||||
FramebufferCacheOpenGLImpl::FramebufferCacheOpenGLImpl() = default;
|
||||
|
||||
FramebufferCacheOpenGL::~FramebufferCacheOpenGL() = default;
|
||||
FramebufferCacheOpenGLImpl::~FramebufferCacheOpenGLImpl() = default;
|
||||
|
||||
GLuint FramebufferCacheOpenGL::GetFramebuffer(const FramebufferCacheKey& key) {
|
||||
GLuint FramebufferCacheOpenGLImpl::GetFramebuffer(const FramebufferCacheKey& key) {
|
||||
const auto [entry, is_cache_miss] = cache.try_emplace(key);
|
||||
auto& framebuffer{entry->second};
|
||||
if (is_cache_miss) {
|
||||
@@ -40,7 +40,13 @@ GLuint FramebufferCacheOpenGL::GetFramebuffer(const FramebufferCacheKey& key) {
|
||||
return framebuffer.handle;
|
||||
}
|
||||
|
||||
OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheKey& key) {
|
||||
void FramebufferCacheOpenGLImpl::InvalidateTexture(GLuint texture) {
|
||||
for (auto it = cache.begin(); it != cache.end();) {
|
||||
it = TryTextureInvalidation(texture, it);
|
||||
}
|
||||
}
|
||||
|
||||
OGLFramebuffer FramebufferCacheOpenGLImpl::CreateFramebuffer(const FramebufferCacheKey& key) {
|
||||
OGLFramebuffer framebuffer;
|
||||
framebuffer.Create();
|
||||
|
||||
@@ -73,4 +79,19 @@ OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheK
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
FramebufferCacheOpenGLImpl::CacheType::iterator FramebufferCacheOpenGLImpl::TryTextureInvalidation(
|
||||
GLuint texture, CacheType::iterator it) {
|
||||
const auto& [key, framebuffer] = *it;
|
||||
const std::size_t count = key.is_single_buffer ? 1 : static_cast<std::size_t>(key.colors_count);
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
if (texture == key.colors[i]) {
|
||||
return cache.erase(it);
|
||||
}
|
||||
}
|
||||
if (texture == key.zeta) {
|
||||
return cache.erase(it);
|
||||
}
|
||||
return ++it;
|
||||
}
|
||||
|
||||
} // namespace OpenGL
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <glad/glad.h>
|
||||
@@ -17,6 +18,9 @@
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class FramebufferCacheOpenGLImpl;
|
||||
using FramebufferCacheOpenGL = std::shared_ptr<FramebufferCacheOpenGLImpl>;
|
||||
|
||||
struct alignas(sizeof(u64)) FramebufferCacheKey {
|
||||
bool is_single_buffer = false;
|
||||
bool stencil_enable = false;
|
||||
@@ -51,18 +55,28 @@ struct hash<OpenGL::FramebufferCacheKey> {
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class FramebufferCacheOpenGL {
|
||||
class FramebufferCacheOpenGLImpl {
|
||||
public:
|
||||
FramebufferCacheOpenGL();
|
||||
~FramebufferCacheOpenGL();
|
||||
FramebufferCacheOpenGLImpl();
|
||||
~FramebufferCacheOpenGLImpl();
|
||||
|
||||
/// Returns and caches a framebuffer with the passed arguments.
|
||||
GLuint GetFramebuffer(const FramebufferCacheKey& key);
|
||||
|
||||
/// Invalidates a texture inside the cache.
|
||||
void InvalidateTexture(GLuint texture);
|
||||
|
||||
private:
|
||||
using CacheType = std::unordered_map<FramebufferCacheKey, OGLFramebuffer>;
|
||||
|
||||
/// Returns a new framebuffer from the passed arguments.
|
||||
OGLFramebuffer CreateFramebuffer(const FramebufferCacheKey& key);
|
||||
|
||||
/// Attempts to destroy the framebuffer cache entry in `it` and returns the next one.
|
||||
CacheType::iterator TryTextureInvalidation(GLuint texture, CacheType::iterator it);
|
||||
|
||||
OpenGLState local_state;
|
||||
std::unordered_map<FramebufferCacheKey, OGLFramebuffer> cache;
|
||||
CacheType cache;
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
|
||||
@@ -81,8 +81,10 @@ struct DrawParameters {
|
||||
};
|
||||
|
||||
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
|
||||
: res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
|
||||
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
|
||||
: framebuffer_cache{std::make_shared<FramebufferCacheOpenGLImpl>()},
|
||||
res_cache{*this, framebuffer_cache}, shader_cache{*this, system},
|
||||
global_cache{*this}, system{system}, screen_info{info},
|
||||
buffer_cache(*this, STREAM_BUFFER_SIZE) {
|
||||
// Create sampler objects
|
||||
for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
|
||||
texture_samplers[i].Create();
|
||||
@@ -512,7 +514,7 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
|
||||
depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil;
|
||||
}
|
||||
|
||||
current_state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey);
|
||||
current_state.draw.draw_framebuffer = framebuffer_cache->GetFramebuffer(fbkey);
|
||||
SyncViewport(current_state);
|
||||
|
||||
return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};
|
||||
|
||||
@@ -209,10 +209,10 @@ private:
|
||||
|
||||
OpenGLState state;
|
||||
|
||||
FramebufferCacheOpenGL framebuffer_cache;
|
||||
RasterizerCacheOpenGL res_cache;
|
||||
ShaderCacheOpenGL shader_cache;
|
||||
GlobalRegionCacheOpenGL global_cache;
|
||||
FramebufferCacheOpenGL framebuffer_cache;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
|
||||
@@ -561,8 +561,9 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
|
||||
dst_surface->MarkAsModified(true, *this);
|
||||
}
|
||||
|
||||
CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||
: RasterizerCacheObject{params.host_ptr}, params{params},
|
||||
CachedSurface::CachedSurface(const SurfaceParams& params, FramebufferCacheOpenGL framebuffer_cache_)
|
||||
: RasterizerCacheObject{params.host_ptr}, framebuffer_cache{std::move(framebuffer_cache_)},
|
||||
texture{framebuffer_cache}, discrepant_view{framebuffer_cache}, params{params},
|
||||
gl_target{SurfaceTargetToGL(params.target)}, cached_size_in_bytes{params.size_in_bytes} {
|
||||
|
||||
const auto optional_cpu_addr{
|
||||
@@ -611,6 +612,8 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||
OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.gpu_addr, params.IdentityString());
|
||||
}
|
||||
|
||||
CachedSurface::~CachedSurface() = default;
|
||||
|
||||
MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64));
|
||||
void CachedSurface::LoadGLBuffer() {
|
||||
MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
|
||||
@@ -852,8 +855,9 @@ void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
|
||||
}
|
||||
}
|
||||
|
||||
RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer)
|
||||
: RasterizerCache{rasterizer} {
|
||||
RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer,
|
||||
FramebufferCacheOpenGL framebuffer_cache)
|
||||
: RasterizerCache{rasterizer}, framebuffer_cache{std::move(framebuffer_cache)} {
|
||||
read_framebuffer.Create();
|
||||
draw_framebuffer.Create();
|
||||
copy_pbo.Create();
|
||||
@@ -961,7 +965,7 @@ Surface RasterizerCacheOpenGL::GetUncachedSurface(const SurfaceParams& params) {
|
||||
Surface surface{TryGetReservedSurface(params)};
|
||||
if (!surface) {
|
||||
// No reserved surface available, create a new one and reserve it
|
||||
surface = std::make_shared<CachedSurface>(params);
|
||||
surface = std::make_shared<CachedSurface>(params, framebuffer_cache);
|
||||
ReserveSurface(surface);
|
||||
}
|
||||
return surface;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "video_core/engines/fermi_2d.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/rasterizer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||
#include "video_core/surface.h"
|
||||
@@ -350,7 +351,8 @@ class RasterizerOpenGL;
|
||||
|
||||
class CachedSurface final : public RasterizerCacheObject {
|
||||
public:
|
||||
explicit CachedSurface(const SurfaceParams& params);
|
||||
explicit CachedSurface(const SurfaceParams& params, FramebufferCacheOpenGL framebuffer_cache_);
|
||||
~CachedSurface();
|
||||
|
||||
VAddr GetCpuAddr() const override {
|
||||
return cpu_addr;
|
||||
@@ -426,6 +428,7 @@ private:
|
||||
|
||||
void EnsureTextureDiscrepantView();
|
||||
|
||||
FramebufferCacheOpenGL framebuffer_cache;
|
||||
OGLTexture texture;
|
||||
OGLTexture discrepant_view;
|
||||
std::vector<std::vector<u8>> gl_buffer;
|
||||
@@ -434,7 +437,7 @@ private:
|
||||
GLenum gl_internal_format{};
|
||||
std::size_t cached_size_in_bytes{};
|
||||
std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
std::size_t memory_size;
|
||||
std::size_t memory_size{};
|
||||
bool reinterpreted = false;
|
||||
bool must_reload = false;
|
||||
VAddr cpu_addr{};
|
||||
@@ -442,7 +445,8 @@ private:
|
||||
|
||||
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
|
||||
public:
|
||||
explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer);
|
||||
explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer,
|
||||
FramebufferCacheOpenGL framebuffer_cache);
|
||||
|
||||
/// Get a surface based on the texture configuration
|
||||
Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config,
|
||||
@@ -499,6 +503,8 @@ private:
|
||||
/// destroyed when used with different surface parameters.
|
||||
std::unordered_map<SurfaceReserveKey, Surface> surface_reserve;
|
||||
|
||||
FramebufferCacheOpenGL framebuffer_cache;
|
||||
|
||||
OGLFramebuffer read_framebuffer;
|
||||
OGLFramebuffer draw_framebuffer;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <glad/glad.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/gl_state.h"
|
||||
@@ -15,6 +16,16 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
OGLTexture::OGLTexture(FramebufferCacheOpenGL framebuffer_cache)
|
||||
: framebuffer_cache{std::move(framebuffer_cache)} {}
|
||||
|
||||
OGLTexture::OGLTexture(OGLTexture&& o) noexcept
|
||||
: handle{std::exchange(o.handle, 0)}, framebuffer_cache{std::move(o.framebuffer_cache)} {}
|
||||
|
||||
OGLTexture::~OGLTexture() {
|
||||
Release();
|
||||
}
|
||||
|
||||
void OGLTexture::Create(GLenum target) {
|
||||
if (handle != 0)
|
||||
return;
|
||||
@@ -28,6 +39,9 @@ void OGLTexture::Release() {
|
||||
return;
|
||||
|
||||
MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
|
||||
if (framebuffer_cache) {
|
||||
framebuffer_cache->InvalidateTexture(handle);
|
||||
}
|
||||
glDeleteTextures(1, &handle);
|
||||
OpenGLState::GetCurState().UnbindTexture(handle).Apply();
|
||||
handle = 0;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <glad/glad.h>
|
||||
#include "common/common_types.h"
|
||||
@@ -11,15 +12,15 @@
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class FramebufferCacheOpenGLImpl;
|
||||
using FramebufferCacheOpenGL = std::shared_ptr<FramebufferCacheOpenGLImpl>;
|
||||
|
||||
class OGLTexture : private NonCopyable {
|
||||
public:
|
||||
OGLTexture() = default;
|
||||
explicit OGLTexture(FramebufferCacheOpenGL framebuffer_cache);
|
||||
OGLTexture(OGLTexture&& o) noexcept;
|
||||
|
||||
OGLTexture(OGLTexture&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
|
||||
|
||||
~OGLTexture() {
|
||||
Release();
|
||||
}
|
||||
~OGLTexture();
|
||||
|
||||
OGLTexture& operator=(OGLTexture&& o) noexcept {
|
||||
Release();
|
||||
@@ -34,6 +35,9 @@ public:
|
||||
void Release();
|
||||
|
||||
GLuint handle = 0;
|
||||
|
||||
private:
|
||||
FramebufferCacheOpenGL framebuffer_cache;
|
||||
};
|
||||
|
||||
class OGLSampler : private NonCopyable {
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenGL {
|
||||
|
||||
/// Structure used for storing information about the textures for the Switch screen
|
||||
struct TextureInfo {
|
||||
OGLTexture resource;
|
||||
OGLTexture resource{nullptr};
|
||||
GLsizei width;
|
||||
GLsizei height;
|
||||
GLenum gl_format;
|
||||
|
||||
Reference in New Issue
Block a user