Runtime texture replacement API

This commit is contained in:
Luke Street
2026-05-29 21:11:39 -06:00
parent f4eb2ee151
commit c214a67adf
8 changed files with 552 additions and 279 deletions
-1
View File
@@ -91,7 +91,6 @@ typedef struct {
bool startFullscreen;
bool allowJoystickBackgroundEvents;
bool pauseOnFocusLost;
bool allowTextureReplacements;
bool allowTextureDumps;
bool allowCpuAdapter;
int32_t windowPosX;
-2
View File
@@ -31,8 +31,6 @@ typedef struct {
const AuroraStats* aurora_get_stats();
void aurora_enable_vsync(bool enabled);
void aurora_set_texture_replacements_enabled(bool enabled);
void aurora_reload_texture_replacements();
#ifdef __cplusplus
}
+68
View File
@@ -0,0 +1,68 @@
#ifndef AURORA_TEXTURE_HPP
#define AURORA_TEXTURE_HPP
#include <cstdint>
#include <filesystem>
#include <span>
#include <string_view>
#include <variant>
#include <vector>
namespace aurora::texture {
struct TextureSourceKey {
uint64_t textureHash = 0;
uint64_t tlutHash = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t format = 0;
bool hasTlut = false;
bool operator==(const TextureSourceKey&) const = default;
};
struct TexturePointerKey {
const void* data = nullptr;
bool operator==(const TexturePointerKey&) const = default;
};
using ReplacementKey = std::variant<TexturePointerKey, TextureSourceKey>;
struct RawTextureReplacement {
std::span<const uint8_t> bytes;
uint32_t width = 0;
uint32_t height = 0;
uint32_t mipCount = 1;
uint32_t gxFormat = 0;
std::string_view label = {};
};
struct ReplacementOptions {
int32_t priority = 0;
};
struct ReplacementRegistration {
uint64_t id = 0;
ReplacementKey key;
};
struct ReplacementGroup {
std::vector<ReplacementRegistration> registrations;
};
ReplacementRegistration register_replacement(ReplacementKey key, RawTextureReplacement replacement,
ReplacementOptions options = {});
void unregister_replacement(const ReplacementRegistration& registration);
void unregister_replacements(std::span<const ReplacementRegistration> registrations);
void unregister_replacements(const ReplacementGroup& group);
void unregister_replacements(const ReplacementKey& key);
void clear_replacements();
ReplacementGroup load_replacement_directory(const std::filesystem::path& root, ReplacementOptions options = {});
void reload_replacement_directory(const std::filesystem::path& root, ReplacementGroup& group,
ReplacementOptions options = {});
} // namespace aurora::texture
#endif
-7
View File
@@ -1089,10 +1089,3 @@ void pop_debug_group() {
}
const AuroraStats* aurora_get_stats() { return &aurora::gfx::g_stats; }
void aurora_set_texture_replacements_enabled(const bool enabled) {
aurora::g_config.allowTextureReplacements = enabled;
aurora::gfx::texture_replacement::reload();
}
void aurora_reload_texture_replacements() { aurora::gfx::texture_replacement::reload(); }
File diff suppressed because it is too large Load Diff
-1
View File
@@ -6,7 +6,6 @@
namespace aurora::gfx::texture_replacement {
void initialize() noexcept;
void shutdown() noexcept;
void reload() noexcept;
void register_tlut(const GXTlutObj* obj, const void* data, GXTlutFmt format, uint16_t entries) noexcept;
void load_tlut(const GXTlutObj* obj, uint32_t idx) noexcept;
std::optional<TextureHandle> find_replacement(const GXTexObj_& obj) noexcept;
-1
View File
@@ -1,7 +1,6 @@
#include "command_processor.hpp"
#include "../gfx/common.hpp"
#include "../gfx/texture_replacement.hpp"
#include "dolphin/gx/GXAurora.h"
#include "gx.hpp"
#include "gx_fmt.hpp"
+16 -4
View File
@@ -15,6 +15,7 @@
#include <absl/container/flat_hash_set.h>
#include <tracy/Tracy.hpp>
#include <atomic>
#include <cfloat>
#include <mutex>
#include <optional>
@@ -78,6 +79,14 @@ struct TlutObjectCache {
absl::flat_hash_map<u32, CachedTextureEntry> s_textureObjectCaches;
absl::flat_hash_map<u32, TlutObjectCache> s_tlutObjectCaches;
std::atomic_bool s_staticTextureCacheClearPending = false;
void do_clear_static_texture_cache() noexcept {
s_textureObjectCaches.clear();
for (auto& [_, cache] : s_tlutObjectCaches) {
cache.staticTextureUsers.clear();
}
}
DynamicPaletteKey make_dynamic_palette_key(const GXTexObj_& obj, const GXState::CopyTextureRef& source) {
return {
@@ -147,6 +156,9 @@ gfx::TextureHandle get_tlut_texture(const GXTlutObj_& tlut) {
gfx::TextureHandle resolve_static_texture(const GXTexObj_& obj) {
ZoneScoped;
if (s_staticTextureCacheClearPending.exchange(false, std::memory_order_acq_rel)) {
do_clear_static_texture_cache();
}
if (obj.texObjId != 0) {
if (const auto it = s_textureObjectCaches.find(obj.texObjId); it != s_textureObjectCaches.end()) {
@@ -179,6 +191,9 @@ gfx::TextureHandle resolve_static_texture(const GXTexObj_& obj) {
gfx::TextureHandle resolve_static_palette_texture(const GXTexObj_& obj, const GXTlutObj_& tlut) {
ZoneScoped;
if (s_staticTextureCacheClearPending.exchange(false, std::memory_order_acq_rel)) {
do_clear_static_texture_cache();
}
if (obj.texObjId != 0) {
if (const auto it = s_textureObjectCaches.find(obj.texObjId); it != s_textureObjectCaches.end()) {
@@ -370,10 +385,7 @@ void clear_copy_texture_cache() noexcept {
}
void clear_static_texture_cache() noexcept {
s_textureObjectCaches.clear();
for (auto& [_, cache] : s_tlutObjectCaches) {
cache.staticTextureUsers.clear();
}
s_staticTextureCacheClearPending.store(true, std::memory_order_release);
}
void evict_copy_texture(const void* dest) noexcept {