From ea2584c54de0bbf28c7c549e5cfe8cb0c76e85cf Mon Sep 17 00:00:00 2001 From: BreadFish64 Date: Sat, 27 Jun 2020 13:13:37 -0500 Subject: [PATCH] generic texture allocator --- .../renderer_opengl/gl_rasterizer.cpp | 19 +++---- .../renderer_opengl/gl_resource_manager.cpp | 57 +++++++++++++++++++ .../renderer_opengl/gl_resource_manager.h | 2 + 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 8398b884f..941166326 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -777,21 +777,20 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) { // which causes unpredictable behavior on the host. // Making a copy to sample from eliminates this issue and seems to be fairly cheap. temp_tex.Create(); - glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, temp_tex.handle); auto [internal_format, format, type] = GetFormatTuple(color_surface->pixel_format); - ASSERT_MSG(GLAD_GL_ARB_texture_storage, "ARB_texture_storage not supported"); - glTexStorage2D(GL_TEXTURE_2D, color_surface->max_level + 1, internal_format, - color_surface->GetScaledWidth(), color_surface->GetScaledHeight()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + OGLTexture::Allocate(GL_TEXTURE_2D, color_surface->max_level, internal_format, format, type, + color_surface->GetScaledWidth(), color_surface->GetScaledHeight()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, state.texture_units[0].texture_2d); - for (std::size_t mip{0}; mip <= color_surface->max_level; ++mip) { - glCopyImageSubData(color_surface->texture.handle, GL_TEXTURE_2D, mip, 0, 0, 0, - temp_tex.handle, GL_TEXTURE_2D, mip, 0, 0, 0, - color_surface->GetScaledWidth() >> mip, - color_surface->GetScaledHeight() >> mip, 1); + for (std::size_t level{0}; level <= color_surface->max_level; ++level) { + glCopyImageSubData(color_surface->texture.handle, GL_TEXTURE_2D, level, 0, 0, 0, + temp_tex.handle, GL_TEXTURE_2D, level, 0, 0, 0, + color_surface->GetScaledWidth() >> level, + color_surface->GetScaledHeight() >> level, 1); } for (auto& unit : state.texture_units) { diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index 836cbb90c..19bc83aa3 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -9,6 +9,7 @@ #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" +#include "video_core/renderer_opengl/gl_vars.h" MICROPROFILE_DEFINE(OpenGL_ResourceCreation, "OpenGL", "Resource Creation", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_RGB(128, 128, 192)); @@ -51,6 +52,62 @@ void OGLTexture::Release() { handle = 0; } +void OGLTexture::Allocate(GLenum target, GLsizei levels, GLenum internalformat, + GLenum format, GLenum type, GLsizei width, GLsizei height, + GLsizei depth) { + const bool tex_storage = GLAD_GL_ARB_texture_storage || GLES; + + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE: + if (tex_storage) { + glTexStorage1D(target, levels, internalformat, width); + } else { + for (GLsizei level{0}; level < levels; ++level) { + width >>= 1; + glTexImage1D(target, level, internalformat, width, 0, format, type, nullptr); + } + } + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_CUBE_MAP: + if (tex_storage) { + glTexStorage2D(target, levels, internalformat, width, height); + } else { + for (GLsizei level{0}; level < levels; ++level) { + width >>= 1; + if (target != GL_TEXTURE_1D_ARRAY) + height >>= 1; + glTexImage2D(target, level, internalformat, width, height, 0, format, type, + nullptr); + } + } + break; + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + if (tex_storage) { + glTexStorage3D(target, levels, internalformat, width, height, depth); + } else { + for (GLsizei level{0}; level < levels; ++level) { + glTexImage3D(target, level, internalformat, width, height, depth, 0, format, type, + nullptr); + } + width >>= 1; + height >>= 1; + if (target == GL_TEXTURE_3D) + depth >>= 1; + } + break; + } + + if (!tex_storage) { + glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels - 1); + } +} + void OGLSampler::Create() { if (handle != 0) return; diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 9b9f150e1..db326ed9a 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -59,6 +59,8 @@ public: /// Deletes the internal OpenGL resource void Release(); + static void Allocate(GLenum target, GLsizei levels, GLenum internalformat, GLenum format, GLenum type, GLsizei width, GLsizei height = 1, GLsizei depth = 1); + GLuint handle = 0; };