[D3D12] Try to reload textures when a watch is triggered
This commit is contained in:
parent
227268ef65
commit
91ef453534
|
@ -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*>(®s.values[r]);
|
reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(®s.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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue