diff --git a/src/mods/shader.hpp b/src/mods/shader.hpp index 9ad3a82e..0e77d8ff 100644 --- a/src/mods/shader.hpp +++ b/src/mods/shader.hpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,8 @@ static bool using_custom_inject = false; static bool using_counted_shaders = false; struct __declspec(uuid("018e7b9c-23fd-7863-baf8-a8dad2a6db9d")) DeviceData { + std::shared_mutex mutex; + std::unordered_map modded_pipeline_root_indexes; std::unordered_map modded_pipeline_layouts; std::unordered_set unmodified_shaders; @@ -94,11 +97,15 @@ struct __declspec(uuid("018e7b9c-23fd-7863-baf8-a8dad2a6db9d")) DeviceData { bool trace_unmodified_shaders = false; int32_t expected_constant_buffer_index = -1; uint32_t expected_constant_buffer_space = 0; - std::shared_mutex mutex; CustomShaders custom_shaders; }; +struct __declspec(uuid("1640985b-42c7-4e93-bd27-fc13cade5982")) CommandListData { + bool trace_unmodified_shaders = false; + CustomShaders custom_shaders; +}; + static void OnInitDevice(reshade::api::device* device) { std::stringstream s; s << "mods::shader::OnInitDevice("; @@ -123,6 +130,20 @@ static void OnDestroyDevice(reshade::api::device* device) { device->destroy_private_data(); } +static void OnInitCommandList(reshade::api::command_list* cmd_list) { + auto& data = cmd_list->create_private_data(); + auto* device = cmd_list->get_device(); + auto& device_data = device->get_private_data(); + if (std::addressof(device_data) == nullptr) return; + std::shared_lock local_device_lock(device_data.mutex); + data.custom_shaders = device_data.custom_shaders; + data.trace_unmodified_shaders = device_data.trace_unmodified_shaders; +} + +static void OnDestroyCommandList(reshade::api::command_list* cmd_list) { + cmd_list->destroy_private_data(); +} + // Shader Injection static bool OnCreatePipelineLayout( reshade::api::device* device, @@ -614,6 +635,9 @@ static bool PushShaderInjections( auto injection_layout = layout; auto device_api = cmd_list->get_device()->get_api(); uint32_t param_index = 0; + + bool use_root_constants = (device_api == reshade::api::device_api::d3d12 || device_api == reshade::api::device_api::vulkan); + if (device_api == reshade::api::device_api::d3d12 || device_api == reshade::api::device_api::vulkan) { if ( auto pair = device_data->modded_pipeline_root_indexes.find(layout.handle); @@ -627,10 +651,8 @@ static bool PushShaderInjections( reshade::log::message(reshade::log::level::warning, s.str().c_str()); return false; } - - } else { - // Must be done before draw - + } + if (!use_root_constants || use_pipeline_layout_cloning) { if ( auto pair = device_data->modded_pipeline_layouts.find(layout.handle); pair != device_data->modded_pipeline_layouts.end()) { @@ -675,9 +697,7 @@ static bool HandlePreDraw( reshade::api::command_list* cmd_list, bool is_dispatch, std::function& on_drawn) { - auto* device = cmd_list->get_device(); - auto& device_data = device->get_private_data(); - const std::unique_lock local_device_lock(device_data.mutex); + auto& data = cmd_list->get_private_data(); auto& shader_state = renodx::utils::shader::GetCurrentState(cmd_list); @@ -687,7 +707,7 @@ static bool HandlePreDraw( auto& swapchain_state = cmd_list->get_private_data(); if (!swapchain_state.current_render_targets.empty()) { auto rv = swapchain_state.current_render_targets.at(0); - resource_tag = renodx::utils::resource::GetResourceTag(device, rv); + resource_tag = renodx::utils::resource::GetResourceTag(cmd_list->get_device(), rv); } } @@ -703,22 +723,31 @@ static bool HandlePreDraw( continue; } } - auto custom_shader_info_pair = device_data.custom_shaders.find(shader_hash); - bool is_custom_shader = custom_shader_info_pair != device_data.custom_shaders.end(); + auto custom_shader_info_pair = data.custom_shaders.find(shader_hash); + bool is_custom_shader = custom_shader_info_pair != data.custom_shaders.end(); if (!is_custom_shader) { if ( !is_dispatch - && device_data.trace_unmodified_shaders - && renodx::utils::swapchain::HasBackBufferRenderTarget(cmd_list) - && !device_data.unmodified_shaders.contains(shader_hash)) { - std::stringstream s; - s << "mods::shader::HandlePreDraw(unmodified "; - s << stage; - s << " shader writing to swapchain: "; - s << PRINT_CRC32(shader_hash); - s << ")"; - reshade::log::message(reshade::log::level::warning, s.str().c_str()); - device_data.unmodified_shaders.emplace(shader_hash); + && data.trace_unmodified_shaders + && renodx::utils::swapchain::HasBackBufferRenderTarget(cmd_list)) { + auto* device = cmd_list->get_device(); + auto& device_data = device->get_private_data(); + std::shared_lock local_device_lock(device_data.mutex); + if (!device_data.unmodified_shaders.contains(shader_hash)) { + std::stringstream s; + s << "mods::shader::HandlePreDraw(unmodified "; + s << stage; + s << " shader writing to swapchain: "; + s << PRINT_CRC32(shader_hash); + s << ")"; + reshade::log::message(reshade::log::level::warning, s.str().c_str()); + local_device_lock.unlock(); + { + std::unique_lock write_lock(device_data.mutex); + device_data.unmodified_shaders.emplace(shader_hash); + } + local_device_lock.lock(); + } } continue; // move to next shader @@ -781,6 +810,8 @@ static bool HandlePreDraw( if (found_custom_shader) { if (should_inject_cbuffer && shader_injection_size != 0 && shader_state.pipeline_layout.handle != 0u) { + auto& device_data = cmd_list->get_device()->get_private_data(); + std::shared_lock local_device_lock(device_data.mutex); PushShaderInjections(cmd_list, &device_data, &shader_state, @@ -925,6 +956,8 @@ static void Use(DWORD fdw_reason, CustomShaders new_custom_shaders, T* new_injec reshade::register_event(OnInitDevice); reshade::register_event(OnDestroyDevice); + reshade::register_event(OnInitCommandList); + reshade::register_event(OnDestroyCommandList); for (const auto& [hash, shader] : (new_custom_shaders)) { if (shader.on_replace != nullptr) using_custom_replace = true; @@ -1003,6 +1036,8 @@ static void Use(DWORD fdw_reason, CustomShaders new_custom_shaders, T* new_injec reshade::unregister_event(OnInitDevice); reshade::unregister_event(OnDestroyDevice); + reshade::unregister_event(OnInitCommandList); + reshade::unregister_event(OnDestroyCommandList); reshade::unregister_event(OnPresent); diff --git a/src/utils/settings.hpp b/src/utils/settings.hpp index e1daefb4..5ebc1346 100644 --- a/src/utils/settings.hpp +++ b/src/utils/settings.hpp @@ -3,6 +3,7 @@ #define ImTextureID ImU64 #include +#include #include #include @@ -262,8 +263,6 @@ static void SaveGlobalSettings(reshade::api::effect_runtime* runtime) { // Runs first // https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html static void OnRegisterOverlay(reshade::api::effect_runtime* runtime) { - const std::unique_lock lock(renodx::utils::mutex::global_mutex); - bool changed_preset = false; if (use_presets) { changed_preset = ImGui::SliderInt( @@ -466,6 +465,7 @@ static void OnRegisterOverlay(reshade::api::effect_runtime* runtime) { } if (changed) { + const std::unique_lock lock(renodx::utils::mutex::global_mutex); setting->Write(); any_change = true; }