From f8edc761fc6e621c557f58b83c929344d4a90531 Mon Sep 17 00:00:00 2001 From: gibbed Date: Wed, 9 Aug 2017 02:28:47 -0500 Subject: [PATCH] Vulkan: Do near-exact lookups for the frontbuffer texture (may break everything). --- src/xenia/gpu/vulkan/texture_cache.cc | 52 +++++++++++++++++++ src/xenia/gpu/vulkan/texture_cache.h | 2 + .../gpu/vulkan/vulkan_command_processor.cc | 15 ++++-- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/xenia/gpu/vulkan/texture_cache.cc b/src/xenia/gpu/vulkan/texture_cache.cc index 7bd5a71f9..3f699a708 100644 --- a/src/xenia/gpu/vulkan/texture_cache.cc +++ b/src/xenia/gpu/vulkan/texture_cache.cc @@ -672,6 +672,58 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) { return sampler; } +bool TextureFormatIsSimilar(TextureFormat left, TextureFormat right) { +#define COMPARE_FORMAT(x, y) \ + if ((left == TextureFormat::x && right == TextureFormat::y) || \ + (left == TextureFormat::y && right == TextureFormat::x)) { \ + return true; \ + } + if (left == right) return true; + COMPARE_FORMAT(k_2_10_10_10, k_2_10_10_10_AS_16_16_16_16); + return false; +#undef COMPARE_FORMAT +} + +TextureCache::Texture* TextureCache::Lookup(const TextureInfo& texture_info) { + auto texture_hash = texture_info.hash(); + for (auto it = textures_.find(texture_hash); it != textures_.end(); ++it) { + if (it->second->texture_info == texture_info) { + return it->second; + } + } + // slow path + for (auto it = textures_.begin(); it != textures_.end(); ++it) { + const auto& other_texture_info = it->second->texture_info; +#define COMPARE_FIELD(x) \ + if (texture_info.x != other_texture_info.x) continue + COMPARE_FIELD(guest_address); + COMPARE_FIELD(dimension); + COMPARE_FIELD(width); + COMPARE_FIELD(height); + COMPARE_FIELD(depth); + COMPARE_FIELD(endianness); + COMPARE_FIELD(is_tiled); + COMPARE_FIELD(has_packed_mips); + COMPARE_FIELD(input_length); +#undef COMPARE_FIELD + if (!TextureFormatIsSimilar(texture_info.texture_format, + other_texture_info.texture_format)) { + continue; + } + /*const auto format_info = texture_info.format_info(); + const auto other_format_info = other_texture_info.format_info(); +#define COMPARE_FIELD(x) if (format_info->x != other_format_info->x) continue + COMPARE_FIELD(type); + COMPARE_FIELD(block_width); + COMPARE_FIELD(block_height); + COMPARE_FIELD(bits_per_pixel); +#undef COMPARE_FIELD*/ + return it->second; + } + + return nullptr; +} + TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address, uint32_t width, uint32_t height, diff --git a/src/xenia/gpu/vulkan/texture_cache.h b/src/xenia/gpu/vulkan/texture_cache.h index 863d1a2b0..241faed88 100644 --- a/src/xenia/gpu/vulkan/texture_cache.h +++ b/src/xenia/gpu/vulkan/texture_cache.h @@ -92,6 +92,8 @@ class TextureCache { // TODO(benvanik): ReadTexture. + Texture* Lookup(const TextureInfo& texture_info); + // Looks for a texture either containing or matching these parameters. // Caller is responsible for checking if the texture returned is an exact // match or just contains the texture given by the parameters. diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index a13513004..db3b7ce00 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -395,10 +395,19 @@ void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, } auto swap_fb = reinterpret_cast(swap_state_.front_buffer_texture); + auto& regs = *register_file_; + int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0; + auto group = + reinterpret_cast(®s.values[r]); + auto& fetch = group->texture_fetch; + + TextureInfo texture_info; + if (!TextureInfo::Prepare(group->texture_fetch, &texture_info)) { + assert_always(); + } + // Issue the commands to copy the game's frontbuffer to our backbuffer. - auto texture = texture_cache_->LookupAddress( - frontbuffer_ptr, xe::round_up(frontbuffer_width, 32), - /*xe::round_up(*/ frontbuffer_height /*, 32)*/, TextureFormat::k_8_8_8_8); + auto texture = texture_cache_->Lookup(texture_info); if (texture) { texture->in_flight_fence = current_batch_fence_;