diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 50af451884..3481db1a8d 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -274,6 +274,9 @@ namespace rsx //Set when a hw blit engine incompatibility is detected bool blit_engine_incompatibility_warning_raised = false; + //Set when a shader read-only texture data suddenly becomes contested, usually by fbo memory + bool read_only_tex_invalidate = false; + //Memory usage const s32 m_max_zombie_objects = 64; //Limit on how many texture objects to keep around for reuse after they are invalidated std::atomic m_unreleased_texture_objects = { 0 }; //Number of invalidated objects not yet freed from memory @@ -782,6 +785,7 @@ namespace rsx { //This space was being used for other purposes other than framebuffer storage //Delete used resources before attaching it to framebuffer memory + read_only_tex_invalidate = true; free_texture_section(region); m_texture_memory_in_use -= region.get_section_size(); } @@ -1875,6 +1879,20 @@ namespace rsx return m_texture_memory_in_use; } + /** + * The read only texture invalidate flag is set if a read only texture is trampled by framebuffer memory + * If set, all cached read only textures are considered invalid and should be re-fetched from the texture cache + */ + virtual void clear_ro_tex_invalidate_intr() + { + read_only_tex_invalidate = false; + } + + virtual bool get_ro_tex_invalidate_intr() const + { + return read_only_tex_invalidate; + } + void tag_framebuffer(u32 texaddr) { if (!g_cfg.video.strict_rendering_mode) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 7d593570fc..e4c0407395 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -176,21 +176,6 @@ void GLGSRender::begin() init_buffers(rsx::framebuffer_creation_context::context_draw); } -namespace -{ - GLenum get_gl_target_for_texture(const rsx::texture_dimension_extended type) - { - switch (type) - { - case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D; - case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D; - case rsx::texture_dimension_extended::texture_dimension_cubemap: return GL_TEXTURE_CUBE_MAP; - case rsx::texture_dimension_extended::texture_dimension_3d: return GL_TEXTURE_3D; - } - fmt::throw_exception("Unknown texture target" HERE); - } -} - void GLGSRender::end() { std::chrono::time_point state_check_start = steady_clock::now(); @@ -321,7 +306,7 @@ void GLGSRender::end() if (tex.enabled()) { - GLenum target = get_gl_target_for_texture(sampler_state->image_type); + GLenum target = gl::get_target(sampler_state->image_type); if (sampler_state->image_handle) { glBindTexture(target, sampler_state->image_handle); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 78925df545..4697459867 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -365,6 +365,8 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk break; } + m_gl_texture_cache.clear_ro_tex_invalidate_intr(); + //Mark buffer regions as NO_ACCESS on Cell visible side if (g_cfg.video.write_color_buffers) { @@ -394,6 +396,12 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk depth_format_gl.format, depth_format_gl.type, true); } } + + if (m_gl_texture_cache.get_ro_tex_invalidate_intr()) + { + //Invalidate cached sampler state + m_samplers_dirty.store(true); + } } std::array, 4> GLGSRender::copy_render_targets_to_memory() diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 41d6d2c6f3..f711325888 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -8,6 +8,18 @@ namespace gl { + GLenum get_target(rsx::texture_dimension_extended type) + { + switch (type) + { + case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D; + case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D; + case rsx::texture_dimension_extended::texture_dimension_cubemap: return GL_TEXTURE_CUBE_MAP; + case rsx::texture_dimension_extended::texture_dimension_3d: return GL_TEXTURE_3D; + } + fmt::throw_exception("Unknown texture target" HERE); + } + GLenum get_sized_internal_format(u32 texture_format) { switch (texture_format) diff --git a/rpcs3/Emu/RSX/GL/GLTexture.h b/rpcs3/Emu/RSX/GL/GLTexture.h index 7e49de3a93..494886ad73 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.h +++ b/rpcs3/Emu/RSX/GL/GLTexture.h @@ -10,6 +10,7 @@ namespace rsx namespace gl { + GLenum get_target(rsx::texture_dimension_extended type); GLenum get_sized_internal_format(u32 gcm_format); std::tuple get_format_type(u32 texture_format); GLenum wrap_mode(rsx::texture_wrap_mode wrap); diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 75fb7056d8..47edcb05ab 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -765,8 +765,9 @@ namespace gl break; } - glBindTexture(GL_TEXTURE_2D, vram_texture); - apply_component_mapping_flags(GL_TEXTURE_2D, gcm_format, flags); + auto target = gl::get_target(type); + glBindTexture(target, vram_texture); + apply_component_mapping_flags(target, gcm_format, flags); auto& cached = create_texture(vram_texture, rsx_address, rsx_size, width, height, depth, mipmaps); cached.set_dirty(false);