From 30d45356a37601c322c103a693acbf3a9d33c32f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 15 Mar 2017 23:19:58 +0300 Subject: [PATCH] gl: Debugging argb8 hw scale (broken atm/ WIP) --- rpcs3/Emu/RSX/GL/GLTextureCache.h | 129 +++++++++++++--- rpcs3/Emu/RSX/rsx_cache.h | 7 +- rpcs3/Emu/RSX/rsx_methods.cpp | 9 +- rpcs3/GLGSRender.vcxproj | 245 +++++++++++++++--------------- 4 files changed, 244 insertions(+), 146 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 1a55f2ec10..5e4c069685 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -9,10 +9,11 @@ #include #include #include +#include #include "GLRenderTargets.h" #include "../Common/TextureUtils.h" -#include +#include "../../Memory/vm.h" class GLGSRender; @@ -441,8 +442,16 @@ namespace gl glBindTexture(GL_TEXTURE_2D, rgb565_surface); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB565, 4096, 4096); - fbo_argb8.color[0] = argb8_surface; - fbo_rgb565.color[0] = rgb565_surface; + s32 old_fbo = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); + + fbo_argb8.bind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, argb8_surface, 0); + + fbo_rgb565.bind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rgb565_surface, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); fbo_argb8.check(); fbo_rgb565.check(); @@ -458,33 +467,46 @@ namespace gl glDeleteTextures(1, &rgb565_surface); } - u32 scale_image(u32 src, const areai src_rect, const areai dst_rect, const position2i clip_offset, const size2i clip_dims, bool is_argb8) + u32 scale_image(u32 src, u32 dst, const areai src_rect, const areai dst_rect, const position2i dst_offset, const position2i clip_offset, const size2i dst_dims, const size2i clip_dims, bool is_argb8) { - blit_src.color[0] = src; + s32 old_fbo = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); + + blit_src.bind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src, 0); blit_src.check(); u32 src_surface = 0; - u32 dst_tex = 0; + u32 dst_tex = dst; - glGenTextures(1, &dst_tex); - glBindTexture(GL_TEXTURE_2D, dst_tex); + if (!dst_tex) + { + glGenTextures(1, &dst_tex); + glBindTexture(GL_TEXTURE_2D, dst_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (is_argb8) + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, dst_dims.width, dst_dims.height); + else + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB565, dst_dims.width, dst_dims.height); + } if (is_argb8) { - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, clip_dims.width, clip_dims.height); blit_src.blit(fbo_argb8, src_rect, dst_rect); src_surface = argb8_surface; } else { - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB565, clip_dims.width, clip_dims.height); blit_src.blit(fbo_rgb565, src_rect, dst_rect); src_surface = rgb565_surface; } glCopyImageSubData(src_surface, GL_TEXTURE_2D, 0, clip_offset.x, clip_offset.y, 0, - dst_tex, GL_TEXTURE_2D, 0, 0, 0, 0, clip_dims.width, clip_dims.height, 1); + dst_tex, GL_TEXTURE_2D, 0, dst_offset.x, dst_offset.y, 0, clip_dims.width, clip_dims.height, 1); + glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); return dst_tex; } }; @@ -515,6 +537,18 @@ namespace gl return nullptr; } + cached_texture_section *find_texture(u32 texaddr, u32 range) + { + auto test = std::make_pair(texaddr, range); + for (cached_texture_section &tex : m_texture_cache) + { + if (tex.overlaps(test) && !tex.is_dirty()) + return &tex; + } + + return nullptr; + } + cached_texture_section& create_texture(u32 id, u32 texaddr, u32 texsize, u32 w, u32 h, u16 mipmap) { for (cached_texture_section &tex : m_texture_cache) @@ -657,11 +691,15 @@ namespace gl { m_renderer = renderer; m_renderer_thread = std::this_thread::get_id(); + + m_hw_blitter.init(); } void close() { clear(); + + m_hw_blitter.destroy(); } template @@ -695,6 +733,8 @@ namespace gl return; } + LOG_ERROR(RSX, "REGULAR IFC: address=0x%X + 0x%X, w=%d h=%d", texaddr, range, tex.width(), tex.height()); + /** * Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise * (Turbo: Super Stunt Squad does this; bypassing the need for a sync object) @@ -780,10 +820,25 @@ namespace gl return; } - if (!tex.width() || !tex.height()) - { - LOG_ERROR(RSX, "Texture upload requested but invalid texture dimensions passed"); - return; + /** + * Check for subslices from the cache in case we only have a subset a larger texture + */ + cached_texture = find_texture(texaddr, range); + if (cached_texture) + { + const u32 format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + const u32 address_offset = texaddr - cached_texture->get_section_base(); + const u32 bpp = get_format_block_size_in_bytes(format); + + u16 offset_y = address_offset / tex.pitch(); + u16 offset_x = address_offset % tex.pitch(); + + offset_y /= bpp; + offset_y /= bpp; + + GLenum ifmt = gl::get_sized_internal_format(format); + u32 texture_id = create_temporary_subresource(cached_texture->id(), ifmt, offset_x, offset_y, tex.width(), tex.height()); + if (texture_id) return; } gl_texture.init(index, tex); @@ -977,28 +1032,60 @@ namespace gl bool upload_scaled_image(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) { + if (dst.swizzled) + return false; + u32 tmp_tex = 0; bool dst_is_argb8 = (dst.format == rsx::blit_engine::transfer_destination_format::a8r8g8b8); bool src_is_argb8 = (dst.format == rsx::blit_engine::transfer_destination_format::a8r8g8b8); - GLenum src_gl_format = src_is_argb8? GL_RGBA8: GL_RGB565; + GLenum src_gl_sized_format = src_is_argb8? GL_RGBA8: GL_RGB565; + GLenum src_gl_format = src_is_argb8 ? GL_RGBA : GL_RGB; GLenum src_gl_type = src_is_argb8? GL_UNSIGNED_INT_8_8_8_8: GL_UNSIGNED_SHORT_5_6_5; glGenTextures(1, &tmp_tex); glBindTexture(GL_TEXTURE_2D, tmp_tex); - glPixelStorei(GL_UNPACK_ROW_LENGTH, src.pitch); - glTexStorage2D(GL_TEXTURE_2D, 0, src_gl_format, src.width, src.height); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, src.width, src.height, src_gl_format, src_gl_type, src.pixels); + glPixelStorei(GL_UNPACK_ROW_LENGTH, src.pitch / (src_is_argb8? 4: 2)); + glPixelStorei(GL_UNPACK_SWAP_BYTES, !src_is_argb8); + glTexStorage2D(GL_TEXTURE_2D, 1, src_gl_sized_format, src.width, src.height); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, src.width, dst.clip_height, src_gl_format, src_gl_type, src.pixels); - const areai src_area = {src.offset_x, src.offset_y, src.offset_x + src.width, src.offset_y + src.height}; + const areai src_area = {0, 0, src.width, src.slice_h}; const areai dst_area = {0, 0, dst.width, dst.height}; const position2i clip_offset = {dst.clip_x, dst.clip_y}; + const position2i dst_offset = {dst.offset_x, dst.offset_y}; const size2i clip_dimensions = {dst.clip_width, dst.clip_height}; + const size2i dst_dimensions = {dst.pitch/(dst_is_argb8? 4: 2), dst.height}; - u32 texture = m_hw_blitter.scale_image(tmp_tex, src_area, dst_area, clip_offset, clip_dimensions, dst_is_argb8); + auto old_cached_texture = find_texture(dst.rsx_address, dst.pitch * dst.height); + u32 dst_surface = 0; + + if (old_cached_texture && old_cached_texture->matches(old_cached_texture->get_section_base(), dst.width, dst.height, 1)) + dst_surface = old_cached_texture->id(); + + u32 texture_id = m_hw_blitter.scale_image(tmp_tex, dst_surface, src_area, dst_area, dst_offset, clip_offset, dst_dimensions, clip_dimensions, dst_is_argb8); glDeleteTextures(1, &tmp_tex); +/* glBindTexture(GL_TEXTURE_2D, texture_id); + glPixelStorei(GL_PACK_SWAP_BYTES, !dst_is_argb8); + glPixelStorei(GL_PACK_ROW_LENGTH, dst.pitch / (dst_is_argb8 ? 4 : 2)); + glGetTextureImageEXT(texture_id, GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, dst.pixels); */ + + LOG_ERROR(RSX, "SIFM: address=0x%X + 0x%X, x=%d(%d), y=%d(%d), w=%d(%d), h=%d(%d)", dst.rsx_address, dst.pitch * dst.height, + dst.offset_x, dst.clip_x, dst.offset_y, dst.clip_y, dst.width, dst.clip_width, dst.height, dst.clip_height); + + if (dst_surface) + return true; + + std::lock_guard lock(m_section_mutex); + + cached_texture_section &cached = create_texture(texture_id, dst.rsx_address, dst.pitch * dst.height, dst.width, dst.height, 1); + cached.protect(utils::protection::ro); + cached.set_dirty(false); + return true; } }; diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index 8a31197b9b..328647efc4 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -2,6 +2,7 @@ #include #include "Utilities/VirtualMemory.h" #include "Emu/Memory/vm.h" +#include "gcm_enums.h" namespace rsx { @@ -37,7 +38,7 @@ namespace rsx u16 offset_y; u16 width; u16 height; - u16 slice; + u16 slice_h; u16 pitch; void *pixels; }; @@ -45,6 +46,8 @@ namespace rsx struct blit_dst_info { blit_engine::transfer_destination_format format; + u16 offset_x; + u16 offset_y; u16 width; u16 height; u16 pitch; @@ -52,8 +55,10 @@ namespace rsx u16 clip_y; u16 clip_width; u16 clip_height; + bool swizzled; void *pixels; + u32 rsx_address; }; class shaders_cache diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index e62283541e..d66e057d80 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -550,7 +550,9 @@ namespace rsx src_info.width = in_w; src_info.height = in_h; src_info.pitch = in_pitch; - src_info.slice = slice_h; + src_info.slice_h = slice_h; + src_info.offset_x = in_x; + src_info.offset_y = in_y; src_info.pixels = pixels_src; dst_info.format = dst_color_format; @@ -560,8 +562,11 @@ namespace rsx dst_info.clip_y = clip_y; dst_info.clip_width = clip_w; dst_info.clip_height = clip_h; - dst_info.pitch = in_pitch; + dst_info.offset_x = out_x; + dst_info.offset_y = out_y; + dst_info.pitch = out_pitch; dst_info.pixels = pixels_dst; + dst_info.rsx_address = get_address(dst_offset, dst_dma); dst_info.swizzled = (method_registers.blit_engine_context_surface() == blit_engine::context_surface::swizzle2d); if (need_convert) diff --git a/rpcs3/GLGSRender.vcxproj b/rpcs3/GLGSRender.vcxproj index c50c613aed..3c8811888b 100644 --- a/rpcs3/GLGSRender.vcxproj +++ b/rpcs3/GLGSRender.vcxproj @@ -1,123 +1,124 @@ - - - - - Debug - LLVM - x64 - - - Debug - MemLeak - x64 - - - Debug - x64 - - - Release - LLVM - x64 - - - Release - x64 - - - - GLGSRender - 8.1 - {3384223A-6D97-4799-9862-359F85312892} - - - - StaticLibrary - Unicode - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) - - - - - ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) - - - - - ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) - - - - - ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) - - - - - ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) - - - - - {c4a10229-4712-4bd2-b63e-50d93c67a038} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug - LLVM + x64 + + + Debug - MemLeak + x64 + + + Debug + x64 + + + Release - LLVM + x64 + + + Release + x64 + + + + GLGSRender + 8.1 + {3384223A-6D97-4799-9862-359F85312892} + + + + StaticLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) + + + + + ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) + Disabled + + + + + ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) + + + + + ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) + + + + + ..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories) + + + + + {c4a10229-4712-4bd2-b63e-50d93c67a038} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file