mirror of
https://github.com/encounter/aurora.git
synced 2026-07-09 18:19:33 -07:00
Texture loading fixes (#170)
* Implement PNG & arb texture replacements Fixes #119 For arb textures it's just making sure the file parsing can handle them. Idk if we need to do something special for it. * Allow non-mipmapped textures to be replaced by mipmapped textures Some of Henriko's textures (like the cuttable grass) rely on this. The mipmap bool is no longer part of the runtime key. * Make texture name the texture replacement key Might as well? Helped me debug some stuff * Oops that broke it bad * libpng instead of spng * I did it again * Update libpng fetch * Add zlib fetch * Forgot to set the hash * Add zlib redirect * Add INCLUDE_DIR(S) to redirect * Prefer shared for libpng * Set CMAKE_FIND_PACKAGE_TARGETS_GLOBAL --------- Co-authored-by: Luke Street <luke@street.dev>
This commit is contained in:
committed by
GitHub
parent
974d11dfe7
commit
f7f3d52cfc
@@ -34,10 +34,12 @@ add_library(aurora_gx STATIC
|
||||
lib/dolphin/gx/GXTransform.cpp
|
||||
lib/dolphin/gx/GXVert.cpp
|
||||
lib/dolphin/gx/GXAurora.cpp
|
||||
lib/gfx/png_io.cpp
|
||||
lib/gfx/png_io.hpp
|
||||
)
|
||||
add_library(aurora::gx ALIAS aurora_gx)
|
||||
set_target_properties(aurora_gx PROPERTIES FOLDER "aurora")
|
||||
|
||||
target_link_libraries(aurora_gx PUBLIC aurora::core xxhash)
|
||||
target_link_libraries(aurora_gx PRIVATE absl::btree absl::flat_hash_map dawn::webgpu_dawn sqlite3 TracyClient)
|
||||
target_link_libraries(aurora_gx PRIVATE absl::btree absl::flat_hash_map dawn::webgpu_dawn sqlite3 TracyClient PNG::PNG)
|
||||
target_compile_definitions(aurora_gx PRIVATE WEBGPU_DAWN)
|
||||
|
||||
Vendored
+71
-17
@@ -3,6 +3,13 @@ include(FetchContent)
|
||||
# Don't build tests for third party dependencies
|
||||
set(BUILD_TESTING OFF CACHE INTERNAL "Build tests")
|
||||
|
||||
function(aurora_find_package_global)
|
||||
set(_PREV_FIND_PACKAGE_TARGETS_GLOBAL ${CMAKE_FIND_PACKAGE_TARGETS_GLOBAL})
|
||||
set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL ON)
|
||||
find_package(${ARGV})
|
||||
set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL ${_PREV_FIND_PACKAGE_TARGETS_GLOBAL})
|
||||
endfunction()
|
||||
|
||||
if (AURORA_ENABLE_GX)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/AuroraDawnProvider.cmake)
|
||||
endif ()
|
||||
@@ -10,7 +17,7 @@ endif ()
|
||||
# Abseil is needed for core libraries. It normally comes via Dawn's vendor build.
|
||||
# Otherwise prefer a system package and only fetch it as a last resort.
|
||||
if (NOT TARGET absl::flat_hash_map OR NOT TARGET absl::btree)
|
||||
find_package(absl CONFIG QUIET GLOBAL)
|
||||
aurora_find_package_global(absl CONFIG QUIET GLOBAL)
|
||||
endif ()
|
||||
|
||||
if (TARGET absl::flat_hash_map AND TARGET absl::btree)
|
||||
@@ -77,7 +84,61 @@ else ()
|
||||
endif ()
|
||||
|
||||
if (AURORA_ENABLE_GX)
|
||||
find_package(Freetype QUIET)
|
||||
if (NOT TARGET ZLIB::ZLIB)
|
||||
aurora_find_package_global(ZLIB QUIET)
|
||||
endif ()
|
||||
if (NOT TARGET ZLIB::ZLIB)
|
||||
message(STATUS "aurora: Fetching zlib")
|
||||
FetchContent_Declare(
|
||||
ZLIB
|
||||
URL https://github.com/madler/zlib/releases/download/v1.3.2/zlib-1.3.2.tar.gz
|
||||
URL_HASH SHA256=bb329a0a2cd0274d05519d61c667c062e06990d72e125ee2dfa8de64f0119d16
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(ZLIB)
|
||||
if (NOT TARGET ZLIB::ZLIB)
|
||||
message(FATAL_ERROR "Failed to make zlib available")
|
||||
endif ()
|
||||
# libpng calls find_package(ZLIB) even when zlib was already provided by FetchContent.
|
||||
file(WRITE "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/ZLIBConfig.cmake"
|
||||
"set(ZLIB_FOUND TRUE)\n"
|
||||
"set(ZLIB_INCLUDE_DIR \"${zlib_SOURCE_DIR}\")\n"
|
||||
"set(ZLIB_INCLUDE_DIRS \"${zlib_BINARY_DIR};${zlib_SOURCE_DIR}\")\n"
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (NOT TARGET PNG::PNG)
|
||||
if (TARGET png_shared)
|
||||
add_library(PNG::PNG ALIAS png_shared)
|
||||
elseif (TARGET png_static)
|
||||
add_library(PNG::PNG ALIAS png_static)
|
||||
else ()
|
||||
aurora_find_package_global(PNG QUIET)
|
||||
endif ()
|
||||
endif ()
|
||||
if (NOT TARGET PNG::PNG)
|
||||
message(STATUS "aurora: Fetching libpng")
|
||||
FetchContent_Declare(
|
||||
PNG
|
||||
URL https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.58.tar.gz
|
||||
URL_HASH SHA256=A9D4DF463D36A6E5F9C29BD6F4967312D17E996C1854F3511F833924EB1993CF
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(PNG)
|
||||
if (TARGET png_shared)
|
||||
add_library(PNG::PNG ALIAS png_shared)
|
||||
elseif (TARGET png_static)
|
||||
add_library(PNG::PNG ALIAS png_static)
|
||||
else ()
|
||||
message(FATAL_ERROR "Failed to make libpng available")
|
||||
endif ()
|
||||
else ()
|
||||
message(STATUS "aurora: Using existing libpng")
|
||||
endif ()
|
||||
|
||||
aurora_find_package_global(Freetype QUIET)
|
||||
if (NOT TARGET Freetype::Freetype)
|
||||
message(STATUS "aurora: Fetching Freetype")
|
||||
set(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE)
|
||||
@@ -175,30 +236,22 @@ if (AURORA_ENABLE_GX)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if(AURORA_ENABLE_RMLUI AND NOT TARGET RmlUi)
|
||||
if (AURORA_ENABLE_RMLUI AND NOT TARGET RmlUi)
|
||||
message(STATUS "aurora: Fetching RmlUi")
|
||||
FetchContent_Declare(rmlui
|
||||
URL https://github.com/mikke89/RmlUi/archive/f9b8c9e2935d5df2c7dff2c190d3968e99b0c3dc.tar.gz
|
||||
URL_HASH SHA256=42b830abc2509a8c07cf02ba3313505de3a4642725654f489402022d8fefdd79
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
URL https://github.com/mikke89/RmlUi/archive/f9b8c9e2935d5df2c7dff2c190d3968e99b0c3dc.tar.gz
|
||||
URL_HASH SHA256=42b830abc2509a8c07cf02ba3313505de3a4642725654f489402022d8fefdd79
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(rmlui)
|
||||
|
||||
add_library(rmlui_backends STATIC
|
||||
${rmlui_SOURCE_DIR}/Backends/RmlUi_Platform_SDL.cpp
|
||||
)
|
||||
add_library(rmlui_backends STATIC ${rmlui_SOURCE_DIR}/Backends/RmlUi_Platform_SDL.cpp)
|
||||
# TODO: maybe dont hardcode this to SDL3?
|
||||
target_compile_definitions(rmlui_backends PUBLIC RMLUI_SDL_VERSION_MAJOR=3)
|
||||
|
||||
target_include_directories(rmlui_backends PUBLIC
|
||||
${rmlui_SOURCE_DIR}/Backends
|
||||
)
|
||||
|
||||
target_include_directories(rmlui_backends PUBLIC ${rmlui_SOURCE_DIR}/Backends)
|
||||
target_link_libraries(rmlui_backends PRIVATE rmlui ${AURORA_SDL3_TARGET})
|
||||
|
||||
endif ()
|
||||
|
||||
endif ()
|
||||
|
||||
if (NOT TARGET TracyClient)
|
||||
@@ -212,6 +265,7 @@ if (NOT TARGET TracyClient)
|
||||
URL https://github.com/wolfpld/tracy/archive/a64b9a20294d59421a2f57aeca3c6383d8c48169.tar.gz
|
||||
URL_HASH SHA256=24d342b5127d7f659dc3cf94f24347b348cc736f25b17a691fd7f69541937658
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(tracy)
|
||||
|
||||
|
||||
@@ -11,4 +11,7 @@ std::optional<ConvertedTexture> parse_dds_bytes(ArrayRef<uint8_t> bytes) noexcep
|
||||
std::optional<ConvertedTexture> load_dds_file(const std::filesystem::path& path) noexcept;
|
||||
ByteBuffer encode_rgba8_dds(uint32_t width, uint32_t height, ArrayRef<uint8_t> pixels);
|
||||
bool write_rgba8_dds(const std::filesystem::path& path, uint32_t width, uint32_t height, ArrayRef<u8> pixels) noexcept;
|
||||
|
||||
std::optional<ByteBuffer> read_binary_file(const std::filesystem::path& path) noexcept;
|
||||
|
||||
} // namespace aurora::gfx::dds
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "png_io.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "dds_io.hpp"
|
||||
#include "png.h"
|
||||
#include "../fs_helper.hpp"
|
||||
|
||||
static aurora::Module Log("aurora::gfx::png");
|
||||
|
||||
namespace aurora::gfx::png {
|
||||
|
||||
struct PngStructs {
|
||||
png_structp pStruct;
|
||||
png_infop pInfo;
|
||||
std::ifstream file;
|
||||
|
||||
~PngStructs() {
|
||||
png_destroy_read_struct(&pStruct, &pInfo, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
static void readPngData(png_structp png, png_bytep data, const size_t length) {
|
||||
auto structs = static_cast<PngStructs*>(png_get_io_ptr(png));
|
||||
structs->file.read(reinterpret_cast<char*>(data), static_cast<std::streamsize>(length));
|
||||
|
||||
if (structs->file.eof() || structs->file.fail()) {
|
||||
png_error(png, "file read failed!");
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<ConvertedTexture>
|
||||
load_png_file(const std::filesystem::path& path) noexcept {
|
||||
PngStructs structs{};
|
||||
|
||||
structs.file = std::move(std::ifstream(path, std::ifstream::in | std::ifstream::binary));
|
||||
if (!structs.file) {
|
||||
Log.error("failed to open file: {}", fs_path_to_string(path));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
structs.pStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!structs.pStruct) {
|
||||
Log.error("png_create_read_struct failed");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
structs.pInfo = png_create_info_struct(structs.pStruct);
|
||||
if (!structs.pInfo) {
|
||||
Log.error("png_create_info_struct failed");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// I'm scared of putting any locals after that setjmp.
|
||||
std::vector<png_bytep> rowPointers;
|
||||
ByteBuffer imageData{};
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type, filter_type;
|
||||
size_t rowBytes;
|
||||
int i;
|
||||
|
||||
if (setjmp(png_jmpbuf(structs.pStruct))) {
|
||||
Log.error("libpng encountered an error");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
png_set_read_fn(structs.pStruct, &structs, readPngData);
|
||||
png_read_info(structs.pStruct, structs.pInfo);
|
||||
|
||||
if (!png_get_IHDR(structs.pStruct, structs.pInfo, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) {
|
||||
Log.error("libpng unable to read IHDR");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Always read as RGBA8.
|
||||
png_set_gray_to_rgb(structs.pStruct);
|
||||
png_set_filler(structs.pStruct, 0xFF, PNG_FILLER_AFTER);
|
||||
png_set_expand(structs.pStruct);
|
||||
png_set_strip_16(structs.pStruct);
|
||||
|
||||
png_read_update_info(structs.pStruct, structs.pInfo);
|
||||
rowBytes = png_get_rowbytes(structs.pStruct, structs.pInfo);
|
||||
rowPointers.resize(height);
|
||||
|
||||
imageData.append_zeroes(rowBytes * height);
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
rowPointers[i] = imageData.data() + i * rowBytes;
|
||||
}
|
||||
|
||||
png_read_image(structs.pStruct, rowPointers.data());
|
||||
png_read_end(structs.pStruct, nullptr);
|
||||
|
||||
return ConvertedTexture{
|
||||
.format = wgpu::TextureFormat::RGBA8Unorm,
|
||||
.width = width,
|
||||
.height = height,
|
||||
.mips = 1,
|
||||
.data = std::move(imageData)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "texture_convert.hpp"
|
||||
|
||||
namespace aurora::gfx::png {
|
||||
std::optional<ConvertedTexture> load_png_file(const std::filesystem::path& path) noexcept;
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
#include "png_io.hpp"
|
||||
#include "../fs_helper.hpp"
|
||||
|
||||
using namespace aurora::gx;
|
||||
@@ -34,7 +35,6 @@ struct RuntimeTextureKey {
|
||||
uint64_t tlutHash = 0;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
bool hasMips = false;
|
||||
bool hasTlut = false;
|
||||
uint32_t format = 0;
|
||||
|
||||
@@ -42,8 +42,7 @@ struct RuntimeTextureKey {
|
||||
|
||||
template <typename H>
|
||||
friend H AbslHashValue(H h, const RuntimeTextureKey& key) {
|
||||
return H::combine(std::move(h), key.textureHash, key.tlutHash, key.width, key.height, key.hasMips, key.hasTlut,
|
||||
key.format);
|
||||
return H::combine(std::move(h), key.textureHash, key.tlutHash, key.width, key.height, key.hasTlut, key.format);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -61,7 +60,12 @@ struct CachedReplacement {
|
||||
std::list<RuntimeTextureKey>::iterator lruIt;
|
||||
};
|
||||
|
||||
absl::flat_hash_map<RuntimeTextureKey, std::filesystem::path> s_replacementIndex;
|
||||
struct ReplacementIndexEntry {
|
||||
std::filesystem::path path;
|
||||
bool hasMips;
|
||||
};
|
||||
|
||||
absl::flat_hash_map<RuntimeTextureKey, ReplacementIndexEntry> s_replacementIndex;
|
||||
absl::flat_hash_map<RuntimeTextureKey, CachedReplacement> s_replacementCache;
|
||||
absl::flat_hash_set<RuntimeTextureKey> s_failedKeys;
|
||||
absl::flat_hash_set<RuntimeTextureKey> s_reportedMisses;
|
||||
@@ -258,7 +262,6 @@ RuntimeTextureKey build_runtime_key(const GXTexObj_& obj) noexcept {
|
||||
RuntimeTextureKey key{
|
||||
.width = obj.width(),
|
||||
.height = obj.height(),
|
||||
.hasMips = obj.has_mips(),
|
||||
.hasTlut = is_palette_format(obj.format()),
|
||||
.format = obj.format(),
|
||||
};
|
||||
@@ -275,16 +278,19 @@ RuntimeTextureKey build_runtime_key(const GXTexObj_& obj) noexcept {
|
||||
|
||||
std::string format_replacement_filename(const RuntimeTextureKey& key) {
|
||||
if (key.hasTlut) {
|
||||
return fmt::format("tex1_{}x{}{}_{:016x}_{:016x}_{}.dds", key.width, key.height, key.hasMips ? "_m" : "",
|
||||
return fmt::format("tex1_{}x{}_{:016x}_{:016x}_{}.dds", key.width, key.height,
|
||||
key.textureHash, key.tlutHash, key.format);
|
||||
}
|
||||
return fmt::format("tex1_{}x{}{}_{:016x}_{}.dds", key.width, key.height, key.hasMips ? "_m" : "", key.textureHash,
|
||||
key.format);
|
||||
return fmt::format("tex1_{}x{}_{:016x}_{}.dds", key.width, key.height, key.textureHash, key.format);
|
||||
}
|
||||
|
||||
std::optional<RuntimeTextureKey> parse_replacement_filename(std::string_view filename) noexcept {
|
||||
const size_t dot = filename.rfind('.');
|
||||
if (dot == std::string_view::npos || !iequals_ascii(filename.substr(dot), ".dds")) {
|
||||
if (dot == std::string_view::npos) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!iequals_ascii(filename.substr(dot), ".dds") && !iequals_ascii(filename.substr(dot), ".png")) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -323,7 +329,7 @@ std::optional<RuntimeTextureKey> parse_replacement_filename(std::string_view fil
|
||||
++index;
|
||||
}
|
||||
|
||||
const size_t remaining = partCount - index;
|
||||
size_t remaining = partCount - index;
|
||||
if (remaining != 2 && remaining != 3) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -339,7 +345,12 @@ std::optional<RuntimeTextureKey> parse_replacement_filename(std::string_view fil
|
||||
textureHash = *parsedTex;
|
||||
}
|
||||
|
||||
const auto format = parse_u32(parts[partCount - 1]);
|
||||
auto formatPart = parts[partCount - 1];
|
||||
if (formatPart == "arb") {
|
||||
formatPart = parts[partCount - 2];
|
||||
remaining -= 1;
|
||||
}
|
||||
const auto format = parse_u32(formatPart);
|
||||
if (!format.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -364,32 +375,38 @@ std::optional<RuntimeTextureKey> parse_replacement_filename(std::string_view fil
|
||||
.tlutHash = tlutHash,
|
||||
.width = dimensions->first,
|
||||
.height = dimensions->second,
|
||||
.hasMips = hasMips,
|
||||
.hasTlut = hasTlut,
|
||||
.format = *format,
|
||||
};
|
||||
}
|
||||
|
||||
std::optional<ConvertedTexture> load_replacement(const std::filesystem::path& path, bool hasMips) noexcept {
|
||||
auto base = dds::load_dds_file(path);
|
||||
static std::optional<ConvertedTexture> load_texture_file(const std::filesystem::path& path) {
|
||||
if (path.extension() == ".png") {
|
||||
return png::load_png_file(path);
|
||||
} else {
|
||||
return dds::load_dds_file(path);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<ConvertedTexture> load_replacement(const ReplacementIndexEntry& entry) noexcept {
|
||||
auto base = load_texture_file(entry.path);
|
||||
if (!base.has_value()) {
|
||||
Log.warn("texture_replacement: failed to load texture {}", fs_path_to_string(path));
|
||||
Log.warn("texture_replacement: failed to load texture {}", fs_path_to_string(entry.path));
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!hasMips) {
|
||||
if (!entry.hasMips) {
|
||||
return base;
|
||||
}
|
||||
|
||||
std::vector<ConvertedTexture> more;
|
||||
std::error_code ec;
|
||||
for (uint32_t mipLevel = 1;; ++mipLevel) {
|
||||
const auto mipPath = path.parent_path() / fmt::format("{}_mip{}{}", fs_path_to_string(path.stem()), mipLevel,
|
||||
fs_path_to_string(path.extension()));
|
||||
const auto mipPath = entry.path.parent_path() / fmt::format("{}_mip{}{}", fs_path_to_string(entry.path.stem()), mipLevel, fs_path_to_string(entry.path.extension()));
|
||||
if (!std::filesystem::is_regular_file(mipPath, ec)) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto lvl = dds::load_dds_file(mipPath);
|
||||
auto lvl = load_texture_file(mipPath);
|
||||
const uint32_t ew = std::max(base->width >> mipLevel, 1u);
|
||||
const uint32_t eh = std::max(base->height >> mipLevel, 1u);
|
||||
const bool ok = lvl.has_value() && lvl->format == base->format && lvl->width == ew && lvl->height == eh;
|
||||
@@ -509,7 +526,7 @@ void build_index() noexcept {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!iequals_ascii(fs_path_to_string(path.extension()), ".dds")) {
|
||||
if (!iequals_ascii(fs_path_to_string(path.extension()), ".dds") && !iequals_ascii(fs_path_to_string(path.extension()), ".png")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -528,7 +545,7 @@ void build_index() noexcept {
|
||||
Log.info("Indexed {} texture replacements", s_replacementIndex.size());
|
||||
}
|
||||
|
||||
const std::filesystem::path* find_replacement_path(const RuntimeTextureKey& key) noexcept {
|
||||
const ReplacementIndexEntry* find_replacement_path(const RuntimeTextureKey& key) noexcept {
|
||||
if (const auto it = s_replacementIndex.find(key); it != s_replacementIndex.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
@@ -560,8 +577,8 @@ const gfx::TextureHandle* find_cached_replacement(const RuntimeTextureKey& key)
|
||||
return &cached->second.handle;
|
||||
}
|
||||
|
||||
gfx::TextureHandle load_replacement_texture(const RuntimeTextureKey& key, const std::filesystem::path& path) noexcept {
|
||||
const auto replacement = load_replacement(path, key.hasMips);
|
||||
gfx::TextureHandle load_replacement_texture(const RuntimeTextureKey& key, const ReplacementIndexEntry& entry) noexcept {
|
||||
const auto replacement = load_replacement(entry);
|
||||
if (!replacement.has_value()) {
|
||||
s_failedKeys.insert(key);
|
||||
return {};
|
||||
@@ -753,4 +770,10 @@ std::optional<TextureHandle> find_replacement(const GXTexObj_& obj) noexcept {
|
||||
cache_replacement(key, handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
std::string build_texture_replacement_name(const GXTexObj_& obj) noexcept {
|
||||
const RuntimeTextureKey key = build_runtime_key(obj);
|
||||
return format_replacement_filename(key);
|
||||
}
|
||||
|
||||
} // namespace aurora::gfx::texture_replacement
|
||||
|
||||
@@ -9,5 +9,6 @@ void shutdown() 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;
|
||||
std::string build_texture_replacement_name(const GXTexObj_& obj) noexcept;
|
||||
bool try_bind_replacement(GXTexObj_& obj, GXTexMapID id) noexcept;
|
||||
} // namespace aurora::gfx::texture_replacement
|
||||
|
||||
+7
-1
@@ -161,9 +161,15 @@ gfx::TextureHandle resolve_static_texture(const GXTexObj_& obj) {
|
||||
if (const auto replacement = gfx::texture_replacement::find_replacement(obj); replacement.has_value()) {
|
||||
handle = *replacement;
|
||||
} else {
|
||||
#if DEBUG
|
||||
const auto name = gfx::texture_replacement::build_texture_replacement_name(obj);
|
||||
const auto nameStr = name.c_str();
|
||||
#else
|
||||
const auto nameStr = "GX Static Texture";
|
||||
#endif
|
||||
handle =
|
||||
gfx::new_static_texture_2d(obj.width(), obj.height(), obj.mip_count(), obj.format(),
|
||||
{static_cast<const uint8_t*>(obj.data), UINT32_MAX}, false, "GX Static Texture");
|
||||
{static_cast<const uint8_t*>(obj.data), UINT32_MAX}, false, nameStr);
|
||||
}
|
||||
if (!obj.no_cache()) {
|
||||
store_cached_texture(obj, handle);
|
||||
|
||||
Reference in New Issue
Block a user