[D3D12] Try to reload textures when a watch is triggered

This commit is contained in:
Triang3l 2018-08-26 14:52:18 +03:00
parent 227268ef65
commit 91ef453534
2 changed files with 26 additions and 9 deletions

View File

@ -326,6 +326,14 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
SCOPE_profile_cpu_f("gpu"); SCOPE_profile_cpu_f("gpu");
#endif // FINE_GRAINED_DRAW_SCOPES #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. // Update the texture keys and the textures.
uint32_t used_texture_mask = uint32_t used_texture_mask =
used_vertex_texture_mask | used_pixel_texture_mask; used_vertex_texture_mask | used_pixel_texture_mask;
@ -337,7 +345,6 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
continue; continue;
} }
TextureBinding& binding = texture_bindings_[index]; TextureBinding& binding = texture_bindings_[index];
uint32_t r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + index * 6; uint32_t r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + index * 6;
auto group = auto group =
reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(&regs.values[r]); reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(&regs.values[r]);
@ -345,17 +352,18 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
TextureKeyFromFetchConstant(group->texture_fetch, binding.key, TextureKeyFromFetchConstant(group->texture_fetch, binding.key,
binding.swizzle); binding.swizzle);
texture_keys_in_sync_ |= index_bit; texture_keys_in_sync_ |= index_bit;
if (binding.key.IsInvalid() || binding.key == old_key) { if (binding.key.IsInvalid()) {
continue; continue;
} }
bool load = force_load;
if (binding.key != old_key) {
binding.texture = FindOrCreateTexture(binding.key); binding.texture = FindOrCreateTexture(binding.key);
if (binding.texture == nullptr) { load = true;
continue;
} }
if (load && binding.texture != nullptr) {
LoadTextureData(binding.texture); LoadTextureData(binding.texture);
} }
}
// Transition the textures to the needed usage. // Transition the textures to the needed usage.
used_texture_mask = used_vertex_texture_mask | used_pixel_texture_mask; used_texture_mask = used_vertex_texture_mask | used_pixel_texture_mask;
@ -1080,12 +1088,14 @@ void TextureCache::WatchCallback(Texture* texture, bool is_mip) {
} }
XELOGE("Texture %s at %.8X invalidated", is_mip ? "mips" : "base", XELOGE("Texture %s at %.8X invalidated", is_mip ? "mips" : "base",
(is_mip ? texture->key.mip_page : texture->key.base_page) << 12); (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() { void TextureCache::ClearBindings() {
std::memset(texture_bindings_, 0, sizeof(texture_bindings_)); std::memset(texture_bindings_, 0, sizeof(texture_bindings_));
texture_keys_in_sync_ = 0; texture_keys_in_sync_ = 0;
// Already reset everything.
texture_invalidated_.store(false, std::memory_order_relaxed);
} }
} // namespace d3d12 } // namespace d3d12

View File

@ -10,6 +10,7 @@
#ifndef XENIA_GPU_D3D12_TEXTURE_CACHE_H_ #ifndef XENIA_GPU_D3D12_TEXTURE_CACHE_H_
#define XENIA_GPU_D3D12_TEXTURE_CACHE_H_ #define XENIA_GPU_D3D12_TEXTURE_CACHE_H_
#include <atomic>
#include <unordered_map> #include <unordered_map>
#include "xenia/gpu/d3d12/shared_memory.h" #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 // Bit vector with bits reset on fetch constant writes to avoid getting
// texture keys from the fetch constants again and again. // texture keys from the fetch constants again and again.
uint32_t texture_keys_in_sync_ = 0; 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<bool> texture_invalidated_ = false;
}; };
} // namespace d3d12 } // namespace d3d12