Skip to content

Commit

Permalink
feat(unrealengine): add dump lutbuilder option
Browse files Browse the repository at this point in the history
  • Loading branch information
clshortfuse committed Dec 31, 2024
1 parent ad2a263 commit e240423
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 63 deletions.
237 changes: 181 additions & 56 deletions src/games/unrealengine/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,33 @@
#include "../../mods/shader.hpp"
#include "../../mods/swapchain.hpp"
#include "../../utils/date.hpp"
#include "../../utils/path.hpp"
#include "../../utils/platform.hpp"
#include "../../utils/settings.hpp"
#include "../../utils/shader.hpp"
#include "../../utils/shader_dump.hpp"
#include "../../utils/swapchain.hpp"
#include "./shared.h"

namespace {

std::unordered_set<std::uint32_t> drawn_shaders;

#define TracedShaderEntry(value) { \
value, \
{ \
.crc32 = value, \
.code = __##value, \
.on_drawn = [](auto cmd_list) { \
if (drawn_shaders.contains(##value)) return; \
drawn_shaders.emplace(##value); \
reshade::log::message(reshade::log::level::debug, "Replaced " #value); \
}, \
}, \
}
#define TracedShaderEntry(value) \
{ \
value, \
{ \
.crc32 = value, \
.code = __##value, \
.on_drawn = [](auto cmd_list) { \
if (drawn_shaders.contains(value)) return; \
drawn_shaders.emplace(value); \
reshade::log::message( \
reshade::log::level::debug, \
std::format("Replaced 0x{:08}", value).c_str()); \
}, \
}, \
}

renodx::mods::shader::CustomShaders custom_shaders = {
// Crisis Core FF7 Reunion
Expand Down Expand Up @@ -526,6 +533,157 @@ void AddGamePatches() {
}
}

float g_dump_shaders = 0;
std::unordered_set<uint32_t> g_dumped_shaders = {};

bool OnDrawForLUTDump(
reshade::api::command_list* cmd_list,
uint32_t vertex_count,
uint32_t instance_count,
uint32_t first_vertex,
uint32_t first_instance) {
if (g_dump_shaders == 0) return false;

auto shader_state = renodx::utils::shader::GetCurrentState(cmd_list);
auto pixel_shader_hash = shader_state.GetCurrentPixelShaderHash();
if (pixel_shader_hash == 0u) return false;

auto& swapchain_state = cmd_list->get_private_data<renodx::utils::swapchain::CommandListData>();
bool found_lut_render_target = false;

auto* device = cmd_list->get_device();
for (auto render_target : swapchain_state.current_render_targets) {
auto resource_tag = renodx::utils::resource::GetResourceTag(device, render_target);
if (resource_tag == 1.f) {
found_lut_render_target = true;
break;
}
}
if (!found_lut_render_target) return false;

if (custom_shaders.contains(pixel_shader_hash)) return false;

if (g_dumped_shaders.contains(pixel_shader_hash)) return false;

reshade::log::message(
reshade::log::level::debug,
std::format("Dumping lutbuiler: 0x{:08x}", pixel_shader_hash).c_str());

g_dumped_shaders.emplace(pixel_shader_hash);

renodx::utils::path::default_output_folder = "renodx";
renodx::utils::shader::dump::default_dump_folder = ".";
bool found = false;
try {
auto pair = shader_state.current_shader_pipelines.find(reshade::api::pipeline_stage::pixel_shader);
if (pair == shader_state.current_shader_pipelines.end()) return false;

auto pipeline = pair->second;
auto details = renodx::utils::shader::GetPipelineShaderDetails(device, pipeline);
for (const auto& [subobject_index, shader_hash] : details->shader_hashes_by_index) {
// Store immediately in case pipeline destroyed before present
if (shader_hash != pixel_shader_hash) continue;
found = true;
auto shader_data = details->GetShaderData(shader_hash, subobject_index);
if (!shader_data.has_value()) {
std::stringstream s;
s << "utils::shader::dump(Failed to retreive shader data: ";
s << PRINT_CRC32(shader_hash);
s << ")";
reshade::log::message(reshade::log::level::warning, s.str().c_str());
return false;
}

auto shader_version = renodx::utils::shader::compiler::directx::DecodeShaderVersion(shader_data.value());
if (shader_version.GetMajor() == 0) {
// No shader information found
return false;
}

renodx::utils::shader::dump::DumpShader(
shader_hash,
shader_data.value(),
reshade::api::pipeline_subobject_type::pixel_shader,
"lutbuilder_");
}
if (!found) throw std::exception("Pipeline not found");
} catch (...) {
std::stringstream s;
s << "utils::shader::dump(Failed to decode shader data: ";
s << PRINT_CRC32(pixel_shader_hash);
s << ")";
reshade::log::message(reshade::log::level::warning, s.str().c_str());
}

return false;
}

void AddAdvancedSettings() {
for (const auto& [key, format] : UPGRADE_TARGETS) {
auto* new_setting = new renodx::utils::settings::Setting{
.key = "Upgrade_" + key,
.value_type = renodx::utils::settings::SettingValueType::INTEGER,
.default_value = 0.f,
.label = key,
.section = "Resource Upgrades",
.labels = {
"Off",
"Output size",
"Output ratio",
"Any size",
},
.is_global = true,
.is_visible = []() { return settings[0]->GetValue() >= 2; },
};
reshade::get_config_value(nullptr, renodx::utils::settings::global_name.c_str(), ("Upgrade_" + key).c_str(), new_setting->value);
settings.push_back(new_setting);
}

auto* swapchain_setting = new renodx::utils::settings::Setting{
.key = "Upgrade_SwapChainCompatibility",
.value_type = renodx::utils::settings::SettingValueType::INTEGER,
.default_value = 0.f,
.label = "Swap Chain Compatibility Mode",
.section = "Resource Upgrades",
.tooltip = "Enhances support for third-party addons to read the swap chain.",
.labels = {
"Off",
"On",
},
.is_global = true,
.is_visible = []() { return settings[0]->GetValue() >= 2; },
};
reshade::get_config_value(nullptr, renodx::utils::settings::global_name.c_str(), "Upgrade_SwapChainCompatibility", swapchain_setting->value);
renodx::mods::swapchain::swapchain_proxy_compatibility_mode = swapchain_setting->GetValue() != 0;
settings.push_back(swapchain_setting);

auto* lut_dump_setting = new renodx::utils::settings::Setting{
.key = "DumpLUTShaders",
.binding = &g_dump_shaders,
.value_type = renodx::utils::settings::SettingValueType::INTEGER,
.default_value = 0.f,
.label = "Dump LUT Shaders",
.section = "Resource Upgrades",
.tooltip = "Traces and dumps LUT shaders.",
.labels = {
"Off",
"On",
},
.is_global = true,
.is_visible = []() { return settings[0]->GetValue() >= 2; },
};
reshade::get_config_value(nullptr, renodx::utils::settings::global_name.c_str(), "DumpLUTShaders", lut_dump_setting->value);
g_dump_shaders = lut_dump_setting->GetValue();
settings.push_back(lut_dump_setting);

settings.push_back({new renodx::utils::settings::Setting{
.value_type = renodx::utils::settings::SettingValueType::TEXT,
.label = "The application must be restarted for upgrades to take effect.",
.section = "Resource Upgrades",
.is_visible = []() { return settings[0]->GetValue() >= 2; },
}});
}

bool initialized = false;

} // namespace
Expand All @@ -539,53 +697,15 @@ BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) {
if (!reshade::register_addon(h_module)) return FALSE;
reshade::register_event<reshade::addon_event::init_device>(OnInitDevice);
reshade::register_event<reshade::addon_event::init_swapchain>(OnInitSwapchain);
renodx::utils::shader::Use(fdw_reason);
renodx::utils::swapchain::Use(fdw_reason);
renodx::utils::resource::Use(fdw_reason);

if (!initialized) {
AddGamePatches();

for (const auto& [key, format] : UPGRADE_TARGETS) {
auto* new_setting = new renodx::utils::settings::Setting{
.key = "Upgrade_" + key,
.value_type = renodx::utils::settings::SettingValueType::INTEGER,
.default_value = 0.f,
.label = key,
.section = "Resource Upgrades",
.labels = {
"Off",
"Output size",
"Output ratio",
"Any size",
},
.is_global = true,
.is_visible = []() { return settings[0]->GetValue() >= 2; },
};
reshade::get_config_value(nullptr, renodx::utils::settings::global_name.c_str(), ("Upgrade_" + key).c_str(), new_setting->value);
settings.push_back(new_setting);
}
auto* new_setting = new renodx::utils::settings::Setting{
.key = "Upgrade_SwapChainCompatibility",
.value_type = renodx::utils::settings::SettingValueType::INTEGER,
.default_value = 0.f,
.label = "Swap Chain Compatibility Mode",
.section = "Resource Upgrades",
.tooltip = "Enhances support for third-party addons to read the swap chain.",
.labels = {
"Off",
"On",
},
.is_global = true,
.is_visible = []() { return settings[0]->GetValue() >= 2; },
};
reshade::get_config_value(nullptr, renodx::utils::settings::global_name.c_str(), "Upgrade_SwapChainCompatibility", new_setting->value);
renodx::mods::swapchain::swapchain_proxy_compatibility_mode = new_setting->value != 0;
settings.push_back(new_setting);

settings.push_back({new renodx::utils::settings::Setting{
.value_type = renodx::utils::settings::SettingValueType::TEXT,
.label = "The application must be restarted for upgrades to take effect.",
.section = "Resource Upgrades",
.is_visible = []() { return settings[0]->GetValue() >= 2; },
}});
AddAdvancedSettings();

for (auto* new_setting : info_settings) {
settings.push_back(new_setting);
}
Expand All @@ -603,14 +723,19 @@ BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) {
.old_format = reshade::api::format::r10g10b10a2_unorm,
.new_format = reshade::api::format::r16g16b16a16_float,
.dimensions = {.width = 32, .height = 32, .depth = 32},
.resource_tag = 0x01,
.resource_tag = 1.f,
});

initialized = true;
}

reshade::register_event<reshade::addon_event::draw>(OnDrawForLUTDump);

break;
case DLL_PROCESS_DETACH:
renodx::utils::shader::Use(fdw_reason);
renodx::utils::swapchain::Use(fdw_reason);
renodx::utils::resource::Use(fdw_reason);
reshade::unregister_event<reshade::addon_event::init_device>(OnInitDevice);
reshade::unregister_event<reshade::addon_event::init_swapchain>(OnInitSwapchain);
reshade::unregister_addon(h_module);
Expand Down
3 changes: 2 additions & 1 deletion src/mods/swapchain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ static void OnInitResource(
if (private_data.applied_target != nullptr) {
changed = true;
if (private_data.applied_target->resource_tag != -1) {
s << ", tag: " << private_data.applied_target->resource_tag;
renodx::utils::resource::SetResourceTag(device, resource, private_data.applied_target->resource_tag);
}
private_data.resource_upgrade_targets[resource.handle] = private_data.applied_target;
Expand Down Expand Up @@ -2593,7 +2594,7 @@ static void Use(DWORD fdw_reason, T* new_injections = nullptr) {
reshade::register_event<reshade::addon_event::clear_unordered_access_view_float>(OnClearUnorderedAccessViewFloat);

reshade::register_event<reshade::addon_event::copy_texture_region>(OnCopyTextureRegion);
// reshade::register_event<reshade::addon_event::barrier>(OnBarrier);
reshade::register_event<reshade::addon_event::barrier>(OnBarrier);
reshade::register_event<reshade::addon_event::copy_buffer_to_texture>(OnCopyBufferToTexture);

if (!swap_chain_proxy_pixel_shader.empty()) {
Expand Down
4 changes: 3 additions & 1 deletion src/utils/path.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@

namespace renodx::utils::path {

static std::string default_output_folder = "renodx-dev";

static std::filesystem::path GetOutputPath() {
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
wchar_t file_prefix[MAX_PATH] = L"";
GetModuleFileNameW(nullptr, file_prefix, ARRAYSIZE(file_prefix));

std::filesystem::path dump_path = file_prefix;
dump_path = dump_path.parent_path();
dump_path /= "renodx-dev";
dump_path /= default_output_folder;
return dump_path;
}

Expand Down
3 changes: 3 additions & 0 deletions src/utils/shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ struct __declspec(uuid("8707f724-c7e5-420e-89d6-cc032c732d2d")) CommandListData
reshade::api::pipeline_layout pipeline_layout = {0};
std::unordered_map<reshade::api::pipeline_stage, reshade::api::pipeline> pending_replacements;
std::unordered_map<reshade::api::pipeline_stage, uint32_t> current_shaders_hashes;
std::unordered_map<reshade::api::pipeline_stage, reshade::api::pipeline> current_shader_pipelines;

[[nodiscard]] uint32_t GetCurrentShaderHash(reshade::api::pipeline_stage stage) const {
auto pair = current_shaders_hashes.find(stage);
Expand Down Expand Up @@ -618,6 +619,7 @@ static void OnBindPipeline(
found_compatible = true;
if (pipeline.handle == 0u) {
cmd_list_data.current_shaders_hashes.erase(compatible_stage);
cmd_list_data.current_shader_pipelines.erase(compatible_stage);
cmd_list_data.pending_replacements.erase(compatible_stage);
} else {
break;
Expand Down Expand Up @@ -667,6 +669,7 @@ static void OnBindPipeline(
if (auto pair = details.shader_hashes_by_stage.find(compatible_stage);
pair != details.shader_hashes_by_stage.end()) {
cmd_list_data.current_shaders_hashes[compatible_stage] = pair->second;
cmd_list_data.current_shader_pipelines[compatible_stage] = pipeline;
}
if (details.HasReplacementPipeline() && ((details.replacement_stages & compatible_stage) == compatible_stage)) {
auto& replacement_pipeline = details.replacement_pipeline.value();
Expand Down
Loading

0 comments on commit e240423

Please sign in to comment.