summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorameerj <52414509+ameerj@users.noreply.github.com>2021-09-10 01:10:59 -0400
committerFernando Sahmkow <fsahmkow27@gmail.com>2021-11-16 22:11:29 +0100
commitfcf2b2c78a3c45ddcda6594b2fd3df733ceb951c (patch)
tree172fc0c6c7c7bc78f00d986aa42a552692751f46 /src
parentae8d19d17eb5448207ece99ae07507c542c6ddae (diff)
gl_texture_cache: Simplify scaling
We don't need to reconstruct new textures every time we ScaleUp/ScaleDown. We can scale up once, and revert to the original texture whenever scaling down. Fixes memory leaks due to glDeleteTextures being deferred for later handling on some drivers
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp67
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h3
2 files changed, 39 insertions, 31 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index edb8503cb..22fffb19b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -696,6 +696,7 @@ void Image::UploadMemory(const ImageBufferMap& map,
const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
if (is_rescaled) {
ScaleDown();
+ scale_backup.Release();
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, map.buffer);
glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, map.offset, unswizzled_size_bytes);
@@ -727,6 +728,7 @@ void Image::DownloadMemory(ImageBufferMap& map,
const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
if (is_rescaled) {
ScaleDown();
+ scale_backup.Release();
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
@@ -881,17 +883,11 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b
}
}
-bool Image::Scale(bool scale_src, bool scale_dst) {
- if (!runtime->is_rescaling_on) {
- return false;
- }
- if (gl_format == 0 && gl_type == 0) {
- // compressed textures
- return false;
- }
- if (info.type == ImageType::Linear) {
- UNIMPLEMENTED();
- return false;
+bool Image::Scale() {
+ if (scale_backup.handle) {
+ // This was a texture which was scaled previously, no need to repeat scaling
+ std::swap(texture, scale_backup);
+ return true;
}
const GLenum attachment = [this] {
switch (GetFormatType(info.format)) {
@@ -924,41 +920,36 @@ bool Image::Scale(bool scale_src, bool scale_dst) {
const auto& resolution = runtime->resolution;
const u32 up = resolution.up_scale;
const u32 down = resolution.down_shift;
+ const auto scale = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); };
- const auto scale_up = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); };
- const u32 scaled_width = scale_up(info.size.width);
- const u32 scaled_height = is_2d ? scale_up(info.size.height) : info.size.height;
+ const u32 scaled_width = scale(info.size.width);
+ const u32 scaled_height = is_2d ? scale(info.size.height) : info.size.height;
const u32 original_width = info.size.width;
const u32 original_height = info.size.height;
- const u32 src_width = scale_src ? scaled_width : original_width;
- const u32 src_height = scale_src ? scaled_height : original_height;
- const u32 dst_width = scale_dst ? scaled_width : original_width;
- const u32 dst_height = scale_dst ? scaled_height : original_height;
-
auto dst_info = info;
- dst_info.size.width = dst_width;
- dst_info.size.height = dst_height;
- auto dst_texture = MakeImage(dst_info, gl_internal_format);
+ dst_info.size.width = scaled_width;
+ dst_info.size.height = scaled_height;
+ scale_backup = MakeImage(dst_info, gl_internal_format);
const GLuint read_fbo = runtime->rescale_read_fbo.handle;
const GLuint draw_fbo = runtime->rescale_draw_fbo.handle;
for (s32 layer = 0; layer < info.resources.layers; ++layer) {
for (s32 level = 0; level < info.resources.levels; ++level) {
- const u32 src_level_width = std::max(1u, src_width >> level);
- const u32 src_level_height = std::max(1u, src_height >> level);
- const u32 dst_level_width = std::max(1u, dst_width >> level);
- const u32 dst_level_height = std::max(1u, dst_height >> level);
+ const u32 src_level_width = std::max(1u, original_width >> level);
+ const u32 src_level_height = std::max(1u, original_height >> level);
+ const u32 dst_level_width = std::max(1u, scaled_width >> level);
+ const u32 dst_level_height = std::max(1u, scaled_height >> level);
glNamedFramebufferTextureLayer(read_fbo, attachment, texture.handle, level, layer);
- glNamedFramebufferTextureLayer(draw_fbo, attachment, dst_texture.handle, level, layer);
+ glNamedFramebufferTextureLayer(draw_fbo, attachment, scale_backup.handle, level, layer);
glBlitNamedFramebuffer(read_fbo, draw_fbo, 0, 0, src_level_width, src_level_height, 0,
0, dst_level_width, dst_level_height, mask, filter);
glNamedFramebufferTextureLayer(read_fbo, attachment, 0, level, layer);
glNamedFramebufferTextureLayer(draw_fbo, attachment, 0, level, layer);
}
}
- texture = std::move(dst_texture);
+ std::swap(texture, scale_backup);
return true;
}
@@ -966,16 +957,32 @@ bool Image::ScaleUp() {
if (True(flags & ImageFlagBits::Rescaled)) {
return false;
}
+ if (!runtime->is_rescaling_on) {
+ return false;
+ }
+ if (gl_format == 0 && gl_type == 0) {
+ // compressed textures
+ return false;
+ }
+ if (info.type == ImageType::Linear) {
+ UNIMPLEMENTED();
+ return false;
+ }
flags |= ImageFlagBits::Rescaled;
- return Scale(false, true);
+ return Scale();
}
bool Image::ScaleDown() {
if (False(flags & ImageFlagBits::Rescaled)) {
return false;
}
+ if (!scale_backup.handle) {
+ LOG_ERROR(Render_OpenGL, "Downscaling an upscaled texture that didn't backup original");
+ return false;
+ }
flags &= ~ImageFlagBits::Rescaled;
- return Scale(true, false);
+ std::swap(texture, scale_backup);
+ return true;
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 28c91b368..f4dcc6f9b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -203,9 +203,10 @@ private:
void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);
- bool Scale(bool scale_src, bool scale_dst);
+ bool Scale();
OGLTexture texture;
+ OGLTexture scale_backup;
OGLTextureView store_view;
GLenum gl_internal_format = GL_NONE;
GLenum gl_format = GL_NONE;