summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgibbed <rick@gibbed.us>2017-08-09 02:28:47 -0500
committergibbed <rick@gibbed.us>2017-08-09 02:28:47 -0500
commitf8edc761fc6e621c557f58b83c929344d4a90531 (patch)
tree5d2d4d1f7d89a82d189829dbe51d46a94364be45
parentff1a3aaa670b5efd490e3de30bdf46c09c6d8ce0 (diff)
Vulkan: Do near-exact lookups for the frontbuffer texture (may break everything).
-rw-r--r--src/xenia/gpu/vulkan/texture_cache.cc52
-rw-r--r--src/xenia/gpu/vulkan/texture_cache.h2
-rw-r--r--src/xenia/gpu/vulkan/vulkan_command_processor.cc15
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<VkImage>(swap_state_.front_buffer_texture);
+ auto& regs = *register_file_;
+ int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0;
+ auto group =
+ reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(&regs.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_;