diff options
| author | a1xd <[email protected]> | 2021-04-08 02:30:01 -0400 |
|---|---|---|
| committer | a1xd <[email protected]> | 2021-04-08 02:30:01 -0400 |
| commit | c55d1bfd01147fa014ac07d4b03ef3cad8427ae6 (patch) | |
| tree | 39ffa4a79bc6b019443521f10203f787c4b98698 | |
| parent | unmark fill as const (diff) | |
| download | rawaccel-c55d1bfd01147fa014ac07d4b03ef3cad8427ae6.tar.xz rawaccel-c55d1bfd01147fa014ac07d4b03ef3cad8427ae6.zip | |
optimize a bit/refactor modify
| -rw-r--r-- | common/accel-invoke.hpp | 11 | ||||
| -rw-r--r-- | common/accel-jump.hpp | 5 | ||||
| -rw-r--r-- | common/accel-natural.hpp | 8 | ||||
| -rw-r--r-- | common/rawaccel-base.hpp | 5 | ||||
| -rw-r--r-- | common/rawaccel-validate.hpp | 12 | ||||
| -rw-r--r-- | common/rawaccel.hpp | 323 | ||||
| -rw-r--r-- | common/utility.hpp | 27 | ||||
| -rw-r--r-- | driver/driver.cpp | 33 | ||||
| -rw-r--r-- | driver/driver.vcxproj | 12 | ||||
| -rw-r--r-- | wrapper/wrapper.vcxproj | 2 |
10 files changed, 189 insertions, 249 deletions
diff --git a/common/accel-invoke.hpp b/common/accel-invoke.hpp index 0e264c1..f2a95dc 100644 --- a/common/accel-invoke.hpp +++ b/common/accel-invoke.hpp @@ -20,7 +20,16 @@ namespace rawaccel { accel_invoker(const accel_args& args) { cb = visit_accel([](auto&& arg) { - return &invoke_impl<remove_ref_t<decltype(arg)>>; + using T = remove_ref_t<decltype(arg)>; + + if constexpr (is_same_v<T, motivity>) { + static_assert(sizeof motivity == sizeof binlog_lut); + return &invoke_impl<binlog_lut>; + } + else { + return &invoke_impl<T>; + } + }, make_mode(args), accel_union{}); } diff --git a/common/accel-jump.hpp b/common/accel-jump.hpp index 2d13cae..30f9a49 100644 --- a/common/accel-jump.hpp +++ b/common/accel-jump.hpp @@ -2,9 +2,6 @@ #include "rawaccel-base.hpp" -#define _USE_MATH_DEFINES -#include <math.h> - namespace rawaccel { struct jump_base { @@ -18,7 +15,7 @@ namespace rawaccel { smooth_rate = 0; } else { - smooth_rate = 2 * M_PI / (args.offset * args.smooth); + smooth_rate = 2 * PI / (args.offset * args.smooth); } } diff --git a/common/accel-natural.hpp b/common/accel-natural.hpp index 28e17c2..8d25351 100644 --- a/common/accel-natural.hpp +++ b/common/accel-natural.hpp @@ -26,8 +26,8 @@ namespace rawaccel { { if (x <= offset) return 1; - double offset_x = x - offset; - double decay = exp(-accel * offset_x); + double offset_x = offset - x; + double decay = exp(accel * offset_x); return limit * (1 - (decay * offset_x + offset) / x) + 1; } @@ -41,8 +41,8 @@ namespace rawaccel { { if (x <= offset) return 1; - double offset_x = x - offset; - double decay = exp(-accel * offset_x); + double offset_x = offset - x; + double decay = exp(accel * offset_x); double output = limit * (offset_x + decay / accel) + constant; return output / x + 1; } diff --git a/common/rawaccel-base.hpp b/common/rawaccel-base.hpp index 6ce4468..dde56f5 100644 --- a/common/rawaccel-base.hpp +++ b/common/rawaccel-base.hpp @@ -17,6 +17,9 @@ namespace rawaccel { inline constexpr size_t LUT_CAPACITY = 1025; + inline constexpr double MAX_NORM = 16; + inline constexpr double PI = 3.14159265358979323846; + enum class accel_mode { classic, jump, @@ -79,7 +82,7 @@ namespace rawaccel { vec2<accel_args> argsv; vec2d sens = { 1, 1 }; - vec2d dir_multipliers = {}; + vec2d dir_multipliers = { 1, 1 }; domain_args dom_args = {}; vec2d range_weights = { 1, 1 }; diff --git a/common/rawaccel-validate.hpp b/common/rawaccel-validate.hpp index 230ddac..4f7dd9c 100644 --- a/common/rawaccel-validate.hpp +++ b/common/rawaccel-validate.hpp @@ -141,6 +141,10 @@ namespace rawaccel { error("max speed is less than min speed"); } + if (args.degrees_snap < 0 || args.degrees_snap > 45) { + error("snap angle must be between 0 and 45 degrees"); + } + if (args.sens.x == 0 || args.sens.y == 0) { error("sens multiplier is 0"); } @@ -150,12 +154,12 @@ namespace rawaccel { error("domain weights"" must be positive"); } - if (args.dom_args.lp_norm <= 0) { - error("Lp norm must be positive"); + if (args.dir_multipliers.x <= 0 || args.dir_multipliers.y <= 0) { + error("directional multipliers must be positive"); } - if (args.dir_multipliers.x < 0 || args.dir_multipliers.y < 0) { - error("directional multipliers can not be negative"); + if (args.dom_args.lp_norm < 2) { + error("Lp norm is less than 2 (default=2)"); } if (args.range_weights.x <= 0 || args.range_weights.y <= 0) { diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 6710a0c..fb2d81a 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -2,235 +2,170 @@ #include "accel-invoke.hpp" -#define _USE_MATH_DEFINES -#include <math.h> - namespace rawaccel { - /// <summary> Struct to hold vector rotation details. </summary> - struct rotator { - - /// <summary> Rotational vector, which points in the direction of the post-rotation positive x axis. </summary> - vec2d rot_vec = { 1, 0 }; - - /// <summary> - /// Rotates given input vector according to struct's rotational vector. - /// </summary> - /// <param name="input">Input vector to be rotated</param> - /// <returns>2d vector of rotated input.</returns> - inline vec2d apply(const vec2d& input) const { - return { - input.x * rot_vec.x - input.y * rot_vec.y, - input.x * rot_vec.y + input.y * rot_vec.x - }; - } - - rotator(double degrees) { - double rads = degrees * M_PI / 180; - rot_vec = { cos(rads), sin(rads) }; - } - - rotator() = default; - }; - - struct snapper { - double threshold = 0; - - inline vec2d apply(const vec2d& input) const { - if (input.x != 0 && input.y != 0) { - double angle = fabs(atan(input.y / input.x)); - auto mag = [&] { return sqrtsd(input.x * input.x + input.y * input.y); }; - - if (angle > M_PI_2 - threshold) return { 0, _copysign(mag(), input.y) }; - if (angle < threshold) return { _copysign(mag(), input.x), 0 }; - } - - return input; - } - - snapper(double degrees) : threshold(minsd(fabs(degrees), 45)* M_PI / 180) {} - - snapper() = default; - }; - - inline void clamp_speed(vec2d& v, double min, double max, double norm) { - double speed = sqrtsd(v.x * v.x + v.y * v.y) * norm; - double ratio = clampsd(speed, min, max) / speed; - v.x *= ratio; - v.y *= ratio; + inline vec2d direction(double degrees) + { + double radians = degrees * PI / 180; + return { cos(radians), sin(radians) }; } - struct weighted_distance { - double p = 2.0; - double p_inverse = 0.5; - bool lp_norm_infinity = false; - double sigma_x = 1.0; - double sigma_y = 1.0; - - weighted_distance(const domain_args& args) - { - sigma_x = args.domain_weights.x; - sigma_y = args.domain_weights.y; - if (args.lp_norm <= 0) - { - lp_norm_infinity = true; - p = 0.0; - p_inverse = 0.0; - } - else - { - lp_norm_infinity = false; - p = args.lp_norm; - p_inverse = 1 / args.lp_norm; - } - } - - inline double calculate(double x, double y) - { - double abs_scaled_x = fabs(x) * sigma_x; - double abs_scaled_y = fabs(y) * sigma_y; - - if (lp_norm_infinity) { - return maxsd(abs_scaled_x, abs_scaled_y); - } - - if (p == 2) { - return sqrtsd(abs_scaled_x * abs_scaled_x + - abs_scaled_y * abs_scaled_y); - } - - double dist_p = pow(abs_scaled_x, p) + pow(abs_scaled_y, p); - return pow(dist_p, p_inverse); - } + constexpr vec2d rotate(const vec2d& v, const vec2d& direction) + { + return { + v.x * direction.x - v.y * direction.y, + v.x * direction.y + v.y * direction.x + }; + } - weighted_distance() = default; - }; + inline double magnitude(const vec2d& v) + { + return sqrt(v.x * v.x + v.y * v.y); + } - inline double directional_weight(const vec2d& in, const vec2d& weights) + inline double lp_distance(const vec2d& v, double p) { - double atan_scale = M_2_PI * atan2(fabs(in.y), fabs(in.x)); - return atan_scale * (weights.y - weights.x) + weights.x; + return pow(pow(v.x, p) + pow(v.y, p), 1 / p); } - /// <summary> Struct to hold variables and methods for modifying mouse input </summary> - struct mouse_modifier { + class mouse_modifier { + public: + enum accel_distance_mode : unsigned char { + separate, + max, + Lp, + euclidean, + }; + bool apply_rotate = false; + bool compute_ref_angle = false; bool apply_snap = false; - bool apply_speed_clamp = false; - bool by_component = false; + bool cap_speed = false; + accel_distance_mode dist_mode = euclidean; bool apply_directional_weight = false; - rotator rotate; - snapper snap; - double dpi_factor = 1; + bool apply_dir_mul_x = false; + bool apply_dir_mul_y = false; + + vec2d rot_vec = { 1, 0 }; + double snap = 0; + double dpi_norm_factor = 1; double speed_min = 0; double speed_max = 0; - weighted_distance distance; + vec2d domain_weights = { 1, 1 }; + double p = 2; vec2d range_weights = { 1, 1 }; - vec2<accel_union> accels; + vec2d directional_multipliers = { 1, 1 }; vec2d sensitivity = { 1, 1 }; - vec2d directional_multipliers = {}; + vec2<accel_union> accel; - mouse_modifier(const settings& args) : - by_component(!args.combine_mags), - dpi_factor(1000 / args.dpi), - speed_min(args.speed_min), - speed_max(args.speed_max), - range_weights(args.range_weights) +#ifdef _KERNEL_MODE + __forceinline +#endif + void modify(vec2d& in, const vec2<accel_invoker>& inv, milliseconds time = 1) const { - if (args.degrees_rotation != 0) { - rotate = rotator(args.degrees_rotation); - apply_rotate = true; - } - - if (args.degrees_snap != 0) { - snap = snapper(args.degrees_snap); - apply_snap = true; - } - - if (args.sens.x != 0) sensitivity.x = args.sens.x; - if (args.sens.y != 0) sensitivity.y = args.sens.y; + double ips_factor = dpi_norm_factor / time; + double reference_angle = 0; - directional_multipliers.x = fabs(args.dir_multipliers.x); - directional_multipliers.y = fabs(args.dir_multipliers.y); + if (apply_rotate) in = rotate(in, rot_vec); - apply_speed_clamp = speed_max > 0; - - if ((!by_component && args.argsv.x.mode == accel_mode::noaccel) || - (args.argsv.x.mode == accel_mode::noaccel && - args.argsv.y.mode == accel_mode::noaccel)) { - return; + if (compute_ref_angle && in.y != 0) { + if (in.x == 0) { + reference_angle = PI / 2; + } + else { + reference_angle = atan(fabs(in.y / in.x)); + + if (apply_snap) { + if (reference_angle > PI / 2 - snap) { + reference_angle = PI / 2; + in = { 0, _copysign(magnitude(in), in.y) }; + } + else if (reference_angle < snap) { + reference_angle = 0; + in = { _copysign(magnitude(in), in.x), 0 }; + } + } + } } - accels.x = accel_union(args.argsv.x); - accels.y = accel_union(args.argsv.y); - - distance = weighted_distance(args.dom_args); - - apply_directional_weight = range_weights.x != range_weights.y; - } - - void modify(vec2d& movement, const vec2<accel_invoker>& inv = {}, milliseconds time = 1) { - apply_rotation(movement); - apply_angle_snap(movement); - apply_acceleration(movement, inv, time); - apply_sensitivity(movement); - } - - inline void apply_rotation(vec2d& movement) { - if (apply_rotate) movement = rotate.apply(movement); - } - - inline void apply_angle_snap(vec2d& movement) { - if (apply_snap) movement = snap.apply(movement); - } - - inline void apply_acceleration(vec2d& movement, const vec2<accel_invoker>& inv, milliseconds time) { - double norm = dpi_factor / time; - - if (apply_speed_clamp) { - clamp_speed(movement, speed_min, speed_max, norm); + if (cap_speed) { + double speed = magnitude(in) * ips_factor; + double ratio = clampsd(speed, speed_min, speed_max) / speed; + in.x *= ratio; + in.y *= ratio; } - if (!by_component) { - double mag = distance.calculate(movement.x, movement.y); - double speed = mag * norm; + vec2d abs_weighted_vel = { + fabs(in.x * ips_factor * domain_weights.x), + fabs(in.y * ips_factor * domain_weights.y) + }; - double weight; + if (dist_mode == separate) { + in.x *= inv.x.invoke(accel.x, abs_weighted_vel.x, range_weights.x); + in.y *= inv.y.invoke(accel.y, abs_weighted_vel.y, range_weights.y); + } + else { + double speed; - if (apply_directional_weight) { - weight = directional_weight(movement, range_weights); + if (dist_mode == max) { + speed = maxsd(abs_weighted_vel.x, abs_weighted_vel.y); + } + else if (dist_mode == Lp) { + speed = lp_distance(abs_weighted_vel, p); } else { - weight = range_weights.x; + speed = magnitude(abs_weighted_vel); } - double scale = inv.x.invoke(accels.x, speed, weight); - movement.x *= scale; - movement.y *= scale; - } - else { - if (movement.x != 0) { - double x = fabs(movement.x) * norm * distance.sigma_x; - movement.x *= inv.x.invoke(accels.x, x, range_weights.x); - } - if (movement.y != 0) { - double y = fabs(movement.y) * norm * distance.sigma_y; - movement.y *= inv.y.invoke(accels.y, y, range_weights.y); + double weight = range_weights.x; + + if (apply_directional_weight) { + double diff = range_weights.y - range_weights.x; + weight += 2 / PI * reference_angle * diff; } - } - } - - inline void apply_sensitivity(vec2d& movement) { - movement.x *= sensitivity.x; - movement.y *= sensitivity.y; + double scale = inv.x.invoke(accel.x, speed, weight); + in.x *= scale; + in.y *= scale; + } - if (directional_multipliers.x > 0 && movement.x < 0) { - movement.x *= directional_multipliers.x; + if (apply_dir_mul_x && in.x < 0) { + in.x *= directional_multipliers.x; } - if (directional_multipliers.y > 0 && movement.y < 0) { - movement.y *= directional_multipliers.y; + + if (apply_dir_mul_y && in.y < 0) { + in.y *= directional_multipliers.y; } + + in.x *= sensitivity.x; + in.y *= sensitivity.y; + } + + mouse_modifier(const settings& args) : + rot_vec(direction(args.degrees_rotation)), + snap(args.degrees_snap * PI / 180), + dpi_norm_factor(1000 / args.dpi), + speed_min(args.speed_min), + speed_max(args.speed_max), + p(args.dom_args.lp_norm), + domain_weights(args.dom_args.domain_weights), + range_weights(args.range_weights), + directional_multipliers(args.dir_multipliers), + sensitivity(args.sens), + accel({ { args.argsv.x }, { args.argsv.y } }) + { + cap_speed = speed_max > 0 && speed_min <= speed_max; + apply_rotate = rot_vec.x != 1; + apply_snap = snap != 0; + apply_directional_weight = range_weights.x != range_weights.y; + compute_ref_angle = apply_snap || apply_directional_weight; + apply_dir_mul_x = directional_multipliers.x != 1; + apply_dir_mul_y = directional_multipliers.y != 1; + + if (!args.combine_mags) dist_mode = separate; + else if (p >= MAX_NORM) dist_mode = max; + else if (p > 2) dist_mode = Lp; + else dist_mode = euclidean; } mouse_modifier() = default; diff --git a/common/utility.hpp b/common/utility.hpp index a8e5f83..cbd19e3 100644 --- a/common/utility.hpp +++ b/common/utility.hpp @@ -1,24 +1,7 @@ #pragma once -#ifdef _MANAGED -#include <math.h> -#else -#include <emmintrin.h> -#endif - namespace rawaccel { -#ifdef _MANAGED - inline double sqrtsd(double val) { return sqrt(val); } -#else - inline double sqrtsd(double val) { - __m128d src = _mm_load_sd(&val); - __m128d dst = _mm_sqrt_sd(src, src); - _mm_store_sd(&val, dst); - return val; - } -#endif - constexpr double minsd(double a, double b) { return (a < b) ? a : b; @@ -92,4 +75,14 @@ namespace rawaccel { template <typename T> using remove_ref_t = typename remove_ref<T>::type; + + template <typename T, typename U> + struct is_same { static constexpr bool value = false; }; + + template <typename T> + struct is_same<T, T> { static constexpr bool value = true; }; + + template <typename T, typename U> + inline constexpr bool is_same_v = is_same<T, U>::value; + } diff --git a/driver/driver.cpp b/driver/driver.cpp index fa2415d..feace77 100644 --- a/driver/driver.cpp +++ b/driver/driver.cpp @@ -23,6 +23,7 @@ struct { extern "C" PULONG InitSafeBootMode; +__declspec(guard(ignore)) VOID RawaccelCallback( IN PDEVICE_OBJECT DeviceObject, @@ -56,26 +57,18 @@ Arguments: auto num_packets = InputDataEnd - InputDataStart; - bool any = num_packets > 0; - bool rel_move = !(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE); - bool dev_match = global.args.device_id[0] == 0 || - global.args.ignore == - bool(wcsncmp(devExt->dev_id, global.args.device_id, ra::MAX_DEV_ID_LEN)); - - if (any && rel_move && dev_match) { - milliseconds time; - - if (global.args.time_min == global.args.time_max) { - time = global.args.time_min; - } - else { - counter_t now = KeQueryPerformanceCounter(NULL).QuadPart; - counter_t ticks = now - devExt->counter; - devExt->counter = now; - milliseconds t = ticks * global.tick_interval / num_packets; - time = ra::clampsd(t, global.args.time_min, global.args.time_max); - } - + if (num_packets > 0 && + !(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE) && + (global.args.device_id[0] == 0 || + bool(wcsncmp(devExt->dev_id, global.args.device_id, ra::MAX_DEV_ID_LEN)) == + global.args.ignore)) { + counter_t now = KeQueryPerformanceCounter(NULL).QuadPart; + counter_t ticks = now - devExt->counter; + devExt->counter = now; + milliseconds raw_elapsed = ticks * global.tick_interval; + milliseconds time = ra::clampsd(raw_elapsed / num_packets, + global.args.time_min, + global.args.time_max); auto it = InputDataStart; do { if (it->LastX || it->LastY) { diff --git a/driver/driver.vcxproj b/driver/driver.vcxproj index 9034680..c2e4629 100644 --- a/driver/driver.vcxproj +++ b/driver/driver.vcxproj @@ -30,6 +30,7 @@ <ConfigurationType>Driver</ConfigurationType> <OverrideDefaultRuntimeLibrary>true</OverrideDefaultRuntimeLibrary> <SpectreMitigation>Spectre</SpectreMitigation> + <Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation> </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows7</TargetVersion> @@ -38,6 +39,7 @@ <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> + <Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> @@ -74,18 +76,18 @@ </RuntimeLibrary> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <CallingConvention>StdCall</CallingConvention> - <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput> + <AssemblerOutput>AssemblyCode</AssemblerOutput> <ExpandAttributedSource>false</ExpandAttributedSource> <UseUnicodeForAssemblerListing>false</UseUnicodeForAssemblerListing> <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation> <Optimization>MaxSpeed</Optimization> <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> <IntrinsicFunctions>true</IntrinsicFunctions> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <FavorSizeOrSpeed>Neither</FavorSizeOrSpeed> <WholeProgramOptimization>false</WholeProgramOptimization> <BufferSecurityCheck>true</BufferSecurityCheck> <ControlFlowGuard>Guard</ControlFlowGuard> - <FloatingPointModel>Precise</FloatingPointModel> + <FloatingPointModel>Fast</FloatingPointModel> </ClCompile> <Link> <LinkTimeCodeGeneration> @@ -114,9 +116,11 @@ <RuntimeLibrary> </RuntimeLibrary> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> - <FloatingPointModel>Precise</FloatingPointModel> + <FloatingPointModel>Fast</FloatingPointModel> <CallingConvention>StdCall</CallingConvention> <Optimization>MaxSpeed</Optimization> + <ControlFlowGuard>Guard</ControlFlowGuard> + <BufferSecurityCheck>true</BufferSecurityCheck> </ClCompile> <Link> <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> diff --git a/wrapper/wrapper.vcxproj b/wrapper/wrapper.vcxproj index 8de0cfb..cd121a2 100644 --- a/wrapper/wrapper.vcxproj +++ b/wrapper/wrapper.vcxproj @@ -57,6 +57,7 @@ <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <LanguageStandard>stdcpp17</LanguageStandard> + <FloatingPointModel>Fast</FloatingPointModel> </ClCompile> <Link> <AdditionalDependencies>User32.lib;</AdditionalDependencies> @@ -70,6 +71,7 @@ <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <LanguageStandard>stdcpp17</LanguageStandard> + <FloatingPointModel>Fast</FloatingPointModel> </ClCompile> <Link> <AdditionalDependencies>User32.lib;</AdditionalDependencies> |