From 894cc9d876a70947aecc7a1a3f9ef869e8088f42 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Wed, 17 Nov 2021 12:21:17 +0800 Subject: Fix image update/download error when width too small --- .../renderer_opengl/gl_texture_cache.cpp | 27 ++++++++++++++-------- src/video_core/renderer_opengl/gl_texture_cache.h | 1 + 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 2f7d98d8b..5cfb6bb8a 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -317,13 +317,12 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) { } } -OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format) { +OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format, + GLsizei gl_num_levels) { const GLenum target = ImageTarget(info); const GLsizei width = info.size.width; const GLsizei height = info.size.height; const GLsizei depth = info.size.depth; - const int max_host_mip_levels = std::bit_width(info.size.width); - const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels); const GLsizei num_layers = info.resources.layers; const GLsizei num_samples = info.num_samples; @@ -335,10 +334,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form } switch (target) { case GL_TEXTURE_1D_ARRAY: - glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers); + glTextureStorage2D(handle, gl_num_levels, gl_internal_format, width, num_layers); break; case GL_TEXTURE_2D_ARRAY: - glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers); + glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, num_layers); break; case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { // TODO: Where should 'fixedsamplelocations' come from? @@ -348,10 +347,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form break; } case GL_TEXTURE_RECTANGLE: - glTextureStorage2D(handle, num_levels, gl_internal_format, width, height); + glTextureStorage2D(handle, gl_num_levels, gl_internal_format, width, height); break; case GL_TEXTURE_3D: - glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth); + glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, depth); break; case GL_TEXTURE_BUFFER: UNREACHABLE(); @@ -686,7 +685,9 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, gl_format = tuple.format; gl_type = tuple.type; } - texture = MakeImage(info, gl_internal_format); + const int max_host_mip_levels = std::bit_width(info.size.width); + gl_num_levels = std::min(info.resources.levels, max_host_mip_levels); + texture = MakeImage(info, gl_internal_format, gl_num_levels); current_texture = texture.handle; if (runtime->device.HasDebuggingToolAttached()) { const std::string name = VideoCommon::Name(*this); @@ -714,6 +715,9 @@ void Image::UploadMemory(const ImageBufferMap& map, u32 current_image_height = std::numeric_limits::max(); for (const VideoCommon::BufferImageCopy& copy : copies) { + if (copy.image_subresource.base_level >= gl_num_levels) { + continue; + } if (current_row_length != copy.buffer_row_length) { current_row_length = copy.buffer_row_length; glPixelStorei(GL_UNPACK_ROW_LENGTH, current_row_length); @@ -743,6 +747,9 @@ void Image::DownloadMemory(ImageBufferMap& map, u32 current_image_height = std::numeric_limits::max(); for (const VideoCommon::BufferImageCopy& copy : copies) { + if (copy.image_subresource.base_level >= gl_num_levels) { + continue; + } if (current_row_length != copy.buffer_row_length) { current_row_length = copy.buffer_row_length; glPixelStorei(GL_PACK_ROW_LENGTH, current_row_length); @@ -782,7 +789,7 @@ GLuint Image::StorageHandle() noexcept { } store_view.Create(); glTextureView(store_view.handle, ImageTarget(info), current_texture, GL_RGBA8, 0, - info.resources.levels, 0, info.resources.layers); + gl_num_levels, 0, info.resources.layers); return store_view.handle; default: return current_texture; @@ -946,7 +953,7 @@ void Image::Scale(bool up_scale) { auto dst_info = info; dst_info.size.width = scaled_width; dst_info.size.height = scaled_height; - upscaled_backup = MakeImage(dst_info, gl_internal_format); + upscaled_backup = MakeImage(dst_info, gl_internal_format, gl_num_levels); } const u32 src_width = up_scale ? original_width : scaled_width; const u32 src_height = up_scale ? original_height : scaled_height; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 1bb762568..30037a6a2 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -219,6 +219,7 @@ private: GLenum gl_internal_format = GL_NONE; GLenum gl_format = GL_NONE; GLenum gl_type = GL_NONE; + GLsizei gl_num_levels{}; TextureCacheRuntime* runtime{}; GLuint current_texture{}; }; -- cgit v1.2.3