diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 3139c11015..25e3450983 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -250,8 +251,14 @@ OGLTexture RasterizerCacheOpenGL::AllocateSurfaceTexture(const FormatTuple& form cur_state.Apply(); glActiveTexture(GL_TEXTURE0); - glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0, - format_tuple.format, format_tuple.type, nullptr); + if (GL_ARB_texture_storage) { + // Allocate all possible mipmap levels upfront + auto levels = std::log2(std::max(width, height)) + 1; + glTexStorage2D(GL_TEXTURE_2D, levels, format_tuple.internal_format, width, height); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0, + format_tuple.format, format_tuple.type, nullptr); + } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -273,17 +280,22 @@ static void AllocateTextureCube(GLuint texture, const FormatTuple& format_tuple, cur_state.texture_cube_unit.texture_cube = texture; cur_state.Apply(); glActiveTexture(TextureUnits::TextureCube.Enum()); - - for (auto faces : { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - }) { - glTexImage2D(faces, 0, format_tuple.internal_format, width, width, 0, format_tuple.format, - format_tuple.type, nullptr); + if (GL_ARB_texture_storage) { + // Allocate all possible mipmap levels in case the game uses them later + auto levels = std::log2(width) + 1; + glTexStorage2D(GL_TEXTURE_CUBE_MAP, levels, format_tuple.internal_format, width, width); + } else { + for (auto faces : { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + }) { + glTexImage2D(faces, 0, format_tuple.internal_format, width, width, 0, + format_tuple.format, format_tuple.type, nullptr); + } } // Restore previous texture bindings @@ -1250,9 +1262,14 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::Texture::TextureInf width = surface->GetScaledWidth(); height = surface->GetScaledHeight(); } - for (u32 level = surface->max_level + 1; level <= max_level; ++level) { - glTexImage2D(GL_TEXTURE_2D, level, format_tuple.internal_format, width >> level, - height >> level, 0, format_tuple.format, format_tuple.type, nullptr); + // If we are using ARB_texture_storage then we've already allocated all of the mipmap + // levels + if (!GL_ARB_texture_storage) { + for (u32 level = surface->max_level + 1; level <= max_level; ++level) { + glTexImage2D(GL_TEXTURE_2D, level, format_tuple.internal_format, width >> level, + height >> level, 0, format_tuple.format, format_tuple.type, + nullptr); + } } if (surface->is_custom || !texture_filterer->IsNull()) { // TODO: proper mipmap support for custom textures