From 6cb957c0e1346b6245c3a6eb72d3ffb47d08c19b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 28 Jan 2022 22:42:55 +0300 Subject: [PATCH] rsx: Validate requested images before attempting to upload them - Do not allow dimensions of 0 to reach the backend APIs --- rpcs3/Emu/RSX/Common/texture_cache.h | 10 ++++++++++ rpcs3/Emu/RSX/GL/GLDraw.cpp | 18 ++++++++++++------ rpcs3/Emu/RSX/RSXThread.cpp | 2 +- rpcs3/Emu/RSX/VK/VKDraw.cpp | 20 ++++++++++++++------ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 86e4dabb9ca7..b3317d56b296 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2084,6 +2084,7 @@ namespace rsx { case rsx::texture_dimension_extended::texture_dimension_1d: attributes.depth = 1; + attributes.height = 1; attributes.slice_h = 1; scale.height = scale.depth = 0.f; subsurface_count = 1; @@ -2113,6 +2114,15 @@ namespace rsx fmt::throw_exception("Unsupported texture dimension %d", static_cast(extended_dimension)); } + // Validation + if (!attributes.width || !attributes.height || !attributes.depth) + { + rsx_log.warning("Image at address 0x%x has invalid dimensions. Type=%d, Dims=%dx%dx%d", + attributes.address, static_cast(extended_dimension), + attributes.width, attributes.height, attributes.depth); + return {}; + } + if (options.is_compressed_format) { // Compressed textures cannot be 1D in some APIs diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 1226976bf447..dd1c645d0318 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -298,15 +298,17 @@ void GLGSRender::load_texture_env() if (tex.enabled()) { *sampler_state = m_gl_texture_cache.upload_texture(cmd, tex, m_rtts); - - if (m_textures_dirty[i]) - m_fs_sampler_states[i].apply(tex, fs_sampler_state[i].get()); } else { *sampler_state = {}; } + if (m_textures_dirty[i] && sampler_state->validate()) + { + m_fs_sampler_states[i].apply(tex, fs_sampler_state[i].get()); + } + m_textures_dirty[i] = false; } } @@ -327,12 +329,16 @@ void GLGSRender::load_texture_env() if (rsx::method_registers.vertex_textures[i].enabled()) { *sampler_state = m_gl_texture_cache.upload_texture(cmd, rsx::method_registers.vertex_textures[i], m_rtts); - - if (m_vertex_textures_dirty[i]) - m_vs_sampler_states[i].apply(tex, vs_sampler_state[i].get()); } else + { *sampler_state = {}; + } + + if (m_vertex_textures_dirty[i] && sampler_state->validate()) + { + m_vs_sampler_states[i].apply(tex, vs_sampler_state[i].get()); + } m_vertex_textures_dirty[i] = false; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 483d9af94088..d67db0b659df 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1934,7 +1934,7 @@ namespace rsx auto &tex = rsx::method_registers.fragment_textures[i]; current_fp_texture_state.clear(i); - if (tex.enabled()) + if (tex.enabled() && sampler_descriptors[i]->format_class != RSX_FORMAT_CLASS_UNDEFINED) { current_fragment_program.texture_params[i].scale[0] = sampler_descriptors[i]->scale_x; current_fragment_program.texture_params[i].scale[1] = sampler_descriptors[i]->scale_y; diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index fc8564cb2a59..1acf0e8c52e9 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -177,7 +177,14 @@ void VKGSRender::load_texture_env() { check_heap_status(VK_HEAP_CHECK_TEXTURE_UPLOAD_STORAGE); *sampler_state = m_texture_cache.upload_texture(*m_current_command_buffer, tex, m_rtts); + } + else + { + *sampler_state = {}; + } + if (sampler_state->validate()) + { if (sampler_state->is_cyclic_reference) { check_for_cyclic_refs |= true; @@ -295,10 +302,6 @@ void VKGSRender::load_texture_env() border_color, compare_enabled, depth_compare_mode); } } - else - { - *sampler_state = {}; - } m_textures_dirty[i] = false; } @@ -321,7 +324,14 @@ void VKGSRender::load_texture_env() { check_heap_status(VK_HEAP_CHECK_TEXTURE_UPLOAD_STORAGE); *sampler_state = m_texture_cache.upload_texture(*m_current_command_buffer, tex, m_rtts); + } + else + { + *sampler_state = {}; + } + if (sampler_state->validate()) + { if (sampler_state->is_cyclic_reference || sampler_state->external_subresource_desc.do_not_cache) { check_for_cyclic_refs |= true; @@ -353,8 +363,6 @@ void VKGSRender::load_texture_env() VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, border_color); } } - else - *sampler_state = {}; m_vertex_textures_dirty[i] = false; }