mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-23 23:26:06 +02:00
Mesh streaming pool (fixes loading crashes on older GPUs) - 1.0.0 forced MeshStreaming.PoolSize to 3.5 GiB on every card. An RX 580 crashed while loading with DXGI_ERROR_DEVICE_RESET, and the oversized pool is the likely cause. The pool is now a quarter of the largest hardware adapter's dedicated video memory, capped at 3.5 GiB; cards of 6 GB or less keep the game's own 520 MB. The card, its memory and the chosen size are logged once at startup. Remote players (busy servers) - Transform interpolate is inline plain arithmetic: 22 -> 5.8 ns per joint. It was 4% of a busy server's client frame, since every player within 200 m has the whole skeleton interpolated every frame. - Players out of the camera's view and more than 8 m away are sampled at 20 Hz, like far players. Their position still updates every frame for collision, sound and nametags, and a player coming into view is sampled that frame. Expression hooks (run for every expression the game executes) - No profiler zones in the expression hooks: taking a sample switched them on, inflating the very samples that measured the hooks. - The throwdown lab pump does one sorted lookup of the running graph and skips everything else for graphs it doesn't watch (graph_throttle gets throttled_graph for this). Settings and memory reads - Script gameplay-setting and native-setting gets are served from small per-thread caches, keyed on the asset/key address, its first 8 name bytes and a new profile::Store::changes() counter, instead of a store lookup each call. - Per-frame reads in the client tick, native settings and population controls use memory::peek instead of ReadProcessMemory. - Script error logging probes each argument pointer once.
51 lines
2.1 KiB
C++
51 lines
2.1 KiB
C++
#pragma once
|
|
#include "Extension/Profile/runtime_internal.h"
|
|
|
|
namespace dingosdk::profile_runtime {
|
|
struct NativeSettingValue { std::uintptr_t type; const void* data; };
|
|
|
|
static_assert(sizeof(NativeSettingValue) == 16);
|
|
|
|
struct NativeSettingsFunctions {
|
|
const NativeSettingValue* (*get)(std::uintptr_t, const char*){};
|
|
bool (*set)(std::uintptr_t, const char*, std::uintptr_t, const NativeSettingValue*){};
|
|
};
|
|
|
|
NativeSettingsFunctions& native_settings();
|
|
|
|
unsigned native_settings_location(std::uintptr_t group);
|
|
|
|
template<class T> std::optional<dingosdk::Json> native_scalar(const void* data) {
|
|
T value{};
|
|
if (!memory::peek(reinterpret_cast<std::uintptr_t>(data), value)) return {};
|
|
if constexpr (std::is_floating_point_v<T>) if (!std::isfinite(value)) return {};
|
|
if constexpr (std::is_same_v<T, std::uint64_t>) if (value > INT64_MAX) return {};
|
|
return dingosdk::Json(value);
|
|
}
|
|
|
|
std::optional<dingosdk::Json> native_setting_json(const NativeSettingValue* input);
|
|
|
|
template<class T> bool restore_native_scalar(std::uintptr_t group, const char* key,
|
|
std::uintptr_t type, const dingosdk::Json& saved) {
|
|
if constexpr (std::is_same_v<T, bool>) { if (!saved.is_boolean()) return false; }
|
|
else if constexpr (std::is_integral_v<T>) {
|
|
if (!saved.is_number_integer() || saved < (std::numeric_limits<T>::lowest)() ||
|
|
saved > (std::numeric_limits<T>::max)()) return false;
|
|
} else {
|
|
if (!saved.is_number_float() || !std::isfinite(saved.get<double>()) ||
|
|
std::abs(saved.get<double>()) > (std::numeric_limits<T>::max)()) return false;
|
|
}
|
|
const T value = saved.get<T>();
|
|
const NativeSettingValue borrowed{type, &value};
|
|
// The original setter clones the boxed value into its existing node.
|
|
return native_settings().set(group, key, type, &borrowed);
|
|
}
|
|
|
|
bool restore_native_setting(std::uintptr_t group, const char* key, std::uintptr_t type,
|
|
const dingosdk::Json& saved);
|
|
|
|
const NativeSettingValue* native_setting_get(std::uintptr_t group, const char* key);
|
|
|
|
bool native_setting_set(std::uintptr_t group, const char* key, std::uintptr_t type, const NativeSettingValue* value);
|
|
}
|