From 91ef453534d7e6f280c789b0d47325107375f0ca Mon Sep 17 00:00:00 2001 From: Triang3l Date: Sun, 26 Aug 2018 14:52:18 +0300 Subject: [PATCH] [D3D12] Try to reload textures when a watch is triggered --- src/xenia/gpu/d3d12/texture_cache.cc | 28 +++++++++++++++++++--------- src/xenia/gpu/d3d12/texture_cache.h | 7 +++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 52e45f12c..29772ae57 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -326,6 +326,14 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask, SCOPE_profile_cpu_f("gpu"); #endif // FINE_GRAINED_DRAW_SCOPES + // If a texture was invalidated, ignore whether bindings have been changed + // when determining whether textures need to be reloaded. + bool force_load = + texture_invalidated_.exchange(false, std::memory_order_relaxed); + if (force_load) { + texture_keys_in_sync_ = 0; + } + // Update the texture keys and the textures. uint32_t used_texture_mask = used_vertex_texture_mask | used_pixel_texture_mask; @@ -337,7 +345,6 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask, continue; } TextureBinding& binding = texture_bindings_[index]; - uint32_t r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + index * 6; auto group = reinterpret_cast(®s.values[r]); @@ -345,16 +352,17 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask, TextureKeyFromFetchConstant(group->texture_fetch, binding.key, binding.swizzle); texture_keys_in_sync_ |= index_bit; - if (binding.key.IsInvalid() || binding.key == old_key) { + if (binding.key.IsInvalid()) { continue; } - - binding.texture = FindOrCreateTexture(binding.key); - if (binding.texture == nullptr) { - continue; + bool load = force_load; + if (binding.key != old_key) { + binding.texture = FindOrCreateTexture(binding.key); + load = true; + } + if (load && binding.texture != nullptr) { + LoadTextureData(binding.texture); } - - LoadTextureData(binding.texture); } // Transition the textures to the needed usage. @@ -1080,12 +1088,14 @@ void TextureCache::WatchCallback(Texture* texture, bool is_mip) { } XELOGE("Texture %s at %.8X invalidated", is_mip ? "mips" : "base", (is_mip ? texture->key.mip_page : texture->key.base_page) << 12); - // TODO(Triang3l): Notify bindings that ranges should be requested again. + texture_invalidated_.store(true, std::memory_order_relaxed); } void TextureCache::ClearBindings() { std::memset(texture_bindings_, 0, sizeof(texture_bindings_)); texture_keys_in_sync_ = 0; + // Already reset everything. + texture_invalidated_.store(false, std::memory_order_relaxed); } } // namespace d3d12 diff --git a/src/xenia/gpu/d3d12/texture_cache.h b/src/xenia/gpu/d3d12/texture_cache.h index 75544eea0..b056ce98e 100644 --- a/src/xenia/gpu/d3d12/texture_cache.h +++ b/src/xenia/gpu/d3d12/texture_cache.h @@ -10,6 +10,7 @@ #ifndef XENIA_GPU_D3D12_TEXTURE_CACHE_H_ #define XENIA_GPU_D3D12_TEXTURE_CACHE_H_ +#include #include #include "xenia/gpu/d3d12/shared_memory.h" @@ -316,6 +317,12 @@ class TextureCache { // Bit vector with bits reset on fetch constant writes to avoid getting // texture keys from the fetch constants again and again. uint32_t texture_keys_in_sync_ = 0; + + // Whether a texture has been invalidated (a watch has been triggered), so + // need to try to reload textures, disregarding whether fetch constants have + // been changed. A simple notification (texture validity is protected by a + // mutex), so memory_order_relaxed is enough. + std::atomic texture_invalidated_ = false; }; } // namespace d3d12