From 7c47b0029cbfc281da24d48304e035b3cfb75902 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 2 Jan 2022 12:01:31 +0300 Subject: [PATCH] gl: Fully drop alignment restriction for compressed textures - This is just not part of spec, there is no enforcement for multiple of block size for width or height of s3tc compressed images. - This restriction does indeed exist for ASTC and ETC but we're not using those formats. --- rpcs3/Emu/RSX/GL/GLTexture.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 68c3597697..2cbbb31cf8 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -586,14 +586,6 @@ namespace gl gl::viewable_image* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type) { - if (rsx::is_compressed_host_format(gcm_format)) - { - //Compressed formats have a 4-byte alignment - //TODO: Verify that samplers are not affected by the padding - width = utils::align(width, 4); - height = utils::align(height, 4); - } - const GLenum target = get_target(type); const GLenum internal_format = get_sized_internal_format(gcm_format); const auto format_class = rsx::classify_format(gcm_format); @@ -620,8 +612,6 @@ namespace gl if (rsx::is_compressed_host_format(format)) [[likely]] { caps.supports_vtc_decoding = gl::get_driver_caps().vendor_NVIDIA; - - unpack_settings.row_length(utils::align(dst->width(), 4)); unpack_settings.apply(); glBindTexture(static_cast(dst->get_target()), dst->id()); @@ -637,24 +627,28 @@ namespace gl case texture::target::texture1D: { const GLsizei size = layout.width_in_block * format_block_size; + ensure(usz(size) <= staging_buffer.size()); glCompressedTexSubImage1D(GL_TEXTURE_1D, layout.level, 0, layout.width_in_texel, gl_format, size, staging_buffer.data()); break; } case texture::target::texture2D: { const GLsizei size = layout.width_in_block * layout.height_in_block * format_block_size; + ensure(usz(size) <= staging_buffer.size()); glCompressedTexSubImage2D(GL_TEXTURE_2D, layout.level, 0, 0, layout.width_in_texel, layout.height_in_texel, gl_format, size, staging_buffer.data()); break; } case texture::target::textureCUBE: { const GLsizei size = layout.width_in_block * layout.height_in_block * format_block_size; + ensure(usz(size) <= staging_buffer.size()); glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + layout.layer, layout.level, 0, 0, layout.width_in_texel, layout.height_in_texel, gl_format, size, staging_buffer.data()); break; } case texture::target::texture3D: { const GLsizei size = layout.width_in_block * layout.height_in_block * layout.depth * format_block_size; + ensure(usz(size) <= staging_buffer.size()); glCompressedTexSubImage3D(GL_TEXTURE_3D, layout.level, 0, 0, 0, layout.width_in_texel, layout.height_in_texel, layout.depth, gl_format, size, staging_buffer.data()); break; } @@ -799,9 +793,20 @@ namespace gl void upload_texture(texture* dst, u32 gcm_format, bool is_swizzled, const std::vector& subresources_layout) { // Calculate staging buffer size - const u32 aligned_pitch = utils::align(dst->pitch(), 4); - usz texture_data_sz = dst->depth() * dst->height() * aligned_pitch; - std::vector data_upload_buf(texture_data_sz); + std::vector data_upload_buf; + + if (rsx::is_compressed_host_format(gcm_format)) + { + const auto& desc = subresources_layout[0]; + const usz texture_data_sz = desc.width_in_block * desc.height_in_block * desc.depth * rsx::get_format_block_size_in_bytes(gcm_format); + data_upload_buf.resize(texture_data_sz); + } + else + { + const auto aligned_pitch = utils::align(dst->pitch(), 4); + const usz texture_data_sz = dst->depth() * dst->height() * aligned_pitch; + data_upload_buf.resize(texture_data_sz); + } // TODO: GL drivers support byteswapping and this should be used instead of doing so manually const auto format_type = get_format_type(gcm_format);