Skip to content

Commit e56be2e

Browse files
committed
feat(random): fix addon init/uninit, support multithreading
1 parent d5144c8 commit e56be2e

1 file changed

Lines changed: 86 additions & 24 deletions

File tree

src/utils/random.hpp

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,36 @@
55

66
#pragma once
77

8+
#include <algorithm>
89
#include <chrono>
10+
#include <cstdint>
11+
#include <initializer_list>
12+
#include <mutex>
913
#include <random>
14+
#include <utility>
15+
#include <vector>
1016

1117
#include <include/reshade.hpp>
1218

19+
#include "./cross_addon.hpp"
20+
1321
namespace renodx::utils::random {
1422

23+
[[deprecated("Use random::Use() instead")]]
1524
static std::vector<float*> binds;
1625

1726
namespace internal {
18-
static std::vector<std::mt19937> generators;
1927

20-
static constexpr const auto RANDOM_RANGE = static_cast<float>((std::mt19937::max)() - (std::mt19937::min)());
28+
using FloatRandomizer = std::pair<float*, std::mt19937>;
29+
30+
struct __declspec(uuid("b9c38ad7-3b9a-4fa9-94a7-18e9214bc9a6")) SharedData {
31+
std::mutex mutex;
32+
cross_addon::vector<FloatRandomizer> binds;
33+
};
34+
35+
static cross_addon::Shared<SharedData> shared;
36+
37+
static constexpr const auto RANDOM_RANGE = static_cast<double>((std::mt19937::max)()) - static_cast<double>((std::mt19937::min)()) + 1.0;
2138

2239
static void OnPresent(
2340
reshade::api::command_queue* queue,
@@ -26,39 +43,84 @@ static void OnPresent(
2643
const reshade::api::rect* dest_rect,
2744
uint32_t dirty_rect_count,
2845
const reshade::api::rect* dirty_rects) {
29-
auto binds_count = binds.size();
30-
auto generators_count = generators.size();
31-
32-
for (size_t i = 0; i < binds_count; ++i) {
33-
if (generators_count <= i) {
34-
std::mt19937 generator = std::mt19937(std::chrono::system_clock::now().time_since_epoch().count() + i);
35-
generators.push_back(generator);
36-
++generators_count;
37-
}
38-
*binds[i] = (generators[i]() + (std::mt19937::min)()) / RANDOM_RANGE;
46+
auto* data = shared.data;
47+
if (data == nullptr) return;
48+
49+
std::lock_guard lock(data->mutex);
50+
for (auto& [value, generator] : data->binds) {
51+
if (value == nullptr) continue;
52+
53+
*value = static_cast<float>(
54+
(static_cast<double>(generator()) - static_cast<double>((std::mt19937::min)())) / RANDOM_RANGE);
3955
}
40-
if (generators_count > binds_count) {
41-
generators.resize(binds_count);
56+
}
57+
} // namespace internal
58+
59+
static bool AddBinding(float* bind) {
60+
if (internal::shared.data == nullptr) {
61+
binds.push_back(bind);
62+
} else {
63+
std::lock_guard lock(internal::shared.data->mutex);
64+
auto& shared_binds = internal::shared.data->binds;
65+
if (std::ranges::any_of(shared_binds, [bind](const internal::FloatRandomizer& item) {
66+
return item.first == bind;
67+
})) {
68+
return false;
69+
}
70+
const auto seed = static_cast<std::mt19937::result_type>(
71+
std::chrono::steady_clock::now().time_since_epoch().count() + shared_binds.size());
72+
shared_binds.push_back({bind, std::mt19937(seed)});
4273
}
74+
return true;
4375
}
4476

45-
static bool attached = false;
46-
} // namespace internal
77+
static bool RemoveBinding(float* bind) {
78+
if (internal::shared.data == nullptr) {
79+
auto it = std::ranges::find(binds, bind);
80+
if (it != binds.end()) {
81+
binds.erase(it);
82+
return true;
83+
}
84+
} else {
85+
std::lock_guard lock(internal::shared.data->mutex);
86+
auto& shared_binds = internal::shared.data->binds;
87+
auto it = std::ranges::find_if(shared_binds, [bind](const internal::FloatRandomizer& item) {
88+
return item.first == bind;
89+
});
90+
if (it != shared_binds.end()) {
91+
shared_binds.erase(it);
92+
return true;
93+
}
94+
}
95+
return false;
96+
}
4797

48-
static void Use(DWORD fdw_reason) {
98+
static void Use(DWORD fdw_reason, std::initializer_list<float*> binds = {}) {
4999
switch (fdw_reason) {
50100
case DLL_PROCESS_ATTACH:
51-
if (internal::attached) return;
52-
internal::attached = true;
53-
reshade::log::message(reshade::log::level::info, "utils::random attached.");
101+
if (internal::shared.RegisterModule()) {
102+
// log started
103+
reshade::log::message(reshade::log::level::info, "utils::random attached...");
104+
}
105+
for (auto* bind : binds) {
106+
AddBinding(bind);
107+
}
108+
for (auto* bind : random::binds) {
109+
AddBinding(bind);
110+
}
54111

55-
reshade::register_event<reshade::addon_event::present>(internal::OnPresent);
112+
internal::shared.RegisterEvent<reshade::addon_event::present>(internal::OnPresent);
56113
break;
57114

58115
case DLL_PROCESS_DETACH:
59-
if (!internal::attached) return;
60-
internal::attached = false;
61-
reshade::unregister_event<reshade::addon_event::present>(internal::OnPresent);
116+
internal::shared.UnregisterEvent<reshade::addon_event::present>(internal::OnPresent);
117+
for (auto* bind : random::binds) {
118+
RemoveBinding(bind);
119+
}
120+
for (auto* bind : binds) {
121+
RemoveBinding(bind);
122+
}
123+
internal::shared.UnregisterModule();
62124

63125
break;
64126
}

0 commit comments

Comments
 (0)