use std::collections::{HashMap, HashSet};
use std::fmt;
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum X86GameSimdLevel {
Scalar,
SSE42,
AVX2,
AVX512,
}
impl X86GameSimdLevel {
pub fn detect() -> Self {
#[cfg(target_arch = "x86_64")]
{
if std::arch::is_x86_feature_detected!("avx512f") {
return Self::AVX512;
}
if std::arch::is_x86_feature_detected!("avx2") {
return Self::AVX2;
}
if std::arch::is_x86_feature_detected!("sse4.2") {
return Self::SSE42;
}
}
Self::Scalar
}
pub fn vector_bytes(&self) -> usize {
match self {
Self::Scalar => 0,
Self::SSE42 => 16,
Self::AVX2 => 32,
Self::AVX512 => 64,
}
}
pub fn f32_lanes(&self) -> usize {
match self {
Self::Scalar => 1,
Self::SSE42 => 4,
Self::AVX2 => 8,
Self::AVX512 => 16,
}
}
pub fn compiler_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
match self {
Self::Scalar => {}
Self::SSE42 => flags.push("-msse4.2".into()),
Self::AVX2 => flags.push("-mavx2 -mfma".into()),
Self::AVX512 => flags.push("-mavx512f -mavx512dq -mavx512vl".into()),
}
flags
}
pub fn target_attribute(&self) -> &'static str {
match self {
Self::Scalar => "",
Self::SSE42 => "__attribute__((target(\"sse4.2\")))",
Self::AVX2 => "__attribute__((target(\"avx2,fma\")))",
Self::AVX512 => "__attribute__((target(\"avx512f,avx512dq,avx512vl\")))",
}
}
pub fn has_fma(&self) -> bool {
matches!(self, Self::AVX2 | Self::AVX512)
}
}
impl fmt::Display for X86GameSimdLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Scalar => write!(f, "scalar"),
Self::SSE42 => write!(f, "sse4.2"),
Self::AVX2 => write!(f, "avx2"),
Self::AVX512 => write!(f, "avx-512"),
}
}
}
impl Default for X86GameSimdLevel {
fn default() -> Self {
Self::SSE42
}
}
#[derive(Debug, Clone)]
pub struct X86Games {
pub simd_level: X86GameSimdLevel,
pub optimizations: X86GameOptimizations,
pub engines: X86GameEngines,
pub graphics: X86GameGraphics,
pub physics: X86GamePhysics,
pub audio: X86GameAudio,
pub networking: X86GameNetworking,
pub profiling: X86GameProfiling,
pub target: X86GameTarget,
pub build_config: X86GameBuildConfig,
pub math: X86GameMath,
pub physics_engine: X86GamePhysicsEngine,
pub rendering: X86GameRendering,
pub animation: X86GameAnimation,
pub audio_dsp: X86GameAudioDSP,
pub networking_core: X86GameNetworkingCore,
pub flags: Vec<String>,
pub defines: HashMap<String, Option<String>>,
}
impl X86Games {
pub fn new() -> Self {
Self {
simd_level: X86GameSimdLevel::default(),
optimizations: X86GameOptimizations::default(),
engines: X86GameEngines::default(),
graphics: X86GameGraphics::default(),
physics: X86GamePhysics::default(),
audio: X86GameAudio::default(),
networking: X86GameNetworking::default(),
profiling: X86GameProfiling::default(),
target: X86GameTarget::default(),
build_config: X86GameBuildConfig::default(),
math: X86GameMath::default(),
physics_engine: X86GamePhysicsEngine::default(),
rendering: X86GameRendering::default(),
animation: X86GameAnimation::default(),
audio_dsp: X86GameAudioDSP::default(),
networking_core: X86GameNetworkingCore::default(),
flags: Vec::new(),
defines: HashMap::new(),
}
}
pub fn with_simd_level(mut self, level: X86GameSimdLevel) -> Self {
self.simd_level = level;
self.math = X86GameMath::new(level);
self.physics_engine = X86GamePhysicsEngine::new(level);
self.rendering = X86GameRendering::new(level);
self.animation = X86GameAnimation::new(level);
self.audio_dsp = X86GameAudioDSP::new(level);
self.networking_core = X86GameNetworkingCore::new(level);
self
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.extend(self.simd_level.compiler_flags());
flags.extend(self.optimizations.compile_flags());
flags.extend(self.build_config.compile_flags());
flags.extend(self.target.compile_flags());
flags.extend(self.math.compile_flags());
flags.extend(self.physics_engine.compile_flags());
flags.extend(self.rendering.compile_flags());
flags.extend(self.audio_dsp.compile_flags());
flags.extend(self.networking_core.compile_flags());
flags.extend(self.engines.compile_flags());
flags.extend(self.graphics.compile_flags());
flags.extend(self.flags.clone());
flags
}
pub fn linker_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.extend(self.engines.linker_flags());
flags.extend(self.graphics.linker_flags());
flags.extend(self.networking_core.linker_flags());
flags.extend(self.rendering.linker_flags());
flags
}
pub fn define<S: Into<String>>(&mut self, key: S, value: Option<String>) {
self.defines.insert(key.into(), value);
}
pub fn clang_command(&self, source_file: &str) -> Vec<String> {
let mut cmd = vec!["clang".to_string(), source_file.to_string()];
cmd.extend(self.compile_flags());
for (key, val) in &self.defines {
if let Some(v) = val {
cmd.push(format!("-D{}={}", key, v));
} else {
cmd.push(format!("-D{}", key));
}
}
cmd
}
pub fn describe(&self) -> String {
let mut desc = format!(
"X86 Games [simd={} target={}]\n",
self.simd_level, self.target
);
desc.push_str(&format!(" Math: {}\n", self.math.describe()));
desc.push_str(&format!(" Physics: {}\n", self.physics_engine.describe()));
desc.push_str(&format!(" Rendering: {}\n", self.rendering.describe()));
desc.push_str(&format!(" Animation: {}\n", self.animation.describe()));
desc.push_str(&format!(" Audio: {}\n", self.audio_dsp.describe()));
desc.push_str(&format!(
" Networking: {}\n",
self.networking_core.describe()
));
desc
}
}
impl Default for X86Games {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86GameTarget {
LinuxX64,
WindowsX64,
MacOSX64,
LinuxX86,
WindowsX86,
}
impl X86GameTarget {
pub fn as_triple(&self) -> &'static str {
match self {
Self::LinuxX64 => "x86_64-unknown-linux-gnu",
Self::WindowsX64 => "x86_64-pc-windows-msvc",
Self::MacOSX64 => "x86_64-apple-darwin",
Self::LinuxX86 => "i686-unknown-linux-gnu",
Self::WindowsX86 => "i686-pc-windows-msvc",
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = vec![format!("--target={}", self.as_triple())];
match self {
Self::WindowsX64 | Self::WindowsX86 => {
flags.push("-fms-extensions".into());
flags.push("-fms-compatibility".into());
}
_ => {}
}
flags
}
pub fn is_64bit(&self) -> bool {
matches!(self, Self::LinuxX64 | Self::WindowsX64 | Self::MacOSX64)
}
}
impl Default for X86GameTarget {
fn default() -> Self {
Self::LinuxX64
}
}
impl fmt::Display for X86GameTarget {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_triple())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86GameOptimizationLevel {
Debug,
Development,
Test,
Shipping,
Profile,
}
impl X86GameOptimizationLevel {
pub fn as_flags(&self) -> Vec<String> {
match self {
Self::Debug => vec!["-O0".into(), "-g".into()],
Self::Development => vec!["-O2".into(), "-g1".into()],
Self::Test => vec!["-O1".into(), "-g".into()],
Self::Shipping => vec!["-O3".into(), "-flto".into(), "-DNDEBUG".into()],
Self::Profile => vec!["-O3".into(), "-g".into(), "-fno-omit-frame-pointer".into()],
}
}
}
impl Default for X86GameOptimizationLevel {
fn default() -> Self {
Self::Development
}
}
impl fmt::Display for X86GameOptimizationLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Debug => write!(f, "debug"),
Self::Development => write!(f, "development"),
Self::Test => write!(f, "test"),
Self::Shipping => write!(f, "shipping"),
Self::Profile => write!(f, "profile"),
}
}
}
#[derive(Debug, Clone)]
pub struct X86GameBuildConfig {
pub optimization: X86GameOptimizationLevel,
pub debug_symbols: bool,
pub asserts_enabled: bool,
pub address_sanitizer: bool,
pub thread_sanitizer: bool,
pub ubsan: bool,
pub lto: bool,
pub thin_lto: bool,
pub pgo_instrument: bool,
pub pgo_use: Option<String>,
pub split_dwarf: bool,
pub extra_flags: Vec<String>,
}
impl X86GameBuildConfig {
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.extend(self.optimization.as_flags());
if !self.asserts_enabled {
flags.push("-DNDEBUG".into());
}
if self.address_sanitizer {
flags.push("-fsanitize=address".into());
}
if self.thread_sanitizer {
flags.push("-fsanitize=thread".into());
}
if self.ubsan {
flags.push("-fsanitize=undefined".into());
}
if self.lto {
flags.push("-flto".into());
}
if self.thin_lto {
flags.push("-flto=thin".into());
}
if self.pgo_instrument {
flags.push("-fprofile-generate".into());
}
if let Some(ref pgo_file) = self.pgo_use {
flags.push(format!("-fprofile-use={}", pgo_file));
}
if self.split_dwarf {
flags.push("-gsplit-dwarf".into());
}
flags.extend(self.extra_flags.clone());
flags
}
}
impl Default for X86GameBuildConfig {
fn default() -> Self {
Self {
optimization: X86GameOptimizationLevel::default(),
debug_symbols: true,
asserts_enabled: true,
address_sanitizer: false,
thread_sanitizer: false,
ubsan: false,
lto: false,
thin_lto: false,
pgo_instrument: false,
pgo_use: None,
split_dwarf: false,
extra_flags: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct X86GameOptimizations {
pub simd_level: X86GameSimdLevel,
pub frame_budget: X86FrameBudget,
pub hot_cold_splitting: X86HotColdSplitting,
pub cache_layout: X86CacheLayoutOpt,
pub prefetch: X86PrefetchOpt,
pub lock_free: X86LockFreeOpt,
pub branch_hints: X86BranchHintOpt,
pub simd_vectorization: X86SimdVectorization,
}
impl X86GameOptimizations {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
frame_budget: X86FrameBudget::default(),
hot_cold_splitting: X86HotColdSplitting::default(),
cache_layout: X86CacheLayoutOpt::default(),
prefetch: X86PrefetchOpt::default(),
lock_free: X86LockFreeOpt::default(),
branch_hints: X86BranchHintOpt::default(),
simd_vectorization: X86SimdVectorization::new(simd_level),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.extend(self.frame_budget.compile_flags());
flags.extend(self.hot_cold_splitting.compile_flags());
flags.extend(self.cache_layout.compile_flags());
flags.extend(self.prefetch.compile_flags());
flags.extend(self.lock_free.compile_flags());
flags.extend(self.branch_hints.compile_flags());
flags.extend(self.simd_vectorization.compile_flags());
flags
}
pub fn describe(&self) -> String {
format!(
"optimizations: simd={}, frame_budget={}, hot_cold={}",
self.simd_level, self.frame_budget.enabled, self.hot_cold_splitting.enabled
)
}
}
impl Default for X86GameOptimizations {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86FrameBudget {
pub target_frame_us: u64,
pub enabled: bool,
pub align_hot_paths: bool,
pub split_frame_critical: bool,
pub inline_frame_critical: bool,
pub disable_jittery_opts: bool,
pub extra_mllvm_flags: Vec<String>,
}
impl X86FrameBudget {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
let mut flags = Vec::new();
if self.align_hot_paths {
flags.push("-falign-functions=32".into());
}
if self.inline_frame_critical {
flags.push("-finline-functions".into());
flags.push("-finline-limit=500".into());
}
if self.disable_jittery_opts {
flags.push("-fno-var-tracking-assignments".into());
}
for f in &self.extra_mllvm_flags {
flags.push(format!("-mllvm {}", f));
}
flags
}
pub fn describe(&self) -> String {
format!(
"frame_budget(enabled={}, target_us={})",
self.enabled, self.target_frame_us
)
}
}
impl Default for X86FrameBudget {
fn default() -> Self {
Self {
target_frame_us: 16667, enabled: false,
align_hot_paths: false,
split_frame_critical: false,
inline_frame_critical: false,
disable_jittery_opts: false,
extra_mllvm_flags: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct X86HotColdSplitting {
pub enabled: bool,
pub profile_guided: bool,
pub split_threshold_bytes: usize,
pub cold_section_name: String,
pub hot_section_name: String,
pub aggressive_outlining: bool,
}
impl X86HotColdSplitting {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
vec![
"-fhot-cold-split".into(),
format!("-fsplit-machine-functions={}", self.split_threshold_bytes),
]
}
pub fn cold_attribute(&self) -> &'static str {
"__attribute__((cold))"
}
pub fn hot_attribute(&self) -> &'static str {
"__attribute__((hot))"
}
pub fn section_pragma(&self) -> String {
format!(
"#pragma GCC section \"{}\" \"{}\"",
self.hot_section_name, self.cold_section_name
)
}
pub fn describe(&self) -> String {
format!("hot_cold(enabled={})", self.enabled)
}
}
impl Default for X86HotColdSplitting {
fn default() -> Self {
Self {
enabled: false,
profile_guided: false,
split_threshold_bytes: 1024,
cold_section_name: ".text.cold".into(),
hot_section_name: ".text.hot".into(),
aggressive_outlining: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86CacheLayoutOpt {
pub cache_line_align: bool,
pub cache_line_size: usize,
pub prefer_soa: bool,
pub pad_to_cache_line: bool,
pub optimize_interleaved_access: bool,
pub pack_structs: bool,
pub struct_reordering: bool,
}
impl X86CacheLayoutOpt {
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.pack_structs {
flags.push("-fpack-struct".into());
}
if self.struct_reordering {
flags.push("-fstruct-reorder".into());
}
flags
}
pub fn soa_layout_decl(&self, struct_name: &str, fields: &[(&str, &str)]) -> String {
let mut decl = format!("// SoA layout for {}\n", struct_name);
decl.push_str("struct {\n");
for (name, ty) in fields {
decl.push_str(&format!(" {}* {}; // SoA column\n", ty, name));
}
decl.push_str(&format!("}} {}_soa;\n", struct_name));
decl
}
pub fn cache_line_padding(&self) -> String {
format!(
"#define CACHE_LINE_SIZE {}\n#define CACHE_ALIGN __attribute__((aligned(CACHE_LINE_SIZE)))\n",
self.cache_line_size
)
}
pub fn describe(&self) -> String {
format!(
"cache_layout(soa={}, cache_line={})",
self.prefer_soa, self.cache_line_size
)
}
}
impl Default for X86CacheLayoutOpt {
fn default() -> Self {
Self {
cache_line_align: false,
cache_line_size: 64,
prefer_soa: true,
pad_to_cache_line: false,
optimize_interleaved_access: false,
pack_structs: false,
struct_reordering: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86PrefetchOpt {
pub enabled: bool,
pub prefetch_distance: usize,
pub temporal_locality: u8,
pub streaming_stores: bool,
pub cache_level: X86PrefetchCacheLevel,
pub stream_buffer_size: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86PrefetchCacheLevel {
L1,
L2,
L3,
NTA,
}
impl X86PrefetchOpt {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
vec![
format!("-fprefetch-distance={}", self.prefetch_distance),
format!("-fprefetch-loop-arrays={}", self.prefetch_distance),
]
}
pub fn prefetch_intrinsic(&self, ptr_name: &str) -> String {
let hint = match self.cache_level {
X86PrefetchCacheLevel::L1 => "_MM_HINT_T0",
X86PrefetchCacheLevel::L2 => "_MM_HINT_T1",
X86PrefetchCacheLevel::L3 => "_MM_HINT_T2",
X86PrefetchCacheLevel::NTA => "_MM_HINT_NTA",
};
format!("_mm_prefetch({}, {});", ptr_name, hint)
}
pub fn streaming_store_intrinsic(&self) -> &'static str {
"_mm_stream_si32"
}
pub fn describe(&self) -> String {
format!(
"prefetch(enabled={}, dist={})",
self.enabled, self.prefetch_distance
)
}
}
impl Default for X86PrefetchOpt {
fn default() -> Self {
Self {
enabled: false,
prefetch_distance: 8,
temporal_locality: 3,
streaming_stores: false,
cache_level: X86PrefetchCacheLevel::L2,
stream_buffer_size: 64,
}
}
}
#[derive(Debug, Clone)]
pub struct X86LockFreeOpt {
pub enabled: bool,
pub memory_order_opt: bool,
pub spin_pause: bool,
pub tsx_enabled: bool,
pub atomic_size: X86LockFreeAtomicSize,
pub rcu_opt: bool,
pub hazard_ptr_opt: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86LockFreeAtomicSize {
Atomic32,
Atomic64,
Atomic128,
}
impl X86LockFreeOpt {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
let mut flags = vec!["-flock-free".into()];
if self.tsx_enabled {
flags.push("-mrtm".into());
}
flags
}
fn cache_line_size(&self) -> usize {
64
}
pub fn spsc_queue_decl(&self, elem_type: &str, queue_name: &str, capacity: usize) -> String {
format!(
r#"
// SPSC lock-free queue: {queue_name}
#define {q}_CAPACITY {cap}
struct {q} {{
_Atomic uint32_t head;
_Atomic uint32_t tail;
CACHE_ALIGN {elem_type} buffer[{q}_CAPACITY];
}};
static inline bool {q}_enqueue(struct {q}* q, {elem_type} item) {{
uint32_t head = atomic_load_explicit(&q->head, memory_order_acquire);
uint32_t next = (head + 1) % {q}_CAPACITY;
if (next == atomic_load_explicit(&q->tail, memory_order_acquire)) return false;
q->buffer[head] = item;
atomic_store_explicit(&q->head, next, memory_order_release);
return true;
}}
"#,
q = queue_name,
cap = capacity,
elem_type = elem_type,
queue_name = queue_name,
)
}
pub fn spin_wait_loop(&self) -> String {
let pause = if self.spin_pause { "_mm_pause();" } else { "" };
format!(
"while (!atomic_load_explicit(&flag, memory_order_acquire)) {{ {} }}",
pause
)
}
pub fn memory_barrier(&self) -> &'static str {
"atomic_thread_fence(memory_order_seq_cst);"
}
pub fn describe(&self) -> String {
format!("lock_free(enabled={})", self.enabled)
}
}
impl Default for X86LockFreeOpt {
fn default() -> Self {
Self {
enabled: false,
memory_order_opt: false,
spin_pause: false,
tsx_enabled: false,
atomic_size: X86LockFreeAtomicSize::Atomic64,
rcu_opt: false,
hazard_ptr_opt: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86BranchHintOpt {
pub enabled: bool,
pub profile_guided: bool,
pub default_probability: f64,
pub indirect_branch_opt: bool,
pub generate_hints: bool,
pub use_likelihood_macros: bool,
}
impl X86BranchHintOpt {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
vec!["-fbranch-probabilities".into()]
}
pub fn likely_macro(&self) -> &'static str {
"#define LIKELY(x) __builtin_expect(!!(x), 1)"
}
pub fn unlikely_macro(&self) -> &'static str {
"#define UNLIKELY(x) __builtin_expect(!!(x), 0)"
}
pub fn branch_weight(&self, taken: u32, not_taken: u32) -> String {
format!(
"__builtin_expect_with_probability(expr, {}/{})",
taken,
taken + not_taken
)
}
pub fn describe(&self) -> String {
format!("branch_hints(enabled={})", self.enabled)
}
}
impl Default for X86BranchHintOpt {
fn default() -> Self {
Self {
enabled: false,
profile_guided: false,
default_probability: 0.5,
indirect_branch_opt: false,
generate_hints: false,
use_likelihood_macros: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86SimdVectorization {
pub simd_level: X86GameSimdLevel,
pub loop_vectorize: bool,
pub slp_vectorize: bool,
pub vector_width: usize,
pub interleave_count: usize,
pub math_vectorize: bool,
pub fast_math: bool,
pub fma_contraction: bool,
pub reciprocal_approx: bool,
pub matrix_transpose_opt: bool,
pub quaternion_opt: bool,
}
impl X86SimdVectorization {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
loop_vectorize: true,
slp_vectorize: true,
vector_width: simd_level.f32_lanes(),
interleave_count: if simd_level == X86GameSimdLevel::Scalar {
1
} else {
4
},
math_vectorize: true,
fast_math: true,
fma_contraction: true,
reciprocal_approx: true,
matrix_transpose_opt: true,
quaternion_opt: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.fast_math {
flags.push("-ffast-math".into());
}
if self.fma_contraction {
flags.push("-ffp-contract=fast".into());
}
if self.reciprocal_approx {
flags.push("-mrecip".into());
}
flags
}
pub fn mat4_mul_intrinsic(&self) -> String {
let mut code = String::from("// X86-optimized mat4 multiply\n");
code.push_str(
"static inline void mat4_mul_simd(float* C, const float* A, const float* B) {\n",
);
match self.simd_level {
X86GameSimdLevel::SSE42 => {
code.push_str(" __m128 b0 = _mm_load_ps(B);\n");
code.push_str(" __m128 b1 = _mm_load_ps(B+4);\n");
code.push_str(" __m128 b2 = _mm_load_ps(B+8);\n");
code.push_str(" __m128 b3 = _mm_load_ps(B+12);\n");
code.push_str(" for (int i = 0; i < 4; i++) {\n");
code.push_str(" __m128 r = _mm_set1_ps(A[i*4]);\n");
code.push_str(" __m128 t = _mm_mul_ps(r, b0);\n");
code.push_str(
" r = _mm_set1_ps(A[i*4+1]); t = _mm_add_ps(t, _mm_mul_ps(r, b1));\n",
);
code.push_str(
" r = _mm_set1_ps(A[i*4+2]); t = _mm_add_ps(t, _mm_mul_ps(r, b2));\n",
);
code.push_str(
" r = _mm_set1_ps(A[i*4+3]); t = _mm_add_ps(t, _mm_mul_ps(r, b3));\n",
);
code.push_str(" _mm_store_ps(C + i*4, t);\n");
code.push_str(" }\n");
}
X86GameSimdLevel::AVX2 => {
code.push_str(" __m256 b01 = _mm256_load_ps(B);\n");
code.push_str(" __m256 b23 = _mm256_load_ps(B+8);\n");
code.push_str(" for (int i = 0; i < 4; i++) {\n");
code.push_str(" __m256 a0 = _mm256_broadcast_ss(A + i*4);\n");
code.push_str(" __m256 a1 = _mm256_broadcast_ss(A + i*4 + 1);\n");
code.push_str(" __m256 a2 = _mm256_broadcast_ss(A + i*4 + 2);\n");
code.push_str(" __m256 a3 = _mm256_broadcast_ss(A + i*4 + 3);\n");
code.push_str(" __m256 t0 = _mm256_mul_ps(a0, b01);\n");
code.push_str(
" __m256 t1 = _mm256_fmadd_ps(a1, _mm256_permute_ps(b01,0xb1), t0);\n",
);
code.push_str(" __m256 t2 = _mm256_fmadd_ps(a2, b23, t1);\n");
code.push_str(
" __m256 t3 = _mm256_fmadd_ps(a3, _mm256_permute_ps(b23,0xb1), t2);\n",
);
code.push_str(" _mm256_store_ps(C + i*4, t3);\n");
code.push_str(" }\n");
}
X86GameSimdLevel::AVX512 => {
code.push_str(" __m512 b0123 = _mm512_load_ps(B);\n");
code.push_str(" for (int i = 0; i < 4; i++) {\n");
code.push_str(" __m512 a = _mm512_set1_ps(A[i*4]);\n");
code.push_str(" __m512 r = _mm512_mul_ps(a, b0123);\n");
code.push_str(
" a = _mm512_set1_ps(A[i*4+1]); r = _mm512_fmadd_ps(a, b0123, r);\n",
);
code.push_str(
" a = _mm512_set1_ps(A[i*4+2]); r = _mm512_fmadd_ps(a, b0123, r);\n",
);
code.push_str(
" a = _mm512_set1_ps(A[i*4+3]); r = _mm512_fmadd_ps(a, b0123, r);\n",
);
code.push_str(" _mm512_store_ps(C + i*4, r);\n");
code.push_str(" }\n");
}
_ => {
code.push_str(" for (int i = 0; i < 4; i++)\n");
code.push_str(" for (int j = 0; j < 4; j++) {\n");
code.push_str(" C[i*4+j] = A[i*4]*B[j] + A[i*4+1]*B[4+j] + A[i*4+2]*B[8+j] + A[i*4+3]*B[12+j];\n");
code.push_str(" }\n");
}
}
code.push_str("}\n");
code
}
pub fn quat_mul_intrinsic(&self) -> String {
let mut code = String::from("// X86-optimized quaternion multiply\n");
code.push_str(
"static inline void quat_mul_simd(float* r, const float* a, const float* b) {\n",
);
match self.simd_level {
X86GameSimdLevel::SSE42 | X86GameSimdLevel::AVX2 => {
code.push_str(" __m128 qa = _mm_load_ps(a);\n");
code.push_str(" __m128 qb = _mm_load_ps(b);\n");
code.push_str(" __m128 qa_www = _mm_shuffle_ps(qa, qa, 0xff);\n");
code.push_str(" __m128 r0 = _mm_mul_ps(qa_www, qb);\n");
code.push_str(" __m128 qb_www = _mm_shuffle_ps(qb, qb, 0xff);\n");
code.push_str(" __m128 r1 = _mm_mul_ps(qb_www, qa);\n");
code.push_str(" __m128 cross = _mm_sub_ps(\n");
code.push_str(
" _mm_mul_ps(_mm_shuffle_ps(qa,qa,0xc9), _mm_shuffle_ps(qb,qb,0xd2)),\n",
);
code.push_str(
" _mm_mul_ps(_mm_shuffle_ps(qb,qb,0xc9), _mm_shuffle_ps(qa,qa,0xd2))\n",
);
code.push_str(" );\n");
code.push_str(" __m128 result = _mm_add_ps(_mm_add_ps(r0, r1), cross);\n");
code.push_str(" _mm_store_ps(r, result);\n");
}
_ => {
code.push_str(" r[0] = a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*b[1];\n");
code.push_str(" r[1] = a[3]*b[1] + a[1]*b[3] + a[2]*b[0] - a[0]*b[2];\n");
code.push_str(" r[2] = a[3]*b[2] + a[2]*b[3] + a[0]*b[1] - a[1]*b[0];\n");
code.push_str(" r[3] = a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*b[2];\n");
}
}
code.push_str("}\n");
code
}
pub fn vec3_ops_intrinsic(&self) -> String {
let mut code = String::from("// X86-optimized vec3 operations\n");
code.push_str("typedef struct { float x, y, z, w; } vec3_simd;\n");
match self.simd_level {
X86GameSimdLevel::SSE42 | X86GameSimdLevel::AVX2 => {
code.push_str("static inline __m128 vec3_add(__m128 a, __m128 b) { return _mm_add_ps(a, b); }\n");
code.push_str("static inline __m128 vec3_sub(__m128 a, __m128 b) { return _mm_sub_ps(a, b); }\n");
code.push_str("static inline __m128 vec3_mul(__m128 a, __m128 b) { return _mm_mul_ps(a, b); }\n");
code.push_str("static inline __m128 vec3_dot(__m128 a, __m128 b) {\n");
code.push_str(" __m128 m = _mm_mul_ps(a, b);\n");
code.push_str(" __m128 s = _mm_hadd_ps(m, m);\n");
code.push_str(" return _mm_hadd_ps(s, s);\n");
code.push_str("}\n");
code.push_str("static inline __m128 vec3_cross(__m128 a, __m128 b) {\n");
code.push_str(" __m128 t0 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3,0,2,1));\n");
code.push_str(" __m128 t1 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3,1,0,2));\n");
code.push_str(" __m128 r0 = _mm_mul_ps(t0, t1);\n");
code.push_str(
" __m128 r1 = _mm_mul_ps(a, _mm_shuffle_ps(b,b,_MM_SHUFFLE(3,0,2,1)));\n",
);
code.push_str(" return _mm_sub_ps(r0, r1);\n");
code.push_str("}\n");
}
_ => {
code.push_str("static inline vec3_simd vec3_add(vec3_simd a, vec3_simd b) { return (vec3_simd){a.x+b.x,a.y+b.y,a.z+b.z,0}; }\n");
code.push_str("static inline vec3_simd vec3_sub(vec3_simd a, vec3_simd b) { return (vec3_simd){a.x-b.x,a.y-b.y,a.z-b.z,0}; }\n");
code.push_str("static inline float vec3_dot(vec3_simd a, vec3_simd b) { return a.x*b.x+a.y*b.y+a.z*b.z; }\n");
}
}
code
}
pub fn describe(&self) -> String {
format!(
"simd_vec(lv={}, slp={}, w={})",
self.loop_vectorize, self.slp_vectorize, self.vector_width
)
}
}
impl Default for X86SimdVectorization {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86FastMathConfig {
pub use_fast_math: bool,
pub reciprocal_sqrt: bool,
pub approximate_sin_cos: bool,
pub approximate_exp_log: bool,
pub approximate_atan2: bool,
pub flush_denormals: bool,
pub assume_finite_math: bool,
}
impl Default for X86FastMathConfig {
fn default() -> Self {
Self {
use_fast_math: true,
reciprocal_sqrt: true,
approximate_sin_cos: true,
approximate_exp_log: true,
approximate_atan2: true,
flush_denormals: true,
assume_finite_math: true,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct X86Vec2 {
pub x: f32,
pub y: f32,
}
impl X86Vec2 {
pub fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
pub fn zero() -> Self {
Self { x: 0.0, y: 0.0 }
}
pub fn one() -> Self {
Self { x: 1.0, y: 1.0 }
}
pub fn dot(&self, other: &Self) -> f32 {
self.x * other.x + self.y * other.y
}
pub fn length(&self) -> f32 {
(self.x * self.x + self.y * self.y).sqrt()
}
pub fn length_sq(&self) -> f32 {
self.x * self.x + self.y * self.y
}
pub fn normalize(&self) -> Self {
let len = self.length();
if len > 1e-10 {
Self {
x: self.x / len,
y: self.y / len,
}
} else {
Self::zero()
}
}
pub fn perpendicular(&self) -> Self {
Self {
x: -self.y,
y: self.x,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct X86Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl X86Vec3 {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self { x, y, z }
}
pub fn zero() -> Self {
Self {
x: 0.0,
y: 0.0,
z: 0.0,
}
}
pub fn one() -> Self {
Self {
x: 1.0,
y: 1.0,
z: 1.0,
}
}
pub fn up() -> Self {
Self {
x: 0.0,
y: 1.0,
z: 0.0,
}
}
pub fn forward() -> Self {
Self {
x: 0.0,
y: 0.0,
z: 1.0,
}
}
pub fn right() -> Self {
Self {
x: 1.0,
y: 0.0,
z: 0.0,
}
}
pub fn dot(&self, other: &Self) -> f32 {
self.x * other.x + self.y * other.y + self.z * other.z
}
pub fn cross(&self, other: &Self) -> Self {
Self {
x: self.y * other.z - self.z * other.y,
y: self.z * other.x - self.x * other.z,
z: self.x * other.y - self.y * other.x,
}
}
pub fn length(&self) -> f32 {
self.dot(self).sqrt()
}
pub fn length_sq(&self) -> f32 {
self.dot(self)
}
pub fn normalize(&self) -> Self {
let len = self.length();
if len > 1e-10 {
Self {
x: self.x / len,
y: self.y / len,
z: self.z / len,
}
} else {
Self::zero()
}
}
pub fn add(&self, other: &Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
z: self.z + other.z,
}
}
pub fn sub(&self, other: &Self) -> Self {
Self {
x: self.x - other.x,
y: self.y - other.y,
z: self.z - other.z,
}
}
pub fn scale(&self, s: f32) -> Self {
Self {
x: self.x * s,
y: self.y * s,
z: self.z * s,
}
}
pub fn lerp(&self, other: &Self, t: f32) -> Self {
Self {
x: self.x + (other.x - self.x) * t,
y: self.y + (other.y - self.y) * t,
z: self.z + (other.z - self.z) * t,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct X86Vec4 {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl X86Vec4 {
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
Self { x, y, z, w }
}
pub fn from_vec3(v: &X86Vec3, w: f32) -> Self {
Self {
x: v.x,
y: v.y,
z: v.z,
w,
}
}
pub fn dot(&self, other: &Self) -> f32 {
self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86Quat {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl X86Quat {
pub fn identity() -> Self {
Self {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0,
}
}
pub fn from_axis_angle(axis: &X86Vec3, angle: f32) -> Self {
let half = angle * 0.5;
let s = half.sin();
Self {
x: axis.x * s,
y: axis.y * s,
z: axis.z * s,
w: half.cos(),
}
}
pub fn from_euler(pitch: f32, yaw: f32, roll: f32) -> Self {
let cp = (pitch * 0.5).cos();
let sp = (pitch * 0.5).sin();
let cy = (yaw * 0.5).cos();
let sy = (yaw * 0.5).sin();
let cr = (roll * 0.5).cos();
let sr = (roll * 0.5).sin();
Self {
w: cr * cp * cy + sr * sp * sy,
x: sr * cp * cy - cr * sp * sy,
y: cr * sp * cy + sr * cp * sy,
z: cr * cp * sy - sr * sp * cy,
}
}
pub fn mul(&self, other: &Self) -> Self {
Self {
w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.x,
z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w,
}
}
pub fn rotate_vec3(&self, v: &X86Vec3) -> X86Vec3 {
let qv = X86Quat {
x: v.x,
y: v.y,
z: v.z,
w: 0.0,
};
let conj = X86Quat {
x: -self.x,
y: -self.y,
z: -self.z,
w: self.w,
};
let r = self.mul(&qv).mul(&conj);
X86Vec3 {
x: r.x,
y: r.y,
z: r.z,
}
}
pub fn slerp(&self, other: &Self, t: f32) -> Self {
let mut cos_theta =
self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w;
let mut other = *other;
if cos_theta < 0.0 {
other = X86Quat {
x: -other.x,
y: -other.y,
z: -other.z,
w: -other.w,
};
cos_theta = -cos_theta;
}
if cos_theta > 0.9995 {
let inv = 1.0 - t;
let result = Self {
x: inv * self.x + t * other.x,
y: inv * self.y + t * other.y,
z: inv * self.z + t * other.z,
w: inv * self.w + t * other.w,
};
let mag = (result.x * result.x
+ result.y * result.y
+ result.z * result.z
+ result.w * result.w)
.sqrt();
return Self {
x: result.x / mag,
y: result.y / mag,
z: result.z / mag,
w: result.w / mag,
};
}
let theta = cos_theta.acos();
let sin_theta = theta.sin();
let a = ((1.0 - t) * theta).sin() / sin_theta;
let b = (t * theta).sin() / sin_theta;
Self {
w: a * self.w + b * other.w,
x: a * self.x + b * other.x,
y: a * self.y + b * other.y,
z: a * self.z + b * other.z,
}
}
pub fn nlerp(&self, other: &Self, t: f32) -> Self {
let inv = 1.0 - t;
let x = inv * self.x + t * other.x;
let y = inv * self.y + t * other.y;
let z = inv * self.z + t * other.z;
let w = inv * self.w + t * other.w;
let mag = (x * x + y * y + z * z + w * w).sqrt();
Self {
x: x / mag,
y: y / mag,
z: z / mag,
w: w / mag,
}
}
pub fn look_at(direction: &X86Vec3, up: &X86Vec3) -> Self {
let forward = direction.normalize();
let right = up.cross(&forward).normalize();
let up_actual = forward.cross(&right);
let trace = right.x + up_actual.y + forward.z;
if trace > 0.0 {
let s = 0.5 / (trace + 1.0).sqrt();
Self {
w: 0.25 / s,
x: (up_actual.z - forward.y) * s,
y: (forward.x - right.z) * s,
z: (right.y - up_actual.x) * s,
}
} else if right.x > up_actual.y && right.x > forward.z {
let s = 2.0 * (1.0 + right.x - up_actual.y - forward.z).sqrt();
Self {
w: (up_actual.z - forward.y) / s,
x: 0.25 * s,
y: (up_actual.x + right.y) / s,
z: (forward.x + right.z) / s,
}
} else if up_actual.y > forward.z {
let s = 2.0 * (1.0 + up_actual.y - right.x - forward.z).sqrt();
Self {
w: (forward.x - right.z) / s,
x: (up_actual.x + right.y) / s,
y: 0.25 * s,
z: (forward.y + up_actual.z) / s,
}
} else {
let s = 2.0 * (1.0 + forward.z - right.x - up_actual.y).sqrt();
Self {
w: (right.y - up_actual.x) / s,
x: (forward.x + right.z) / s,
y: (forward.y + up_actual.z) / s,
z: 0.25 * s,
}
}
}
pub fn to_mat4(&self) -> X86Mat4 {
let xx = self.x * self.x;
let yy = self.y * self.y;
let zz = self.z * self.z;
let xy = self.x * self.y;
let xz = self.x * self.z;
let yz = self.y * self.z;
let wx = self.w * self.x;
let wy = self.w * self.y;
let wz = self.w * self.z;
X86Mat4 {
m: [
[1.0 - 2.0 * (yy + zz), 2.0 * (xy - wz), 2.0 * (xz + wy), 0.0],
[2.0 * (xy + wz), 1.0 - 2.0 * (xx + zz), 2.0 * (yz - wx), 0.0],
[2.0 * (xz - wy), 2.0 * (yz + wx), 1.0 - 2.0 * (xx + yy), 0.0],
[0.0, 0.0, 0.0, 1.0],
],
}
}
}
impl Default for X86Quat {
fn default() -> Self {
Self::identity()
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86Mat4 {
pub m: [[f32; 4]; 4],
}
impl X86Mat4 {
pub fn identity() -> Self {
let mut m = [[0.0f32; 4]; 4];
m[0][0] = 1.0;
m[1][1] = 1.0;
m[2][2] = 1.0;
m[3][3] = 1.0;
Self { m }
}
pub fn translate(pos: &X86Vec3) -> Self {
let mut r = Self::identity();
r.m[0][3] = pos.x;
r.m[1][3] = pos.y;
r.m[2][3] = pos.z;
r
}
pub fn scale(s: &X86Vec3) -> Self {
let mut r = Self::identity();
r.m[0][0] = s.x;
r.m[1][1] = s.y;
r.m[2][2] = s.z;
r
}
pub fn from_quat(q: &X86Quat) -> Self {
q.to_mat4()
}
pub fn from_trs(translation: &X86Vec3, rotation: &X86Quat, scale: &X86Vec3) -> Self {
let r = rotation.to_mat4();
Self {
m: [
[
r.m[0][0] * scale.x,
r.m[0][1] * scale.y,
r.m[0][2] * scale.z,
translation.x,
],
[
r.m[1][0] * scale.x,
r.m[1][1] * scale.y,
r.m[1][2] * scale.z,
translation.y,
],
[
r.m[2][0] * scale.x,
r.m[2][1] * scale.y,
r.m[2][2] * scale.z,
translation.z,
],
[0.0, 0.0, 0.0, 1.0],
],
}
}
pub fn perspective(fov_y: f32, aspect: f32, near: f32, far: f32) -> Self {
let f = 1.0 / (fov_y * 0.5).tan();
let nf = 1.0 / (near - far);
Self {
m: [
[f / aspect, 0.0, 0.0, 0.0],
[0.0, f, 0.0, 0.0],
[0.0, 0.0, (far + near) * nf, 2.0 * far * near * nf],
[0.0, 0.0, -1.0, 0.0],
],
}
}
pub fn ortho(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> Self {
Self {
m: [
[
2.0 / (right - left),
0.0,
0.0,
-(right + left) / (right - left),
],
[
0.0,
2.0 / (top - bottom),
0.0,
-(top + bottom) / (top - bottom),
],
[0.0, 0.0, -2.0 / (far - near), -(far + near) / (far - near)],
[0.0, 0.0, 0.0, 1.0],
],
}
}
pub fn mul(&self, other: &Self) -> Self {
let mut r = [[0.0f32; 4]; 4];
for i in 0..4 {
for j in 0..4 {
r[i][j] = self.m[i][0] * other.m[0][j]
+ self.m[i][1] * other.m[1][j]
+ self.m[i][2] * other.m[2][j]
+ self.m[i][3] * other.m[3][j];
}
}
Self { m: r }
}
pub fn transform_vec3(&self, v: &X86Vec3) -> X86Vec3 {
let x = self.m[0][0] * v.x + self.m[0][1] * v.y + self.m[0][2] * v.z + self.m[0][3];
let y = self.m[1][0] * v.x + self.m[1][1] * v.y + self.m[1][2] * v.z + self.m[1][3];
let z = self.m[2][0] * v.x + self.m[2][1] * v.y + self.m[2][2] * v.z + self.m[2][3];
X86Vec3 { x, y, z }
}
pub fn inverse(&self) -> Option<Self> {
let m = &self.m;
let mut inv = [[0.0f32; 4]; 4];
inv[0][0] =
m[1][1] * m[2][2] * m[3][3] - m[1][1] * m[2][3] * m[3][2] - m[2][1] * m[1][2] * m[3][3]
+ m[2][1] * m[1][3] * m[3][2]
+ m[3][1] * m[1][2] * m[2][3]
- m[3][1] * m[1][3] * m[2][2];
inv[1][0] = -m[1][0] * m[2][2] * m[3][3]
+ m[1][0] * m[2][3] * m[3][2]
+ m[2][0] * m[1][2] * m[3][3]
- m[2][0] * m[1][3] * m[3][2]
- m[3][0] * m[1][2] * m[2][3]
+ m[3][0] * m[1][3] * m[2][2];
inv[2][0] =
m[1][0] * m[2][1] * m[3][3] - m[1][0] * m[2][3] * m[3][1] - m[2][0] * m[1][1] * m[3][3]
+ m[2][0] * m[1][3] * m[3][1]
+ m[3][0] * m[1][1] * m[2][3]
- m[3][0] * m[1][3] * m[2][1];
inv[3][0] = -m[1][0] * m[2][1] * m[3][2]
+ m[1][0] * m[2][2] * m[3][1]
+ m[2][0] * m[1][1] * m[3][2]
- m[2][0] * m[1][2] * m[3][1]
- m[3][0] * m[1][1] * m[2][2]
+ m[3][0] * m[1][2] * m[2][1];
let det =
m[0][0] * inv[0][0] + m[0][1] * inv[1][0] + m[0][2] * inv[2][0] + m[0][3] * inv[3][0];
if det.abs() < 1e-10 {
return None;
}
let det_inv = 1.0 / det;
inv[0][1] = -m[0][1] * m[2][2] * m[3][3]
+ m[0][1] * m[2][3] * m[3][2]
+ m[2][1] * m[0][2] * m[3][3]
- m[2][1] * m[0][3] * m[3][2]
- m[3][1] * m[0][2] * m[2][3]
+ m[3][1] * m[0][3] * m[2][2];
inv[1][1] =
m[0][0] * m[2][2] * m[3][3] - m[0][0] * m[2][3] * m[3][2] - m[2][0] * m[0][2] * m[3][3]
+ m[2][0] * m[0][3] * m[3][2]
+ m[3][0] * m[0][2] * m[2][3]
- m[3][0] * m[0][3] * m[2][2];
inv[2][1] = -m[0][0] * m[2][1] * m[3][3]
+ m[0][0] * m[2][3] * m[3][1]
+ m[2][0] * m[0][1] * m[3][3]
- m[2][0] * m[0][3] * m[3][1]
- m[3][0] * m[0][1] * m[2][3]
+ m[3][0] * m[0][3] * m[2][1];
inv[3][1] =
m[0][0] * m[2][1] * m[3][2] - m[0][0] * m[2][2] * m[3][1] - m[2][0] * m[0][1] * m[3][2]
+ m[2][0] * m[0][2] * m[3][1]
+ m[3][0] * m[0][1] * m[2][2]
- m[3][0] * m[0][2] * m[2][1];
inv[0][2] =
m[0][1] * m[1][2] * m[3][3] - m[0][1] * m[1][3] * m[3][2] - m[1][1] * m[0][2] * m[3][3]
+ m[1][1] * m[0][3] * m[3][2]
+ m[3][1] * m[0][2] * m[1][3]
- m[3][1] * m[0][3] * m[1][2];
inv[1][2] = -m[0][0] * m[1][2] * m[3][3]
+ m[0][0] * m[1][3] * m[3][2]
+ m[1][0] * m[0][2] * m[3][3]
- m[1][0] * m[0][3] * m[3][2]
- m[3][0] * m[0][2] * m[1][3]
+ m[3][0] * m[0][3] * m[1][2];
inv[2][2] =
m[0][0] * m[1][1] * m[3][3] - m[0][0] * m[1][3] * m[3][1] - m[1][0] * m[0][1] * m[3][3]
+ m[1][0] * m[0][3] * m[3][1]
+ m[3][0] * m[0][1] * m[1][3]
- m[3][0] * m[0][3] * m[1][1];
inv[3][2] = -m[0][0] * m[1][1] * m[3][2]
+ m[0][0] * m[1][2] * m[3][1]
+ m[1][0] * m[0][1] * m[3][2]
- m[1][0] * m[0][2] * m[3][1]
- m[3][0] * m[0][1] * m[1][2]
+ m[3][0] * m[0][2] * m[1][1];
inv[0][3] = -m[0][1] * m[1][2] * m[2][3]
+ m[0][1] * m[1][3] * m[2][2]
+ m[1][1] * m[0][2] * m[2][3]
- m[1][1] * m[0][3] * m[2][2]
- m[2][1] * m[0][2] * m[1][3]
+ m[2][1] * m[0][3] * m[1][2];
inv[1][3] =
m[0][0] * m[1][2] * m[2][3] - m[0][0] * m[1][3] * m[2][2] - m[1][0] * m[0][2] * m[2][3]
+ m[1][0] * m[0][3] * m[2][2]
+ m[2][0] * m[0][2] * m[1][3]
- m[2][0] * m[0][3] * m[1][2];
inv[2][3] = -m[0][0] * m[1][1] * m[2][3]
+ m[0][0] * m[1][3] * m[2][1]
+ m[1][0] * m[0][1] * m[2][3]
- m[1][0] * m[0][3] * m[2][1]
- m[2][0] * m[0][1] * m[1][3]
+ m[2][0] * m[0][3] * m[1][1];
inv[3][3] =
m[0][0] * m[1][1] * m[2][2] - m[0][0] * m[1][2] * m[2][1] - m[1][0] * m[0][1] * m[2][2]
+ m[1][0] * m[0][2] * m[2][1]
+ m[2][0] * m[0][1] * m[1][2]
- m[2][0] * m[0][2] * m[1][1];
for i in 0..4 {
for j in 0..4 {
inv[i][j] *= det_inv;
}
}
Some(Self { m: inv })
}
}
impl Default for X86Mat4 {
fn default() -> Self {
Self::identity()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct X86FixedQ16(i32);
impl X86FixedQ16 {
pub const ONE: Self = Self(65536);
pub const ZERO: Self = Self(0);
pub fn from_float(f: f32) -> Self {
Self((f * 65536.0) as i32)
}
pub fn to_float(&self) -> f32 {
self.0 as f32 / 65536.0
}
pub fn from_int(i: i32) -> Self {
Self(i << 16)
}
pub fn to_int(&self) -> i32 {
self.0 >> 16
}
pub fn add(&self, other: Self) -> Self {
Self(self.0 + other.0)
}
pub fn sub(&self, other: Self) -> Self {
Self(self.0 - other.0)
}
pub fn mul(&self, other: Self) -> Self {
Self(((self.0 as i64 * other.0 as i64) >> 16) as i32)
}
pub fn div(&self, other: Self) -> Self {
Self(((self.0 as i64) << 16 / other.0 as i64) as i32)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct X86FixedQ8(i32);
impl X86FixedQ8 {
pub const ONE: Self = Self(1 << 24);
pub fn from_float(f: f32) -> Self {
Self((f * 16777216.0) as i32)
}
pub fn to_float(&self) -> f32 {
self.0 as f32 / 16777216.0
}
}
#[derive(Debug, Clone)]
pub struct X86Interpolation;
impl X86Interpolation {
pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
a + (b - a) * t.clamp(0.0, 1.0)
}
pub fn lerp_vec3(a: &X86Vec3, b: &X86Vec3, t: f32) -> X86Vec3 {
a.lerp(b, t)
}
pub fn smoothstep(edge0: f32, edge1: f32, x: f32) -> f32 {
let t = ((x - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
t * t * (3.0 - 2.0 * t)
}
pub fn smootherstep(edge0: f32, edge1: f32, x: f32) -> f32 {
let t = ((x - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
}
pub fn cubic_hermite(p0: f32, m0: f32, p1: f32, m1: f32, t: f32) -> f32 {
let t2 = t * t;
let t3 = t2 * t;
(2.0 * t3 - 3.0 * t2 + 1.0) * p0
+ (t3 - 2.0 * t2 + t) * m0
+ (-2.0 * t3 + 3.0 * t2) * p1
+ (t3 - t2) * m1
}
pub fn catmull_rom(p0: f32, p1: f32, p2: f32, p3: f32, t: f32) -> f32 {
0.5 * ((2.0 * p1)
+ (-p0 + p2) * t
+ (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t * t
+ (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t * t * t)
}
pub fn catmull_rom_vec3(
p0: &X86Vec3,
p1: &X86Vec3,
p2: &X86Vec3,
p3: &X86Vec3,
t: f32,
) -> X86Vec3 {
X86Vec3 {
x: Self::catmull_rom(p0.x, p1.x, p2.x, p3.x, t),
y: Self::catmull_rom(p0.y, p1.y, p2.y, p3.y, t),
z: Self::catmull_rom(p0.z, p1.z, p2.z, p3.z, t),
}
}
}
#[derive(Debug, Clone)]
pub struct X86GameRandom {
pub state: u64,
pub inc: u64,
}
impl X86GameRandom {
pub fn pcg(seed: u64) -> Self {
Self {
state: 0,
inc: (seed << 1) | 1,
}
}
pub fn pcg_next_u32(&mut self) -> u32 {
let old_state = self.state;
self.state = old_state
.wrapping_mul(6364136223846793005)
.wrapping_add(self.inc | 1);
let xor_shifted = (((old_state >> 18) ^ old_state) >> 27) as u32;
let rot = (old_state >> 59) as u32;
(xor_shifted >> rot) | (xor_shifted << ((-(rot as i32)) & 31))
}
pub fn pcg_next_f32(&mut self) -> f32 {
(self.pcg_next_u32() as f32) / (u32::MAX as f32)
}
pub fn pcg_range(&mut self, min: f32, max: f32) -> f32 {
min + self.pcg_next_f32() * (max - min)
}
pub fn xorshift128(state: [u64; 2]) -> Self {
Self {
state: state[0],
inc: state[1],
}
}
pub fn xorshift_next_u64(&mut self) -> u64 {
let mut s1 = self.state;
let s0 = self.inc;
self.state = s0;
s1 ^= s1 << 23;
self.inc = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26);
self.inc.wrapping_add(s0)
}
pub fn xorshift_next_f32(&mut self) -> f32 {
(self.xorshift_next_u64() as f32) / (u64::MAX as f32)
}
}
impl Default for X86GameRandom {
fn default() -> Self {
Self::pcg(0x853c49e6748fea9b)
}
}
#[derive(Debug, Clone)]
pub struct X86GameMath {
pub simd_level: X86GameSimdLevel,
pub fast_math: X86FastMathConfig,
pub use_fixed_point: bool,
pub optimize_trig: bool,
pub matrix_major: X86MatrixMajor,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86MatrixMajor {
ColumnMajor,
RowMajor,
}
impl X86GameMath {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
fast_math: X86FastMathConfig::default(),
use_fixed_point: false,
optimize_trig: true,
matrix_major: X86MatrixMajor::ColumnMajor,
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.fast_math.use_fast_math {
flags.push("-ffast-math".into());
}
if self.fast_math.reciprocal_sqrt {
flags.push("-mrecip".into());
flags.push("-mrecip=sqrtf,rsqrtf,vec-sqrtf,vec-rsqrtf".into());
}
if self.fast_math.flush_denormals {
flags.push("-ffp-contract=fast".into());
}
flags
}
pub fn describe(&self) -> String {
format!(
"math(simd={}, fast={}, fixed_pt={})",
self.simd_level, self.fast_math.use_fast_math, self.use_fixed_point
)
}
pub fn fast_rsqrt_code(&self) -> String {
let mut code = String::from("static inline float fast_rsqrt(float x) {\n");
match self.simd_level {
X86GameSimdLevel::SSE42 | X86GameSimdLevel::AVX2 => {
code.push_str(" __m128 v = _mm_set_ss(x);\n");
code.push_str(" v = _mm_rsqrt_ss(v);\n");
code.push_str(" return _mm_cvtss_f32(v);\n");
}
_ => {
code.push_str(" long i; float x2, y;\n");
code.push_str(" x2 = x * 0.5f;\n");
code.push_str(" y = x;\n");
code.push_str(" i = *(long*)&y;\n");
code.push_str(" i = 0x5f3759df - (i >> 1);\n");
code.push_str(" y = *(float*)&i;\n");
code.push_str(" y = y * (1.5f - (x2 * y * y));\n");
code.push_str(" return y;\n");
}
}
code.push_str("}\n");
code
}
pub fn fast_sincos_code(&self) -> String {
r#"// Fast approximate sin/cos for game use
static inline float fast_sin(float x) {
// Range reduce to [-PI, PI]
const float PI = 3.14159265358979323846f;
const float B = 4.0f / PI;
const float C = -4.0f / (PI * PI);
float y = B * x + C * x * (x < 0 ? -x : x);
const float P = 0.225f;
return P * (y * (y < 0 ? -y : y) - y) + y;
}
static inline float fast_cos(float x) {
return fast_sin(x + 1.5707963267948966f); // PI/2
}
"#
.to_string()
}
pub fn quat_slerp_code(&self) -> String {
let mut code = String::from("static inline void quat_slerp_simd(float* r, const float* a, const float* b, float t) {\n");
match self.simd_level {
X86GameSimdLevel::SSE42 | X86GameSimdLevel::AVX2 => {
code.push_str(" __m128 qa = _mm_load_ps(a);\n");
code.push_str(" __m128 qb = _mm_load_ps(b);\n");
code.push_str(" float cos_theta = _mm_cvtss_f32(_mm_dp_ps(qa, qb, 0xf1));\n");
code.push_str(" if (cos_theta < 0.0f) { qb = _mm_sub_ps(_mm_setzero_ps(), qb); cos_theta = -cos_theta; }\n");
code.push_str(" __m128 result;\n");
code.push_str(" if (cos_theta > 0.9995f) {\n");
code.push_str(" result = _mm_add_ps(_mm_mul_ps(qa, _mm_set1_ps(1.0f-t)), _mm_mul_ps(qb, _mm_set1_ps(t)));\n");
code.push_str(" result = _mm_mul_ps(result, _mm_rsqrt_ps(_mm_dp_ps(result, result, 0xff)));\n");
code.push_str(" } else {\n");
code.push_str(" float theta = acosf(cos_theta);\n");
code.push_str(" float sin_theta = sinf(theta);\n");
code.push_str(" float wa = sinf((1.0f-t)*theta) / sin_theta;\n");
code.push_str(" float wb = sinf(t*theta) / sin_theta;\n");
code.push_str(" result = _mm_add_ps(_mm_mul_ps(qa, _mm_set1_ps(wa)), _mm_mul_ps(qb, _mm_set1_ps(wb)));\n");
code.push_str(" }\n");
code.push_str(" _mm_store_ps(r, result);\n");
}
_ => {
code.push_str(" // Scalar slerp\n");
code.push_str(" r[0] = a[0]; r[1] = a[1]; r[2] = a[2]; r[3] = a[3];\n");
code.push_str(" // (simplified for brevity; full slerp above for SSE)\n");
}
}
code.push_str("}\n");
code
}
}
impl Default for X86GameMath {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86AABB {
pub min: X86Vec3,
pub max: X86Vec3,
}
impl X86AABB {
pub fn new(min: X86Vec3, max: X86Vec3) -> Self {
Self { min, max }
}
pub fn center(&self) -> X86Vec3 {
self.min.add(&self.max).scale(0.5)
}
pub fn extents(&self) -> X86Vec3 {
self.max.sub(&self.min).scale(0.5)
}
pub fn contains(&self, point: &X86Vec3) -> bool {
point.x >= self.min.x
&& point.x <= self.max.x
&& point.y >= self.min.y
&& point.y <= self.max.y
&& point.z >= self.min.z
&& point.z <= self.max.z
}
pub fn intersects(&self, other: &Self) -> bool {
self.min.x <= other.max.x
&& self.max.x >= other.min.x
&& self.min.y <= other.max.y
&& self.max.y >= other.min.y
&& self.min.z <= other.max.z
&& self.max.z >= other.min.z
}
pub fn expand(&self, amount: f32) -> Self {
Self {
min: self.min.sub(&X86Vec3::new(amount, amount, amount)),
max: self.max.add(&X86Vec3::new(amount, amount, amount)),
}
}
pub fn surface_area(&self) -> f32 {
let d = self.max.sub(&self.min);
2.0 * (d.x * d.y + d.y * d.z + d.z * d.x)
}
}
impl Default for X86AABB {
fn default() -> Self {
Self {
min: X86Vec3::zero(),
max: X86Vec3::zero(),
}
}
}
#[derive(Debug, Clone)]
pub struct X86OBB {
pub center: X86Vec3,
pub extents: X86Vec3,
pub orientation: X86Quat,
}
impl X86OBB {
pub fn new(center: X86Vec3, extents: X86Vec3, orientation: X86Quat) -> Self {
Self {
center,
extents,
orientation,
}
}
pub fn intersects_obb(&self, other: &Self) -> bool {
let a = self.axes();
let b = other.axes();
let axes: Vec<X86Vec3> = [
a[0],
a[1],
a[2],
b[0],
b[1],
b[2],
a[0].cross(&b[0]),
a[0].cross(&b[1]),
a[0].cross(&b[2]),
a[1].cross(&b[0]),
a[1].cross(&b[1]),
a[1].cross(&b[2]),
a[2].cross(&b[0]),
a[2].cross(&b[1]),
a[2].cross(&b[2]),
]
.into_iter()
.filter(|v| v.length_sq() > 1e-10)
.collect();
for axis in &axes {
let ax = axis.normalize();
let (min_a, max_a) = self.project_onto(&ax);
let (min_b, max_b) = other.project_onto(&ax);
if max_a < min_b || max_b < min_a {
return false;
}
}
true
}
fn axes(&self) -> [X86Vec3; 3] {
let m = self.orientation.to_mat4().m;
[
X86Vec3::new(m[0][0], m[1][0], m[2][0]),
X86Vec3::new(m[0][1], m[1][1], m[2][1]),
X86Vec3::new(m[0][2], m[1][2], m[2][2]),
]
}
fn project_onto(&self, axis: &X86Vec3) -> (f32, f32) {
let a = self.axes();
let c = self.center.dot(axis);
let r = self.extents.x * a[0].dot(axis).abs()
+ self.extents.y * a[1].dot(axis).abs()
+ self.extents.z * a[2].dot(axis).abs();
(c - r, c + r)
}
pub fn to_aabb(&self) -> X86AABB {
let a = self.axes();
let mut min = X86Vec3::new(f32::MAX, f32::MAX, f32::MAX);
let mut max = X86Vec3::new(f32::MIN, f32::MIN, f32::MIN);
for ix in &[-1.0_f32, 1.0_f32] {
for iy in &[-1.0_f32, 1.0_f32] {
for iz in &[-1.0_f32, 1.0_f32] {
let corner = self
.center
.add(&a[0].scale(self.extents.x * ix))
.add(&a[1].scale(self.extents.y * iy))
.add(&a[2].scale(self.extents.z * iz));
min.x = min.x.min(corner.x);
min.y = min.y.min(corner.y);
min.z = min.z.min(corner.z);
max.x = max.x.max(corner.x);
max.y = max.y.max(corner.y);
max.z = max.z.max(corner.z);
}
}
}
X86AABB { min, max }
}
pub fn contains(&self, point: &X86Vec3) -> bool {
let local = point.sub(&self.center);
let a = self.axes();
for i in 0..3 {
let proj = local.dot(&a[i]);
let ext = match i {
0 => self.extents.x,
1 => self.extents.y,
_ => self.extents.z,
};
if proj.abs() > ext + 1e-6 {
return false;
}
}
true
}
pub fn closest_point(&self, point: &X86Vec3) -> X86Vec3 {
let local = point.sub(&self.center);
let a = self.axes();
let mut result = self.center;
let exts = [self.extents.x, self.extents.y, self.extents.z];
for i in 0..3 {
let mut d = local.dot(&a[i]);
d = d.clamp(-exts[i], exts[i]);
result = result.add(&a[i].scale(d));
}
result
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86Sphere {
pub center: X86Vec3,
pub radius: f32,
}
impl X86Sphere {
pub fn new(center: X86Vec3, radius: f32) -> Self {
Self { center, radius }
}
pub fn contains(&self, point: &X86Vec3) -> bool {
point.sub(&self.center).length_sq() <= self.radius * self.radius
}
pub fn intersects_sphere(&self, other: &Self) -> bool {
let dist_sq = self.center.sub(&other.center).length_sq();
let r_sum = self.radius + other.radius;
dist_sq <= r_sum * r_sum
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86Capsule {
pub a: X86Vec3,
pub b: X86Vec3,
pub radius: f32,
}
impl X86Capsule {
pub fn new(a: X86Vec3, b: X86Vec3, radius: f32) -> Self {
Self { a, b, radius }
}
pub fn closest_point(&self, point: &X86Vec3) -> X86Vec3 {
let ab = self.b.sub(&self.a);
let t = point.sub(&self.a).dot(&ab) / ab.dot(&ab);
let t = t.clamp(0.0, 1.0);
self.a.add(&ab.scale(t))
}
}
#[derive(Debug, Clone)]
pub struct X86ConvexHull {
pub vertices: Vec<X86Vec3>,
pub faces: Vec<[usize; 3]>,
}
impl X86ConvexHull {
pub fn new(vertices: Vec<X86Vec3>) -> Self {
let faces = Vec::new();
Self { vertices, faces }
}
pub fn support_point(&self, direction: &X86Vec3) -> X86Vec3 {
let mut best = self.vertices[0];
let mut best_dot = best.dot(direction);
for v in &self.vertices[1..] {
let d = v.dot(direction);
if d > best_dot {
best_dot = d;
best = *v;
}
}
best
}
}
#[derive(Debug, Clone)]
pub struct X86GJK {
pub max_iterations: usize,
pub epsilon: f32,
pub simplex: Vec<X86Vec3>,
}
impl X86GJK {
pub fn new() -> Self {
Self {
max_iterations: 32,
epsilon: 1e-6,
simplex: Vec::with_capacity(4),
}
}
pub fn distance(
&mut self,
shape_a: &X86ConvexHull,
shape_b: &X86ConvexHull,
) -> Option<(f32, X86Vec3, X86Vec3)> {
self.simplex.clear();
let dir = X86Vec3::new(1.0, 0.0, 0.0);
let a = shape_a.support_point(&dir);
let b = shape_b.support_point(&dir.scale(-1.0));
let mut v = a.sub(&b);
self.simplex.push(v);
let mut dir = v.scale(-1.0);
for _ in 0..self.max_iterations {
let a = shape_a.support_point(&dir);
let b = shape_b.support_point(&dir.scale(-1.0));
let w = a.sub(&b);
let v_dot_w = v.dot(&w);
if v_dot_w > 0.0 && v.dot(&dir) <= v_dot_w + self.epsilon {
return None; }
self.simplex.push(w);
match self.simplex.len() {
2 => {
let ao = self.simplex[0].scale(-1.0);
let ab = self.simplex[1].sub(&self.simplex[0]);
if ao.dot(&ab) > 0.0 {
dir = ao.sub(&ab.scale(ao.dot(&ab) / ab.dot(&ab)));
} else {
dir = ao;
}
}
3 => {
let a = self.simplex[2];
let b = self.simplex[1];
let c = self.simplex[0];
let ao = a.scale(-1.0);
let ab = b.sub(&a);
let ac = c.sub(&a);
let abc = ab.cross(&ac);
if abc.cross(&ac).dot(&ao) > 0.0 {
if ac.dot(&ao) > 0.0 {
self.simplex = vec![a, c];
dir = ac.cross(&ao).cross(&ac);
} else {
if ab.dot(&ao) > 0.0 {
self.simplex = vec![a, b];
dir = ab.cross(&ao).cross(&ab);
} else {
self.simplex = vec![a];
dir = ao;
}
}
} else {
if ab.cross(&abc).dot(&ao) > 0.0 {
self.simplex = vec![a, b];
dir = ab.cross(&ao).cross(&ab);
} else {
if abc.dot(&ao) > 0.0 {
dir = abc;
} else {
self.simplex = vec![a, c];
dir = abc.scale(-1.0);
}
}
}
}
4 => {
let (closest, _) = self.epa_distance(shape_a, shape_b);
return closest;
}
_ => {}
}
v = w;
}
None
}
fn epa_distance(
&self,
_shape_a: &X86ConvexHull,
_shape_b: &X86ConvexHull,
) -> (Option<(f32, X86Vec3, X86Vec3)>, Vec<X86Vec3>) {
let depth = 0.0;
let normal = X86Vec3::new(0.0, 1.0, 0.0);
let contact = X86Vec3::zero();
(Some((depth, contact, normal)), Vec::new())
}
pub fn intersect(&mut self, shape_a: &X86ConvexHull, shape_b: &X86ConvexHull) -> bool {
self.distance(shape_a, shape_b).is_some()
}
}
impl Default for X86GJK {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86EPA {
pub max_iterations: usize,
pub tolerance: f32,
pub max_faces: usize,
}
impl X86EPA {
pub fn new() -> Self {
Self {
max_iterations: 64,
tolerance: 1e-4,
max_faces: 256,
}
}
pub fn compute_penetration(
&self,
simplex: &[X86Vec3],
_a: &X86ConvexHull,
_b: &X86ConvexHull,
) -> Option<(f32, X86Vec3)> {
if simplex.len() < 4 {
return None;
}
Some((0.0, X86Vec3::new(0.0, 1.0, 0.0)))
}
}
impl Default for X86EPA {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86Ray {
pub origin: X86Vec3,
pub direction: X86Vec3,
}
impl X86Ray {
pub fn new(origin: X86Vec3, direction: X86Vec3) -> Self {
Self {
origin,
direction: direction.normalize(),
}
}
pub fn point_at(&self, t: f32) -> X86Vec3 {
self.origin.add(&self.direction.scale(t))
}
}
#[derive(Debug, Clone, Copy)]
pub struct X86RayHit {
pub hit: bool,
pub distance: f32,
pub point: X86Vec3,
pub normal: X86Vec3,
pub triangle_index: usize,
}
impl Default for X86RayHit {
fn default() -> Self {
Self {
hit: false,
distance: f32::MAX,
point: X86Vec3::zero(),
normal: X86Vec3::up(),
triangle_index: 0,
}
}
}
#[derive(Debug, Clone)]
pub struct X86RayCaster;
impl X86RayCaster {
pub fn ray_vs_triangle(ray: &X86Ray, v0: &X86Vec3, v1: &X86Vec3, v2: &X86Vec3) -> X86RayHit {
let edge1 = v1.sub(v0);
let edge2 = v2.sub(v0);
let h = ray.direction.cross(&edge2);
let a = edge1.dot(&h);
if a.abs() < 1e-7 {
return X86RayHit::default();
}
let f = 1.0 / a;
let s = ray.origin.sub(v0);
let u = f * s.dot(&h);
if u < 0.0 || u > 1.0 {
return X86RayHit::default();
}
let q = s.cross(&edge1);
let v = f * ray.direction.dot(&q);
if v < 0.0 || u + v > 1.0 {
return X86RayHit::default();
}
let t = f * edge2.dot(&q);
if t > 1e-7 {
X86RayHit {
hit: true,
distance: t,
point: ray.point_at(t),
normal: edge1.cross(&edge2).normalize(),
triangle_index: 0,
}
} else {
X86RayHit::default()
}
}
pub fn ray_vs_aabb(ray: &X86Ray, aabb: &X86AABB) -> bool {
let mut tmin = f32::NEG_INFINITY;
let mut tmax = f32::INFINITY;
let inv_dir = X86Vec3::new(
1.0 / ray.direction.x,
1.0 / ray.direction.y,
1.0 / ray.direction.z,
);
let t1 = (aabb.min.x - ray.origin.x) * inv_dir.x;
let t2 = (aabb.max.x - ray.origin.x) * inv_dir.x;
tmin = tmin.max(t1.min(t2));
tmax = tmax.min(t1.max(t2));
let t1 = (aabb.min.y - ray.origin.y) * inv_dir.y;
let t2 = (aabb.max.y - ray.origin.y) * inv_dir.y;
tmin = tmin.max(t1.min(t2));
tmax = tmax.min(t1.max(t2));
let t1 = (aabb.min.z - ray.origin.z) * inv_dir.z;
let t2 = (aabb.max.z - ray.origin.z) * inv_dir.z;
tmin = tmin.max(t1.min(t2));
tmax = tmax.min(t1.max(t2));
tmax > tmin.max(0.0)
}
pub fn ray_vs_sphere(ray: &X86Ray, sphere: &X86Sphere) -> Option<f32> {
let oc = ray.origin.sub(&sphere.center);
let a = ray.direction.dot(&ray.direction);
let b = 2.0 * oc.dot(&ray.direction);
let c = oc.dot(&oc) - sphere.radius * sphere.radius;
let disc = b * b - 4.0 * a * c;
if disc < 0.0 {
return None;
}
let t = (-b - disc.sqrt()) / (2.0 * a);
if t > 0.0 {
Some(t)
} else {
None
}
}
}
#[derive(Debug, Clone)]
pub struct X86RigidBody {
pub position: X86Vec3,
pub orientation: X86Quat,
pub linear_velocity: X86Vec3,
pub angular_velocity: X86Vec3,
pub mass: f32,
pub inv_mass: f32,
pub inertia: X86Vec3,
pub inv_inertia: X86Vec3,
pub force_accumulator: X86Vec3,
pub torque_accumulator: X86Vec3,
pub linear_damping: f32,
pub angular_damping: f32,
pub is_kinematic: bool,
pub restitution: f32,
pub friction: f32,
}
impl X86RigidBody {
pub fn new(position: X86Vec3, mass: f32) -> Self {
let inv_mass = if mass > 0.0 { 1.0 / mass } else { 0.0 };
let inertia = if mass > 0.0 {
X86Vec3::new(mass, mass, mass)
} else {
X86Vec3::one()
};
let inv_inertia = if mass > 0.0 {
X86Vec3::new(inv_mass, inv_mass, inv_mass)
} else {
X86Vec3::zero()
};
Self {
position,
orientation: X86Quat::identity(),
linear_velocity: X86Vec3::zero(),
angular_velocity: X86Vec3::zero(),
mass,
inv_mass,
inertia,
inv_inertia,
force_accumulator: X86Vec3::zero(),
torque_accumulator: X86Vec3::zero(),
linear_damping: 0.98,
angular_damping: 0.98,
is_kinematic: false,
restitution: 0.2,
friction: 0.5,
}
}
pub fn apply_force(&mut self, force: &X86Vec3) {
self.force_accumulator = self.force_accumulator.add(force);
}
pub fn apply_force_at_point(&mut self, force: &X86Vec3, point: &X86Vec3) {
self.force_accumulator = self.force_accumulator.add(force);
let r = point.sub(&self.position);
self.torque_accumulator = self.torque_accumulator.add(&r.cross(force));
}
pub fn apply_impulse(&mut self, impulse: &X86Vec3, contact_point: &X86Vec3) {
if self.is_kinematic {
return;
}
self.linear_velocity = self.linear_velocity.add(&impulse.scale(self.inv_mass));
let r = contact_point.sub(&self.position);
let angular_impulse = r.cross(impulse);
self.angular_velocity = self.angular_velocity.add(&X86Vec3::new(
angular_impulse.x * self.inv_inertia.x,
angular_impulse.y * self.inv_inertia.y,
angular_impulse.z * self.inv_inertia.z,
));
}
pub fn integrate(&mut self, dt: f32) {
if self.is_kinematic {
return;
}
let accel = self.force_accumulator.scale(self.inv_mass);
self.linear_velocity = self.linear_velocity.add(&accel.scale(dt));
self.linear_velocity = self.linear_velocity.scale(self.linear_damping);
self.position = self.position.add(&self.linear_velocity.scale(dt));
let ang_accel = X86Vec3::new(
self.torque_accumulator.x * self.inv_inertia.x,
self.torque_accumulator.y * self.inv_inertia.y,
self.torque_accumulator.z * self.inv_inertia.z,
);
self.angular_velocity = self.angular_velocity.add(&ang_accel.scale(dt));
self.angular_velocity = self.angular_velocity.scale(self.angular_damping);
let angle = self.angular_velocity.length() * dt;
if angle > 1e-6 {
let axis = self.angular_velocity.normalize();
let dq = X86Quat::from_axis_angle(&axis, angle);
self.orientation = dq.mul(&self.orientation);
}
self.force_accumulator = X86Vec3::zero();
self.torque_accumulator = X86Vec3::zero();
}
}
#[derive(Debug, Clone)]
pub enum X86Constraint {
Contact {
body_a: usize,
body_b: usize,
contact_point: X86Vec3,
normal: X86Vec3,
penetration: f32,
friction: f32,
restitution: f32,
},
Distance {
body_a: usize,
body_b: usize,
anchor_a: X86Vec3,
anchor_b: X86Vec3,
min_distance: f32,
max_distance: f32,
},
Hinge {
body_a: usize,
body_b: usize,
pivot: X86Vec3,
axis: X86Vec3,
min_angle: f32,
max_angle: f32,
},
BallSocket {
body_a: usize,
body_b: usize,
pivot_a: X86Vec3,
pivot_b: X86Vec3,
},
Fixed {
body_a: usize,
body_b: usize,
anchor: X86Vec3,
},
}
#[derive(Debug, Clone)]
pub struct X86ConstraintSolver {
pub iterations: usize,
pub baumgarte_factor: f32,
pub allowed_penetration: f32,
}
impl X86ConstraintSolver {
pub fn new() -> Self {
Self {
iterations: 10,
baumgarte_factor: 0.2,
allowed_penetration: 0.01,
}
}
pub fn solve(&self, constraints: &[X86Constraint], bodies: &mut [X86RigidBody], dt: f32) {
for _ in 0..self.iterations {
for c in constraints {
match c {
X86Constraint::Contact {
body_a,
body_b,
contact_point,
normal,
penetration,
friction: _,
restitution,
} => {
let a = &bodies[*body_a];
let b = &bodies[*body_b];
let r_a = contact_point.sub(&a.position);
let r_b = contact_point.sub(&b.position);
let rel_vel = b
.linear_velocity
.add(&b.angular_velocity.cross(&r_b))
.sub(&a.linear_velocity.add(&a.angular_velocity.cross(&r_a)));
let contact_vel = rel_vel.dot(normal);
if contact_vel > 0.0 {
continue;
}
let inv_mass_sum = a.inv_mass + b.inv_mass;
let j_mag = -(1.0 + *restitution) * contact_vel / inv_mass_sum;
let impulse = normal.scale(j_mag);
bodies[*body_a].apply_impulse(&impulse, contact_point);
let neg_impulse = impulse.scale(-1.0);
bodies[*body_b].apply_impulse(&neg_impulse, contact_point);
if *penetration > self.allowed_penetration {
let bias = self.baumgarte_factor / dt
* (penetration - self.allowed_penetration).max(0.0);
let correction = normal.scale(inv_mass_sum * bias);
let inv_mass_a = bodies[*body_a].inv_mass;
let pos_a = bodies[*body_a].position;
bodies[*body_a].position = pos_a.add(&correction.scale(inv_mass_a));
let neg_corr = correction.scale(-1.0);
let inv_mass_b = bodies[*body_b].inv_mass;
let pos_b = bodies[*body_b].position;
bodies[*body_b].position = pos_b.add(&neg_corr.scale(inv_mass_b));
}
}
_ => { }
}
}
}
}
}
impl Default for X86ConstraintSolver {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub enum X86BroadphaseAlgorithm {
SweepAndPrune,
BVH,
SpatialGrid { cell_size: f32 },
}
#[derive(Debug, Clone)]
pub struct X86SweepAndPrune {
pub endpoints: Vec<(f32, usize, bool)>, pub active: HashSet<usize>,
}
impl X86SweepAndPrune {
pub fn new() -> Self {
Self {
endpoints: Vec::new(),
active: HashSet::new(),
}
}
pub fn find_pairs(&mut self, aabbs: &[(usize, X86AABB)]) -> Vec<(usize, usize)> {
self.endpoints.clear();
self.active.clear();
for (id, aabb) in aabbs {
self.endpoints.push((aabb.min.x, *id, true));
self.endpoints.push((aabb.max.x, *id, false));
}
self.endpoints
.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(std::cmp::Ordering::Equal));
let mut pairs = Vec::new();
self.active.clear();
for &(_coord, id, is_min) in &self.endpoints {
if is_min {
for &active_id in &self.active {
pairs.push((id, active_id));
}
self.active.insert(id);
} else {
self.active.remove(&id);
}
}
pairs
}
}
impl Default for X86SweepAndPrune {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86BVH {
pub nodes: Vec<X86BVHNode>,
pub root: Option<usize>,
}
#[derive(Debug, Clone)]
pub struct X86BVHNode {
pub aabb: X86AABB,
pub left: Option<usize>,
pub right: Option<usize>,
pub body_index: Option<usize>,
pub parent: Option<usize>,
}
impl X86BVH {
pub fn new() -> Self {
Self {
nodes: Vec::new(),
root: None,
}
}
pub fn build(&mut self, bodies: &[(usize, X86AABB)]) {
self.nodes.clear();
for (id, aabb) in bodies {
self.nodes.push(X86BVHNode {
aabb: *aabb,
left: None,
right: None,
body_index: Some(*id),
parent: None,
});
}
self.root = if !self.nodes.is_empty() {
Some(0)
} else {
None
};
}
pub fn query(&self, aabb: &X86AABB) -> Vec<usize> {
let mut results = Vec::new();
if let Some(root) = self.root {
self.query_node(root, aabb, &mut results);
}
results
}
fn query_node(&self, node_idx: usize, aabb: &X86AABB, results: &mut Vec<usize>) {
let node = &self.nodes[node_idx];
if !node.aabb.intersects(aabb) {
return;
}
if let Some(id) = node.body_index {
results.push(id);
}
if let Some(left) = node.left {
self.query_node(left, aabb, results);
}
if let Some(right) = node.right {
self.query_node(right, aabb, results);
}
}
}
impl Default for X86BVH {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86SpatialGrid {
pub cell_size: f32,
pub cells: HashMap<(i32, i32, i32), Vec<usize>>,
}
impl X86SpatialGrid {
pub fn new(cell_size: f32) -> Self {
Self {
cell_size,
cells: HashMap::new(),
}
}
fn cell_key(&self, pos: &X86Vec3) -> (i32, i32, i32) {
(
(pos.x / self.cell_size).floor() as i32,
(pos.y / self.cell_size).floor() as i32,
(pos.z / self.cell_size).floor() as i32,
)
}
pub fn insert(&mut self, id: usize, aabb: &X86AABB) {
let min_key = self.cell_key(&aabb.min);
let max_key = self.cell_key(&aabb.max);
for x in min_key.0..=max_key.0 {
for y in min_key.1..=max_key.1 {
for z in min_key.2..=max_key.2 {
self.cells.entry((x, y, z)).or_default().push(id);
}
}
}
}
pub fn query(&self, aabb: &X86AABB) -> Vec<usize> {
let mut results = HashSet::new();
let min_key = self.cell_key(&aabb.min);
let max_key = self.cell_key(&aabb.max);
for x in min_key.0..=max_key.0 {
for y in min_key.1..=max_key.1 {
for z in min_key.2..=max_key.2 {
if let Some(ids) = self.cells.get(&(x, y, z)) {
results.extend(ids);
}
}
}
}
results.into_iter().collect()
}
}
#[derive(Debug, Clone)]
pub struct X86GamePhysicsEngine {
pub simd_level: X86GameSimdLevel,
pub use_gjk_epa: bool,
pub use_simd_narrowphase: bool,
pub broadphase: X86BroadphaseAlgorithm,
pub continuous_collision: bool,
pub max_bodies: usize,
pub substeps: usize,
}
impl X86GamePhysicsEngine {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
use_gjk_epa: true,
use_simd_narrowphase: true,
broadphase: X86BroadphaseAlgorithm::SweepAndPrune,
continuous_collision: false,
max_bodies: 4096,
substeps: 4,
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.use_simd_narrowphase {
flags.extend(self.simd_level.compiler_flags());
}
if self.continuous_collision {
flags.push("-DX86_PHYSICS_CCD".into());
}
flags
}
pub fn describe(&self) -> String {
format!(
"physics_engine(gjk={}, simd_narrow={}, bodies={})",
self.use_gjk_epa, self.use_simd_narrowphase, self.max_bodies
)
}
pub fn gjk_support_simd_code(&self) -> String {
let mut code = String::from("// SIMD-optimized GJK support function\n");
code.push_str("static inline float gjk_support_simd(\n");
code.push_str(" const float* vertices, int count, const float* dir) {\n");
match self.simd_level {
X86GameSimdLevel::SSE42 => {
code.push_str(" __m128 best_v = _mm_load_ps(vertices);\n");
code.push_str(" __m128 best_dot = _mm_dp_ps(best_v, _mm_load_ps(dir), 0x7f);\n");
code.push_str(" for (int i = 1; i < count; i++) {\n");
code.push_str(" __m128 v = _mm_load_ps(vertices + i*4);\n");
code.push_str(" __m128 d = _mm_dp_ps(v, _mm_load_ps(dir), 0x7f);\n");
code.push_str(
" if (_mm_comigt_ss(d, best_dot)) { best_v = v; best_dot = d; }\n",
);
code.push_str(" }\n");
code.push_str(" return _mm_cvtss_f32(best_dot);\n");
}
X86GameSimdLevel::AVX2 => {
code.push_str(" __m256 dir8 = _mm256_broadcast_ps((__m128*)(dir));\n");
code.push_str(" __m256 best_v = _mm256_load_ps(vertices);\n");
code.push_str(" __m256 best_dot = _mm256_dp_ps(best_v, dir8, 0xff);\n");
code.push_str(" for (int i = 2; i < count; i += 2) {\n");
code.push_str(" __m256 v = _mm256_load_ps(vertices + i*4);\n");
code.push_str(" __m256 d = _mm256_dp_ps(v, dir8, 0xff);\n");
code.push_str(" __m256 mask = _mm256_cmp_ps(d, best_dot, _CMP_GT_OQ);\n");
code.push_str(" best_v = _mm256_blendv_ps(best_v, v, mask);\n");
code.push_str(" best_dot = _mm256_max_ps(best_dot, d);\n");
code.push_str(" }\n");
}
_ => {
code.push_str(" float best = -INFINITY;\n");
code.push_str(" for (int i = 0; i < count; i++) {\n");
code.push_str(" float d = vertices[i*4]*dir[0] + vertices[i*4+1]*dir[1] + vertices[i*4+2]*dir[2];\n");
code.push_str(" if (d > best) best = d;\n");
code.push_str(" }\n");
code.push_str(" return best;\n");
}
}
code.push_str("}\n");
code
}
}
impl Default for X86GamePhysicsEngine {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ShaderLanguage {
HLSL,
GLSL,
MSL,
SPIRV,
WGSL,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ShaderTarget {
SPIRV,
DXIL,
MSLBinary,
GLSLVulkan,
WGSLBinary,
}
#[derive(Debug, Clone)]
pub struct X86ShaderCompiler {
pub source_language: X86ShaderLanguage,
pub target: X86ShaderTarget,
pub entry_point: String,
pub shader_model: X86ShaderModelVersion,
pub optimization_level: u32,
pub debug_info: bool,
pub include_dirs: Vec<PathBuf>,
pub defines: HashMap<String, String>,
pub invert_y: bool,
pub row_major: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ShaderModelVersion {
SM50,
SM60,
SM65,
Vulkan12,
Metal22,
Metal30,
WebGPU,
}
impl X86ShaderCompiler {
pub fn new() -> Self {
Self {
source_language: X86ShaderLanguage::HLSL,
target: X86ShaderTarget::SPIRV,
entry_point: "main".into(),
shader_model: X86ShaderModelVersion::SM60,
optimization_level: 3,
debug_info: false,
include_dirs: Vec::new(),
defines: HashMap::new(),
invert_y: false,
row_major: true,
}
}
pub fn dxc_compile_command(&self, source: &str, output: &str) -> Vec<String> {
let mut cmd = vec!["dxc".into(), source.into()];
cmd.push(format!("-E {}", self.entry_point));
cmd.push(format!("-T {}", self.hlsl_profile()));
if self.target == X86ShaderTarget::SPIRV {
cmd.push("-spirv".into());
}
cmd.push(format!("-Fo {}", output));
for (k, v) in &self.defines {
cmd.push(format!("-D {}={}", k, v));
}
if self.invert_y {
cmd.push("-fvk-invert-y".into());
}
if self.row_major {
cmd.push("-Zpr".into());
}
cmd
}
fn hlsl_profile(&self) -> String {
let base = match self.shader_model {
X86ShaderModelVersion::SM50 => "5_0",
X86ShaderModelVersion::SM60 => "6_0",
X86ShaderModelVersion::SM65 => "6_5",
_ => "6_0",
};
format!("vs_{}", base) }
pub fn glslang_compile_command(&self, source: &str, output: &str) -> Vec<String> {
let mut cmd = vec!["glslangValidator".into(), source.into()];
cmd.push("-V".into());
cmd.push("-o".into());
cmd.push(output.into());
if self.debug_info {
cmd.push("-g".into());
}
cmd
}
}
impl Default for X86ShaderCompiler {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86DescriptorSet {
pub set_number: u32,
pub bindings: Vec<X86DescriptorBinding>,
}
#[derive(Debug, Clone)]
pub struct X86DescriptorBinding {
pub binding: u32,
pub descriptor_type: X86DescriptorType,
pub count: u32,
pub shader_stages: X86ShaderStageFlags,
pub immutable_samplers: Vec<X86SamplerState>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86DescriptorType {
UniformBuffer,
StorageBuffer,
SampledImage,
StorageImage,
Sampler,
CombinedImageSampler,
InputAttachment,
AccelerationStructure,
}
#[derive(Debug, Clone, Default)]
pub struct X86ShaderStageFlags {
pub vertex: bool,
pub fragment: bool,
pub geometry: bool,
pub tess_control: bool,
pub tess_eval: bool,
pub compute: bool,
}
impl X86ShaderStageFlags {
pub fn all_graphics() -> Self {
Self {
vertex: true,
fragment: true,
geometry: false,
tess_control: false,
tess_eval: false,
compute: false,
}
}
pub fn all() -> Self {
Self {
vertex: true,
fragment: true,
geometry: true,
tess_control: true,
tess_eval: true,
compute: true,
}
}
}
#[derive(Debug, Clone)]
pub struct X86SamplerState {
pub mag_filter: X86FilterMode,
pub min_filter: X86FilterMode,
pub mip_filter: X86FilterMode,
pub address_u: X86AddressMode,
pub address_v: X86AddressMode,
pub address_w: X86AddressMode,
pub mip_lod_bias: f32,
pub max_anisotropy: f32,
pub compare_op: X86CompareOp,
pub min_lod: f32,
pub max_lod: f32,
pub border_color: X86BorderColor,
}
impl Default for X86SamplerState {
fn default() -> Self {
Self {
mag_filter: X86FilterMode::Linear,
min_filter: X86FilterMode::Linear,
mip_filter: X86FilterMode::Linear,
address_u: X86AddressMode::Repeat,
address_v: X86AddressMode::Repeat,
address_w: X86AddressMode::Repeat,
mip_lod_bias: 0.0,
max_anisotropy: 1.0,
compare_op: X86CompareOp::Never,
min_lod: 0.0,
max_lod: 1000.0,
border_color: X86BorderColor::Black,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86FilterMode {
Nearest,
Linear,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AddressMode {
Repeat,
MirroredRepeat,
ClampToEdge,
ClampToBorder,
MirrorClampToEdge,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CompareOp {
Never,
Less,
Equal,
LessEqual,
Greater,
NotEqual,
GreaterEqual,
Always,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BorderColor {
Black,
White,
TransparentBlack,
}
#[derive(Debug, Clone)]
pub struct X86RootSignature {
pub root_parameters: Vec<X86RootParameter>,
pub static_samplers: Vec<X86StaticSampler>,
pub flags: X86RootSignatureFlags,
}
#[derive(Debug, Clone)]
pub enum X86RootParameter {
DescriptorTable {
visibility: X86ShaderStageFlags,
ranges: Vec<X86DescriptorRange>,
},
RootConstants {
visibility: X86ShaderStageFlags,
num_values: u32,
register: u32,
space: u32,
},
RootDescriptor {
visibility: X86ShaderStageFlags,
register: u32,
space: u32,
},
}
#[derive(Debug, Clone)]
pub struct X86DescriptorRange {
pub range_type: X86DescriptorType,
pub num_descriptors: u32,
pub base_register: u32,
pub register_space: u32,
pub offset: u32,
}
#[derive(Debug, Clone)]
pub struct X86StaticSampler {
pub register: u32,
pub register_space: u32,
pub filter: X86FilterMode,
pub address_u: X86AddressMode,
pub address_v: X86AddressMode,
pub address_w: X86AddressMode,
}
#[derive(Debug, Clone, Default)]
pub struct X86RootSignatureFlags {
pub allow_input_assembler: bool,
pub deny_vertex_shader: bool,
pub deny_hull_shader: bool,
pub deny_domain_shader: bool,
pub deny_geometry_shader: bool,
pub deny_pixel_shader: bool,
pub allow_stream_output: bool,
}
#[derive(Debug, Clone)]
pub struct X86VertexLayout {
pub binding: u32,
pub stride: u32,
pub input_rate: X86VertexInputRate,
pub attributes: Vec<X86VertexAttribute>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86VertexInputRate {
Vertex,
Instance,
}
#[derive(Debug, Clone)]
pub struct X86VertexAttribute {
pub location: u32,
pub binding: u32,
pub format: X86VertexFormat,
pub offset: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86VertexFormat {
Float32,
Float32x2,
Float32x3,
Float32x4,
UInt8Normalized,
UInt8x4Normalized,
Int8,
Int8x2,
Int8x4,
UInt16,
UInt16x2,
UInt16x4,
Int16,
Int16x2,
Int16x4,
UInt32,
UInt32x2,
UInt32x3,
UInt32x4,
Int32,
Int32x2,
Int32x3,
Int32x4,
Float16x2,
Float16x4,
UInt10_10_10_2,
}
impl X86VertexFormat {
pub fn size_bytes(&self) -> u32 {
match self {
Self::Float32 | Self::UInt32 | Self::Int32 => 4,
Self::Float32x2 | Self::UInt16x2 | Self::Int16x2 | Self::Float16x2 => 4,
Self::Float32x3 => 12,
Self::Float32x4
| Self::UInt8x4Normalized
| Self::Int8x4
| Self::Int16x4
| Self::UInt16x4
| Self::Float16x4
| Self::UInt10_10_10_2 => 4,
Self::UInt8Normalized => 1,
Self::Int8 => 1,
Self::Int8x2 => 2,
Self::UInt16 | Self::Int16 => 2,
Self::UInt32x2 | Self::Int32x2 => 8,
Self::UInt32x3 | Self::Int32x3 => 12,
Self::UInt32x4 | Self::Int32x4 => 16,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86IndexFormat {
UInt16,
UInt32,
}
impl X86IndexFormat {
pub fn size_bytes(&self) -> u32 {
match self {
Self::UInt16 => 2,
Self::UInt32 => 4,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86TextureFormat {
R8Unorm,
R8SNorm,
R8UInt,
R8SInt,
R8G8Unorm,
R8G8SNorm,
R8G8UInt,
R8G8SInt,
R8G8B8A8Unorm,
R8G8B8A8SNorm,
R8G8B8A8SRGB,
B8G8R8A8Unorm,
B8G8R8A8SRGB,
R16Float,
R16Unorm,
R16UInt,
R16G16Float,
R16G16Unorm,
R16G16B16A16Float,
R16G16B16A16Unorm,
R32Float,
R32UInt,
R32SInt,
R32G32Float,
R32G32UInt,
R32G32B32Float,
R32G32B32A32Float,
R32G32B32A32UInt,
BC1RGBUnorm,
BC1RGBASRGB,
BC3Unorm,
BC3SRGB,
BC5Unorm,
BC5SNorm,
BC7Unorm,
BC7SRGB,
D16Unorm,
D24UnormS8UInt,
D32Float,
D32FloatS8UInt,
ASTC4x4,
ASTC6x6,
ASTC8x8,
}
impl X86TextureFormat {
pub fn is_compressed(&self) -> bool {
matches!(
self,
Self::BC1RGBUnorm
| Self::BC1RGBASRGB
| Self::BC3Unorm
| Self::BC3SRGB
| Self::BC5Unorm
| Self::BC5SNorm
| Self::BC7Unorm
| Self::BC7SRGB
| Self::ASTC4x4
| Self::ASTC6x6
| Self::ASTC8x8
)
}
pub fn is_depth(&self) -> bool {
matches!(
self,
Self::D16Unorm | Self::D24UnormS8UInt | Self::D32Float | Self::D32FloatS8UInt
)
}
pub fn block_size(&self) -> u32 {
match self {
Self::BC1RGBUnorm | Self::BC1RGBASRGB => 8,
Self::BC3Unorm
| Self::BC3SRGB
| Self::BC5Unorm
| Self::BC5SNorm
| Self::BC7Unorm
| Self::BC7SRGB => 16,
Self::ASTC4x4 | Self::ASTC6x6 | Self::ASTC8x8 => 16,
_ => 0,
}
}
}
#[derive(Debug, Clone)]
pub struct X86RenderPass {
pub name: String,
pub attachments: Vec<X86RenderPassAttachment>,
pub subpasses: Vec<X86Subpass>,
pub dependencies: Vec<X86SubpassDependency>,
}
#[derive(Debug, Clone)]
pub struct X86RenderPassAttachment {
pub format: X86TextureFormat,
pub samples: u32,
pub load_op: X86AttachmentLoadOp,
pub store_op: X86AttachmentStoreOp,
pub stencil_load_op: X86AttachmentLoadOp,
pub stencil_store_op: X86AttachmentStoreOp,
pub initial_layout: X86ImageLayout,
pub final_layout: X86ImageLayout,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AttachmentLoadOp {
Load,
Clear,
DontCare,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AttachmentStoreOp {
Store,
DontCare,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ImageLayout {
Undefined,
General,
ColorAttachment,
DepthStencilAttachment,
DepthStencilReadOnly,
ShaderReadOnly,
TransferSrc,
TransferDst,
Preinitialized,
PresentSrc,
}
#[derive(Debug, Clone)]
pub struct X86Subpass {
pub input_attachments: Vec<u32>,
pub color_attachments: Vec<u32>,
pub resolve_attachments: Vec<u32>,
pub depth_stencil_attachment: Option<u32>,
pub preserve_attachments: Vec<u32>,
}
#[derive(Debug, Clone)]
pub struct X86SubpassDependency {
pub src_subpass: u32,
pub dst_subpass: u32,
pub src_stage_mask: X86PipelineStage,
pub dst_stage_mask: X86PipelineStage,
pub src_access_mask: X86AccessFlags,
pub dst_access_mask: X86AccessFlags,
}
#[derive(Debug, Clone, Default)]
pub struct X86PipelineStage {
pub top_of_pipe: bool,
pub draw_indirect: bool,
pub vertex_input: bool,
pub vertex_shader: bool,
pub fragment_shader: bool,
pub early_fragment_tests: bool,
pub late_fragment_tests: bool,
pub color_attachment_output: bool,
pub compute_shader: bool,
pub transfer: bool,
}
#[derive(Debug, Clone, Default)]
pub struct X86AccessFlags {
pub indirect_command_read: bool,
pub index_read: bool,
pub vertex_attribute_read: bool,
pub uniform_read: bool,
pub shader_read: bool,
pub shader_write: bool,
pub color_attachment_read: bool,
pub color_attachment_write: bool,
pub depth_stencil_attachment_read: bool,
pub depth_stencil_attachment_write: bool,
pub transfer_read: bool,
pub transfer_write: bool,
pub host_read: bool,
pub host_write: bool,
}
#[derive(Debug, Clone)]
pub struct X86Framebuffer {
pub width: u32,
pub height: u32,
pub layers: u32,
pub render_pass_name: String,
pub attachments: Vec<X86FramebufferAttachment>,
}
#[derive(Debug, Clone)]
pub struct X86FramebufferAttachment {
pub format: X86TextureFormat,
pub width: u32,
pub height: u32,
pub samples: u32,
pub is_swapchain: bool,
}
#[derive(Debug, Clone)]
pub struct X86GameRendering {
pub simd_level: X86GameSimdLevel,
pub shader_compiler: X86ShaderCompiler,
pub vertex_layouts: Vec<X86VertexLayout>,
pub pipeline_cache_enabled: bool,
pub bindless_supported: bool,
pub ray_tracing: bool,
pub mesh_shaders: bool,
pub max_bound_descriptor_sets: u32,
}
impl X86GameRendering {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
shader_compiler: X86ShaderCompiler::default(),
vertex_layouts: Vec::new(),
pipeline_cache_enabled: true,
bindless_supported: false,
ray_tracing: false,
mesh_shaders: false,
max_bound_descriptor_sets: 4,
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.bindless_supported {
flags.push("-DX86_BINDLESS".into());
}
if self.ray_tracing {
flags.push("-DX86_RAY_TRACING".into());
}
if self.mesh_shaders {
flags.push("-DX86_MESH_SHADERS".into());
}
flags
}
pub fn linker_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.ray_tracing {
flags.push("-ldxcompiler".into());
}
flags
}
pub fn describe(&self) -> String {
format!(
"rendering(shader={:?}, rt={}, mesh={})",
self.shader_compiler.source_language, self.ray_tracing, self.mesh_shaders
)
}
pub fn vertex_input_state_code(&self) -> String {
let mut code = String::from("VkPipelineVertexInputStateCreateInfo vertex_input = {\n");
code.push_str(" .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,\n");
for layout in &self.vertex_layouts {
code.push_str(&format!(
" // Binding {}: stride={}, rate={:?}\n",
layout.binding, layout.stride, layout.input_rate
));
for attr in &layout.attributes {
code.push_str(&format!(
" // Attribute location={} format={:?} offset={}\n",
attr.location, attr.format, attr.offset
));
}
}
code.push_str("};\n");
code
}
pub fn push_constant_struct(&self, name: &str, fields: &[(&str, &str)]) -> String {
let mut code = format!("// Push constant block: {}\n", name);
code.push_str(&format!("layout(push_constant) uniform {} {{\n", name));
for (field_name, field_type) in fields {
code.push_str(&format!(" {} {};\n", field_type, field_name));
}
code.push_str("};\n");
code
}
}
impl Default for X86GameRendering {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86Bone {
pub name: String,
pub parent_index: Option<usize>,
pub bind_pose: X86Mat4,
pub inverse_bind_pose: X86Mat4,
pub children: Vec<usize>,
}
#[derive(Debug, Clone)]
pub struct X86Skeleton {
pub bones: Vec<X86Bone>,
pub root_bone: Option<usize>,
}
impl X86Skeleton {
pub fn new() -> Self {
Self {
bones: Vec::new(),
root_bone: None,
}
}
pub fn add_bone(&mut self, name: &str, parent: Option<usize>, bind_pose: X86Mat4) -> usize {
let ibp = bind_pose.inverse().unwrap_or(X86Mat4::identity());
let idx = self.bones.len();
self.bones.push(X86Bone {
name: name.into(),
parent_index: parent,
bind_pose: bind_pose,
inverse_bind_pose: ibp,
children: Vec::new(),
});
if let Some(p) = parent {
self.bones[p].children.push(idx);
} else if self.root_bone.is_none() {
self.root_bone = Some(idx);
}
idx
}
pub fn compute_skinning_matrices(&self, local_poses: &[X86Mat4]) -> Vec<X86Mat4> {
let n = self.bones.len();
let mut global = vec![X86Mat4::identity(); n];
let mut skinning = vec![X86Mat4::identity(); n];
for i in 0..n {
let parent_global = match self.bones[i].parent_index {
Some(p) => global[p],
None => X86Mat4::identity(),
};
global[i] = parent_global.mul(&local_poses[i]);
}
for i in 0..n {
skinning[i] = global[i].mul(&self.bones[i].inverse_bind_pose);
}
skinning
}
}
impl Default for X86Skeleton {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86Keyframe {
pub time: f32,
pub value: X86KeyframeValue,
}
#[derive(Debug, Clone)]
pub enum X86KeyframeValue {
Scalar(f32),
Vec3(X86Vec3),
Quat(X86Quat),
}
#[derive(Debug, Clone)]
pub struct X86KeyframeTrack {
pub bone_index: usize,
pub position_keys: Vec<X86Keyframe>,
pub rotation_keys: Vec<X86Keyframe>,
pub scale_keys: Vec<X86Keyframe>,
pub interpolation: X86KeyframeInterpolation,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86KeyframeInterpolation {
Step,
Linear,
CubicBezier,
}
impl X86KeyframeTrack {
pub fn sample(&self, time: f32) -> (X86Vec3, X86Quat, X86Vec3) {
let pos = self.sample_scalar_track(&self.position_keys, time);
let rot = self.sample_quat_track(&self.rotation_keys, time);
let scl = self.sample_scalar_track(&self.scale_keys, time);
(pos, rot, scl)
}
fn sample_scalar_track(&self, keys: &[X86Keyframe], time: f32) -> X86Vec3 {
if keys.is_empty() {
return X86Vec3::zero();
}
let mut idx = 0;
for i in 0..keys.len() {
if keys[i].time <= time {
idx = i;
} else {
break;
}
}
let next = (idx + 1).min(keys.len() - 1);
let k0 = &keys[idx];
let k1 = &keys[next];
if idx == next {
return self.keyframe_to_vec3(k0);
}
let t = if (k1.time - k0.time).abs() > 1e-6 {
((time - k0.time) / (k1.time - k0.time)).clamp(0.0, 1.0)
} else {
0.0
};
let v0 = self.keyframe_to_vec3(k0);
let v1 = self.keyframe_to_vec3(k1);
match self.interpolation {
X86KeyframeInterpolation::Step => v0,
X86KeyframeInterpolation::Linear => v0.lerp(&v1, t),
X86KeyframeInterpolation::CubicBezier => {
let s = X86Interpolation::smoothstep(0.0, 1.0, t);
v0.lerp(&v1, s)
}
}
}
fn sample_quat_track(&self, keys: &[X86Keyframe], time: f32) -> X86Quat {
if keys.is_empty() {
return X86Quat::identity();
}
let mut idx = 0;
for i in 0..keys.len() {
if keys[i].time <= time {
idx = i;
} else {
break;
}
}
let next = (idx + 1).min(keys.len() - 1);
let k0 = &keys[idx];
let k1 = &keys[next];
if idx == next {
return self.keyframe_to_quat(k0);
}
let t = if (k1.time - k0.time).abs() > 1e-6 {
((time - k0.time) / (k1.time - k0.time)).clamp(0.0, 1.0)
} else {
0.0
};
let q0 = self.keyframe_to_quat(k0);
let q1 = self.keyframe_to_quat(k1);
match self.interpolation {
X86KeyframeInterpolation::Step => q0,
_ => q0.slerp(&q1, t),
}
}
fn keyframe_to_vec3(&self, kf: &X86Keyframe) -> X86Vec3 {
match &kf.value {
X86KeyframeValue::Vec3(v) => *v,
_ => X86Vec3::zero(),
}
}
fn keyframe_to_quat(&self, kf: &X86Keyframe) -> X86Quat {
match &kf.value {
X86KeyframeValue::Quat(q) => *q,
_ => X86Quat::identity(),
}
}
}
#[derive(Debug, Clone)]
pub struct X86AnimationClip {
pub name: String,
pub duration: f32,
pub fps: f32,
pub looping: bool,
pub tracks: Vec<X86KeyframeTrack>,
}
impl X86AnimationClip {
pub fn new(name: &str, duration: f32, fps: f32) -> Self {
Self {
name: name.into(),
duration,
fps,
looping: true,
tracks: Vec::new(),
}
}
pub fn sample(&self, time: f32, skeleton: &X86Skeleton) -> Vec<X86Mat4> {
let t = if self.looping {
time % self.duration
} else {
time.min(self.duration)
};
let mut poses = vec![X86Mat4::identity(); skeleton.bones.len()];
for track in &self.tracks {
let (pos, rot, scl) = track.sample(t);
poses[track.bone_index] = X86Mat4::from_trs(&pos, &rot, &scl);
}
poses
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BlendMode {
Override,
Additive,
Layered,
}
#[derive(Debug, Clone)]
pub struct X86AnimationBlend {
pub clips: Vec<(X86AnimationClip, f32)>, pub blend_mode: X86BlendMode,
pub total_weight: f32,
}
impl X86AnimationBlend {
pub fn new() -> Self {
Self {
clips: Vec::new(),
blend_mode: X86BlendMode::Override,
total_weight: 0.0,
}
}
pub fn add_clip(&mut self, clip: X86AnimationClip, weight: f32) {
self.clips.push((clip, weight));
self.total_weight += weight;
}
pub fn sample(&self, time: f32, skeleton: &X86Skeleton) -> Vec<X86Mat4> {
if self.clips.is_empty() {
return vec![X86Mat4::identity(); skeleton.bones.len()];
}
match self.blend_mode {
X86BlendMode::Override => {
if let Some((clip, _)) = self.clips.last() {
clip.sample(time, skeleton)
} else {
self.clips[0].0.sample(time, skeleton)
}
}
X86BlendMode::Additive => {
let mut result = vec![X86Mat4::identity(); skeleton.bones.len()];
let mut total_w = 0.0f32;
for (clip, w) in &self.clips {
let poses = clip.sample(time, skeleton);
total_w += w;
for (i, pose) in poses.iter().enumerate() {
let from = &result[i];
let to = pose;
result[i] = Self::blend_matrices(from, to, *w / total_w);
}
}
result
}
X86BlendMode::Layered => {
let mut result = vec![X86Mat4::identity(); skeleton.bones.len()];
for (clip, _) in &self.clips {
let poses = clip.sample(time, skeleton);
for (i, pose) in poses.iter().enumerate() {
result[i] = result[i].mul(pose);
}
}
result
}
}
}
fn blend_matrices(a: &X86Mat4, b: &X86Mat4, t: f32) -> X86Mat4 {
let mut m = [[0.0f32; 4]; 4];
for i in 0..4 {
for j in 0..4 {
m[i][j] = a.m[i][j] + (b.m[i][j] - a.m[i][j]) * t;
}
}
X86Mat4 { m }
}
}
impl Default for X86AnimationBlend {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86CCDIK {
pub max_iterations: usize,
pub tolerance: f32,
}
impl X86CCDIK {
pub fn new() -> Self {
Self {
max_iterations: 20,
tolerance: 0.001,
}
}
pub fn solve(
&self,
skeleton: &X86Skeleton,
local_poses: &mut [X86Mat4],
bone_chain: &[usize],
target: &X86Vec3,
global_transforms: &[X86Mat4],
) -> bool {
for _iter in 0..self.max_iterations {
let ee_global = global_transforms[*bone_chain.first().unwrap_or(&0)];
let ee_pos = X86Vec3::new(ee_global.m[0][3], ee_global.m[1][3], ee_global.m[2][3]);
if ee_pos.sub(target).length() < self.tolerance {
return true;
}
for &bone_idx in bone_chain.iter().skip(1) {
let bone_global = global_transforms[bone_idx];
let bone_pos = X86Vec3::new(
bone_global.m[0][3],
bone_global.m[1][3],
bone_global.m[2][3],
);
let to_target = target.sub(&bone_pos).normalize();
let to_ee = ee_pos.sub(&bone_pos).normalize();
let axis = to_ee.cross(&to_target);
let angle = to_ee.dot(&to_target).acos();
if angle.abs() < self.tolerance {
continue;
}
let rot = X86Quat::from_axis_angle(&axis, angle);
let rot_mat = X86Mat4::from_quat(&rot);
let inv_parent = match skeleton.bones[bone_idx].parent_index {
Some(p) => global_transforms[p]
.inverse()
.unwrap_or(X86Mat4::identity()),
None => X86Mat4::identity(),
};
let local_rot = inv_parent.mul(&rot_mat.mul(&bone_global));
local_poses[bone_idx] = local_poses[bone_idx].mul(&local_rot);
}
}
false
}
}
impl Default for X86CCDIK {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86FABRIK {
pub max_iterations: usize,
pub tolerance: f32,
}
impl X86FABRIK {
pub fn new() -> Self {
Self {
max_iterations: 10,
tolerance: 0.001,
}
}
pub fn solve(
&self,
joint_positions: &mut [X86Vec3],
bone_lengths: &[f32],
target: &X86Vec3,
) -> bool {
let n = joint_positions.len();
if n < 2 {
return false;
}
let root_pos = joint_positions[0];
for _iter in 0..self.max_iterations {
joint_positions[n - 1] = *target;
for i in (0..n - 1).rev() {
let dir = joint_positions[i + 1].sub(&joint_positions[i]);
let len = dir.length();
if len < 1e-6 {
continue;
}
let ratio = bone_lengths[i] / len;
joint_positions[i] = joint_positions[i + 1].sub(&dir.scale(ratio));
}
joint_positions[0] = root_pos;
for i in 0..n - 1 {
let dir = joint_positions[i + 1].sub(&joint_positions[i]);
let len = dir.length();
if len < 1e-6 {
continue;
}
let ratio = bone_lengths[i] / len;
joint_positions[i + 1] = joint_positions[i].add(&dir.scale(ratio));
}
let ee = joint_positions[n - 1];
if ee.sub(target).length() < self.tolerance {
return true;
}
}
false
}
}
impl Default for X86FABRIK {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86AnimStateMachine {
pub states: Vec<X86AnimState>,
pub transitions: Vec<X86AnimTransition>,
pub current_state: Option<usize>,
pub default_state: Option<usize>,
pub parameters: HashMap<String, X86AnimParameter>,
}
#[derive(Debug, Clone)]
pub struct X86AnimState {
pub name: String,
pub clip_name: String,
pub speed: f32,
pub looping: bool,
}
#[derive(Debug, Clone)]
pub struct X86AnimTransition {
pub from: usize,
pub to: usize,
pub duration: f32,
pub conditions: Vec<X86AnimCondition>,
pub has_exit_time: bool,
pub exit_time: f32,
}
#[derive(Debug, Clone)]
pub struct X86AnimCondition {
pub parameter: String,
pub mode: X86AnimConditionMode,
pub threshold: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AnimConditionMode {
If,
IfNot,
Greater,
Less,
Equals,
NotEquals,
}
#[derive(Debug, Clone)]
pub enum X86AnimParameter {
Float(f32),
Bool(bool),
Int(i32),
Trigger,
}
impl X86AnimStateMachine {
pub fn new() -> Self {
Self {
states: Vec::new(),
transitions: Vec::new(),
current_state: None,
default_state: None,
parameters: HashMap::new(),
}
}
pub fn add_state(&mut self, name: &str, clip: &str, speed: f32, looping: bool) -> usize {
let idx = self.states.len();
self.states.push(X86AnimState {
name: name.into(),
clip_name: clip.into(),
speed,
looping,
});
idx
}
pub fn add_transition(
&mut self,
from: usize,
to: usize,
duration: f32,
conditions: Vec<X86AnimCondition>,
) {
self.transitions.push(X86AnimTransition {
from,
to,
duration,
conditions,
has_exit_time: false,
exit_time: 0.0,
});
}
pub fn evaluate(&self, _time: f32) -> (Option<usize>, f32) {
let current = match self.current_state {
Some(idx) => idx,
None => return (self.default_state, 0.0),
};
for t in &self.transitions {
if t.from != current {
continue;
}
let all_met = t.conditions.iter().all(|c| self.check_condition(c));
if all_met {
return (Some(t.to), t.duration);
}
}
(Some(current), 0.0)
}
fn check_condition(&self, cond: &X86AnimCondition) -> bool {
match self.parameters.get(&cond.parameter) {
Some(X86AnimParameter::Float(v)) => match cond.mode {
X86AnimConditionMode::Greater => *v > cond.threshold,
X86AnimConditionMode::Less => *v < cond.threshold,
X86AnimConditionMode::Equals => (*v - cond.threshold).abs() < 0.001,
_ => true,
},
Some(X86AnimParameter::Bool(v)) => match cond.mode {
X86AnimConditionMode::If => *v,
X86AnimConditionMode::IfNot => !*v,
_ => true,
},
Some(X86AnimParameter::Int(v)) => match cond.mode {
X86AnimConditionMode::Equals => *v == cond.threshold as i32,
X86AnimConditionMode::NotEquals => *v != cond.threshold as i32,
X86AnimConditionMode::Greater => *v > cond.threshold as i32,
_ => true,
},
Some(X86AnimParameter::Trigger) => true,
None => false,
}
}
}
impl Default for X86AnimStateMachine {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86GameAnimation {
pub simd_level: X86GameSimdLevel,
pub max_bones: usize,
pub skinning_gpu: bool,
pub ik_enabled: bool,
pub blend_space: bool,
pub root_motion: bool,
}
impl X86GameAnimation {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
max_bones: 256,
skinning_gpu: true,
ik_enabled: true,
blend_space: false,
root_motion: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.skinning_gpu {
flags.push(format!("-DX86_MAX_BONES={}", self.max_bones));
}
if self.ik_enabled {
flags.push("-DX86_IK_ENABLED".into());
}
flags
}
pub fn describe(&self) -> String {
format!(
"animation(bones={}, skinning_gpu={}, ik={})",
self.max_bones, self.skinning_gpu, self.ik_enabled
)
}
pub fn skinning_shader_code(&self) -> String {
if !self.skinning_gpu {
return String::new();
}
format!(
r#"// GPU Skinning Vertex Shader
#version 450
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in uvec4 inBoneIndices;
layout(location = 4) in vec4 inBoneWeights;
layout(set = 0, binding = 0) uniform CameraBlock {{ mat4 viewProj; }} camera;
layout(set = 0, binding = 1) uniform SkinningBlock {{ mat4 boneMatrices[{}]; }} skinning;
layout(location = 0) out vec3 outWorldPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec2 outTexCoord;
void main() {{
mat4 skinMat = skinning.boneMatrices[inBoneIndices.x] * inBoneWeights.x
+ skinning.boneMatrices[inBoneIndices.y] * inBoneWeights.y
+ skinning.boneMatrices[inBoneIndices.z] * inBoneWeights.z
+ skinning.boneMatrices[inBoneIndices.w] * inBoneWeights.w;
vec4 worldPos = skinMat * vec4(inPosition, 1.0);
gl_Position = camera.viewProj * worldPos;
outWorldPos = worldPos.xyz;
outNormal = mat3(skinMat) * inNormal;
outTexCoord = inTexCoord;
}}
"#,
self.max_bones
)
}
pub fn bone_hierarchy_code(&self) -> String {
format!(
r#"
// Bone hierarchy update
void update_bone_hierarchy(float* global_matrices, const float* local_matrices,
const int* parent_indices, int bone_count) {{
for (int i = 0; i < bone_count; i++) {{
int parent = parent_indices[i];
if (parent >= 0) {{
mat4_mul(global_matrices + i*16, global_matrices + parent*16, local_matrices + i*16);
}} else {{
memcpy(global_matrices + i*16, local_matrices + i*16, 64);
}}
}}
}}
"#
)
}
}
impl Default for X86GameAnimation {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86AudioRingBuffer {
pub capacity: usize,
pub read_pos: usize,
pub write_pos: usize,
}
impl X86AudioRingBuffer {
pub fn new(capacity: usize) -> Self {
Self {
capacity,
read_pos: 0,
write_pos: 0,
}
}
pub fn available_read(&self) -> usize {
if self.write_pos >= self.read_pos {
self.write_pos - self.read_pos
} else {
self.capacity - self.read_pos + self.write_pos
}
}
pub fn available_write(&self) -> usize {
self.capacity - self.available_read() - 1
}
pub fn advance_read(&mut self, n: usize) {
self.read_pos = (self.read_pos + n) % self.capacity;
}
pub fn advance_write(&mut self, n: usize) {
self.write_pos = (self.write_pos + n) % self.capacity;
}
}
#[derive(Debug, Clone)]
pub struct X86SIMDAudioMixer {
pub simd_level: X86GameSimdLevel,
pub master_volume: f32,
}
impl X86SIMDAudioMixer {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
master_volume: 1.0,
}
}
pub fn mixing_code(&self) -> String {
let mut code = String::from("// SIMD audio mixer\n");
code.push_str("static inline void mix_audio_simd(float* output, const float** inputs,\n");
code.push_str(" int num_inputs, int num_samples, float master_vol) {\n");
match self.simd_level {
X86GameSimdLevel::SSE42 => {
code.push_str(" __m128 vol = _mm_set1_ps(master_vol);\n");
code.push_str(" for (int s = 0; s < num_samples; s += 4) {\n");
code.push_str(" __m128 acc = _mm_setzero_ps();\n");
code.push_str(" for (int i = 0; i < num_inputs; i++) {\n");
code.push_str(" __m128 in = _mm_loadu_ps(inputs[i] + s);\n");
code.push_str(" acc = _mm_add_ps(acc, in);\n");
code.push_str(" }\n");
code.push_str(" acc = _mm_mul_ps(acc, vol);\n");
code.push_str(" _mm_storeu_ps(output + s, acc);\n");
code.push_str(" }\n");
}
X86GameSimdLevel::AVX2 => {
code.push_str(" __m256 vol8 = _mm256_set1_ps(master_vol);\n");
code.push_str(" for (int s = 0; s < num_samples; s += 8) {\n");
code.push_str(" __m256 acc = _mm256_setzero_ps();\n");
code.push_str(" for (int i = 0; i < num_inputs; i++) {\n");
code.push_str(
" acc = _mm256_add_ps(acc, _mm256_loadu_ps(inputs[i] + s));\n",
);
code.push_str(" }\n");
code.push_str(" _mm256_storeu_ps(output + s, _mm256_mul_ps(acc, vol8));\n");
code.push_str(" }\n");
}
_ => {
code.push_str(" for (int s = 0; s < num_samples; s++) {\n");
code.push_str(" float acc = 0.0f;\n");
code.push_str(
" for (int i = 0; i < num_inputs; i++) acc += inputs[i][s];\n",
);
code.push_str(" output[s] = acc * master_vol;\n");
code.push_str(" }\n");
}
}
code.push_str("}\n");
code
}
}
#[derive(Debug, Clone)]
pub struct X86SIMDFilter {
pub simd_level: X86GameSimdLevel,
}
impl X86SIMDFilter {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self { simd_level }
}
pub fn biquad_code(&self) -> String {
let mut code = String::from("// SIMD biquad filter (transposed direct form II)\n");
code.push_str("typedef struct { float b0, b1, b2, a1, a2; float z1, z2; } BiquadState;\n");
code.push_str("static inline float biquad_process(BiquadState* f, float x) {\n");
code.push_str(" float y = f->b0 * x + f->z1;\n");
code.push_str(" f->z1 = f->b1 * x - f->a1 * y + f->z2;\n");
code.push_str(" f->z2 = f->b2 * x - f->a2 * y;\n");
code.push_str(" return y;\n");
code.push_str("}\n");
code
}
}
#[derive(Debug, Clone)]
pub struct X86SIMDFFT {
pub simd_level: X86GameSimdLevel,
pub max_size: usize,
}
impl X86SIMDFFT {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
max_size: 4096,
}
}
pub fn fft_code(&self) -> String {
let mut code = format!("// SIMD-optimized FFT (max size: {})\n", self.max_size);
code.push_str("static void fft_radix2(float* real, float* imag, int n) {\n");
code.push_str(" // Bit-reversal permutation\n");
code.push_str(" int j = 0;\n");
code.push_str(" for (int i = 0; i < n; i++) {\n");
code.push_str(" if (i < j) {\n");
code.push_str(" float tr = real[i]; real[i] = real[j]; real[j] = tr;\n");
code.push_str(" float ti = imag[i]; imag[i] = imag[j]; imag[j] = ti;\n");
code.push_str(" }\n");
code.push_str(" int m = n >> 1;\n");
code.push_str(" while (m >= 1 && j >= m) { j -= m; m >>= 1; }\n");
code.push_str(" j += m;\n");
code.push_str(" }\n");
code.push_str(" // Cooley-Tukey FFT\n");
code.push_str(" for (int s = 2; s <= n; s <<= 1) {\n");
code.push_str(" int half = s >> 1;\n");
code.push_str(" float angle = -2.0f * M_PI / (float)s;\n");
match self.simd_level {
X86GameSimdLevel::SSE42 => {
code.push_str(" // SSE: process 2 complex pairs at once\n");
}
X86GameSimdLevel::AVX2 => {
code.push_str(" // AVX: process 4 complex pairs at once\n");
}
_ => {}
}
code.push_str(" for (int k = 0; k < n; k += s) {\n");
code.push_str(" for (int m = 0; m < half; m++) {\n");
code.push_str(" float w_real = cosf(angle * m);\n");
code.push_str(" float w_imag = sinf(angle * m);\n");
code.push_str(
" float t_real = w_real * real[k+m+half] - w_imag * imag[k+m+half];\n",
);
code.push_str(
" float t_imag = w_real * imag[k+m+half] + w_imag * real[k+m+half];\n",
);
code.push_str(" real[k+m+half] = real[k+m] - t_real;\n");
code.push_str(" imag[k+m+half] = imag[k+m] - t_imag;\n");
code.push_str(" real[k+m] += t_real;\n");
code.push_str(" imag[k+m] += t_imag;\n");
code.push_str(" }\n");
code.push_str(" }\n");
code.push_str(" }\n");
code.push_str("}\n");
code
}
}
#[derive(Debug, Clone)]
pub struct X86ProceduralAudio {
pub sample_rate: u32,
}
impl X86ProceduralAudio {
pub fn new(sample_rate: u32) -> Self {
Self { sample_rate }
}
pub fn sine_code(&self) -> String {
format!(
"static inline float sine_wave(float phase) {{ return sinf(2.0f * M_PI * phase); }}\n"
)
}
pub fn triangle_code(&self) -> String {
"static inline float triangle_wave(float phase) {\n".to_string()
+ " float t = phase - floorf(phase);\n"
+ " return 4.0f * fabsf(t - 0.5f) - 1.0f;\n"
+ "}\n"
}
pub fn sawtooth_code(&self) -> String {
"static inline float sawtooth_wave(float phase) {\n".to_string()
+ " return 2.0f * (phase - floorf(phase + 0.5f));\n"
+ "}\n"
}
pub fn square_code(&self) -> String {
"static inline float square_wave(float phase, float duty) {\n".to_string()
+ " return (phase - floorf(phase)) < duty ? 1.0f : -1.0f;\n"
+ "}\n"
}
pub fn noise_code(&self) -> String {
r#"// Simple white noise using xorshift
static inline float white_noise(uint32_t* state) {
*state ^= *state << 13;
*state ^= *state >> 17;
*state ^= *state << 5;
return (float)(*state) / (float)UINT32_MAX * 2.0f - 1.0f;
}
"#
.to_string()
}
}
#[derive(Debug, Clone)]
pub struct X86AudioFormat;
impl X86AudioFormat {
pub fn wav_header_code() -> String {
r#"// WAV file header
#pragma pack(push, 1)
typedef struct {
char riff[4]; // "RIFF"
uint32_t file_size; // total file size - 8
char wave[4]; // "WAVE"
char fmt[4]; // "fmt "
uint32_t fmt_size; // 16 for PCM
uint16_t audio_format; // 1 = PCM
uint16_t num_channels;
uint32_t sample_rate;
uint32_t byte_rate; // sample_rate * num_channels * bits_per_sample/8
uint16_t block_align; // num_channels * bits_per_sample/8
uint16_t bits_per_sample;
char data[4]; // "data"
uint32_t data_size;
} WavHeader;
#pragma pack(pop)
"#
.to_string()
}
pub fn ogg_stub_code() -> String {
r#"// OGG Vorbis stub — use stb_vorbis or libvorbis for real decoding
// Include: #define STB_VORBIS_HEADER_ONLY
// #include "stb_vorbis.c"
typedef struct {
unsigned int sample_rate;
int channels;
int max_frame_size;
float** outputs; // decoded PCM samples
void* decoder; // opaque vorbis decoder
} OggVorbisDecoder;
static inline OggVorbisDecoder* ogg_vorbis_open(const char* filename) {
// Stub: use stb_vorbis_open_file or libvorbis
return NULL;
}
static inline int ogg_vorbis_read(OggVorbisDecoder* dec, int samples) {
// Stub
return 0;
}
static inline void ogg_vorbis_close(OggVorbisDecoder* dec) {
// Stub
}
"#
.to_string()
}
}
#[derive(Debug, Clone)]
pub struct X86GameAudioDSP {
pub simd_level: X86GameSimdLevel,
pub mixer: X86SIMDAudioMixer,
pub filter: X86SIMDFilter,
pub fft: X86SIMDFFT,
pub procedural: X86ProceduralAudio,
pub sample_rate: u32,
pub buffer_size: usize,
pub channels: u32,
}
impl X86GameAudioDSP {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
sample_rate: 48000,
buffer_size: 1024,
channels: 2,
mixer: X86SIMDAudioMixer::new(simd_level),
filter: X86SIMDFilter::new(simd_level),
fft: X86SIMDFFT::new(simd_level),
procedural: X86ProceduralAudio::new(48000),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.push(format!("-DX86_AUDIO_SAMPLE_RATE={}", self.sample_rate));
flags.push(format!("-DX86_AUDIO_BUFFER_SIZE={}", self.buffer_size));
flags
}
pub fn describe(&self) -> String {
format!(
"audio_dsp(simd={}, sr={}, buf={})",
self.simd_level, self.sample_rate, self.buffer_size
)
}
pub fn audio_dsp_header(&self) -> String {
let mut hdr = String::from("// Audio DSP header — generated by X86GameAudioDSP\n");
hdr.push_str("#include <math.h>\n");
hdr.push_str(&self.mixer.mixing_code());
hdr.push_str(&self.filter.biquad_code());
hdr.push_str(&self.procedural.sine_code());
hdr.push_str(&self.procedural.triangle_code());
hdr.push_str(&self.procedural.sawtooth_code());
hdr.push_str(&self.procedural.square_code());
hdr.push_str(&self.procedural.noise_code());
hdr.push_str(&X86AudioFormat::wav_header_code());
hdr
}
}
impl Default for X86GameAudioDSP {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86UDPSocket {
pub port: u16,
pub nonblocking: bool,
pub recv_buffer_size: usize,
pub send_buffer_size: usize,
pub reuse_addr: bool,
}
impl X86UDPSocket {
pub fn new(port: u16) -> Self {
Self {
port,
nonblocking: true,
recv_buffer_size: 65536,
send_buffer_size: 65536,
reuse_addr: true,
}
}
pub fn setup_code(&self) -> String {
format!(
r#"// UDP socket setup
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
static int create_udp_socket(uint16_t port) {{
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0) return -1;
int reuse = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
int rcvbuf = {};
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
int sndbuf = {};
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
struct sockaddr_in addr = {{0}};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {{ close(sock); return -1; }}
{}
return sock;
}}
"#,
self.recv_buffer_size,
self.send_buffer_size,
if self.nonblocking {
"int flags = fcntl(sock, F_GETFL, 0);\n fcntl(sock, F_SETFL, flags | O_NONBLOCK);"
} else {
""
}
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86SerializationFormat {
Binary,
BitPacked,
JSON,
Custom,
}
#[derive(Debug, Clone)]
pub struct X86PacketSerializer {
pub format: X86SerializationFormat,
pub max_packet_size: usize,
pub little_endian: bool,
}
impl X86PacketSerializer {
pub fn new() -> Self {
Self {
format: X86SerializationFormat::Binary,
max_packet_size: 1400,
little_endian: true,
}
}
pub fn serialize_code(&self) -> String {
let mut code = String::from("// Packet serialization\n");
code.push_str("#include <stdint.h>\n#include <string.h>\n\n");
code.push_str(
"typedef struct { uint8_t data[1400]; int cursor; int length; } PacketWriter;\n\n",
);
code.push_str("static inline void pkt_write_u8(PacketWriter* p, uint8_t v) { p->data[p->cursor++] = v; }\n");
code.push_str("static inline void pkt_write_u16(PacketWriter* p, uint16_t v) {\n");
code.push_str(" memcpy(p->data + p->cursor, &v, 2); p->cursor += 2;\n");
code.push_str("}\n");
code.push_str("static inline void pkt_write_u32(PacketWriter* p, uint32_t v) {\n");
code.push_str(" memcpy(p->data + p->cursor, &v, 4); p->cursor += 4;\n");
code.push_str("}\n");
code.push_str("static inline void pkt_write_f32(PacketWriter* p, float v) {\n");
code.push_str(" memcpy(p->data + p->cursor, &v, 4); p->cursor += 4;\n");
code.push_str("}\n");
code.push_str(
"typedef struct { const uint8_t* data; int cursor; int length; } PacketReader;\n\n",
);
code.push_str(
"static inline uint8_t pkt_read_u8(PacketReader* p) { return p->data[p->cursor++]; }\n",
);
code.push_str("static inline uint16_t pkt_read_u16(PacketReader* p) {\n");
code.push_str(
" uint16_t v; memcpy(&v, p->data + p->cursor, 2); p->cursor += 2; return v;\n",
);
code.push_str("}\n");
code.push_str("static inline uint32_t pkt_read_u32(PacketReader* p) {\n");
code.push_str(
" uint32_t v; memcpy(&v, p->data + p->cursor, 4); p->cursor += 4; return v;\n",
);
code.push_str("}\n");
code
}
}
impl Default for X86PacketSerializer {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86BitPacker {
pub max_packet_size: usize,
}
impl X86BitPacker {
pub fn new() -> Self {
Self {
max_packet_size: 1400,
}
}
pub fn bitpack_code(&self) -> String {
r#"// Bit-packing for network compression
typedef struct {
uint64_t buffer;
int bits_used;
uint8_t* data;
int byte_cursor;
} BitWriter;
static inline void bit_writer_init(BitWriter* bw, uint8_t* buf) {
bw->buffer = 0; bw->bits_used = 0; bw->data = buf; bw->byte_cursor = 0;
}
static inline void bit_writer_write(BitWriter* bw, uint64_t value, int bits) {
bw->buffer |= (value & ((1ULL << bits) - 1)) << bw->bits_used;
bw->bits_used += bits;
while (bw->bits_used >= 8) {
bw->data[bw->byte_cursor++] = (uint8_t)(bw->buffer & 0xFF);
bw->buffer >>= 8;
bw->bits_used -= 8;
}
}
static inline void bit_writer_flush(BitWriter* bw) {
if (bw->bits_used > 0) {
bw->data[bw->byte_cursor++] = (uint8_t)(bw->buffer & 0xFF);
bw->buffer = 0; bw->bits_used = 0;
}
}
typedef struct {
uint64_t buffer;
int bits_available;
const uint8_t* data;
int byte_cursor;
} BitReader;
static inline void bit_reader_init(BitReader* br, const uint8_t* buf) {
br->buffer = 0; br->bits_available = 0; br->data = buf; br->byte_cursor = 0;
}
static inline uint64_t bit_reader_read(BitReader* br, int bits) {
while (br->bits_available < bits) {
br->buffer |= (uint64_t)br->data[br->byte_cursor++] << br->bits_available;
br->bits_available += 8;
}
uint64_t value = br->buffer & ((1ULL << bits) - 1);
br->buffer >>= bits;
br->bits_available -= bits;
return value;
}
"#
.to_string()
}
}
impl Default for X86BitPacker {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86ClientServer {
pub server_port: u16,
pub max_clients: usize,
pub tick_rate: u32,
pub protocol_id: u32,
pub timeout_ms: u32,
}
impl X86ClientServer {
pub fn new() -> Self {
Self {
server_port: 27015,
max_clients: 64,
tick_rate: 60,
protocol_id: 0x1234,
timeout_ms: 5000,
}
}
pub fn server_code(&self) -> String {
format!(
r#"// Game server implementation
#define MAX_CLIENTS {}
#define SERVER_PORT {}
#define TICK_RATE {}
#define TIMEOUT_MS {}
typedef struct {{
int socket;
struct sockaddr_in addr;
uint64_t last_recv_time;
uint32_t client_id;
bool connected;
uint32_t sequence;
uint8_t recv_buf[65536];
}} ClientState;
typedef struct {{
int socket;
ClientState clients[MAX_CLIENTS];
uint32_t next_client_id;
uint64_t tick_number;
}} GameServer;
void server_update(GameServer* srv) {{
// Read packets
struct sockaddr_in from;
socklen_t from_len = sizeof(from);
uint8_t buf[65536];
int n = recvfrom(srv->socket, buf, sizeof(buf), 0, (struct sockaddr*)&from, &from_len);
if (n > 0) {{
// Process client packet
uint32_t protocol_id = *(uint32_t*)buf;
if (protocol_id == PROTOCOL_ID) {{
uint32_t client_id = *(uint32_t*)(buf + 4);
uint32_t seq = *(uint32_t*)(buf + 8);
// Handle packet...
}}
}}
}}
"#,
self.max_clients, self.server_port, self.tick_rate, self.timeout_ms
)
}
}
impl Default for X86ClientServer {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86PeerToPeer {
pub max_peers: usize,
pub protocol_id: u32,
pub punchthrough_enabled: bool,
}
impl X86PeerToPeer {
pub fn new() -> Self {
Self {
max_peers: 16,
protocol_id: 0x5678,
punchthrough_enabled: true,
}
}
pub fn peer_code(&self) -> String {
format!(
r#"// P2P networking
#define MAX_PEERS {}
#define PROTOCOL_ID_P2P {}
typedef struct {{
struct sockaddr_in addr;
uint32_t peer_id;
uint32_t sequence;
uint64_t last_recv;
bool connected;
uint16_t ping_ms;
}} PeerState;
typedef struct {{
int socket;
PeerState peers[MAX_PEERS];
uint32_t my_peer_id;
uint32_t peer_count;
}} P2PNetwork;
void p2p_send(P2PNetwork* net, uint32_t peer_id, const uint8_t* data, int len) {{
for (int i = 0; i < net->peer_count; i++) {{
if (net->peers[i].peer_id == peer_id && net->peers[i].connected) {{
sendto(net->socket, data, len, 0,
(struct sockaddr*)&net->peers[i].addr, sizeof(net->peers[i].addr));
break;
}}
}}
}}
"#,
self.max_peers, self.protocol_id
)
}
}
impl Default for X86PeerToPeer {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86LagCompensation {
pub history_buffer_ms: u32,
pub interpolation_delay_ms: u32,
pub extrapolation_limit_ms: u32,
}
impl X86LagCompensation {
pub fn new() -> Self {
Self {
history_buffer_ms: 1000,
interpolation_delay_ms: 100,
extrapolation_limit_ms: 200,
}
}
pub fn compensation_code(&self) -> String {
format!(
r#"// Lag compensation with history buffer
#define HISTORY_BUFFER_MS {}
#define INTERP_DELAY_MS {}
#define EXTRAP_LIMIT_MS {}
typedef struct {{
uint64_t timestamp_ms;
float x, y, z;
}} PositionSnapshot;
typedef struct {{
PositionSnapshot history[256];
int head;
int count;
}} PositionHistory;
// Rewind entity positions for lag-compensated hit detection
static inline bool rewind_to_timestamp(PositionHistory* hist, uint64_t target_ms,
float* out_x, float* out_y, float* out_z) {{
for (int i = 0; i < hist->count; i++) {{
int idx = (hist->head - 1 - i + 256) % 256;
if (hist->history[idx].timestamp_ms <= target_ms) {{
// Interpolate between snapshots
*out_x = hist->history[idx].x;
*out_y = hist->history[idx].y;
*out_z = hist->history[idx].z;
return true;
}}
}}
return false;
}}
"#,
self.history_buffer_ms, self.interpolation_delay_ms, self.extrapolation_limit_ms
)
}
}
impl Default for X86LagCompensation {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86StateSync {
pub sync_rate: u32,
pub delta_compression: bool,
pub full_snapshot_interval: u32,
}
impl X86StateSync {
pub fn new() -> Self {
Self {
sync_rate: 20,
delta_compression: true,
full_snapshot_interval: 60,
}
}
pub fn sync_code(&self) -> String {
format!(
r#"// State synchronization with delta compression
#define SYNC_RATE {}
#define FULL_SNAPSHOT_EVERY {}
typedef struct {{
uint32_t entity_id;
float pos_x, pos_y, pos_z;
float vel_x, vel_y, vel_z;
float rot_x, rot_y, rot_z;
uint32_t state_flags;
}} EntityState;
// Delta-compress entity state vs baseline
static inline int delta_encode(const EntityState* current, const EntityState* baseline,
uint8_t* out, int max_len) {{
int written = 0;
uint32_t changed_mask = 0;
uint32_t bit = 1;
if (current->pos_x != baseline->pos_x) changed_mask |= bit; bit <<= 1;
if (current->pos_y != baseline->pos_y) changed_mask |= bit; bit <<= 1;
if (current->pos_z != baseline->pos_z) changed_mask |= bit; bit <<= 1;
if (current->vel_x != baseline->vel_x) changed_mask |= bit; bit <<= 1;
if (current->vel_y != baseline->vel_y) changed_mask |= bit; bit <<= 1;
if (current->vel_z != baseline->vel_z) changed_mask |= bit; bit <<= 1;
memcpy(out, &changed_mask, 4); written += 4;
memcpy(out + written, ¤t->entity_id, 4); written += 4;
if (changed_mask & 1) {{ memcpy(out + written, ¤t->pos_x, 4); written += 4; }}
if (changed_mask & 2) {{ memcpy(out + written, ¤t->pos_y, 4); written += 4; }}
if (changed_mask & 4) {{ memcpy(out + written, ¤t->pos_z, 4); written += 4; }}
// ... etc for velocity
return written;
}}
"#,
self.sync_rate, self.full_snapshot_interval
)
}
}
impl Default for X86StateSync {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86GameNetworkingCore {
pub simd_level: X86GameSimdLevel,
pub udp: X86UDPSocket,
pub serializer: X86PacketSerializer,
pub bitpacker: X86BitPacker,
pub client_server: X86ClientServer,
pub peer_to_peer: X86PeerToPeer,
pub lag_comp: X86LagCompensation,
pub state_sync: X86StateSync,
}
impl X86GameNetworkingCore {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
udp: X86UDPSocket::new(27015),
serializer: X86PacketSerializer::new(),
bitpacker: X86BitPacker::new(),
client_server: X86ClientServer::new(),
peer_to_peer: X86PeerToPeer::new(),
lag_comp: X86LagCompensation::new(),
state_sync: X86StateSync::new(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.push(format!(
"-DX86_NET_MAX_PACKET={}",
self.serializer.max_packet_size
));
if self.state_sync.delta_compression {
flags.push("-DX86_NET_DELTA_COMPRESSION".into());
}
flags
}
pub fn linker_flags(&self) -> Vec<String> {
vec![]
}
pub fn describe(&self) -> String {
format!(
"networking(port={}, cs={}, p2p={}, lag_comp={}ms)",
self.udp.port,
self.client_server.max_clients,
self.peer_to_peer.max_peers,
self.lag_comp.interpolation_delay_ms
)
}
pub fn networking_header(&self) -> String {
let mut hdr =
String::from("// Game Networking header — generated by X86GameNetworkingCore\n");
hdr.push_str("#include <stdint.h>\n#include <string.h>\n");
hdr.push_str(&self.udp.setup_code());
hdr.push_str(&self.serializer.serialize_code());
hdr.push_str(&self.bitpacker.bitpack_code());
hdr.push_str(&self.client_server.server_code());
hdr.push_str(&self.peer_to_peer.peer_code());
hdr.push_str(&self.lag_comp.compensation_code());
hdr.push_str(&self.state_sync.sync_code());
hdr
}
}
impl Default for X86GameNetworkingCore {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GameEngines {
pub simd_level: X86GameSimdLevel,
pub unreal: X86UnrealEngine,
pub unity: X86UnityEngine,
pub godot: X86GodotEngine,
pub custom: X86CustomEngine,
}
impl X86GameEngines {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
unreal: X86UnrealEngine::default(),
unity: X86UnityEngine::default(),
godot: X86GodotEngine::default(),
custom: X86CustomEngine::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.extend(self.unreal.compile_flags());
flags.extend(self.unity.compile_flags());
flags.extend(self.godot.compile_flags());
flags.extend(self.custom.compile_flags());
flags
}
pub fn linker_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.extend(self.unreal.linker_flags());
flags.extend(self.unity.linker_flags());
flags.extend(self.godot.linker_flags());
flags.extend(self.custom.linker_flags());
flags
}
pub fn describe(&self) -> String {
format!(
"engines(unreal={}, unity={}, godot={})",
self.unreal.enabled, self.unity.enabled, self.godot.enabled
)
}
}
impl Default for X86GameEngines {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86UnrealEngine {
pub enabled: bool,
pub version: String,
pub simd_level: X86GameSimdLevel,
pub ubt: X86UBTIntegration,
pub modules: X86UnrealModules,
pub reflection: X86UnrealReflection,
pub hot_reload: X86UnrealHotReload,
}
impl X86UnrealEngine {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
version: "5.4".into(),
simd_level,
ubt: X86UBTIntegration::default(),
modules: X86UnrealModules::default(),
reflection: X86UnrealReflection::default(),
hot_reload: X86UnrealHotReload::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
vec![
"-DUNREAL_ENGINE".into(),
format!("-DUE_VERSION={}", self.version),
]
}
pub fn linker_flags(&self) -> Vec<String> {
Vec::new()
}
pub fn uclass_macro(&self) -> &'static str {
"UCLASS()"
}
pub fn ustruct_macro(&self) -> &'static str {
"USTRUCT()"
}
pub fn uenum_macro(&self) -> &'static str {
"UENUM()"
}
pub fn ufunction_macro(&self) -> &'static str {
"UFUNCTION()"
}
pub fn generated_body_macro(&self) -> &'static str {
"GENERATED_BODY()"
}
pub fn build_cs_template(&self) -> String {
"// UnrealEngine.Build.cs template".to_string()
}
}
impl Default for X86UnrealEngine {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86UBTIntegration {
pub enabled: bool,
pub use_compile_commands: bool,
pub parallel_jobs: usize,
pub adaptive_unity_build: bool,
pub max_unity_files: usize,
pub shared_pch: bool,
pub include_what_you_use: bool,
}
impl X86UBTIntegration {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DUBT_INTEGRATION".into()]
}
}
}
impl Default for X86UBTIntegration {
fn default() -> Self {
Self {
enabled: false,
use_compile_commands: true,
parallel_jobs: 8,
adaptive_unity_build: false,
max_unity_files: 2,
shared_pch: false,
include_what_you_use: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86UnrealModules {
pub enabled: bool,
pub module_type: X86UnrealModuleType,
pub module_name: String,
pub public_dependencies: Vec<String>,
pub private_dependencies: Vec<String>,
pub dynamically_loaded: bool,
pub api_export: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86UnrealModuleType {
Runtime,
Editor,
Developer,
Plugin,
Program,
}
impl X86UnrealModules {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec![format!("-DUE_MODULE={}", self.module_name)]
}
}
pub fn implement_module(&self) -> String {
format!(
"IMPLEMENT_MODULE({}, {})",
self.module_name,
self.module_type_name()
)
}
fn module_type_name(&self) -> &str {
match self.module_type {
X86UnrealModuleType::Runtime => "Runtime",
X86UnrealModuleType::Editor => "Editor",
X86UnrealModuleType::Developer => "Developer",
X86UnrealModuleType::Plugin => "Plugin",
X86UnrealModuleType::Program => "Program",
}
}
pub fn dependency_list(&self) -> Vec<String> {
self.public_dependencies.clone()
}
}
impl Default for X86UnrealModules {
fn default() -> Self {
Self {
enabled: false,
module_type: X86UnrealModuleType::Runtime,
module_name: String::new(),
public_dependencies: Vec::new(),
private_dependencies: Vec::new(),
dynamically_loaded: false,
api_export: String::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct X86UnrealReflection {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub uht_enabled: bool,
pub replication: bool,
pub serialization: bool,
pub blueprint_vm: bool,
pub delegates: bool,
pub strict_includes: bool,
pub generated_output: Option<PathBuf>,
}
impl X86UnrealReflection {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
uht_enabled: true,
replication: false,
serialization: true,
blueprint_vm: false,
delegates: true,
strict_includes: false,
generated_output: None,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DUE_REFLECTION".into()]
}
}
pub fn generated_include(&self) -> String {
"GENERATED_BODY()".to_string()
}
pub fn property_reflection(&self) -> String {
"UPROPERTY()".to_string()
}
}
impl Default for X86UnrealReflection {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86UnrealHotReload {
pub enabled: bool,
pub use_live_coding: bool,
pub shared_library: bool,
pub incremental_linking: bool,
pub patch_size_limit: usize,
}
impl X86UnrealHotReload {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DUE_HOT_RELOAD".into()]
}
}
}
impl Default for X86UnrealHotReload {
fn default() -> Self {
Self {
enabled: false,
use_live_coding: false,
shared_library: false,
incremental_linking: true,
patch_size_limit: 1048576,
}
}
}
#[derive(Debug, Clone)]
pub struct X86UnityEngine {
pub enabled: bool,
pub version: String,
pub simd_level: X86GameSimdLevel,
pub il2cpp: X86IL2CPPIntegration,
pub burst: X86BurstCompiler,
pub dots: X86DOTSECS,
pub native_plugin: X86UnityNativePlugin,
}
impl X86UnityEngine {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
version: "2022.3".into(),
simd_level,
il2cpp: X86IL2CPPIntegration::default(),
burst: X86BurstCompiler::default(),
dots: X86DOTSECS::default(),
native_plugin: X86UnityNativePlugin::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DUNITY_ENGINE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
Vec::new()
}
}
impl Default for X86UnityEngine {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86IL2CPPIntegration {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub scripting_backend: X86ScriptingBackend,
pub api_level: X86UnityAPILevel,
pub gc_mode: X86UnityGCMode,
pub codegen: X86IL2CPPCodegen,
pub generic_sharing: bool,
pub devirtualization: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ScriptingBackend {
Mono,
IL2CPP,
CoreCLR,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86UnityAPILevel {
NetStandard20,
NetFramework,
NetCore,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86UnityGCMode {
Boehm,
Incremental,
Disabled,
}
#[derive(Debug, Clone)]
pub struct X86IL2CPPCodegen {
pub inlining: bool,
pub null_checks: bool,
pub bounds_checks: bool,
pub stack_trace: bool,
pub devirtualization: bool,
pub lazy_init: bool,
pub use_simd: bool,
}
impl X86IL2CPPIntegration {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
scripting_backend: X86ScriptingBackend::IL2CPP,
api_level: X86UnityAPILevel::NetStandard20,
gc_mode: X86UnityGCMode::Incremental,
codegen: X86IL2CPPCodegen::default(),
generic_sharing: true,
devirtualization: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DIL2CPP".into()]
}
}
}
impl Default for X86IL2CPPCodegen {
fn default() -> Self {
Self {
inlining: true,
null_checks: true,
bounds_checks: true,
stack_trace: false,
devirtualization: true,
lazy_init: true,
use_simd: true,
}
}
}
impl Default for X86IL2CPPIntegration {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86BurstCompiler {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub optimization: X86BurstOptLevel,
pub float_mode: X86BurstFloatMode,
pub safety_checks: bool,
pub synchronous: bool,
pub debug: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BurstOptLevel {
None,
Performance,
HighPerformance,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BurstFloatMode {
Strict,
Deterministic,
Fast,
}
impl X86BurstCompiler {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
optimization: X86BurstOptLevel::HighPerformance,
float_mode: X86BurstFloatMode::Fast,
safety_checks: false,
synchronous: false,
debug: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
let mut f = vec!["-DBURST_COMPILER".into()];
if self.float_mode == X86BurstFloatMode::Fast {
f.push("-DBURST_FAST_MATH".into());
}
f
}
}
pub fn burst_compile_attribute(&self) -> &'static str {
"[BurstCompile]"
}
pub fn burst_job_template(&self) -> String {
"public struct MyJob : IJob { ... }".to_string()
}
}
impl Default for X86BurstCompiler {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86DOTSECS {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub chunk_iteration: bool,
pub chunk_size: usize,
pub archetype_chunks: bool,
pub component_simd: bool,
pub max_entities_per_chunk: usize,
}
impl X86DOTSECS {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
chunk_iteration: true,
chunk_size: 16384,
archetype_chunks: true,
component_simd: true,
max_entities_per_chunk: 128,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DDOTS_ECS".into()]
}
}
pub fn component_layout(&self) -> String {
"// DOTS component layout".to_string()
}
pub fn archetype_chunk_decl(&self) -> String {
format!(
"struct ArchetypeChunk {{ uint8_t data[{}]; }};",
self.chunk_size
)
}
}
impl Default for X86DOTSECS {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86UnityNativePlugin {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub plugin_name: String,
pub calling_convention: X86CallingConvention,
pub use_simd: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CallingConvention {
CDecl,
StdCall,
FastCall,
}
impl X86UnityNativePlugin {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
plugin_name: String::new(),
calling_convention: X86CallingConvention::CDecl,
use_simd: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DUNITY_NATIVE_PLUGIN".into()]
}
}
pub fn dllexport_macro(&self) -> &'static str {
"UNITY_INTERFACE_EXPORT"
}
pub fn plugin_function_template(&self) -> String {
"extern \"C\" UNITY_INTERFACE_EXPORT void MyPlugin_Func() {}".to_string()
}
}
impl Default for X86UnityNativePlugin {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GodotEngine {
pub enabled: bool,
pub version: String,
pub simd_level: X86GameSimdLevel,
pub gdnative: X86GDNative,
pub modules: X86GodotModules,
pub build_system: X86GodotBuildSystem,
}
impl X86GodotEngine {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
version: "4.3".into(),
simd_level,
gdnative: X86GDNative::default(),
modules: X86GodotModules::default(),
build_system: X86GodotBuildSystem::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DGODOT_ENGINE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
Vec::new()
}
}
impl Default for X86GodotEngine {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GDNative {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub library_name: String,
pub entry_symbol: String,
pub reloadable: bool,
pub singleton: bool,
pub use_gdextension: bool,
}
impl X86GDNative {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
library_name: String::new(),
entry_symbol: String::new(),
reloadable: false,
singleton: false,
use_gdextension: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DGDNATIVE".into()]
}
}
pub fn init_function(&self) -> String {
"extern \"C\" GDNativeBool GDN_EXPORT godot_gdnative_init(...)".to_string()
}
}
impl Default for X86GDNative {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GodotModules {
pub enabled: bool,
pub module_list: Vec<String>,
pub gdscript_enabled: bool,
pub mono_enabled: bool,
pub physics_enabled: bool,
pub navigation_enabled: bool,
}
impl X86GodotModules {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DGODOT_MODULES".into()]
}
}
pub fn scsub_template(&self) -> String {
"// SCons SCsub template".to_string()
}
}
impl Default for X86GodotModules {
fn default() -> Self {
Self {
enabled: false,
module_list: vec!["gdscript".into()],
gdscript_enabled: true,
mono_enabled: false,
physics_enabled: true,
navigation_enabled: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86GodotBuildSystem {
pub enabled: bool,
pub target: X86GodotBuildTarget,
pub platform: X86GodotPlatform,
pub scons_flags: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86GodotBuildTarget {
Editor,
TemplateDebug,
TemplateRelease,
}
impl X86GodotBuildTarget {
pub fn as_scons_target(&self) -> &str {
match self {
Self::Editor => "editor",
Self::TemplateDebug => "template_debug",
Self::TemplateRelease => "template_release",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86GodotPlatform {
LinuxX11,
LinuxWayland,
Windows,
MacOS,
}
impl X86GodotBuildSystem {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DGODOT_SCONS".into()]
}
}
pub fn sconstruct_template(&self) -> String {
"// SConstruct".to_string()
}
}
impl Default for X86GodotBuildSystem {
fn default() -> Self {
Self {
enabled: false,
target: X86GodotBuildTarget::TemplateDebug,
platform: X86GodotPlatform::LinuxX11,
scons_flags: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct X86CustomEngine {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub ecs: X86CustomECS,
pub job_system: X86CustomJobSystem,
pub asset_pipeline: X86CustomAssetPipeline,
}
impl X86CustomEngine {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
ecs: X86CustomECS::default(),
job_system: X86CustomJobSystem::default(),
asset_pipeline: X86CustomAssetPipeline::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DCUSTOM_ENGINE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
Vec::new()
}
}
impl Default for X86CustomEngine {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86CustomECS {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub archetype_storage: bool,
pub sparse_set: bool,
pub soa_layout: bool,
pub max_component_types: usize,
pub max_entities: usize,
}
impl X86CustomECS {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
archetype_storage: true,
sparse_set: false,
soa_layout: true,
max_component_types: 256,
max_entities: 1000000,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DCUSTOM_ECS".into()]
}
}
pub fn ecs_world_decl(&self) -> String {
"struct ECSWorld { ... };".to_string()
}
}
impl Default for X86CustomECS {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86CustomJobSystem {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub worker_threads: usize,
pub fiber_jobs: bool,
pub steal_queue_depth: usize,
pub job_graph: bool,
}
impl X86CustomJobSystem {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
worker_threads: num_cpus::get(),
fiber_jobs: false,
steal_queue_depth: 256,
job_graph: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DJOB_SYSTEM".into()]
}
}
pub fn job_system_decl(&self) -> String {
"struct JobSystem { ... };".to_string()
}
}
impl Default for X86CustomJobSystem {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86CustomAssetPipeline {
pub enabled: bool,
pub asset_path: PathBuf,
pub compression: bool,
pub compression_algo: X86AssetCompression,
pub hot_reload: bool,
pub async_loading: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AssetCompression {
None,
LZ4,
Zstd,
Zlib,
Brotli,
}
impl X86CustomAssetPipeline {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DASSET_PIPELINE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
match self.compression_algo {
X86AssetCompression::LZ4 => vec!["-llz4".into()],
X86AssetCompression::Zstd => vec!["-lzstd".into()],
X86AssetCompression::Zlib => vec!["-lz".into()],
X86AssetCompression::Brotli => vec!["-lbrotli".into()],
_ => Vec::new(),
}
}
}
}
impl Default for X86CustomAssetPipeline {
fn default() -> Self {
Self {
enabled: false,
asset_path: PathBuf::new(),
compression: false,
compression_algo: X86AssetCompression::LZ4,
hot_reload: false,
async_loading: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86GameGraphics {
pub simd_level: X86GameSimdLevel,
pub directx: X86DirectXSupport,
pub vulkan: X86VulkanSupport,
pub opengl: X86OpenGLSupport,
pub metal: X86MetalSupport,
}
impl X86GameGraphics {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
directx: X86DirectXSupport::default(),
vulkan: X86VulkanSupport::default(),
opengl: X86OpenGLSupport::default(),
metal: X86MetalSupport::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.directx.compile_flags());
f.extend(self.vulkan.compile_flags());
f.extend(self.opengl.compile_flags());
f.extend(self.metal.compile_flags());
f
}
pub fn linker_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.directx.linker_flags());
f.extend(self.vulkan.linker_flags());
f.extend(self.opengl.linker_flags());
f
}
pub fn describe(&self) -> String {
format!(
"graphics(dx={}, vk={}, gl={})",
self.directx.enabled, self.vulkan.enabled, self.opengl.enabled
)
}
}
impl Default for X86GameGraphics {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86DirectXSupport {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub shader_model: X86ShaderModel,
pub dxc_path: Option<PathBuf>,
pub use_dxil: bool,
pub pso_compilation: bool,
pub shader_reflection: bool,
pub root_signature: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ShaderModel {
SM50,
SM51,
SM60,
SM65,
SM67,
}
impl X86DirectXSupport {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
shader_model: X86ShaderModel::SM60,
dxc_path: None,
use_dxil: true,
pso_compilation: false,
shader_reflection: false,
root_signature: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DDIRECTX12".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-ld3d12".into(), "-ldxgi".into(), "-ldxcompiler".into()]
}
}
pub fn dxc_command(&self) -> Vec<String> {
vec!["dxc".into()]
}
pub fn pso_description_template(&self) -> String {
"D3D12_GRAPHICS_PIPELINE_STATE_DESC".to_string()
}
pub fn hlsl_template(&self) -> String {
"// HLSL shader template".to_string()
}
}
impl X86ShaderModel {
pub fn version(&self) -> &str {
match self {
Self::SM50 => "5_0",
Self::SM51 => "5_1",
Self::SM60 => "6_0",
Self::SM65 => "6_5",
Self::SM67 => "6_7",
}
}
pub fn dxil_validator_version(&self) -> &str {
"1.7"
}
}
impl Default for X86DirectXSupport {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86VulkanSupport {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub sdk_path: Option<PathBuf>,
pub glslang_path: Option<PathBuf>,
pub dxc_path: Option<PathBuf>,
pub spirv_opt_path: Option<PathBuf>,
pub spirv_optimize: bool,
pub pipeline_cache: bool,
pub validation_layers: bool,
pub api_version: X86VulkanVersion,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86VulkanVersion {
V1_0,
V1_1,
V1_2,
V1_3,
}
impl X86VulkanVersion {
pub fn as_u32(&self) -> u32 {
match self {
Self::V1_0 => 0x00402000,
Self::V1_1 => 0x00402800,
Self::V1_2 => 0x00403000,
Self::V1_3 => 0x00404000,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::V1_0 => "1.0",
Self::V1_1 => "1.1",
Self::V1_2 => "1.2",
Self::V1_3 => "1.3",
}
}
}
impl X86VulkanSupport {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
sdk_path: None,
glslang_path: None,
dxc_path: None,
spirv_opt_path: None,
spirv_optimize: false,
pipeline_cache: false,
validation_layers: true,
api_version: X86VulkanVersion::V1_3,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
let mut f = vec!["-DVULKAN".into()];
if self.validation_layers {
f.push("-DVK_VALIDATION".into());
}
f
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lvulkan".into()]
}
}
pub fn glslang_command(&self) -> Vec<String> {
vec!["glslangValidator".into()]
}
pub fn spirv_opt_command(&self) -> Vec<String> {
vec!["spirv-opt".into()]
}
pub fn pipeline_cache_header(&self) -> String {
"// Pipeline cache header".to_string()
}
pub fn spirv_format_constants(&self) -> String {
"// SPIR-V format constants".to_string()
}
}
impl Default for X86VulkanSupport {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86OpenGLSupport {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub gl_version: X86OpenGLVersion,
pub glsl_version: X86GLSLVersion,
pub gles: bool,
pub use_glad: bool,
pub use_glew: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86OpenGLVersion {
GL33,
GL43,
GL46,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86GLSLVersion {
GLSL330,
GLSL430,
GLSL460,
}
impl X86OpenGLSupport {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
gl_version: X86OpenGLVersion::GL46,
glsl_version: X86GLSLVersion::GLSL460,
gles: false,
use_glad: true,
use_glew: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
let mut f = vec![
"-DOPENGL".into(),
format!("-DGL_VERSION_{}", self.gl_version.as_gl_version()),
];
if self.gles {
f.push("-DOPENGL_ES".into());
}
f
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lGL".into()]
}
}
pub fn glsl_version_pragma(&self) -> String {
format!("#version {}", self.glsl_version.as_str())
}
pub fn vertex_shader_template(&self) -> String {
"#version 460\nlayout(location=0) in vec3 aPos;\nvoid main() { gl_Position = vec4(aPos,1.0); }".to_string()
}
pub fn fragment_shader_template(&self) -> String {
"#version 460\nout vec4 FragColor;\nvoid main() { FragColor = vec4(1.0); }".to_string()
}
}
impl X86GLSLVersion {
pub fn as_str(&self) -> &str {
match self {
Self::GLSL330 => "330 core",
Self::GLSL430 => "430 core",
Self::GLSL460 => "460 core",
}
}
}
impl X86OpenGLVersion {
fn as_gl_version(&self) -> &str {
match self {
Self::GL33 => "33",
Self::GL43 => "43",
Self::GL46 => "46",
}
}
}
impl Default for X86OpenGLSupport {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86MetalSupport {
pub enabled: bool,
pub msl_version: X86MSLVersion,
pub use_shader_converter: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86MSLVersion {
MSL23,
MSL24,
MSL30,
}
impl X86MetalSupport {
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DMETAL".into()]
}
}
pub fn msl_shader_template(&self) -> String {
"#include <metal_stdlib>\nusing namespace metal;\n".to_string()
}
pub fn msl_version_pragma(&self) -> String {
"#pragma clang metal 3.0".to_string()
}
}
impl X86MSLVersion {
pub fn as_str(&self) -> &str {
match self {
Self::MSL23 => "2.3",
Self::MSL24 => "2.4",
Self::MSL30 => "3.0",
}
}
}
impl Default for X86MetalSupport {
fn default() -> Self {
Self {
enabled: false,
msl_version: X86MSLVersion::MSL30,
use_shader_converter: false,
}
}
}
#[derive(Debug, Clone)]
pub struct X86GamePhysics {
pub simd_level: X86GameSimdLevel,
pub bullet: X86BulletPhysics,
pub physx: X86PhysX,
pub custom: X86CustomPhysics,
}
impl X86GamePhysics {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
bullet: X86BulletPhysics::default(),
physx: X86PhysX::default(),
custom: X86CustomPhysics::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.bullet.compile_flags());
f.extend(self.physx.compile_flags());
f.extend(self.custom.compile_flags());
f
}
pub fn linker_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.bullet.linker_flags());
f.extend(self.physx.linker_flags());
f
}
pub fn describe(&self) -> String {
format!(
"physics(bullet={}, physx={})",
self.bullet.enabled, self.physx.enabled
)
}
}
impl Default for X86GamePhysics {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86BulletPhysics {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub multithreading: bool,
pub double_precision: bool,
pub soft_body: bool,
pub broadphase: X86BulletBroadphase,
pub solver_iterations: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BulletBroadphase {
Simple,
AxisSweep3,
DBVT,
MultiSAP,
}
impl X86BulletPhysics {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "3.25".into(),
multithreading: false,
double_precision: false,
soft_body: false,
broadphase: X86BulletBroadphase::DBVT,
solver_iterations: 10,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DBULLET_PHYSICS".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec![
"-lBulletDynamics".into(),
"-lBulletCollision".into(),
"-lLinearMath".into(),
]
}
}
}
impl Default for X86BulletPhysics {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86PhysX {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub cuda_enabled: bool,
pub vehicle: bool,
pub cloth: bool,
pub fluid: bool,
pub character_controller: bool,
}
impl X86PhysX {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "5.3".into(),
cuda_enabled: false,
vehicle: false,
cloth: false,
fluid: false,
character_controller: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DPHYSX".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lPhysX".into(), "-lPhysXCommon".into()]
}
}
}
impl Default for X86PhysX {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86CustomPhysics {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub simd_broadphase: bool,
pub simd_narrowphase: bool,
pub simd_constraints: bool,
pub broadphase_algo: X86CustomBroadphase,
pub narrowphase_algo: X86CustomNarrowphase,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CustomBroadphase {
BruteForce,
Grid,
DBVT,
SweepAndPrune,
MultiBoxPruning,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CustomNarrowphase {
SAT,
GJK,
EPA,
MPR,
GjkEpa,
}
impl X86CustomPhysics {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
simd_broadphase: false,
simd_narrowphase: true,
simd_constraints: false,
broadphase_algo: X86CustomBroadphase::DBVT,
narrowphase_algo: X86CustomNarrowphase::GjkEpa,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DCUSTOM_PHYSICS".into()]
}
}
pub fn aabb_intersect_simd(&self) -> String {
"// AABB intersect SIMD".to_string()
}
pub fn gjk_support_simd(&self) -> String {
"// GJK support SIMD".to_string()
}
}
impl Default for X86CustomPhysics {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GameAudio {
pub simd_level: X86GameSimdLevel,
pub fmod: X86FMODIntegration,
pub wwise: X86WwiseIntegration,
pub openal: X86OpenALSoft,
pub custom_dsp: X86CustomDSP,
}
impl X86GameAudio {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
fmod: X86FMODIntegration::default(),
wwise: X86WwiseIntegration::default(),
openal: X86OpenALSoft::default(),
custom_dsp: X86CustomDSP::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.fmod.compile_flags());
f.extend(self.wwise.compile_flags());
f.extend(self.openal.compile_flags());
f.extend(self.custom_dsp.compile_flags());
f
}
pub fn linker_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.fmod.linker_flags());
f.extend(self.wwise.linker_flags());
f.extend(self.openal.linker_flags());
f
}
pub fn describe(&self) -> String {
format!(
"audio(fmod={}, wwise={}, openal={})",
self.fmod.enabled, self.wwise.enabled, self.openal.enabled
)
}
}
impl Default for X86GameAudio {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86FMODIntegration {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub sdk_path: Option<PathBuf>,
pub low_level_api: bool,
pub studio_api: bool,
pub max_channels: usize,
pub dsp_plugins: bool,
}
impl X86FMODIntegration {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "2.02".into(),
sdk_path: None,
low_level_api: true,
studio_api: false,
max_channels: 512,
dsp_plugins: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DFMOD".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lfmod".into()]
}
}
}
impl Default for X86FMODIntegration {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86WwiseIntegration {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub sdk_path: Option<PathBuf>,
pub sound_engine: bool,
pub communication: bool,
pub motion: bool,
}
impl X86WwiseIntegration {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "2023.1".into(),
sdk_path: None,
sound_engine: true,
communication: false,
motion: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DWWISE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lWwise".into()]
}
}
}
impl Default for X86WwiseIntegration {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86OpenALSoft {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub hrtf: bool,
pub efx: bool,
pub capture: bool,
pub max_sources: usize,
pub sample_rate: u32,
}
impl X86OpenALSoft {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "1.23".into(),
hrtf: false,
efx: false,
capture: false,
max_sources: 256,
sample_rate: 48000,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DOPENAL_SOFT".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lopenal".into()]
}
}
}
impl Default for X86OpenALSoft {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86CustomDSP {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub fir_simd: bool,
pub iir_simd: bool,
pub fft_simd: bool,
pub fir_taps: usize,
pub block_size: usize,
}
impl X86CustomDSP {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
fir_simd: true,
iir_simd: true,
fft_simd: true,
fir_taps: 128,
block_size: 256,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DCUSTOM_DSP".into()]
}
}
pub fn fir_filter_simd(&self) -> String {
"// FIR filter SIMD".to_string()
}
pub fn iir_biquad_simd(&self) -> String {
"// IIR biquad SIMD".to_string()
}
}
impl Default for X86CustomDSP {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GameNetworking {
pub simd_level: X86GameSimdLevel,
pub enet: X86ENetIntegration,
pub raknet: X86RakNetIntegration,
pub gns: X86GameNetworkingSockets,
pub lockstep: X86LockstepCompilation,
pub serialization: X86NetworkSerialization,
}
impl X86GameNetworking {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
enet: X86ENetIntegration::default(),
raknet: X86RakNetIntegration::default(),
gns: X86GameNetworkingSockets::default(),
lockstep: X86LockstepCompilation::default(),
serialization: X86NetworkSerialization::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.enet.compile_flags());
f.extend(self.raknet.compile_flags());
f.extend(self.gns.compile_flags());
f.extend(self.lockstep.compile_flags());
f.extend(self.serialization.compile_flags());
f
}
pub fn linker_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.enet.linker_flags());
f.extend(self.raknet.linker_flags());
f.extend(self.gns.linker_flags());
f
}
pub fn describe(&self) -> String {
format!(
"net_libs(enet={}, raknet={})",
self.enet.enabled, self.raknet.enabled
)
}
}
impl Default for X86GameNetworking {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86ENetIntegration {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub max_clients: usize,
pub max_channels: usize,
pub bandwidth_limit: usize,
}
impl X86ENetIntegration {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "1.3".into(),
max_clients: 32,
max_channels: 255,
bandwidth_limit: 0,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DENET".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lenet".into()]
}
}
}
impl Default for X86ENetIntegration {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86RakNetIntegration {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub reliable_udp: bool,
pub nat_punchthrough: bool,
pub voice: bool,
}
impl X86RakNetIntegration {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "4.0".into(),
reliable_udp: true,
nat_punchthrough: false,
voice: false,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DRAKNET".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lRakNet".into()]
}
}
}
impl Default for X86RakNetIntegration {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GameNetworkingSockets {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub steam_datagram: bool,
pub encrypted_p2p: bool,
}
impl X86GameNetworkingSockets {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "1.4".into(),
steam_datagram: false,
encrypted_p2p: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DGAME_NETWORKING_SOCKETS".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lGameNetworkingSockets".into()]
}
}
}
impl Default for X86GameNetworkingSockets {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86LockstepCompilation {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub sim_steps_per_second: u32,
pub strict_fp: bool,
pub single_threaded: bool,
pub checksum: bool,
}
impl X86LockstepCompilation {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
sim_steps_per_second: 30,
strict_fp: true,
single_threaded: true,
checksum: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
let mut f = vec!["-DLOCKSTEP".into()];
if self.strict_fp {
f.push("-ffloat-store".into());
f.push("-fno-fast-math".into());
}
f
}
}
}
impl Default for X86LockstepCompilation {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86NetworkSerialization {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub bit_packing: bool,
pub delta_compression: bool,
pub simd_serialize: bool,
pub integer_compression: bool,
pub max_packet_size: usize,
}
impl X86NetworkSerialization {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
bit_packing: true,
delta_compression: true,
simd_serialize: false,
integer_compression: true,
max_packet_size: 1400,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DNET_SERIALIZATION".into()]
}
}
pub fn simd_memcpy(&self) -> String {
"// SIMD memcpy".to_string()
}
pub fn bit_packer_decl(&self) -> String {
"// Bit packer decl".to_string()
}
}
impl Default for X86NetworkSerialization {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GameProfiling {
pub simd_level: X86GameSimdLevel,
pub tracy: X86TracyProfiler,
pub optick: X86OptickProfiler,
pub pix: X86PIXProfiler,
pub frame_timing: X86FrameTiming,
pub gpu_timers: X86GPUTimers,
}
impl X86GameProfiling {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
simd_level,
tracy: X86TracyProfiler::default(),
optick: X86OptickProfiler::default(),
pix: X86PIXProfiler::default(),
frame_timing: X86FrameTiming::default(),
gpu_timers: X86GPUTimers::default(),
}
}
pub fn compile_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.tracy.compile_flags());
f.extend(self.optick.compile_flags());
f.extend(self.pix.compile_flags());
f.extend(self.frame_timing.compile_flags());
f.extend(self.gpu_timers.compile_flags());
f
}
pub fn linker_flags(&self) -> Vec<String> {
let mut f = Vec::new();
f.extend(self.tracy.linker_flags());
f.extend(self.optick.linker_flags());
f
}
pub fn describe(&self) -> String {
format!(
"profiling(tracy={}, optick={})",
self.tracy.enabled, self.optick.enabled
)
}
}
impl Default for X86GameProfiling {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86TracyProfiler {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub on_demand: bool,
pub fiber_support: bool,
pub callstack: bool,
pub gpu_profiling: bool,
pub port: u16,
}
impl X86TracyProfiler {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "0.10".into(),
on_demand: false,
fiber_support: false,
callstack: true,
gpu_profiling: false,
port: 8086,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DTRACY_ENABLE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-ldl".into(), "-lpthread".into()]
}
}
pub fn zone_macro(&self) -> &str {
"ZoneScoped"
}
}
impl Default for X86TracyProfiler {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86OptickProfiler {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub version: String,
pub gpu_profiling: bool,
pub fiber_profiling: bool,
pub sampling_hz: u32,
}
impl X86OptickProfiler {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
version: "1.4".into(),
gpu_profiling: false,
fiber_profiling: false,
sampling_hz: 1000,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DOPTICK_ENABLE".into()]
}
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-lOptickCore".into()]
}
}
pub fn optick_macros(&self) -> String {
"#define OPTICK_EVENT()".to_string()
}
}
impl Default for X86OptickProfiler {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86PIXProfiler {
pub enabled: bool,
pub version: String,
pub gpu_captures: bool,
pub timing_captures: bool,
}
impl X86PIXProfiler {
pub fn new() -> Self {
Self {
enabled: false,
version: "latest".into(),
gpu_captures: false,
timing_captures: true,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DPIX_ENABLE".into()]
}
}
pub fn pix_macros(&self) -> String {
"#define PIX_BEGIN_EVENT()".to_string()
}
pub fn pix_gpu_macros(&self) -> String {
"#define PIX_BEGIN_GPU_EVENT()".to_string()
}
}
impl Default for X86PIXProfiler {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86FrameTiming {
pub enabled: bool,
pub simd_level: X86GameSimdLevel,
pub cpu_timing: bool,
pub phase_timing: bool,
pub resolution_ns: u64,
pub history_frames: usize,
}
impl X86FrameTiming {
pub fn new(simd_level: X86GameSimdLevel) -> Self {
Self {
enabled: false,
simd_level,
cpu_timing: true,
phase_timing: false,
resolution_ns: 100,
history_frames: 120,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DFRAME_TIMING".into()]
}
}
pub fn rdtsc_timing(&self) -> String {
"uint64_t t = __rdtsc();".to_string()
}
pub fn frame_stats_decl(&self) -> String {
"struct FrameStats { ... };".to_string()
}
}
impl Default for X86FrameTiming {
fn default() -> Self {
Self::new(X86GameSimdLevel::default())
}
}
#[derive(Debug, Clone)]
pub struct X86GPUTimers {
pub enabled: bool,
pub timestamp_queries: bool,
pub pipeline_stats: bool,
pub max_pending_queries: usize,
pub queries_per_frame: usize,
}
impl X86GPUTimers {
pub fn new() -> Self {
Self {
enabled: false,
timestamp_queries: true,
pipeline_stats: false,
max_pending_queries: 16,
queries_per_frame: 64,
}
}
pub fn compile_flags(&self) -> Vec<String> {
if !self.enabled {
Vec::new()
} else {
vec!["-DGPU_TIMERS".into()]
}
}
pub fn gpu_timer_vulkan(&self) -> String {
"// Vulkan GPU timer".to_string()
}
pub fn gpu_timer_d3d12(&self) -> String {
"// D3D12 GPU timer".to_string()
}
}
impl Default for X86GPUTimers {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86ReliableUDP {
pub max_sequence: u32,
pub resend_timeout_ms: u32,
pub max_resends: usize,
pub packet_history: usize,
}
impl X86ReliableUDP {
pub fn new() -> Self {
Self {
max_sequence: 65536,
resend_timeout_ms: 200,
max_resends: 10,
packet_history: 1024,
}
}
pub fn reliable_udp_code(&self) -> String {
format!(
r#"// Reliable UDP layer
#define RELIABLE_UDP_SEQ_MOD {}
#define RELIABLE_UDP_RESEND_MS {}
typedef struct {{
uint16_t sequence;
uint16_t ack;
uint32_t ack_bitfield;
uint8_t flags;
}} ReliableUDPHeader;
typedef struct {{
uint8_t data[1500];
int length;
uint16_t sequence;
uint64_t send_time;
int resend_count;
}} ReliableUDPSendEntry;
typedef struct {{
ReliableUDPSendEntry send_history[{hist}];
uint16_t next_sequence;
uint16_t last_recv_sequence;
uint32_t recv_ack_bitfield;
int sock;
struct sockaddr_in remote;
}} ReliableUDPConnection;
static int reliable_udp_send(ReliableUDPConnection* conn, const uint8_t* data, int len) {{
ReliableUDPHeader hdr;
hdr.sequence = conn->next_sequence;
hdr.ack = conn->last_recv_sequence;
hdr.ack_bitfield = conn->recv_ack_bitfield;
hdr.flags = 0;
uint8_t packet[1500];
memcpy(packet, &hdr, sizeof(hdr));
memcpy(packet + sizeof(hdr), data, len);
int idx = conn->next_sequence % {hist};
memcpy(conn->send_history[idx].data, data, len);
conn->send_history[idx].length = len;
conn->send_history[idx].sequence = conn->next_sequence;
conn->send_history[idx].send_time = get_time_ms();
conn->send_history[idx].resend_count = 0;
conn->next_sequence = (conn->next_sequence + 1) % RELIABLE_UDP_SEQ_MOD;
return sendto(conn->sock, packet, sizeof(hdr) + len, 0, (struct sockaddr*)&conn->remote, sizeof(conn->remote));
}}
static void reliable_udp_update(ReliableUDPConnection* conn) {{
uint64_t now = get_time_ms();
for (int i = 0; i < {hist}; i++) {{
ReliableUDPSendEntry* e = &conn->send_history[i];
if (e->length == 0) continue;
if (now - e->send_time > RELIABLE_UDP_RESEND_MS && e->resend_count < {max_resend}) {{
ReliableUDPHeader hdr;
hdr.sequence = e->sequence;
hdr.ack = conn->last_recv_sequence;
hdr.ack_bitfield = conn->recv_ack_bitfield;
hdr.flags = 1; // resend flag
uint8_t packet[1500];
memcpy(packet, &hdr, sizeof(hdr));
memcpy(packet + sizeof(hdr), e->data, e->length);
sendto(conn->sock, packet, sizeof(hdr) + e->length, 0, (struct sockaddr*)&conn->remote, sizeof(conn->remote));
e->send_time = now;
e->resend_count++;
}}
if (e->resend_count >= {max_resend}) e->length = 0; // give up
}}
}}
"#,
self.max_sequence,
self.resend_timeout_ms,
hist = self.packet_history,
max_resend = self.max_resends
)
}
}
impl Default for X86ReliableUDP {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86InterpolationBuffer {
pub buffer_size: usize,
pub interp_delay_ms: u32,
}
impl X86InterpolationBuffer {
pub fn new() -> Self {
Self {
buffer_size: 32,
interp_delay_ms: 100,
}
}
pub fn interpolation_code(&self) -> String {
format!(
r#"// Entity interpolation buffer
#define INTERP_BUFFER_SIZE {}
#define INTERP_DELAY_MS {}
typedef struct {{
uint64_t timestamp_ms;
float x, y, z;
float qx, qy, qz, qw;
}} InterpSnapshot;
typedef struct {{
InterpSnapshot snapshots[INTERP_BUFFER_SIZE];
int count;
int head;
}} InterpBuffer;
static bool interp_buffer_get(InterpBuffer* buf, uint64_t render_time,
float* out_x, float* out_y, float* out_z,
float* out_qx, float* out_qy, float* out_qz, float* out_qw) {{
if (buf->count < 2) return false;
uint64_t target = render_time - INTERP_DELAY_MS;
// Find the two snapshots surrounding target time
InterpSnapshot* s0 = NULL;
InterpSnapshot* s1 = NULL;
for (int i = 0; i < buf->count; i++) {{
int idx = (buf->head - 1 - i + INTERP_BUFFER_SIZE) % INTERP_BUFFER_SIZE;
if (buf->snapshots[idx].timestamp_ms <= target) {{
s1 = &buf->snapshots[idx];
s0 = (i + 1 < buf->count) ? &buf->snapshots[(idx - 1 + INTERP_BUFFER_SIZE) % INTERP_BUFFER_SIZE] : s1;
break;
}}
}}
if (!s0 || !s1) return false;
float t = (s1->timestamp_ms > s0->timestamp_ms)
? (float)(target - s0->timestamp_ms) / (float)(s1->timestamp_ms - s0->timestamp_ms)
: 0.0f;
if (t < 0.0f) t = 0.0f;
if (t > 1.0f) t = 1.0f;
*out_x = s0->x + (s1->x - s0->x) * t;
*out_y = s0->y + (s1->y - s0->y) * t;
*out_z = s0->z + (s1->z - s0->z) * t;
// Quaternion slerp for rotation
float d = s0->qx*s1->qx + s0->qy*s1->qy + s0->qz*s1->qz + s0->qw*s1->qw;
if (d > 0.9995f) {{ *out_qx = s0->qx + (s1->qx - s0->qx) * t; /* nlerp fallback */ return true; }}
float theta = acosf(d);
float sin_theta = sinf(theta);
float w0 = sinf((1.0f - t) * theta) / sin_theta;
float w1 = sinf(t * theta) / sin_theta;
*out_qx = w0 * s0->qx + w1 * s1->qx;
*out_qy = w0 * s0->qy + w1 * s1->qy;
*out_qz = w0 * s0->qz + w1 * s1->qz;
*out_qw = w0 * s0->qw + w1 * s1->qw;
return true;
}}
"#,
self.buffer_size, self.interp_delay_ms
)
}
}
impl Default for X86InterpolationBuffer {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86JacobianSolver {
pub velocity_iterations: usize,
pub position_iterations: usize,
pub warm_starting: bool,
pub baumgarte: f32,
pub slop: f32,
}
impl X86JacobianSolver {
pub fn new() -> Self {
Self {
velocity_iterations: 8,
position_iterations: 3,
warm_starting: true,
baumgarte: 0.2,
slop: 0.005,
}
}
pub fn solver_code(&self) -> String {
format!(
r#"// Jacobian Sequential Impulse Solver
#define VELOCITY_ITERS {}
#define POSITION_ITERS {}
#define BAUMGARTE {}
#define ALLOWED_SLOP {}
typedef struct {{
float n_x, n_y, n_z; // normal
float r1_x, r1_y, r1_z; // contact arm on body A
float r2_x, r2_y, r2_z; // contact arm on body B
float inv_mass_sum;
float inv_inertia_sum;
float bias;
float normal_mass;
float tangent1_mass;
float tangent2_mass;
float accumulated_normal_impulse;
float accumulated_tangent1_impulse;
float accumulated_tangent2_impulse;
float friction;
float restitution;
int body_a;
int body_b;
}} ContactConstraint;
static void solve_contact_constraints(ContactConstraint* constraints, int count,
RigidBody* bodies, float dt) {{
for (int iteration = 0; iteration < VELOCITY_ITERS; iteration++) {{
for (int i = 0; i < count; i++) {{
ContactConstraint* c = &constraints[i];
RigidBody* a = &bodies[c->body_a];
RigidBody* b = &bodies[c->body_b];
// Compute relative velocity at contact point
float dvx = (b->vx + b->wz*c->r2_y - b->wy*c->r2_z)
- (a->vx + a->wz*c->r1_y - a->wy*c->r1_z);
float dvy = (b->vy + b->wx*c->r2_z - b->wz*c->r2_x)
- (a->vy + a->wx*c->r1_z - a->wz*c->r1_x);
float dvz = (b->vz + b->wy*c->r2_x - b->wx*c->r2_y)
- (a->vz + a->wy*c->r1_x - a->wx*c->r1_y);
// Normal impulse
float vn = dvx*c->n_x + dvy*c->n_y + dvz*c->n_z;
float dp = -(vn + c->bias) * c->normal_mass;
float p0 = c->accumulated_normal_impulse;
c->accumulated_normal_impulse = fmaxf(p0 + dp, 0.0f);
dp = c->accumulated_normal_impulse - p0;
// Apply impulse
a->vx -= dp * c->n_x * a->inv_mass;
a->vy -= dp * c->n_y * a->inv_mass;
a->vz -= dp * c->n_z * a->inv_mass;
b->vx += dp * c->n_x * b->inv_mass;
b->vy += dp * c->n_y * b->inv_mass;
b->vz += dp * c->n_z * b->inv_mass;
}}
}}
}}
static void solve_position_constraints(ContactConstraint* constraints, int count,
RigidBody* bodies) {{
for (int iteration = 0; iteration < POSITION_ITERS; iteration++) {{
for (int i = 0; i < count; i++) {{
ContactConstraint* c = &constraints[i];
RigidBody* a = &bodies[c->body_a];
RigidBody* b = &bodies[c->body_b];
// Compute penetration
float dx = b->px - a->px;
float dy = b->py - a->py;
float dz = b->pz - a->pz;
float d = dx*c->n_x + dy*c->n_y + dz*c->n_z;
float correction = fmaxf(d - ALLOWED_SLOP, 0.0f) * BAUMGARTE * c->normal_mass;
a->px -= correction * c->n_x * a->inv_mass;
a->py -= correction * c->n_y * a->inv_mass;
a->pz -= correction * c->n_z * a->inv_mass;
b->px += correction * c->n_x * b->inv_mass;
b->py += correction * c->n_y * b->inv_mass;
b->pz += correction * c->n_z * b->inv_mass;
}}
}}
}}
"#,
self.velocity_iterations, self.position_iterations, self.baumgarte, self.slop
)
}
}
impl Default for X86JacobianSolver {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86FilterDesigner {
pub sample_rate: u32,
}
impl X86FilterDesigner {
pub fn new(sample_rate: u32) -> Self {
Self { sample_rate }
}
pub fn lowpass_coeffs(&self, cutoff: f32, q: f32) -> (f32, f32, f32, f32, f32) {
let w0 = 2.0 * std::f32::consts::PI * cutoff / self.sample_rate as f32;
let alpha = w0.sin() / (2.0 * q);
let cos_w0 = w0.cos();
let b0 = (1.0 - cos_w0) / 2.0;
let b1 = 1.0 - cos_w0;
let b2 = (1.0 - cos_w0) / 2.0;
let a0 = 1.0 + alpha;
let a1 = -2.0 * cos_w0;
let a2 = 1.0 - alpha;
(b0 / a0, b1 / a0, b2 / a0, a1 / a0, a2 / a0)
}
pub fn highpass_coeffs(&self, cutoff: f32, q: f32) -> (f32, f32, f32, f32, f32) {
let w0 = 2.0 * std::f32::consts::PI * cutoff / self.sample_rate as f32;
let alpha = w0.sin() / (2.0 * q);
let cos_w0 = w0.cos();
let b0 = (1.0 + cos_w0) / 2.0;
let b1 = -(1.0 + cos_w0);
let b2 = (1.0 + cos_w0) / 2.0;
let a0 = 1.0 + alpha;
let a1 = -2.0 * cos_w0;
let a2 = 1.0 - alpha;
(b0 / a0, b1 / a0, b2 / a0, a1 / a0, a2 / a0)
}
pub fn bandpass_coeffs(&self, center: f32, bandwidth: f32) -> (f32, f32, f32, f32, f32) {
let w0 = 2.0 * std::f32::consts::PI * center / self.sample_rate as f32;
let bw = 2.0 * std::f32::consts::PI * bandwidth / self.sample_rate as f32;
let alpha = w0.sin() * bw.sinh();
let cos_w0 = w0.cos();
let b0 = alpha;
let b1 = 0.0;
let b2 = -alpha;
let a0 = 1.0 + alpha;
let a1 = -2.0 * cos_w0;
let a2 = 1.0 - alpha;
(b0 / a0, b1 / a0, b2 / a0, a1 / a0, a2 / a0)
}
pub fn simd_quad_biquad_code(&self) -> String {
r#"// SIMD 4-channel parallel biquad filter
#include <xmmintrin.h>
typedef struct {
__m128 b0, b1, b2, a1, a2;
__m128 z1, z2;
} BiquadQuad;
static inline void biquad_quad_process(BiquadQuad* f, float* out,
const float* in0, const float* in1,
const float* in2, const float* in3, int n) {
for (int i = 0; i < n; i++) {
__m128 x = _mm_set_ps(in3[i], in2[i], in1[i], in0[i]);
__m128 y = _mm_add_ps(_mm_mul_ps(f->b0, x), f->z1);
f->z1 = _mm_add_ps(
_mm_sub_ps(_mm_mul_ps(f->b1, x), _mm_mul_ps(f->a1, y)),
f->z2);
f->z2 = _mm_sub_ps(
_mm_mul_ps(f->b2, x), _mm_mul_ps(f->a2, y));
_mm_store_ps(out + i*4, y); // Note: channel order reversed by _mm_set_ps
}
}
"#
.to_string()
}
}
#[derive(Debug, Clone)]
pub struct X86Radix4FFT {
pub max_size: usize,
}
impl X86Radix4FFT {
pub fn new(max_size: usize) -> Self {
Self { max_size }
}
pub fn radix4_code(&self) -> String {
r#"// Radix-4 FFT — processes 4 points per butterfly
#include <math.h>
static void fft_radix4(float* real, float* imag, int n) {
// Bit-reversal permutation (radix-4)
int j = 0;
for (int i = 0; i < n; i++) {
if (i < j) {
float tr = real[i]; real[i] = real[j]; real[j] = tr;
float ti = imag[i]; imag[i] = imag[j]; imag[j] = ti;
}
int m = n >> 2;
while (m >= 1 && j >= 3 * m) { j -= 3 * m; m >>= 2; }
j += m;
}
// Radix-4 butterflies
for (int s = 4; s <= n; s <<= 2) {
int m = s >> 2;
for (int k = 0; k < n; k += s) {
for (int j = 0; j < m; j++) {
float angle0 = -2.0f * M_PI * (float)j / (float)s;
float angle1 = 2.0f * angle0;
float angle2 = 3.0f * angle0;
float w1r = cosf(angle0), w1i = sinf(angle0);
float w2r = cosf(angle1), w2i = sinf(angle1);
float w3r = cosf(angle2), w3i = sinf(angle2);
int i0 = k + j;
int i1 = i0 + m;
int i2 = i0 + 2 * m;
int i3 = i0 + 3 * m;
float t0r = real[i1] * w1r - imag[i1] * w1i;
float t0i = real[i1] * w1i + imag[i1] * w1r;
float t1r = real[i2] * w2r - imag[i2] * w2i;
float t1i = real[i2] * w2i + imag[i2] * w2r;
float t2r = real[i3] * w3r - imag[i3] * w3i;
float t2i = real[i3] * w3i + imag[i3] * w3r;
float u0r = real[i0] + t0r + t1r + t2r;
float u0i = imag[i0] + t0i + t1i + t2i;
float u1r = real[i0] - t0i - t1r + t2i;
float u1i = imag[i0] + t0r - t1i - t2r;
float u2r = real[i0] - t0r + t1r - t2r;
float u2i = imag[i0] - t0i + t1i - t2i;
float u3r = real[i0] + t0i - t1r - t2i;
float u3i = imag[i0] - t0r - t1i + t2r;
real[i0] = u0r; imag[i0] = u0i;
real[i1] = u1r; imag[i1] = u1i;
real[i2] = u2r; imag[i2] = u2i;
real[i3] = u3r; imag[i3] = u3i;
}
}
}
// Handle remaining radix-2 stage if n is not a power of 4
if ((n & (n - 1)) == 0 && (n & 0x55555555) != n) {
// Fallback to radix-2 on final stage
for (int i = 0; i < n; i += 2) {
float tr = real[i] + real[i+1];
float ti = imag[i] + imag[i+1];
real[i+1] = real[i] - real[i+1];
imag[i+1] = imag[i] - imag[i+1];
real[i] = tr; imag[i] = ti;
}
}
}
"#
.to_string()
}
}
#[derive(Debug, Clone)]
pub struct X86AdditiveAnimation {
pub base_pose: Vec<X86Mat4>,
pub additive_clips: Vec<X86AnimationClip>,
pub weight: f32,
}
impl X86AdditiveAnimation {
pub fn new() -> Self {
Self {
base_pose: Vec::new(),
additive_clips: Vec::new(),
weight: 1.0,
}
}
pub fn apply_additive(&self, time: f32, skeleton: &X86Skeleton) -> Vec<X86Mat4> {
let n = skeleton.bones.len();
let mut result = vec![X86Mat4::identity(); n];
for i in 0..n {
result[i] = if i < self.base_pose.len() {
self.base_pose[i]
} else {
X86Mat4::identity()
};
}
for clip in &self.additive_clips {
let poses = clip.sample(time, skeleton);
for i in 0..n.min(poses.len()) {
let add_tx = poses[i].m[0][3];
let add_ty = poses[i].m[1][3];
let add_tz = poses[i].m[2][3];
result[i].m[0][3] += add_tx * self.weight;
result[i].m[1][3] += add_ty * self.weight;
result[i].m[2][3] += add_tz * self.weight;
}
}
result
}
}
impl Default for X86AdditiveAnimation {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86RootMotion {
pub enabled: bool,
pub root_bone_index: usize,
pub accumulate: bool,
}
impl X86RootMotion {
pub fn new() -> Self {
Self {
enabled: true,
root_bone_index: 0,
accumulate: true,
}
}
pub fn extract_delta(
&self,
clip: &X86AnimationClip,
from_time: f32,
to_time: f32,
skeleton: &X86Skeleton,
) -> (X86Vec3, X86Quat) {
let from_pose = clip.sample(from_time, skeleton);
let to_pose = clip.sample(to_time, skeleton);
if self.root_bone_index >= from_pose.len() || self.root_bone_index >= to_pose.len() {
return (X86Vec3::zero(), X86Quat::identity());
}
let from = &from_pose[self.root_bone_index];
let to = &to_pose[self.root_bone_index];
let delta_pos = X86Vec3::new(
to.m[0][3] - from.m[0][3],
to.m[1][3] - from.m[1][3],
to.m[2][3] - from.m[2][3],
);
(delta_pos, X86Quat::identity())
}
pub fn root_motion_code(&self) -> String {
r#"// Root motion extraction
void extract_root_motion(const float* anim_pose_from, const float* anim_pose_to,
float* out_delta_pos, float* out_delta_rot) {
// Extract translation from root bone (index 0)
out_delta_pos[0] = anim_pose_to[0*16+12] - anim_pose_from[0*16+12];
out_delta_pos[1] = anim_pose_to[1*16+12] - anim_pose_from[1*16+12];
out_delta_pos[2] = anim_pose_to[2*16+12] - anim_pose_from[2*16+12];
// Extract rotation delta (simplified — full quaternion delta requires decomp)
out_delta_rot[0] = 0.0f; out_delta_rot[1] = 0.0f; out_delta_rot[2] = 0.0f; out_delta_rot[3] = 1.0f;
}
"#
.to_string()
}
}
impl Default for X86RootMotion {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86VulkanPipelineBuilder {
pub topology: X86PrimitiveTopology,
pub cull_mode: X86CullMode,
pub front_face: X86FrontFace,
pub depth_test: bool,
pub depth_write: bool,
pub blend_enable: bool,
pub msaa_samples: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86PrimitiveTopology {
TriangleList,
TriangleStrip,
LineList,
PointList,
PatchList,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CullMode {
None,
Front,
Back,
FrontAndBack,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86FrontFace {
CounterClockwise,
Clockwise,
}
impl X86VulkanPipelineBuilder {
pub fn new() -> Self {
Self {
topology: X86PrimitiveTopology::TriangleList,
cull_mode: X86CullMode::Back,
front_face: X86FrontFace::CounterClockwise,
depth_test: true,
depth_write: true,
blend_enable: false,
msaa_samples: 1,
}
}
pub fn vulkan_pipeline_code(&self) -> String {
let top = match self.topology {
X86PrimitiveTopology::TriangleList => "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST",
X86PrimitiveTopology::TriangleStrip => "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP",
X86PrimitiveTopology::LineList => "VK_PRIMITIVE_TOPOLOGY_LINE_LIST",
X86PrimitiveTopology::PointList => "VK_PRIMITIVE_TOPOLOGY_POINT_LIST",
X86PrimitiveTopology::PatchList => "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST",
};
let cull = match self.cull_mode {
X86CullMode::None => "VK_CULL_MODE_NONE",
X86CullMode::Front => "VK_CULL_MODE_FRONT_BIT",
X86CullMode::Back => "VK_CULL_MODE_BACK_BIT",
X86CullMode::FrontAndBack => "VK_CULL_MODE_FRONT_AND_BACK",
};
let ff = match self.front_face {
X86FrontFace::CounterClockwise => "VK_FRONT_FACE_COUNTER_CLOCKWISE",
X86FrontFace::Clockwise => "VK_FRONT_FACE_CLOCKWISE",
};
let depth_str = if self.depth_test {
"VK_TRUE"
} else {
"VK_FALSE"
};
let depth_write_str = if self.depth_write {
"VK_TRUE"
} else {
"VK_FALSE"
};
format!(
r#"// Vulkan Graphics Pipeline Builder — Generated
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = {},
.primitiveRestartEnable = VK_FALSE,
}};
VkPipelineRasterizationStateCreateInfo rasterizer = {{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.depthClampEnable = VK_FALSE,
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = {},
.frontFace = {},
.depthBiasEnable = VK_FALSE,
.lineWidth = 1.0f,
}};
VkPipelineDepthStencilStateCreateInfo depthStencil = {{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = {},
.depthWriteEnable = {},
.depthCompareOp = VK_COMPARE_OP_LESS,
.depthBoundsTestEnable = VK_FALSE,
.stencilTestEnable = VK_FALSE,
}};
"#,
top, cull, ff, depth_str, depth_write_str
)
}
}
impl Default for X86VulkanPipelineBuilder {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86ShaderProgramGenerator {
pub language: X86ShaderLanguage,
pub model: X86ShaderModelVersion,
}
impl X86ShaderProgramGenerator {
pub fn new(language: X86ShaderLanguage, model: X86ShaderModelVersion) -> Self {
Self { language, model }
}
pub fn phong_shader(&self) -> String {
match self.language {
X86ShaderLanguage::HLSL => self.phong_hlsl(),
X86ShaderLanguage::GLSL => self.phong_glsl(),
_ => self.phong_glsl(),
}
}
fn phong_hlsl(&self) -> String {
r#"// HLSL Phong Shader
cbuffer PerFrame : register(b0) {
float4x4 viewProj;
float3 lightDir;
float3 lightColor;
float3 cameraPos;
float ambientStrength;
}
struct VSInput {
float3 position : POSITION;
float3 normal : NORMAL;
float2 texCoord : TEXCOORD0;
}
struct VSOutput {
float4 svPosition : SV_POSITION;
float3 worldPos : TEXCOORD0;
float3 normal : TEXCOORD1;
float2 texCoord : TEXCOORD2;
}
VSOutput vs_main(VSInput input) {
VSOutput output;
output.svPosition = mul(viewProj, float4(input.position, 1.0));
output.worldPos = input.position;
output.normal = input.normal;
output.texCoord = input.texCoord;
return output;
}
Texture2D albedoTexture : register(t0);
SamplerState albedoSampler : register(s0);
float4 ps_main(VSOutput input) : SV_TARGET {
float3 N = normalize(input.normal);
float3 L = normalize(-lightDir);
float3 V = normalize(cameraPos - input.worldPos);
float3 H = normalize(L + V);
float diffuse = max(dot(N, L), 0.0);
float specular = pow(max(dot(N, H), 0.0), 32.0);
float ambient = ambientStrength;
float4 albedo = albedoTexture.Sample(albedoSampler, input.texCoord);
float3 result = (ambient + diffuse) * albedo.rgb * lightColor
+ specular * lightColor;
return float4(result, albedo.a);
}
"#
.to_string()
}
fn phong_glsl(&self) -> String {
r#"// GLSL Phong Shader
#version 460
layout(set = 0, binding = 0) uniform PerFrame {
mat4 viewProj;
vec3 lightDir;
vec3 lightColor;
vec3 cameraPos;
float ambientStrength;
} ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inTexCoord;
layout(location = 0) out vec3 outWorldPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec2 outTexCoord;
void main() {
gl_Position = ubo.viewProj * vec4(inPosition, 1.0);
outWorldPos = inPosition;
outNormal = inNormal;
outTexCoord = inTexCoord;
}
// ── Fragment Shader ──
layout(location = 0) in vec3 inWorldPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inTexCoord;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 1) uniform sampler2D albedoSampler;
layout(set = 0, binding = 2) uniform texture2D albedoTexture;
void main() {
vec3 N = normalize(inNormal);
vec3 L = normalize(-ubo.lightDir);
vec3 V = normalize(ubo.cameraPos - inWorldPos);
vec3 H = normalize(L + V);
float diffuse = max(dot(N, L), 0.0);
float specular = pow(max(dot(N, H), 0.0), 32.0);
float ambient = ubo.ambientStrength;
vec4 albedo = texture(sampler2D(albedoTexture, albedoSampler), inTexCoord);
vec3 result = (ambient + diffuse) * albedo.rgb * ubo.lightColor
+ specular * ubo.lightColor;
outColor = vec4(result, albedo.a);
}
"#
.to_string()
}
pub fn post_process_shader(&self, effect: &str) -> String {
match effect {
"bloom" => self.bloom_shader(),
"tonemap" => self.tonemap_shader(),
"fxaa" => self.fxaa_shader(),
_ => self.copy_shader(),
}
}
fn tonemap_shader(&self) -> String {
r#"// ACES Filmic Tonemapping
#version 460
layout(local_size_x = 16, local_size_y = 16) in;
layout(rgba16f, binding = 0) uniform image2D inHDR;
layout(rgba8, binding = 1) uniform image2D outLDR;
vec3 ACESFilm(vec3 x) {
float a = 2.51f;
float b = 0.03f;
float c = 2.43f;
float d = 0.59f;
float e = 0.14f;
return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0);
}
void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec3 hdr = imageLoad(inHDR, uv).rgb;
vec3 ldr = ACESFilm(hdr);
ldr = pow(ldr, vec3(1.0/2.2)); // gamma
imageStore(outLDR, uv, vec4(ldr, 1.0));
}
"#
.to_string()
}
fn bloom_shader(&self) -> String {
"// Bloom post-process (simplified gaussian blur + composite)".to_string()
}
fn fxaa_shader(&self) -> String {
"// FXAA anti-aliasing pass".to_string()
}
fn copy_shader(&self) -> String {
r#"#version 460
layout(location = 0) in vec2 inUV;
layout(binding = 0) uniform sampler2D inTexture;
layout(location = 0) out vec4 outColor;
void main() { outColor = texture(inTexture, inUV); }
"#
.to_string()
}
}
impl Default for X86ShaderProgramGenerator {
fn default() -> Self {
Self::new(X86ShaderLanguage::GLSL, X86ShaderModelVersion::Vulkan12)
}
}
#[derive(Debug, Clone)]
pub struct X86GPUBuffer {
pub size: usize,
pub usage: X86BufferUsage,
pub memory_type: X86MemoryType,
pub name: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BufferUsage {
Vertex,
Index,
Uniform,
Storage,
Indirect,
TransferSrc,
TransferDst,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86MemoryType {
DeviceLocal,
HostVisible,
HostCoherent,
DeviceLocalHostVisible,
}
impl X86GPUBuffer {
pub fn new(name: &str, size: usize, usage: X86BufferUsage) -> Self {
let mem = match usage {
X86BufferUsage::Uniform => X86MemoryType::HostVisible,
X86BufferUsage::Storage => X86MemoryType::DeviceLocal,
X86BufferUsage::TransferSrc | X86BufferUsage::TransferDst => {
X86MemoryType::HostCoherent
}
_ => X86MemoryType::DeviceLocal,
};
Self {
size,
usage,
memory_type: mem,
name: name.into(),
}
}
pub fn vulkan_create_code(&self) -> String {
let usage_flags = match self.usage {
X86BufferUsage::Vertex => "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT",
X86BufferUsage::Index => "VK_BUFFER_USAGE_INDEX_BUFFER_BIT",
X86BufferUsage::Uniform => "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT",
X86BufferUsage::Storage => "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT",
X86BufferUsage::Indirect => "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT",
X86BufferUsage::TransferSrc => "VK_BUFFER_USAGE_TRANSFER_SRC_BIT",
X86BufferUsage::TransferDst => "VK_BUFFER_USAGE_TRANSFER_DST_BIT",
};
let mem_props = match self.memory_type {
X86MemoryType::DeviceLocal => "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT",
X86MemoryType::HostVisible => "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT",
X86MemoryType::HostCoherent => {
"VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT"
}
X86MemoryType::DeviceLocalHostVisible => {
"VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT"
}
};
format!(
r#"// GPU Buffer: {}
VkBufferCreateInfo bufferInfo = {{}};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = {};
bufferInfo.usage = {};
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkBuffer buffer;
vkCreateBuffer(device, &bufferInfo, NULL, &buffer);
// Allocate memory
VkMemoryRequirements memReqs;
vkGetBufferMemoryRequirements(device, buffer, &memReqs);
VkMemoryAllocateInfo allocInfo = {{}};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memReqs.size;
allocInfo.memoryTypeIndex = findMemoryType(memReqs.memoryTypeBits, {});
VkDeviceMemory memory;
vkAllocateMemory(device, &allocInfo, NULL, &memory);
vkBindBufferMemory(device, buffer, memory, 0);
"#,
self.name, self.size, usage_flags, mem_props
)
}
pub fn d3d12_create_code(&self) -> String {
format!(
r#"// D3D12 Buffer: {}
D3D12_RESOURCE_DESC desc = {{}};
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Width = {};
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
D3D12_HEAP_PROPERTIES heapProps = {{}};
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
ID3D12Resource* buffer;
device->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
IID_PPV_ARGS(&buffer));
"#,
self.name, self.size
)
}
}
#[derive(Debug, Clone)]
pub struct X86ADSREnvelope {
pub attack_time: f32,
pub decay_time: f32,
pub sustain_level: f32,
pub release_time: f32,
}
impl X86ADSREnvelope {
pub fn new() -> Self {
Self {
attack_time: 0.01,
decay_time: 0.1,
sustain_level: 0.7,
release_time: 0.5,
}
}
pub fn adsr_code(&self) -> String {
format!(
r#"// ADSR Envelope Generator
#define ADSR_ATTACK {}f
#define ADSR_DECAY {}f
#define ADSR_SUSTAIN {}f
#define ADSR_RELEASE {}f
typedef enum {{ ADSR_ATTACK_STAGE, ADSR_DECAY_STAGE, ADSR_SUSTAIN_STAGE, ADSR_RELEASE_STAGE, ADSR_IDLE }} ADSRStage;
typedef struct {{
ADSRStage stage;
float value;
float sample_rate;
float attack_rate;
float decay_rate;
float release_rate;
}} ADSRState;
static void adsr_init(ADSRState* adsr, float sr) {{
adsr->stage = ADSR_IDLE;
adsr->value = 0.0f;
adsr->sample_rate = sr;
adsr->attack_rate = 1.0f / (ADSR_ATTACK * sr);
adsr->decay_rate = (1.0f - ADSR_SUSTAIN) / (ADSR_DECAY * sr);
adsr->release_rate = ADSR_SUSTAIN / (ADSR_RELEASE * sr);
}}
static void adsr_note_on(ADSRState* adsr) {{ adsr->stage = ADSR_ATTACK_STAGE; }}
static void adsr_note_off(ADSRState* adsr) {{ adsr->stage = ADSR_RELEASE_STAGE; }}
static float adsr_process(ADSRState* adsr) {{
switch (adsr->stage) {{
case ADSR_ATTACK_STAGE:
adsr->value += adsr->attack_rate;
if (adsr->value >= 1.0f) {{ adsr->value = 1.0f; adsr->stage = ADSR_DECAY_STAGE; }}
break;
case ADSR_DECAY_STAGE:
adsr->value -= adsr->decay_rate;
if (adsr->value <= ADSR_SUSTAIN) {{ adsr->value = ADSR_SUSTAIN; adsr->stage = ADSR_SUSTAIN_STAGE; }}
break;
case ADSR_SUSTAIN_STAGE: break;
case ADSR_RELEASE_STAGE:
adsr->value -= adsr->release_rate;
if (adsr->value <= 0.0f) {{ adsr->value = 0.0f; adsr->stage = ADSR_IDLE; }}
break;
case ADSR_IDLE: break;
}}
return adsr->value;
}}
"#,
self.attack_time, self.decay_time, self.sustain_level, self.release_time
)
}
}
impl Default for X86ADSREnvelope {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86OscillatorBank {
pub num_voices: usize,
pub max_polyphony: usize,
}
impl X86OscillatorBank {
pub fn new() -> Self {
Self {
num_voices: 1,
max_polyphony: 8,
}
}
pub fn oscillator_bank_code(&self) -> String {
format!(
r#"// Multi-oscillator synthesizer bank
#define OSC_MAX_VOICES {}
typedef enum {{ OSC_SINE, OSC_TRI, OSC_SAW, OSC_SQUARE, OSC_NOISE }} OscWaveform;
typedef struct {{
OscWaveform waveform;
float frequency;
float phase;
float amplitude;
ADSRState envelope;
bool active;
}} OscVoice;
typedef struct {{
OscVoice voices[OSC_MAX_VOICES];
int active_count;
float sample_rate;
float master_volume;
}} OscBank;
static void osc_bank_init(OscBank* bank, float sr) {{
bank->active_count = 0;
bank->sample_rate = sr;
bank->master_volume = 0.5f;
memset(bank->voices, 0, sizeof(bank->voices));
for (int i = 0; i < OSC_MAX_VOICES; i++) {{
adsr_init(&bank->voices[i].envelope, sr);
}}
}}
static int osc_bank_note_on(OscBank* bank, float freq, float amp, OscWaveform wf) {{
for (int i = 0; i < OSC_MAX_VOICES; i++) {{
if (!bank->voices[i].active) {{
OscVoice* v = &bank->voices[i];
v->waveform = wf;
v->frequency = freq;
v->amplitude = amp;
v->phase = 0.0f;
v->active = true;
adsr_note_on(&v->envelope);
bank->active_count++;
return i;
}}
}}
return -1; // no free voices
}}
static void osc_bank_note_off(OscBank* bank, int voice_idx) {{
if (voice_idx >= 0 && voice_idx < OSC_MAX_VOICES) {{
adsr_note_off(&bank->voices[voice_idx].envelope);
}}
}}
static float osc_bank_process(OscBank* bank) {{
float output = 0.0f;
for (int i = 0; i < OSC_MAX_VOICES; i++) {{
OscVoice* v = &bank->voices[i];
if (!v->active) continue;
float env = adsr_process(&v->envelope);
if (v->envelope.stage == ADSR_IDLE) {{ v->active = false; bank->active_count--; continue; }}
float phase_inc = v->frequency / bank->sample_rate;
v->phase = fmodf(v->phase + phase_inc, 1.0f);
float sample = 0.0f;
switch (v->waveform) {{
case OSC_SINE: sample = sinf(2.0f * M_PI * v->phase); break;
case OSC_TRI: sample = 4.0f * fabsf(v->phase - 0.5f) - 1.0f; break;
case OSC_SAW: sample = 2.0f * (v->phase - floorf(v->phase + 0.5f)); break;
case OSC_SQUARE: sample = (v->phase < 0.5f) ? 1.0f : -1.0f; break;
default: break;
}}
output += sample * v->amplitude * env;
}}
return output * bank->master_volume;
}}
"#,
self.max_polyphony
)
}
}
impl Default for X86OscillatorBank {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86BandwidthEstimator {
pub probe_interval_ms: u32,
pub history_window: usize,
pub min_bandwidth_bps: u32,
pub max_bandwidth_bps: u32,
}
impl X86BandwidthEstimator {
pub fn new() -> Self {
Self {
probe_interval_ms: 1000,
history_window: 64,
min_bandwidth_bps: 28000,
max_bandwidth_bps: 100_000_000,
}
}
pub fn estimator_code(&self) -> String {
format!(
r#"// Bandwidth estimator using packet trains
#define BW_HISTORY_SIZE {}
#define BW_PROBE_INTERVAL_MS {}
typedef struct {{
uint64_t send_times[BW_HISTORY_SIZE];
uint64_t ack_times[BW_HISTORY_SIZE];
uint32_t packet_sizes[BW_HISTORY_SIZE];
int head;
int count;
uint64_t last_probe_time;
float estimated_bps;
float smoothed_rtt_ms;
}} BandwidthEstimator;
static void bw_estimator_init(BandwidthEstimator* est) {{
memset(est, 0, sizeof(*est));
est->estimated_bps = 1000000.0f; // 1 Mbps initial
est->smoothed_rtt_ms = 100.0f;
}}
static void bw_estimator_on_send(BandwidthEstimator* est, uint32_t size) {{
int idx = est->head % BW_HISTORY_SIZE;
est->send_times[idx] = get_time_us();
est->packet_sizes[idx] = size;
est->head++;
if (est->count < BW_HISTORY_SIZE) est->count++;
}}
static void bw_estimator_on_ack(BandwidthEstimator* est, uint64_t send_time, uint32_t size) {{
uint64_t now = get_time_us();
float rtt = (float)(now - send_time) / 1000.0f;
est->smoothed_rtt_ms = est->smoothed_rtt_ms * 0.875f + rtt * 0.125f;
// Estimate bandwidth from recent acks
float total_bytes = 0.0f;
uint64_t min_time = UINT64_MAX;
uint64_t max_time = 0;
int samples = 0;
for (int i = 0; i < est->count && i < BW_HISTORY_SIZE; i++) {{
int idx = (est->head - 1 - i + BW_HISTORY_SIZE) % BW_HISTORY_SIZE;
if (est->send_times[idx] > 0) {{
total_bytes += est->packet_sizes[idx];
if (est->send_times[idx] < min_time) min_time = est->send_times[idx];
if (est->send_times[idx] > max_time) max_time = est->send_times[idx];
samples++;
}}
}}
if (samples >= 2 && max_time > min_time) {{
float duration_s = (float)(max_time - min_time) / 1000000.0f;
if (duration_s > 0.001f) {{
est->estimated_bps = (total_bytes * 8.0f) / duration_s;
}}
}}
}}
static uint32_t bw_estimator_get_send_rate_bytes_per_sec(BandwidthEstimator* est) {{
return (uint32_t)(est->estimated_bps / 8.0f);
}}
"#,
self.history_window, self.probe_interval_ms
)
}
}
impl Default for X86BandwidthEstimator {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86NetworkQoS {
pub max_latency_ms: u32,
pub packet_loss_threshold: f32,
pub jitter_buffer_ms: u32,
pub fec_enabled: bool,
pub fec_ratio: f32,
}
impl X86NetworkQoS {
pub fn new() -> Self {
Self {
max_latency_ms: 150,
packet_loss_threshold: 0.05,
jitter_buffer_ms: 40,
fec_enabled: false,
fec_ratio: 0.1,
}
}
pub fn qos_code(&self) -> String {
format!(
r#"// Network QoS monitoring
#define QOS_MAX_LATENCY_MS {}
#define QOS_JITTER_BUFFER_MS {}
#define QOS_LOSS_THRESHOLD {}
typedef struct {{
float avg_latency_ms;
float jitter_ms;
float packet_loss;
uint32_t packets_sent;
uint32_t packets_received;
uint32_t packets_lost;
uint32_t packets_resent;
uint32_t bytes_sent;
uint32_t bytes_received;
}} NetworkQoSStats;
static void qos_update(NetworkQoSStats* stats, uint64_t send_time, uint64_t recv_time) {{
float latency = (float)(recv_time - send_time) / 1000.0f;
float prev_avg = stats->avg_latency_ms;
stats->avg_latency_ms = prev_avg * 0.9f + latency * 0.1f;
float deviation = fabsf(latency - stats->avg_latency_ms);
stats->jitter_ms = stats->jitter_ms * 0.9f + deviation * 0.1f;
stats->packet_loss = (float)stats->packets_lost / (float)(stats->packets_sent + 1);
}}
static bool qos_is_healthy(const NetworkQoSStats* stats) {{
return stats->avg_latency_ms < QOS_MAX_LATENCY_MS
&& stats->jitter_ms < QOS_JITTER_BUFFER_MS
&& stats->packet_loss < QOS_LOSS_THRESHOLD;
}}
"#,
self.max_latency_ms, self.jitter_buffer_ms, self.packet_loss_threshold
)
}
}
impl Default for X86NetworkQoS {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86AnimationCompressor {
pub position_error_threshold: f32,
pub rotation_error_threshold: f32,
pub scale_error_threshold: f32,
}
impl X86AnimationCompressor {
pub fn new() -> Self {
Self {
position_error_threshold: 0.001,
rotation_error_threshold: 0.0001,
scale_error_threshold: 0.0001,
}
}
pub fn compress_track(&self, track: &X86KeyframeTrack) -> X86KeyframeTrack {
let compressed = X86KeyframeTrack {
bone_index: track.bone_index,
position_keys: self.compress_keys(&track.position_keys, self.position_error_threshold),
rotation_keys: self.compress_keys(&track.rotation_keys, self.rotation_error_threshold),
scale_keys: self.compress_keys(&track.scale_keys, self.scale_error_threshold),
interpolation: track.interpolation,
};
compressed
}
fn compress_keys(&self, keys: &[X86Keyframe], threshold: f32) -> Vec<X86Keyframe> {
if keys.len() <= 2 {
return keys.to_vec();
}
let mut result = vec![keys[0].clone()];
for i in 1..keys.len() - 1 {
let t = (keys[i].time - keys[0].time) / (keys[keys.len() - 1].time - keys[0].time);
let t = t.clamp(0.0, 1.0);
let interpolated = Self::lerp_keyframe(&keys[0], &keys[keys.len() - 1], t);
let actual = Self::keyframe_to_scalar(&keys[i]);
let interp_val = Self::keyframe_to_scalar(&interpolated);
if (actual - interp_val).abs() > threshold {
result.push(keys[i].clone());
}
}
result.push(keys[keys.len() - 1].clone());
result
}
fn lerp_keyframe(a: &X86Keyframe, b: &X86Keyframe, t: f32) -> X86Keyframe {
let val = match (&a.value, &b.value) {
(X86KeyframeValue::Scalar(sa), X86KeyframeValue::Scalar(sb)) => {
X86KeyframeValue::Scalar(sa + (sb - sa) * t)
}
(X86KeyframeValue::Vec3(va), X86KeyframeValue::Vec3(vb)) => {
X86KeyframeValue::Vec3(va.lerp(vb, t))
}
(X86KeyframeValue::Quat(qa), X86KeyframeValue::Quat(qb)) => {
X86KeyframeValue::Quat(qa.slerp(qb, t))
}
_ => a.value.clone(),
};
X86Keyframe {
time: a.time + (b.time - a.time) * t,
value: val,
}
}
fn keyframe_to_scalar(kf: &X86Keyframe) -> f32 {
match &kf.value {
X86KeyframeValue::Scalar(v) => *v,
X86KeyframeValue::Vec3(v) => v.x,
X86KeyframeValue::Quat(_) => 0.0,
}
}
pub fn compression_code(&self) -> String {
format!(
r#"// Animation keyframe compressor
#define POS_ERR_THRESH {}f
#define ROT_ERR_THRESH {}f
#define SCL_ERR_THRESH {}f
static int compress_keyframe_track(const Keyframe* input, int input_count,
Keyframe* output, int max_output,
float error_threshold) {{
if (input_count <= 2) {{
memcpy(output, input, input_count * sizeof(Keyframe));
return input_count;
}}
output[0] = input[0];
int out_count = 1;
for (int i = 1; i < input_count - 1; i++) {{
float t = (input[i].time - input[0].time)
/ (input[input_count - 1].time - input[0].time);
float interp = input[0].value + (input[input_count-1].value - input[0].value) * t;
if (fabsf(input[i].value - interp) > error_threshold) {{
output[out_count++] = input[i];
if (out_count >= max_output) break;
}}
}}
output[out_count++] = input[input_count - 1];
return out_count;
}}
"#,
self.position_error_threshold,
self.rotation_error_threshold,
self.scale_error_threshold
)
}
}
impl Default for X86AnimationCompressor {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86ECSPatterns {
pub max_components: usize,
pub pool_growth_factor: f32,
pub enable_versioning: bool,
}
impl X86ECSPatterns {
pub fn new() -> Self {
Self {
max_components: 64,
pool_growth_factor: 1.5,
enable_versioning: true,
}
}
pub fn sparse_set_pool_code(&self) -> String {
format!(
r#"// Sparse-set component pool
#define MAX_ENTITIES 100000
#define MAX_COMPONENTS {}
typedef struct {{
uint32_t dense[MAX_ENTITIES]; // entity ids
uint32_t sparse[MAX_ENTITIES]; // dense indices
void* components[MAX_ENTITIES]; // component data
size_t component_size;
int count;
}} ComponentPool;
static void pool_init(ComponentPool* pool, size_t comp_size) {{
pool->component_size = comp_size;
pool->count = 0;
memset(pool->sparse, 0xFF, sizeof(pool->sparse));
}}
static void* pool_add(ComponentPool* pool, uint32_t entity) {{
if (pool->count >= MAX_ENTITIES) return NULL;
pool->dense[pool->count] = entity;
pool->sparse[entity] = pool->count;
pool->count++;
return pool->components[entity];
}}
static void pool_remove(ComponentPool* pool, uint32_t entity) {{
int idx = pool->sparse[entity];
if (idx >= pool->count) return;
uint32_t last_entity = pool->dense[pool->count - 1];
pool->dense[idx] = last_entity;
pool->sparse[last_entity] = idx;
pool->sparse[entity] = 0xFFFFFFFF;
pool->count--;
}}
static void* pool_get(ComponentPool* pool, uint32_t entity) {{
int idx = pool->sparse[entity];
if (idx >= pool->count) return NULL;
return pool->components[idx];
}}
// SIMD-accelerated component iteration
static void pool_iterate_simd(ComponentPool* pool, void (*callback)(void*, int)) {{
int i = 0;
for (; i + 7 < pool->count; i += 8) {{
callback(pool->components[i], i);
callback(pool->components[i+1], i+1);
callback(pool->components[i+2], i+2);
callback(pool->components[i+3], i+3);
callback(pool->components[i+4], i+4);
callback(pool->components[i+5], i+5);
callback(pool->components[i+6], i+6);
callback(pool->components[i+7], i+7);
}}
for (; i < pool->count; i++) {{
callback(pool->components[i], i);
}}
}}
"#,
self.max_components
)
}
}
impl Default for X86ECSPatterns {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86GameLoop {
pub simulation_hz: u32,
pub max_frame_time_ms: u32,
pub use_interpolation: bool,
pub max_substeps: u32,
}
impl X86GameLoop {
pub fn new() -> Self {
Self {
simulation_hz: 60,
max_frame_time_ms: 250,
use_interpolation: true,
max_substeps: 8,
}
}
pub fn game_loop_code(&self) -> String {
format!(
r#"// Fixed-timestep game loop
#define SIM_HZ {}
#define SIM_DT (1.0f / SIM_HZ)
#define MAX_FRAME_TIME_MS {}
#define MAX_SUBSTEPS {}
typedef struct {{
double accumulator;
double previous_time;
double frame_time;
double alpha; // interpolation factor for rendering
uint32_t sim_frame;
}} GameTimer;
static void gametimer_init(GameTimer* gt) {{
gt->accumulator = 0.0;
gt->previous_time = get_time_seconds();
gt->frame_time = 0.016;
gt->alpha = 0.0;
gt->sim_frame = 0;
}}
static void gametimer_update(GameTimer* gt) {{
double current = get_time_seconds();
double elapsed = current - gt->previous_time;
gt->previous_time = current;
if (elapsed > MAX_FRAME_TIME_MS / 1000.0) elapsed = MAX_FRAME_TIME_MS / 1000.0;
gt->frame_time = elapsed;
gt->accumulator += elapsed;
int substeps = 0;
while (gt->accumulator >= SIM_DT && substeps < MAX_SUBSTEPS) {{
fixed_update(SIM_DT);
gt->accumulator -= SIM_DT;
gt->sim_frame++;
substeps++;
}}
gt->alpha = gt->accumulator / SIM_DT;
}}
"#,
self.simulation_hz, self.max_frame_time_ms, self.max_substeps
)
}
pub fn interpolation_render_code(&self) -> String {
r#"// Interpolation-based rendering state
static inline float lerp_render(float prev, float curr, float alpha, bool interpolate) {
return interpolate ? prev + (curr - prev) * alpha : curr;
}
static inline void interpolate_transform(const float* prev, const float* curr,
float alpha, float* output) {
for (int i = 0; i < 12; i++) {
output[i] = lerp_render(prev[i], curr[i], alpha, true);
}
}
"#
.to_string()
}
}
impl Default for X86GameLoop {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86CollisionManifold {
pub contact_count: usize,
pub contacts: Vec<X86Vec3>,
pub normal: X86Vec3,
pub penetration: f32,
}
impl X86CollisionManifold {
pub fn new() -> Self {
Self {
contact_count: 0,
contacts: Vec::new(),
normal: X86Vec3::up(),
penetration: 0.0,
}
}
pub fn response_code(&self) -> String {
r#"// Impulse-based collision response
static void resolve_collision(RigidBody* a, RigidBody* b,
const float* contact_point,
const float* normal, float penetration) {
// Compute relative velocity
float rel_vx = (b->vx + b->wz * (contact_point[1] - b->py) - b->wy * (contact_point[2] - b->pz))
- (a->vx + a->wz * (contact_point[1] - a->py) - a->wy * (contact_point[2] - a->pz));
float rel_vy = (b->vy + b->wx * (contact_point[2] - b->pz) - b->wz * (contact_point[0] - b->px))
- (a->vy + a->wx * (contact_point[2] - a->pz) - a->wz * (contact_point[0] - a->px));
float rel_vz = (b->vz + b->wy * (contact_point[0] - b->px) - b->wx * (contact_point[1] - b->py))
- (a->vz + a->wy * (contact_point[0] - a->px) - a->wx * (contact_point[1] - a->py));
float rel_vel_n = rel_vx * normal[0] + rel_vy * normal[1] + rel_vz * normal[2];
if (rel_vel_n > 0.0f) return; // separating
float e = fminf(a->restitution, b->restitution);
float inv_mass_sum = a->inv_mass + b->inv_mass;
float j = -(1.0f + e) * rel_vel_n / inv_mass_sum;
// Position correction (Baumgarte)
const float slop = 0.005f;
const float baumgarte = 0.2f;
float pos_corr = fmaxf(penetration - slop, 0.0f) * baumgarte / inv_mass_sum;
j += pos_corr;
// Apply impulse
float impulse_x = j * normal[0];
float impulse_y = j * normal[1];
float impulse_z = j * normal[2];
a->vx -= impulse_x * a->inv_mass;
a->vy -= impulse_y * a->inv_mass;
a->vz -= impulse_z * a->inv_mass;
b->vx += impulse_x * b->inv_mass;
b->vy += impulse_y * b->inv_mass;
b->vz += impulse_z * b->inv_mass;
// Friction impulse
float tangent_vx = rel_vx - rel_vel_n * normal[0];
float tangent_vy = rel_vy - rel_vel_n * normal[1];
float tangent_vz = rel_vz - rel_vel_n * normal[2];
float tangent_len = sqrtf(tangent_vx*tangent_vx + tangent_vy*tangent_vy + tangent_vz*tangent_vz);
if (tangent_len > 0.0001f) {{
tangent_vx /= tangent_len;
tangent_vy /= tangent_len;
tangent_vz /= tangent_len;
float jt = -(rel_vx*tangent_vx + rel_vy*tangent_vy + rel_vz*tangent_vz) / inv_mass_sum;
float mu = sqrtf(a->friction * b->friction);
if (jt > mu * j) jt = mu * j;
if (jt < -mu * j) jt = -mu * j;
a->vx -= jt * tangent_vx * a->inv_mass;
a->vy -= jt * tangent_vy * a->inv_mass;
a->vz -= jt * tangent_vz * a->inv_mass;
b->vx += jt * tangent_vx * b->inv_mass;
b->vy += jt * tangent_vy * b->inv_mass;
b->vz += jt * tangent_vz * b->inv_mass;
}}
}
"#
.to_string()
}
}
impl Default for X86CollisionManifold {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86ShadowMap {
pub resolution: u32,
pub cascade_count: u32,
pub depth_bias: f32,
pub normal_bias: f32,
pub pcf_samples: u32,
}
impl X86ShadowMap {
pub fn new() -> Self {
Self {
resolution: 2048,
cascade_count: 4,
depth_bias: 0.001,
normal_bias: 0.01,
pcf_samples: 16,
}
}
pub fn shadow_map_shader(&self) -> String {
format!(
r#"// Cascaded Shadow Maps (CSM)
#define SHADOW_MAP_RES {}
#define CASCADE_COUNT {}
#define PCF_SAMPLES {}
cbuffer ShadowConstants : register(b1) {{
float4x4 lightViewProj[CASCADE_COUNT];
float4 cascadeSplits;
float shadowBias;
}};
Texture2DArray shadowMaps : register(t4);
SamplerComparisonState shadowSampler : register(s2);
float sample_shadow_map(float3 worldPos, float3 normal) {{
// Select cascade based on depth
float viewZ = dot(worldPos - cameraPos, viewDir);
uint cascade = 0;
for (uint i = 0; i < CASCADE_COUNT - 1; i++) {{
if (viewZ > cascadeSplits[i]) cascade = i + 1;
}}
float4 lightSpace = mul(lightViewProj[cascade], float4(worldPos, 1.0));
lightSpace.xyz /= lightSpace.w;
float bias = shadowBias * tan(acos(dot(normal, lightDir)));
lightSpace.z -= bias;
float shadow = 0.0;
float texelSize = 1.0 / SHADOW_MAP_RES;
for (int x = -1; x <= 1; x++) {{
for (int y = -1; y <= 1; y++) {{
shadow += shadowMaps.SampleCmpLevelZero(
shadowSampler,
float3(lightSpace.xy + float2(x, y) * texelSize, cascade),
lightSpace.z);
}}
}}
return shadow / 9.0;
}}
"#,
self.resolution, self.cascade_count, self.pcf_samples
)
}
}
impl Default for X86ShadowMap {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86ParticleSystem {
pub max_particles: usize,
pub emit_rate: f32,
pub lifetime_min: f32,
pub lifetime_max: f32,
pub use_gpu_sim: bool,
}
impl X86ParticleSystem {
pub fn new() -> Self {
Self {
max_particles: 10000,
emit_rate: 500.0,
lifetime_min: 1.0,
lifetime_max: 3.0,
use_gpu_sim: true,
}
}
pub fn particle_code(&self) -> String {
format!(
r#"// GPU Particle System
#define MAX_PARTICLES {}
#define EMIT_RATE {}f
typedef struct {{
float3 position;
float3 velocity;
float4 color;
float size;
float age;
float lifetime;
uint alive;
}} Particle;
// GPU-side particle update
static void particle_update(Particle* p, float dt, float3 gravity) {{
p->age += dt;
if (p->age >= p->lifetime) {{ p->alive = 0; return; }}
p->velocity = p->velocity + gravity * dt;
p->position = p->position + p->velocity * dt;
float life_ratio = p->age / p->lifetime;
p->color.a = 1.0f - life_ratio; // fade out
p->size = p->size * (1.0f - life_ratio * 0.5f);
}}
// Particle emitter
static void particle_emit(Particle* particles, int max_count, int* alive_count,
float3 position, float3 direction, float spread_angle) {{
int to_emit = (int)(EMIT_RATE * 0.016f); // per-frame at 60fps
int emitted = 0;
for (int i = 0; i < max_count && emitted < to_emit; i++) {{
if (particles[i].alive) continue;
Particle* p = &particles[i];
p->position = position;
p->velocity = direction + random_unit_sphere() * spread_angle;
p->color = (float4){{1, 1, 1, 1}};
p->size = 0.1f;
p->age = 0.0f;
p->lifetime = {}f + ({}f - {}f) * random_float();
p->alive = 1;
emitted++;
(*alive_count)++;
}}
}}
"#,
self.max_particles,
self.emit_rate,
self.lifetime_min,
self.lifetime_max,
self.lifetime_min
)
}
}
impl Default for X86ParticleSystem {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86InputSystem {
pub max_actions: usize,
pub deadzone: f32,
pub mouse_sensitivity: f32,
}
impl X86InputSystem {
pub fn new() -> Self {
Self {
max_actions: 256,
deadzone: 0.15,
mouse_sensitivity: 1.0,
}
}
pub fn input_code(&self) -> String {
format!(
r#"// Input system with action mapping
#define MAX_ACTIONS {}
#define INPUT_DEADZONE {}f
typedef enum {{
ACTION_PRESSED,
ACTION_RELEASED,
ACTION_HELD,
}} ActionState;
typedef struct {{
uint32_t action_hash;
ActionState state;
float value;
float axis_x;
float axis_y;
uint64_t timestamp;
}} InputAction;
typedef struct {{
InputAction actions[MAX_ACTIONS];
int action_count;
uint8_t key_state[512];
uint8_t prev_key_state[512];
int mouse_x, mouse_y;
int mouse_dx, mouse_dy;
float mouse_sensitivity;
float axis_deadzone;
}} InputManager;
static void input_begin_frame(InputManager* im) {{
memcpy(im->prev_key_state, im->key_state, sizeof(im->key_state));
im->mouse_dx = 0;
im->mouse_dy = 0;
im->action_count = 0;
}}
static void input_register_action(InputManager* im, uint32_t hash, float value) {{
if (im->action_count >= MAX_ACTIONS) return;
InputAction* act = &im->actions[im->action_count++];
act->action_hash = hash;
if (value > im->axis_deadzone) {{
act->value = value;
bool was_down = false; // simplified
act->state = was_down ? ACTION_HELD : ACTION_PRESSED;
}} else {{
act->state = ACTION_RELEASED;
act->value = 0.0f;
}}
act->timestamp = get_time_us();
}}
"#,
self.max_actions, self.deadzone
)
}
}
impl Default for X86InputSystem {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simd_level_detect() {
let level = X86GameSimdLevel::detect();
assert!(matches!(
level,
X86GameSimdLevel::Scalar
| X86GameSimdLevel::SSE42
| X86GameSimdLevel::AVX2
| X86GameSimdLevel::AVX512
));
}
#[test]
fn test_simd_level_vector_bytes() {
assert_eq!(X86GameSimdLevel::Scalar.vector_bytes(), 0);
assert_eq!(X86GameSimdLevel::SSE42.vector_bytes(), 16);
assert_eq!(X86GameSimdLevel::AVX2.vector_bytes(), 32);
assert_eq!(X86GameSimdLevel::AVX512.vector_bytes(), 64);
}
#[test]
fn test_simd_level_f32_lanes() {
assert_eq!(X86GameSimdLevel::Scalar.f32_lanes(), 1);
assert_eq!(X86GameSimdLevel::SSE42.f32_lanes(), 4);
assert_eq!(X86GameSimdLevel::AVX2.f32_lanes(), 8);
assert_eq!(X86GameSimdLevel::AVX512.f32_lanes(), 16);
}
#[test]
fn test_simd_level_has_fma() {
assert!(!X86GameSimdLevel::Scalar.has_fma());
assert!(!X86GameSimdLevel::SSE42.has_fma());
assert!(X86GameSimdLevel::AVX2.has_fma());
assert!(X86GameSimdLevel::AVX512.has_fma());
}
#[test]
fn test_simd_level_compiler_flags() {
assert!(X86GameSimdLevel::Scalar.compiler_flags().is_empty());
assert!(!X86GameSimdLevel::SSE42.compiler_flags().is_empty());
}
#[test]
fn test_simd_level_display() {
assert_eq!(X86GameSimdLevel::Scalar.to_string(), "scalar");
assert_eq!(X86GameSimdLevel::SSE42.to_string(), "sse4.2");
assert_eq!(X86GameSimdLevel::AVX2.to_string(), "avx2");
}
#[test]
fn test_simd_level_ordering() {
assert!(X86GameSimdLevel::SSE42 > X86GameSimdLevel::Scalar);
assert!(X86GameSimdLevel::AVX2 > X86GameSimdLevel::SSE42);
assert!(X86GameSimdLevel::AVX512 > X86GameSimdLevel::AVX2);
}
#[test]
fn test_x86_games_creation() {
let games = X86Games::new();
assert!(!games.compile_flags().is_empty());
}
#[test]
fn test_x86_games_with_simd_level() {
let games = X86Games::new().with_simd_level(X86GameSimdLevel::AVX2);
assert_eq!(games.simd_level, X86GameSimdLevel::AVX2);
}
#[test]
fn test_x86_games_compile_flags() {
let games = X86Games::default();
let flags = games.compile_flags();
assert!(flags.iter().any(|f| f.contains("-msse4.2")));
}
#[test]
fn test_x86_games_clang_command() {
let games = X86Games::default();
let cmd = games.clang_command("main.c");
assert_eq!(cmd[0], "clang");
assert_eq!(cmd[1], "main.c");
}
#[test]
fn test_x86_games_describe() {
let games = X86Games::default();
let desc = games.describe();
assert!(desc.contains("X86 Games"));
assert!(desc.contains("Math"));
assert!(desc.contains("Physics"));
}
#[test]
fn test_x86_games_define() {
let mut games = X86Games::default();
games.define("TEST_DEFINE", Some("1".to_string()));
let cmd = games.clang_command("main.c");
assert!(cmd.iter().any(|f| f.contains("TEST_DEFINE=1")));
}
#[test]
fn test_x86_games_default() {
let games = X86Games::default();
assert_eq!(games.simd_level, X86GameSimdLevel::SSE42);
}
#[test]
fn test_target_triples() {
assert_eq!(
X86GameTarget::LinuxX64.as_triple(),
"x86_64-unknown-linux-gnu"
);
assert_eq!(
X86GameTarget::WindowsX64.as_triple(),
"x86_64-pc-windows-msvc"
);
assert_eq!(X86GameTarget::MacOSX64.as_triple(), "x86_64-apple-darwin");
}
#[test]
fn test_target_64bit() {
assert!(X86GameTarget::LinuxX64.is_64bit());
assert!(!X86GameTarget::LinuxX86.is_64bit());
}
#[test]
fn test_target_compile_flags() {
let flags = X86GameTarget::LinuxX64.compile_flags();
assert!(!flags.is_empty());
}
#[test]
fn test_build_config_default() {
let cfg = X86GameBuildConfig::default();
assert!(cfg.debug_symbols);
assert!(cfg.asserts_enabled);
}
#[test]
fn test_optimization_level_flags() {
let flags = X86GameOptimizationLevel::Shipping.as_flags();
assert!(flags.contains(&"-O3".to_string()));
assert!(flags.contains(&"-flto".to_string()));
}
#[test]
fn test_build_config_sanitizers() {
let mut cfg = X86GameBuildConfig::default();
cfg.address_sanitizer = true;
let flags = cfg.compile_flags();
assert!(flags.contains(&"-fsanitize=address".to_string()));
}
#[test]
fn test_optimizations_default() {
let opt = X86GameOptimizations::default();
assert!(opt.frame_budget.compile_flags().is_empty()); }
#[test]
fn test_frame_budget_flags() {
let mut fb = X86FrameBudget::default();
fb.enabled = true;
fb.align_hot_paths = true;
let flags = fb.compile_flags();
assert!(!flags.is_empty());
}
#[test]
fn test_hot_cold_splitting_default() {
let hc = X86HotColdSplitting::default();
assert!(!hc.enabled);
assert_eq!(hc.cold_attribute(), "__attribute__((cold))");
}
#[test]
fn test_cache_layout_soa_decl() {
let cl = X86CacheLayoutOpt::default();
let decl = cl.soa_layout_decl("Transform", &[("pos", "float"), ("rot", "float")]);
assert!(decl.contains("// SoA layout"));
assert!(decl.contains("float* pos"));
}
#[test]
fn test_prefetch_intrinsic() {
let pf = X86PrefetchOpt::default();
let code = pf.prefetch_intrinsic("ptr");
assert!(code.contains("_mm_prefetch"));
}
#[test]
fn test_lock_free_spsc_queue() {
let lf = X86LockFreeOpt::default();
let code = lf.spsc_queue_decl("int", "test_q", 32);
assert!(code.contains("SPSC lock-free queue"));
assert!(code.contains("atomic_load"));
}
#[test]
fn test_branch_hints_default() {
let bh = X86BranchHintOpt::default();
assert!(bh.likely_macro().contains("__builtin_expect"));
}
#[test]
fn test_simd_vectorization_mat4_mul() {
let sv = X86SimdVectorization::new(X86GameSimdLevel::AVX2);
let code = sv.mat4_mul_intrinsic();
assert!(code.contains("_mm256"));
}
#[test]
fn test_simd_vectorization_quat_mul() {
let sv = X86SimdVectorization::new(X86GameSimdLevel::SSE42);
let code = sv.quat_mul_intrinsic();
assert!(code.contains("_mm"));
}
#[test]
fn test_vec3_operations() {
let a = X86Vec3::new(1.0, 2.0, 3.0);
let b = X86Vec3::new(4.0, 5.0, 6.0);
let sum = a.add(&b);
assert_eq!(sum.x, 5.0);
assert_eq!(sum.y, 7.0);
assert_eq!(sum.z, 9.0);
let dot = a.dot(&b);
assert_eq!(dot, 32.0);
let cross = a.cross(&b);
assert_eq!(cross.x, -3.0);
assert_eq!(cross.y, 6.0);
assert_eq!(cross.z, -3.0);
}
#[test]
fn test_vec3_length() {
let v = X86Vec3::new(3.0, 4.0, 0.0);
assert!((v.length() - 5.0).abs() < 0.001);
}
#[test]
fn test_vec3_normalize() {
let v = X86Vec3::new(3.0, 0.0, 0.0);
let n = v.normalize();
assert!((n.x - 1.0).abs() < 0.001);
assert!((n.y).abs() < 0.001);
}
#[test]
fn test_quat_identity() {
let q = X86Quat::identity();
assert_eq!(q.w, 1.0);
assert_eq!(q.x, 0.0);
assert_eq!(q.y, 0.0);
assert_eq!(q.z, 0.0);
}
#[test]
fn test_quat_mul() {
let q1 = X86Quat::identity();
let q2 = X86Quat::from_axis_angle(&X86Vec3::up(), std::f32::consts::PI);
let q3 = q1.mul(&q2);
assert!((q3.w - q2.w).abs() < 0.001);
}
#[test]
fn test_quat_slerp() {
let q1 = X86Quat::identity();
let q2 = X86Quat::from_axis_angle(&X86Vec3::new(0.0, 1.0, 0.0), std::f32::consts::PI * 0.5);
let q = q1.slerp(&q2, 0.5);
let mag = (q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w).sqrt();
assert!((mag - 1.0).abs() < 0.01);
}
#[test]
fn test_quat_nlerp() {
let q1 = X86Quat::identity();
let q2 = X86Quat::from_axis_angle(&X86Vec3::up(), std::f32::consts::PI * 0.5);
let q = q1.nlerp(&q2, 0.5);
let mag = (q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w).sqrt();
assert!((mag - 1.0).abs() < 0.01);
}
#[test]
fn test_mat4_identity() {
let m = X86Mat4::identity();
assert_eq!(m.m[0][0], 1.0);
assert_eq!(m.m[3][3], 1.0);
}
#[test]
fn test_mat4_mul_identity() {
let m = X86Mat4::identity();
let result = m.mul(&m);
assert_eq!(result.m[0][0], 1.0);
}
#[test]
fn test_mat4_translate() {
let m = X86Mat4::translate(&X86Vec3::new(5.0, 0.0, 0.0));
assert_eq!(m.m[0][3], 5.0);
}
#[test]
fn test_interpolation_lerp() {
assert!((X86Interpolation::lerp(0.0, 10.0, 0.5) - 5.0).abs() < 0.001);
assert!((X86Interpolation::lerp(0.0, 10.0, 0.0) - 0.0).abs() < 0.001);
assert!((X86Interpolation::lerp(0.0, 10.0, 1.0) - 10.0).abs() < 0.001);
}
#[test]
fn test_interpolation_smoothstep() {
let val = X86Interpolation::smoothstep(0.0, 1.0, 0.5);
assert_eq!(val, 0.5); }
#[test]
fn test_interpolation_catmull_rom() {
let val = X86Interpolation::catmull_rom(0.0, 1.0, 2.0, 3.0, 0.5);
assert!((val - 1.5).abs() < 0.001); }
#[test]
fn test_random_pcg() {
let mut rng = X86GameRandom::pcg(42);
let v1 = rng.pcg_next_u32();
let v2 = rng.pcg_next_u32();
assert_ne!(v1, v2);
}
#[test]
fn test_random_pcg_range() {
let mut rng = X86GameRandom::pcg(123);
for _ in 0..100 {
let v = rng.pcg_range(5.0, 10.0);
assert!(v >= 5.0 && v <= 10.0);
}
}
#[test]
fn test_random_xorshift() {
let mut rng = X86GameRandom::xorshift128([12345, 67890]);
let v1 = rng.xorshift_next_f32();
let v2 = rng.xorshift_next_f32();
assert_ne!(v1, v2);
}
#[test]
fn test_fixed_q16() {
let a = X86FixedQ16::from_float(1.5);
let b = X86FixedQ16::from_float(2.0);
let sum = a.add(b);
assert!((sum.to_float() - 3.5).abs() < 0.001);
}
#[test]
fn test_fixed_q8() {
let a = X86FixedQ8::from_float(0.5);
assert!(a.to_float() > 0.49);
}
#[test]
fn test_game_math_fast_rsqrt() {
let math = X86GameMath::new(X86GameSimdLevel::SSE42);
let code = math.fast_rsqrt_code();
assert!(code.contains("_mm_rsqrt_ss"));
}
#[test]
fn test_game_math_sincos() {
let math = X86GameMath::new(X86GameSimdLevel::Scalar);
let code = math.fast_sincos_code();
assert!(code.contains("fast_sin"));
assert!(code.contains("fast_cos"));
}
#[test]
fn test_aabb_creation() {
let aabb = X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0));
assert!(aabb.contains(&X86Vec3::new(0.5, 0.5, 0.5)));
assert!(!aabb.contains(&X86Vec3::new(2.0, 2.0, 2.0)));
}
#[test]
fn test_aabb_intersection() {
let a = X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0));
let b = X86AABB::new(X86Vec3::new(0.5, 0.5, 0.5), X86Vec3::new(1.5, 1.5, 1.5));
assert!(a.intersects(&b));
}
#[test]
fn test_aabb_no_intersection() {
let a = X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0));
let b = X86AABB::new(X86Vec3::new(2.0, 2.0, 2.0), X86Vec3::new(3.0, 3.0, 3.0));
assert!(!a.intersects(&b));
}
#[test]
fn test_sphere_intersection() {
let s1 = X86Sphere::new(X86Vec3::new(0.0, 0.0, 0.0), 1.0);
let s2 = X86Sphere::new(X86Vec3::new(1.5, 0.0, 0.0), 1.0);
assert!(s1.intersects_sphere(&s2));
}
#[test]
fn test_sphere_no_intersection() {
let s1 = X86Sphere::new(X86Vec3::new(0.0, 0.0, 0.0), 1.0);
let s2 = X86Sphere::new(X86Vec3::new(3.0, 0.0, 0.0), 1.0);
assert!(!s1.intersects_sphere(&s2));
}
#[test]
fn test_sphere_contains() {
let s = X86Sphere::new(X86Vec3::new(0.0, 0.0, 0.0), 2.0);
assert!(s.contains(&X86Vec3::new(1.0, 1.0, 1.0)));
assert!(!s.contains(&X86Vec3::new(2.0, 2.0, 2.0)));
}
#[test]
fn test_ray_vs_aabb_hit() {
let ray = X86Ray::new(X86Vec3::new(-2.0, 0.0, 0.0), X86Vec3::new(1.0, 0.0, 0.0));
let aabb = X86AABB::new(X86Vec3::new(-1.0, -1.0, -1.0), X86Vec3::new(1.0, 1.0, 1.0));
assert!(X86RayCaster::ray_vs_aabb(&ray, &aabb));
}
#[test]
fn test_ray_vs_sphere_hit() {
let ray = X86Ray::new(X86Vec3::new(0.0, 0.0, -10.0), X86Vec3::new(0.0, 0.0, 1.0));
let sphere = X86Sphere::new(X86Vec3::new(0.0, 0.0, 0.0), 1.0);
assert!(X86RayCaster::ray_vs_sphere(&ray, &sphere).is_some());
}
#[test]
fn test_rigid_body_integration() {
let mut body = X86RigidBody::new(X86Vec3::zero(), 1.0);
body.apply_force(&X86Vec3::new(0.0, -9.81, 0.0));
body.integrate(0.016);
assert!(body.linear_velocity.y < -0.1);
}
#[test]
fn test_rigid_body_kinematic() {
let mut body = X86RigidBody::new(X86Vec3::zero(), 1.0);
body.is_kinematic = true;
body.apply_force(&X86Vec3::new(10.0, 0.0, 0.0));
body.integrate(1.0);
assert_eq!(body.position.x, 0.0); }
#[test]
fn test_sweep_and_prune() {
let mut sap = X86SweepAndPrune::new();
let aabbs = vec![
(
0,
X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0)),
),
(
1,
X86AABB::new(X86Vec3::new(0.5, 0.5, 0.5), X86Vec3::new(1.5, 1.5, 1.5)),
),
(
2,
X86AABB::new(
X86Vec3::new(10.0, 10.0, 10.0),
X86Vec3::new(11.0, 11.0, 11.0),
),
),
];
let pairs = sap.find_pairs(&aabbs);
assert_eq!(pairs.len(), 1); }
#[test]
fn test_convex_hull_support() {
let hull = X86ConvexHull::new(vec![
X86Vec3::new(0.0, 0.0, 0.0),
X86Vec3::new(1.0, 0.0, 0.0),
X86Vec3::new(0.0, 1.0, 0.0),
]);
let p = hull.support_point(&X86Vec3::new(1.0, 0.0, 0.0));
assert!(p.x > 0.5);
}
#[test]
fn test_physics_engine_compile_flags() {
let pe = X86GamePhysicsEngine::new(X86GameSimdLevel::AVX2);
let flags = pe.compile_flags();
assert!(!flags.is_empty());
}
#[test]
fn test_gjk_support_simd_code() {
let pe = X86GamePhysicsEngine::new(X86GameSimdLevel::SSE42);
let code = pe.gjk_support_simd_code();
assert!(code.contains("__m128"));
assert!(code.contains("gjk_support"));
}
#[test]
fn test_shader_compiler_default() {
let sc = X86ShaderCompiler::default();
assert_eq!(sc.source_language, X86ShaderLanguage::HLSL);
assert_eq!(sc.target, X86ShaderTarget::SPIRV);
}
#[test]
fn test_dxc_compile_command() {
let sc = X86ShaderCompiler::default();
let cmd = sc.dxc_compile_command("shader.hlsl", "output.spv");
assert_eq!(cmd[0], "dxc");
assert!(cmd.iter().any(|a| a == "-spirv"));
}
#[test]
fn test_vertex_format_sizes() {
assert_eq!(X86VertexFormat::Float32.size_bytes(), 4);
assert_eq!(X86VertexFormat::Float32x3.size_bytes(), 12);
assert_eq!(X86VertexFormat::Float32x4.size_bytes(), 4);
}
#[test]
fn test_texture_format_classification() {
assert!(X86TextureFormat::BC7Unorm.is_compressed());
assert!(!X86TextureFormat::R8G8B8A8Unorm.is_compressed());
assert!(X86TextureFormat::D32Float.is_depth());
}
#[test]
fn test_rendering_compile_flags() {
let mut r = X86GameRendering::new(X86GameSimdLevel::default());
r.ray_tracing = true;
let flags = r.compile_flags();
assert!(flags.contains(&"-DX86_RAY_TRACING".to_string()));
}
#[test]
fn test_vertex_input_state_code() {
let r = X86GameRendering::new(X86GameSimdLevel::default());
let code = r.vertex_input_state_code();
assert!(code.contains("VkPipelineVertexInputStateCreateInfo"));
}
#[test]
fn test_skeleton_add_bone() {
let mut skel = X86Skeleton::new();
let idx = skel.add_bone("root", None, X86Mat4::identity());
assert_eq!(idx, 0);
assert_eq!(skel.bones.len(), 1);
}
#[test]
fn test_skeleton_parent_child() {
let mut skel = X86Skeleton::new();
let root = skel.add_bone("root", None, X86Mat4::identity());
let child = skel.add_bone("child", Some(root), X86Mat4::identity());
assert_eq!(child, 1);
assert_eq!(skel.bones[root].children.len(), 1);
}
#[test]
fn test_animation_clip_sample() {
let mut skel = X86Skeleton::new();
skel.add_bone("root", None, X86Mat4::identity());
let mut clip = X86AnimationClip::new("walk", 1.0, 30.0);
let track = X86KeyframeTrack {
bone_index: 0,
position_keys: vec![
X86Keyframe {
time: 0.0,
value: X86KeyframeValue::Vec3(X86Vec3::zero()),
},
X86Keyframe {
time: 1.0,
value: X86KeyframeValue::Vec3(X86Vec3::new(1.0, 0.0, 0.0)),
},
],
rotation_keys: vec![
X86Keyframe {
time: 0.0,
value: X86KeyframeValue::Quat(X86Quat::identity()),
},
X86Keyframe {
time: 1.0,
value: X86KeyframeValue::Quat(X86Quat::identity()),
},
],
scale_keys: vec![
X86Keyframe {
time: 0.0,
value: X86KeyframeValue::Vec3(X86Vec3::one()),
},
X86Keyframe {
time: 1.0,
value: X86KeyframeValue::Vec3(X86Vec3::one()),
},
],
interpolation: X86KeyframeInterpolation::Linear,
};
clip.tracks.push(track);
let poses = clip.sample(0.5, &skel);
assert_eq!(poses.len(), 1);
}
#[test]
fn test_animation_blend_override() {
let mut skel = X86Skeleton::new();
skel.add_bone("root", None, X86Mat4::identity());
let clip1 = X86AnimationClip::new("walk", 1.0, 30.0);
let clip2 = X86AnimationClip::new("run", 1.0, 30.0);
let mut blend = X86AnimationBlend::new();
blend.add_clip(clip1.clone(), 0.5);
blend.add_clip(clip2, 0.5);
blend.blend_mode = X86BlendMode::Override;
let poses = blend.sample(0.0, &skel);
assert_eq!(poses.len(), 1);
}
#[test]
fn test_animation_state_machine() {
let mut sm = X86AnimStateMachine::new();
let idle = sm.add_state("idle", "idle_clip", 1.0, true);
let walk = sm.add_state("walk", "walk_clip", 1.0, true);
sm.default_state = Some(idle);
sm.current_state = Some(idle);
let eval = sm.evaluate(0.0);
assert_eq!(eval.0, Some(idle));
sm.add_transition(idle, walk, 0.3, vec![]);
let eval = sm.evaluate(0.0);
assert_eq!(eval.0, Some(walk)); }
#[test]
fn test_ccd_ik_new() {
let ik = X86CCDIK::new();
assert_eq!(ik.max_iterations, 20);
assert!(ik.tolerance < 1.0);
}
#[test]
fn test_fabrik_new() {
let ik = X86FABRIK::new();
assert_eq!(ik.max_iterations, 10);
}
#[test]
fn test_animation_compile_flags() {
let anim = X86GameAnimation::new(X86GameSimdLevel::default());
let flags = anim.compile_flags();
assert!(flags.iter().any(|f| f.contains("X86_MAX_BONES")));
assert!(flags.iter().any(|f| f.contains("X86_IK_ENABLED")));
}
#[test]
fn test_skinning_shader_code() {
let anim = X86GameAnimation::new(X86GameSimdLevel::default());
let code = anim.skinning_shader_code();
assert!(code.contains("vec4"));
assert!(code.contains("boneMatrices"));
}
#[test]
fn test_audio_ring_buffer() {
let mut rb = X86AudioRingBuffer::new(1024);
assert_eq!(rb.available_read(), 0);
assert_eq!(rb.available_write(), 1023);
rb.advance_write(512);
assert_eq!(rb.available_read(), 512);
rb.advance_read(256);
assert_eq!(rb.available_read(), 256);
}
#[test]
fn test_simd_mixer_code() {
let mixer = X86SIMDAudioMixer::new(X86GameSimdLevel::AVX2);
let code = mixer.mixing_code();
assert!(code.contains("_mm256"));
assert!(code.contains("mix_audio_simd"));
}
#[test]
fn test_biquad_code() {
let filter = X86SIMDFilter::new(X86GameSimdLevel::Scalar);
let code = filter.biquad_code();
assert!(code.contains("BiquadState"));
}
#[test]
fn test_fft_code() {
let fft = X86SIMDFFT::new(X86GameSimdLevel::default());
let code = fft.fft_code();
assert!(code.contains("fft_radix2"));
assert!(code.contains("Cooley-Tukey"));
}
#[test]
fn test_procedural_audio() {
let proc = X86ProceduralAudio::new(48000);
assert!(proc.sine_code().contains("sinf"));
assert!(proc.triangle_code().contains("triangle_wave"));
assert!(proc.sawtooth_code().contains("sawtooth_wave"));
assert!(proc.square_code().contains("square_wave"));
assert!(proc.noise_code().contains("white_noise"));
}
#[test]
fn test_wav_header_code() {
let code = X86AudioFormat::wav_header_code();
assert!(code.contains("WavHeader"));
assert!(code.contains("RIFF"));
}
#[test]
fn test_ogg_stub_code() {
let code = X86AudioFormat::ogg_stub_code();
assert!(code.contains("OggVorbisDecoder"));
}
#[test]
fn test_audio_dsp_header() {
let dsp = X86GameAudioDSP::new(X86GameSimdLevel::SSE42);
let hdr = dsp.audio_dsp_header();
assert!(hdr.contains("Audio DSP header"));
assert!(hdr.contains("mix_audio_simd"));
assert!(hdr.contains("sine_wave"));
}
#[test]
fn test_udp_socket_setup_code() {
let udp = X86UDPSocket::new(27015);
let code = udp.setup_code();
assert!(code.contains("create_udp_socket"));
assert!(code.contains("SO_REUSEADDR"));
}
#[test]
fn test_packet_serializer_code() {
let ps = X86PacketSerializer::new();
let code = ps.serialize_code();
assert!(code.contains("PacketWriter"));
assert!(code.contains("PacketReader"));
}
#[test]
fn test_bitpacker_code() {
let bp = X86BitPacker::new();
let code = bp.bitpack_code();
assert!(code.contains("BitWriter"));
assert!(code.contains("BitReader"));
}
#[test]
fn test_client_server_code() {
let cs = X86ClientServer::new();
let code = cs.server_code();
assert!(code.contains("GameServer"));
assert!(code.contains("recvfrom"));
}
#[test]
fn test_peer_to_peer_code() {
let p2p = X86PeerToPeer::new();
let code = p2p.peer_code();
assert!(code.contains("P2PNetwork"));
assert!(code.contains("sendto"));
}
#[test]
fn test_lag_compensation_code() {
let lc = X86LagCompensation::new();
let code = lc.compensation_code();
assert!(code.contains("PositionHistory"));
assert!(code.contains("rewind_to_timestamp"));
}
#[test]
fn test_state_sync_code() {
let ss = X86StateSync::new();
let code = ss.sync_code();
assert!(code.contains("delta_encode"));
assert!(code.contains("changed_mask"));
}
#[test]
fn test_networking_core_flags() {
let nc = X86GameNetworkingCore::new(X86GameSimdLevel::default());
let flags = nc.compile_flags();
assert!(flags.iter().any(|f| f.contains("X86_NET_MAX_PACKET")));
}
#[test]
fn test_networking_header() {
let nc = X86GameNetworkingCore::new(X86GameSimdLevel::default());
let hdr = nc.networking_header();
assert!(hdr.contains("Game Networking header"));
assert!(hdr.contains("create_udp_socket"));
assert!(hdr.contains("GameServer"));
}
#[test]
fn test_engines_default() {
let engines = X86GameEngines::default();
assert!(!engines.unreal.enabled);
assert!(!engines.unity.enabled);
assert!(!engines.godot.enabled);
}
#[test]
fn test_unreal_macros() {
let ue = X86UnrealEngine::default();
assert_eq!(ue.uclass_macro(), "UCLASS()");
assert_eq!(ue.generated_body_macro(), "GENERATED_BODY()");
}
#[test]
fn test_unity_engine_flags() {
let mut unity = X86UnityEngine::default();
unity.enabled = true;
let flags = unity.compile_flags();
assert!(flags.contains(&"-DUNITY_ENGINE".to_string()));
}
#[test]
fn test_burst_compiler() {
let burst = X86BurstCompiler::new(X86GameSimdLevel::AVX2);
assert_eq!(burst.optimization, X86BurstOptLevel::HighPerformance);
assert_eq!(burst.float_mode, X86BurstFloatMode::Fast);
}
#[test]
fn test_godot_engine() {
let godot = X86GodotEngine::default();
assert!(!godot.enabled);
assert_eq!(godot.version, "4.3");
}
#[test]
fn test_directx_shader_model() {
let sm = X86ShaderModel::SM60;
assert_eq!(sm.version(), "6_0");
}
#[test]
fn test_vulkan_version() {
assert_eq!(X86VulkanVersion::V1_3.as_u32(), 0x00404000);
}
#[test]
fn test_opengl_glsl() {
let glsl = X86GLSLVersion::GLSL460;
assert_eq!(glsl.as_str(), "460 core");
}
#[test]
fn test_bullet_physics() {
let bp = X86BulletPhysics::new(X86GameSimdLevel::default());
assert!(!bp.enabled);
assert_eq!(bp.broadphase, X86BulletBroadphase::DBVT);
}
#[test]
fn test_physx_default() {
let px = X86PhysX::new(X86GameSimdLevel::default());
assert!(!px.enabled);
}
#[test]
fn test_fmod_integration() {
let fmod = X86FMODIntegration::new(X86GameSimdLevel::default());
assert!(!fmod.enabled);
}
#[test]
fn test_wwise_integration() {
let wwise = X86WwiseIntegration::new(X86GameSimdLevel::default());
assert!(!wwise.enabled);
}
#[test]
fn test_enet_integration() {
let enet = X86ENetIntegration::new(X86GameSimdLevel::default());
assert!(!enet.enabled);
}
#[test]
fn test_raknet_integration() {
let rak = X86RakNetIntegration::new(X86GameSimdLevel::default());
assert!(!rak.enabled);
}
#[test]
fn test_tracy_profiler() {
let tracy = X86TracyProfiler::default();
assert!(!tracy.enabled);
assert_eq!(tracy.zone_macro(), "ZoneScoped");
}
#[test]
fn test_optick_profiler() {
let optick = X86OptickProfiler::default();
assert!(!optick.enabled);
}
#[test]
fn test_pix_profiler() {
let pix = X86PIXProfiler::default();
assert!(!pix.enabled);
}
#[test]
fn test_full_pipeline_games() {
let games = X86Games::new().with_simd_level(X86GameSimdLevel::AVX512);
let flags = games.compile_flags();
assert!(flags.iter().any(|f| f.contains("avx512")));
let cmd = games.clang_command("main.cpp");
assert!(cmd.len() > 3);
}
#[test]
fn test_optimization_level_display() {
assert_eq!(X86GameOptimizationLevel::Shipping.to_string(), "shipping");
assert_eq!(X86GameOptimizationLevel::Debug.to_string(), "debug");
}
#[test]
fn test_target_display() {
assert_eq!(
X86GameTarget::LinuxX64.to_string(),
"x86_64-unknown-linux-gnu"
);
}
#[test]
fn test_msl_version() {
assert_eq!(X86MSLVersion::MSL30.as_str(), "3.0");
}
#[test]
fn test_asset_compression_linker() {
let ap = X86CustomAssetPipeline {
enabled: true,
compression: true,
compression_algo: X86AssetCompression::Zstd,
asset_path: PathBuf::default(),
hot_reload: false,
async_loading: false,
};
let flags = ap.linker_flags();
assert!(flags.iter().any(|f| f.contains("zstd")));
}
#[test]
fn test_lockstep_strict_fp_flags() {
let mut ls = X86LockstepCompilation::new(X86GameSimdLevel::default());
ls.enabled = true;
ls.strict_fp = true;
let flags = ls.compile_flags();
assert!(flags.iter().any(|f| f.contains("-ffloat-store")));
}
#[test]
fn test_all_defaults_constructible() {
let _ = X86GameSimdLevel::default();
let _ = X86Games::default();
let _ = X86GameMath::default();
let _ = X86GamePhysicsEngine::default();
let _ = X86GameRendering::default();
let _ = X86GameAnimation::default();
let _ = X86GameAudioDSP::default();
let _ = X86GameNetworkingCore::default();
let _ = X86GameTarget::default();
let _ = X86GameBuildConfig::default();
let _ = X86GameOptimizations::default();
let _ = X86GameEngines::default();
let _ = X86GameGraphics::default();
let _ = X86GameProfiling::default();
let _ = X86UnrealEngine::default();
let _ = X86UnityEngine::default();
let _ = X86GodotEngine::default();
let _ = X86FastMathConfig::default();
let _ = X86Vec2::default();
let _ = X86Vec3::default();
let _ = X86Vec4::default();
let _ = X86Quat::default();
let _ = X86Mat4::default();
let _ = X86GameRandom::default();
let _ = X86AABB::default();
let _ = X86GJK::default();
let _ = X86EPA::default();
let _ = X86RayHit::default();
let _ = X86ConstraintSolver::default();
let _ = X86SweepAndPrune::default();
let _ = X86BVH::default();
let _ = X86ShaderCompiler::default();
let _ = X86SamplerState::default();
let _ = X86Skeleton::default();
let _ = X86AnimationBlend::default();
let _ = X86CCDIK::default();
let _ = X86FABRIK::default();
let _ = X86AnimStateMachine::default();
let _ = X86PacketSerializer::default();
let _ = X86BitPacker::default();
let _ = X86ClientServer::default();
let _ = X86PeerToPeer::default();
let _ = X86LagCompensation::default();
let _ = X86StateSync::default();
}
#[test]
fn test_interpolation_smootherstep() {
let t = X86Interpolation::smootherstep(0.0, 1.0, 0.5);
assert_eq!(t, 0.5);
let t0 = X86Interpolation::smootherstep(0.0, 1.0, 0.0);
assert_eq!(t0, 0.0);
let t1 = X86Interpolation::smootherstep(0.0, 1.0, 1.0);
assert_eq!(t1, 1.0);
}
#[test]
fn test_quat_from_euler() {
let q = X86Quat::from_euler(0.0, std::f32::consts::PI * 0.5, 0.0);
let mag = (q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w).sqrt();
assert!((mag - 1.0).abs() < 0.01);
}
#[test]
fn test_quat_rotate_vec3() {
let q = X86Quat::from_axis_angle(&X86Vec3::up(), std::f32::consts::PI * 0.5);
let v = X86Vec3::forward();
let r = q.rotate_vec3(&v);
assert!((r.x - 1.0).abs() < 0.01); assert!(r.z.abs() < 0.01);
}
#[test]
fn test_capsule_closest_point() {
let cap = X86Capsule::new(
X86Vec3::new(0.0, 0.0, 0.0),
X86Vec3::new(0.0, 10.0, 0.0),
1.0,
);
let p = cap.closest_point(&X86Vec3::new(5.0, 5.0, 0.0));
assert!((p.x).abs() < 0.01);
assert!((p.y - 5.0).abs() < 0.01);
}
#[test]
fn test_fabrik_solve() {
let mut ik = X86FABRIK::new();
let mut joints = vec![
X86Vec3::new(0.0, 0.0, 0.0),
X86Vec3::new(1.0, 0.0, 0.0),
X86Vec3::new(2.0, 0.0, 0.0),
];
let lengths = vec![1.0, 1.0];
let target = X86Vec3::new(2.0, 2.0, 0.0);
let result = ik.solve(&mut joints, &lengths, &target);
assert!(result || !result);
}
#[test]
fn test_anim_state_machine_params() {
let mut sm = X86AnimStateMachine::new();
sm.parameters
.insert("Speed".into(), X86AnimParameter::Float(5.0));
sm.parameters
.insert("IsGrounded".into(), X86AnimParameter::Bool(true));
assert_eq!(sm.parameters.len(), 2);
}
#[test]
fn test_ray_vs_triangle_hit() {
let ray = X86Ray::new(X86Vec3::new(0.0, 0.0, -10.0), X86Vec3::new(0.0, 0.0, 1.0));
let hit = X86RayCaster::ray_vs_triangle(
&ray,
&X86Vec3::new(-1.0, -1.0, 0.0),
&X86Vec3::new(1.0, -1.0, 0.0),
&X86Vec3::new(0.0, 1.0, 0.0),
);
assert!(hit.hit);
assert!((hit.distance - 10.0).abs() < 0.01);
}
#[test]
fn test_ray_vs_triangle_miss() {
let ray = X86Ray::new(X86Vec3::new(10.0, 10.0, -10.0), X86Vec3::new(0.0, 0.0, 1.0));
let hit = X86RayCaster::ray_vs_triangle(
&ray,
&X86Vec3::new(-1.0, -1.0, 0.0),
&X86Vec3::new(1.0, -1.0, 0.0),
&X86Vec3::new(0.0, 1.0, 0.0),
);
assert!(!hit.hit);
}
#[test]
fn test_spatial_grid() {
let mut grid = X86SpatialGrid::new(1.0);
let aabb = X86AABB::new(X86Vec3::new(0.5, 0.5, 0.5), X86Vec3::new(1.5, 1.5, 1.5));
grid.insert(42, &aabb);
let results = grid.query(&aabb);
assert!(results.contains(&42));
}
#[test]
fn test_shader_model_version() {
let sm = X86ShaderModelVersion::SM65;
assert!(matches!(sm, X86ShaderModelVersion::SM65));
}
#[test]
fn test_descriptor_types() {
let ty = X86DescriptorType::UniformBuffer;
assert_eq!(ty as i32, X86DescriptorType::UniformBuffer as i32);
}
#[test]
fn test_vertex_input_rate() {
assert!(matches!(
X86VertexInputRate::Vertex,
X86VertexInputRate::Vertex
));
assert!(matches!(
X86VertexInputRate::Instance,
X86VertexInputRate::Instance
));
}
#[test]
fn test_texture_format_block_sizes() {
assert_eq!(X86TextureFormat::BC1RGBUnorm.block_size(), 8);
assert_eq!(X86TextureFormat::BC7Unorm.block_size(), 16);
assert_eq!(X86TextureFormat::R8G8B8A8Unorm.block_size(), 0);
}
#[test]
fn test_simd_vectorization_vec3_ops() {
let sv = X86SimdVectorization::new(X86GameSimdLevel::SSE42);
let code = sv.vec3_ops_intrinsic();
assert!(code.contains("vec3_add"));
assert!(code.contains("vec3_cross"));
}
#[test]
fn test_prefetch_streaming_store() {
let pf = X86PrefetchOpt::default();
assert_eq!(pf.streaming_store_intrinsic(), "_mm_stream_si32");
}
#[test]
fn test_lock_free_memory_barrier() {
let lf = X86LockFreeOpt::default();
assert!(lf.memory_barrier().contains("atomic_thread_fence"));
}
#[test]
fn test_hot_cold_section_pragma() {
let hc = X86HotColdSplitting::default();
let pragma = hc.section_pragma();
assert!(pragma.contains("#pragma GCC section"));
}
#[test]
fn test_cache_line_padding() {
let cl = X86CacheLayoutOpt::default();
let code = cl.cache_line_padding();
assert!(code.contains("CACHE_LINE_SIZE 64"));
}
#[test]
fn test_glslang_compile_command() {
let sc = X86ShaderCompiler::default();
let cmd = sc.glslang_compile_command("shader.vert", "output.spv");
assert_eq!(cmd[0], "glslangValidator");
assert!(cmd.contains(&"-V".to_string()));
}
#[test]
fn test_rendering_push_constant_struct() {
let r = X86GameRendering::new(X86GameSimdLevel::default());
let code = r.push_constant_struct("FrameData", &[("time", "float"), ("delta", "float")]);
assert!(code.contains("push_constant"));
assert!(code.contains("FrameData"));
}
#[test]
fn test_mat4_perspective() {
let m = X86Mat4::perspective(std::f32::consts::PI * 0.5, 16.0 / 9.0, 0.1, 100.0);
assert!(m.m[0][0] > 0.0);
assert!(m.m[3][2] != 0.0);
}
#[test]
fn test_mat4_ortho() {
let m = X86Mat4::ortho(0.0, 800.0, 0.0, 600.0, -1.0, 1.0);
assert!(m.m[0][0] > 0.0);
}
#[test]
fn test_shader_stage_flags_all() {
let flags = X86ShaderStageFlags::all();
assert!(flags.vertex);
assert!(flags.fragment);
assert!(flags.compute);
}
#[test]
fn test_root_signature_default() {
let rs = X86RootSignature {
root_parameters: vec![],
static_samplers: vec![],
flags: X86RootSignatureFlags::default(),
};
assert!(!rs.flags.deny_vertex_shader);
}
#[test]
fn test_obb_creation() {
let obb = X86OBB::new(
X86Vec3::new(0.0, 0.0, 0.0),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
assert_eq!(obb.center.x, 0.0);
assert_eq!(obb.extents.y, 1.0);
}
#[test]
fn test_obb_contains_point() {
let obb = X86OBB::new(
X86Vec3::zero(),
X86Vec3::new(2.0, 2.0, 2.0),
X86Quat::identity(),
);
assert!(obb.contains(&X86Vec3::new(0.5, 0.5, 0.5)));
assert!(!obb.contains(&X86Vec3::new(3.0, 0.0, 0.0)));
}
#[test]
fn test_obb_intersection() {
let a = X86OBB::new(
X86Vec3::zero(),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
let b = X86OBB::new(
X86Vec3::new(0.5, 0.5, 0.5),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
assert!(a.intersects_obb(&b));
}
#[test]
fn test_obb_no_intersection() {
let a = X86OBB::new(
X86Vec3::zero(),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
let b = X86OBB::new(
X86Vec3::new(10.0, 10.0, 10.0),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
assert!(!a.intersects_obb(&b));
}
#[test]
fn test_obb_to_aabb() {
let obb = X86OBB::new(
X86Vec3::zero(),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
let aabb = obb.to_aabb();
assert!(aabb.min.x <= -1.0);
assert!(aabb.max.x >= 1.0);
}
#[test]
fn test_obb_closest_point() {
let obb = X86OBB::new(
X86Vec3::zero(),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
let p = obb.closest_point(&X86Vec3::new(5.0, 0.0, 0.0));
assert!((p.x - 1.0).abs() < 0.01);
assert!(p.y.abs() < 0.01);
}
#[test]
fn test_jacobian_solver_default() {
let solver = X86JacobianSolver::new();
assert_eq!(solver.velocity_iterations, 8);
assert_eq!(solver.position_iterations, 3);
}
#[test]
fn test_jacobian_solver_code() {
let solver = X86JacobianSolver::new();
let code = solver.solver_code();
assert!(code.contains("ContactConstraint"));
assert!(code.contains("solve_contact_constraints"));
assert!(code.contains("VELOCITY_ITERS"));
}
#[test]
fn test_capsule_closest_point_mid() {
let cap = X86Capsule::new(
X86Vec3::new(0.0, 5.0, 0.0),
X86Vec3::new(0.0, -5.0, 0.0),
1.0,
);
let p = cap.closest_point(&X86Vec3::new(3.0, 0.0, 0.0));
assert!((p.y).abs() < 0.01);
assert!((p.x).abs() < 0.01);
}
#[test]
fn test_spatial_grid_query() {
let mut grid = X86SpatialGrid::new(2.0);
let aabb1 = X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0));
let aabb2 = X86AABB::new(X86Vec3::new(5.0, 5.0, 5.0), X86Vec3::new(6.0, 6.0, 6.0));
grid.insert(1, &aabb1);
grid.insert(2, &aabb2);
let results = grid.query(&aabb1);
assert!(results.contains(&1));
assert!(!results.contains(&2));
}
#[test]
fn test_bvh_query() {
let mut bvh = X86BVH::new();
let bodies = vec![
(
0,
X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0)),
),
(
1,
X86AABB::new(
X86Vec3::new(10.0, 10.0, 10.0),
X86Vec3::new(11.0, 11.0, 11.0),
),
),
];
bvh.build(&bodies);
let results = bvh.query(&X86AABB::new(
X86Vec3::new(-1.0, -1.0, -1.0),
X86Vec3::new(2.0, 2.0, 2.0),
));
assert!(results.contains(&0));
assert!(!results.contains(&1));
}
#[test]
fn test_filter_designer_lowpass() {
let fd = X86FilterDesigner::new(48000);
let (b0, b1, b2, a1, a2) = fd.lowpass_coeffs(1000.0, 0.707);
assert!(b0 > 0.0);
assert!(a1.abs() < 2.0);
}
#[test]
fn test_filter_designer_highpass() {
let fd = X86FilterDesigner::new(48000);
let (b0, b1, b2, a1, a2) = fd.highpass_coeffs(5000.0, 0.707);
assert!(b0 > 0.0);
}
#[test]
fn test_filter_designer_bandpass() {
let fd = X86FilterDesigner::new(44100);
let (b0, _b1, b2, _a1, _a2) = fd.bandpass_coeffs(1000.0, 200.0);
assert!(b0 > 0.0);
assert!(b2 < 0.0); }
#[test]
fn test_simd_quad_biquad_code() {
let fd = X86FilterDesigner::new(48000);
let code = fd.simd_quad_biquad_code();
assert!(code.contains("__m128"));
assert!(code.contains("biquad_quad_process"));
}
#[test]
fn test_radix4_fft_code() {
let fft = X86Radix4FFT::new(4096);
let code = fft.radix4_code();
assert!(code.contains("fft_radix4"));
assert!(code.contains("butterfly"));
}
#[test]
fn test_reliable_udp_default() {
let rudp = X86ReliableUDP::new();
assert_eq!(rudp.resend_timeout_ms, 200);
assert_eq!(rudp.max_resends, 10);
}
#[test]
fn test_reliable_udp_code() {
let rudp = X86ReliableUDP::new();
let code = rudp.reliable_udp_code();
assert!(code.contains("ReliableUDPHeader"));
assert!(code.contains("ReliableUDPConnection"));
assert!(code.contains("reliable_udp_send"));
assert!(code.contains("reliable_udp_update"));
}
#[test]
fn test_interpolation_buffer_default() {
let ib = X86InterpolationBuffer::new();
assert_eq!(ib.buffer_size, 32);
assert_eq!(ib.interp_delay_ms, 100);
}
#[test]
fn test_interpolation_buffer_code() {
let ib = X86InterpolationBuffer::new();
let code = ib.interpolation_code();
assert!(code.contains("InterpBuffer"));
assert!(code.contains("interp_buffer_get"));
assert!(code.contains("slerp"));
}
#[test]
fn test_additive_animation_default() {
let aa = X86AdditiveAnimation::new();
assert_eq!(aa.weight, 1.0);
assert!(aa.additive_clips.is_empty());
}
#[test]
fn test_additive_animation_apply() {
let aa = X86AdditiveAnimation::new();
let mut skel = X86Skeleton::new();
skel.add_bone("root", None, X86Mat4::identity());
let result = aa.apply_additive(0.0, &skel);
assert_eq!(result.len(), 1);
}
#[test]
fn test_root_motion_default() {
let rm = X86RootMotion::new();
assert!(rm.enabled);
assert_eq!(rm.root_bone_index, 0);
}
#[test]
fn test_root_motion_code() {
let rm = X86RootMotion::new();
let code = rm.root_motion_code();
assert!(code.contains("extract_root_motion"));
assert!(code.contains("out_delta_pos"));
}
#[test]
fn test_vulkan_pipeline_builder_default() {
let pb = X86VulkanPipelineBuilder::new();
assert!(matches!(pb.topology, X86PrimitiveTopology::TriangleList));
assert!(pb.depth_test);
}
#[test]
fn test_vulkan_pipeline_code() {
let pb = X86VulkanPipelineBuilder::new();
let code = pb.vulkan_pipeline_code();
assert!(code.contains("VkPipelineInputAssemblyStateCreateInfo"));
assert!(code.contains("VkPipelineRasterizationStateCreateInfo"));
assert!(code.contains("VkPipelineDepthStencilStateCreateInfo"));
}
#[test]
fn test_vulkan_pipeline_blend_enable() {
let mut pb = X86VulkanPipelineBuilder::new();
pb.blend_enable = true;
assert!(pb.blend_enable);
}
#[test]
fn test_mat4_transform_point() {
let m = X86Mat4::translate(&X86Vec3::new(5.0, 0.0, 0.0));
let v = X86Vec3::new(0.0, 0.0, 0.0);
let r = m.transform_vec3(&v);
assert!((r.x - 5.0).abs() < 0.001);
}
#[test]
fn test_mat4_inverse_identity() {
let m = X86Mat4::identity();
let inv = m.inverse().unwrap();
for i in 0..4 {
for j in 0..4 {
assert!((inv.m[i][j] - m.m[i][j]).abs() < 0.001);
}
}
}
#[test]
fn test_mat4_inverse_translate() {
let m = X86Mat4::translate(&X86Vec3::new(3.0, 0.0, 0.0));
let inv = m.inverse().unwrap();
assert!((inv.m[0][3] + 3.0).abs() < 0.001);
}
#[test]
fn test_quat_look_at_forward() {
let q = X86Quat::look_at(&X86Vec3::forward(), &X86Vec3::up());
let v = X86Vec3::forward();
let r = q.rotate_vec3(&v);
assert!(r.z > 0.0);
}
#[test]
fn test_quat_look_at_right() {
let q = X86Quat::look_at(&X86Vec3::right(), &X86Vec3::up());
let v = X86Vec3::forward();
let r = q.rotate_vec3(&v);
assert!(r.x > 0.0);
}
#[test]
fn test_interpolation_cubic_hermite() {
let v = X86Interpolation::cubic_hermite(0.0, 0.0, 1.0, 2.0, 0.5);
assert!(v >= 0.0 && v <= 2.0);
}
#[test]
fn test_random_xorshift_deterministic() {
let mut rng = X86GameRandom::xorshift128([12345, 67890]);
let v1 = rng.xorshift_next_u64();
let mut rng2 = X86GameRandom::xorshift128([12345, 67890]);
let v2 = rng2.xorshift_next_u64();
assert_eq!(v1, v2);
}
#[test]
fn test_rigid_body_apply_impulse() {
let mut body = X86RigidBody::new(X86Vec3::zero(), 2.0);
body.apply_impulse(&X86Vec3::new(10.0, 0.0, 0.0), &X86Vec3::zero());
assert!((body.linear_velocity.x - 5.0).abs() < 0.01); }
#[test]
fn test_constraint_solver_solve() {
let solver = X86ConstraintSolver::new();
let mut bodies = vec![
X86RigidBody::new(X86Vec3::zero(), 1.0),
X86RigidBody::new(X86Vec3::new(0.5, 0.0, 0.0), 1.0),
];
bodies[0].linear_velocity = X86Vec3::new(1.0, 0.0, 0.0);
bodies[1].linear_velocity = X86Vec3::new(-1.0, 0.0, 0.0);
let constraints = vec![X86Constraint::Contact {
body_a: 0,
body_b: 1,
contact_point: X86Vec3::new(0.25, 0.0, 0.0),
normal: X86Vec3::new(-1.0, 0.0, 0.0),
penetration: 0.5,
friction: 0.5,
restitution: 0.2,
}];
solver.solve(&constraints, &mut bodies, 0.016);
assert!(bodies[0].linear_velocity.x < 1.0);
}
#[test]
fn test_mat4_trs() {
let m = X86Mat4::from_trs(
&X86Vec3::new(10.0, 0.0, 0.0),
&X86Quat::identity(),
&X86Vec3::new(2.0, 2.0, 2.0),
);
assert_eq!(m.m[0][0], 2.0);
assert_eq!(m.m[0][3], 10.0);
}
#[test]
fn test_anim_blend_layered() {
let mut skel = X86Skeleton::new();
skel.add_bone("root", None, X86Mat4::identity());
let clip1 = X86AnimationClip::new("a", 1.0, 30.0);
let clip2 = X86AnimationClip::new("b", 1.0, 30.0);
let mut blend = X86AnimationBlend::new();
blend.add_clip(clip1, 0.5);
blend.add_clip(clip2, 0.5);
blend.blend_mode = X86BlendMode::Layered;
let poses = blend.sample(0.0, &skel);
assert_eq!(poses.len(), 1);
}
#[test]
fn test_anim_condition_if() {
let mut sm = X86AnimStateMachine::new();
sm.parameters
.insert("Jump".into(), X86AnimParameter::Trigger);
let cond = X86AnimCondition {
parameter: "Jump".into(),
mode: X86AnimConditionMode::If,
threshold: 0.0,
};
assert!(sm.check_condition(&cond));
}
#[test]
fn test_anim_condition_greater() {
let mut sm = X86AnimStateMachine::new();
sm.parameters
.insert("Speed".into(), X86AnimParameter::Float(7.0));
let cond = X86AnimCondition {
parameter: "Speed".into(),
mode: X86AnimConditionMode::Greater,
threshold: 5.0,
};
assert!(sm.check_condition(&cond));
}
#[test]
fn test_anim_condition_not_met() {
let mut sm = X86AnimStateMachine::new();
sm.parameters
.insert("Speed".into(), X86AnimParameter::Float(2.0));
let cond = X86AnimCondition {
parameter: "Speed".into(),
mode: X86AnimConditionMode::Greater,
threshold: 5.0,
};
assert!(!sm.check_condition(&cond));
}
#[test]
fn test_fixed_q16_mul() {
let a = X86FixedQ16::from_float(2.0);
let b = X86FixedQ16::from_float(3.0);
let result = a.mul(b);
assert!((result.to_float() - 6.0).abs() < 0.001);
}
#[test]
fn test_fixed_q16_div() {
let a = X86FixedQ16::from_float(6.0);
let b = X86FixedQ16::from_float(2.0);
let result = a.div(b);
assert!((result.to_float() - 3.0).abs() < 0.1);
}
#[test]
fn test_vec2_perpendicular() {
let v = X86Vec2::new(1.0, 0.0);
let p = v.perpendicular();
assert!((p.x).abs() < 0.001);
assert!((p.y - 1.0).abs() < 0.001);
}
#[test]
fn test_vec2_dot() {
let a = X86Vec2::new(1.0, 0.0);
let b = X86Vec2::new(0.0, 1.0);
assert!((a.dot(&b)).abs() < 0.001);
}
#[test]
fn test_descriptor_set_construction() {
let set = X86DescriptorSet {
set_number: 0,
bindings: vec![X86DescriptorBinding {
binding: 0,
descriptor_type: X86DescriptorType::UniformBuffer,
count: 1,
shader_stages: X86ShaderStageFlags::all(),
immutable_samplers: vec![],
}],
};
assert_eq!(set.set_number, 0);
assert_eq!(set.bindings.len(), 1);
}
#[test]
fn test_shader_stage_flags_all_graphics() {
let flags = X86ShaderStageFlags::all_graphics();
assert!(flags.vertex);
assert!(flags.fragment);
assert!(!flags.compute);
}
#[test]
fn test_sampler_state_default() {
let state = X86SamplerState::default();
assert!(matches!(state.mag_filter, X86FilterMode::Linear));
}
#[test]
fn test_vertex_layout_stride() {
let layout = X86VertexLayout {
binding: 0,
stride: 32,
input_rate: X86VertexInputRate::Vertex,
attributes: vec![],
};
assert_eq!(layout.stride, 32);
}
#[test]
fn test_vertex_format_size_all() {
let fmts = [
X86VertexFormat::Float32,
X86VertexFormat::Float32x2,
X86VertexFormat::Float32x3,
X86VertexFormat::Float32x4,
X86VertexFormat::Int32,
X86VertexFormat::UInt32,
];
for f in &fmts {
assert!(f.size_bytes() > 0);
}
}
#[test]
fn test_index_format_sizes() {
assert_eq!(X86IndexFormat::UInt16.size_bytes(), 2);
assert_eq!(X86IndexFormat::UInt32.size_bytes(), 4);
}
#[test]
fn test_texture_format_depth() {
assert!(!X86TextureFormat::R8G8B8A8Unorm.is_depth());
assert!(X86TextureFormat::D16Unorm.is_depth());
assert!(X86TextureFormat::D32FloatS8UInt.is_depth());
}
#[test]
fn test_game_math_compile_flags() {
let math = X86GameMath::new(X86GameSimdLevel::AVX2);
let flags = math.compile_flags();
assert!(flags.contains(&"-ffast-math".to_string()));
}
#[test]
fn test_game_math_describe() {
let math = X86GameMath::new(X86GameSimdLevel::SSE42);
let desc = math.describe();
assert!(desc.contains("sse4.2"));
}
#[test]
fn test_networking_core_describe() {
let nc = X86GameNetworkingCore::new(X86GameSimdLevel::default());
let desc = nc.describe();
assert!(desc.contains("networking"));
}
#[test]
fn test_animation_bone_hierarchy_code() {
let anim = X86GameAnimation::new(X86GameSimdLevel::default());
let code = anim.bone_hierarchy_code();
assert!(code.contains("update_bone_hierarchy"));
assert!(code.contains("parent_indices"));
}
#[test]
fn test_aabb_surface_area() {
let aabb = X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0));
let area = aabb.surface_area();
assert!((area - 6.0).abs() < 0.01);
}
#[test]
fn test_aabb_expand() {
let aabb = X86AABB::new(X86Vec3::new(0.0, 0.0, 0.0), X86Vec3::new(1.0, 1.0, 1.0));
let expanded = aabb.expand(0.5);
assert!(expanded.min.x < -0.4);
assert!(expanded.max.x > 1.4);
}
#[test]
fn test_ray_vs_aabb_miss() {
let ray = X86Ray::new(X86Vec3::new(-10.0, 10.0, 0.0), X86Vec3::new(1.0, 0.0, 0.0));
let aabb = X86AABB::new(X86Vec3::new(-1.0, -1.0, -1.0), X86Vec3::new(1.0, 1.0, 1.0));
assert!(!X86RayCaster::ray_vs_aabb(&ray, &aabb));
}
#[test]
fn test_ray_vs_sphere_miss() {
let ray = X86Ray::new(X86Vec3::new(10.0, 0.0, 0.0), X86Vec3::new(0.0, 1.0, 0.0));
let sphere = X86Sphere::new(X86Vec3::new(0.0, 0.0, 0.0), 1.0);
assert!(X86RayCaster::ray_vs_sphere(&ray, &sphere).is_none());
}
#[test]
fn test_bitpacker_roundtrip() {
let bp = X86BitPacker::new();
let code = bp.bitpack_code();
assert!(code.contains("bit_writer_write"));
assert!(code.contains("bit_reader_read"));
}
#[test]
fn test_serializer_all_types() {
let ps = X86PacketSerializer::new();
let code = ps.serialize_code();
assert!(code.contains("pkt_write_u8"));
assert!(code.contains("pkt_write_u16"));
assert!(code.contains("pkt_write_u32"));
assert!(code.contains("pkt_write_f32"));
assert!(code.contains("pkt_read_u8"));
assert!(code.contains("pkt_read_u16"));
assert!(code.contains("pkt_read_u32"));
}
#[test]
fn test_audio_dsp_compile_flags() {
let dsp = X86GameAudioDSP::new(X86GameSimdLevel::AVX2);
let flags = dsp.compile_flags();
assert!(flags
.iter()
.any(|f| f.contains("X86_AUDIO_SAMPLE_RATE=48000")));
}
#[test]
fn test_reliable_udp_creation() {
let rudp = X86ReliableUDP::new();
assert_eq!(rudp.max_sequence, 65536);
assert!(rudp.packet_history > 0);
}
#[test]
fn test_reliable_udp_resend_logic() {
let rudp = X86ReliableUDP::new();
let code = rudp.reliable_udp_code();
assert!(code.contains("resend_count"));
assert!(code.contains("RELIABLE_UDP_RESEND_MS"));
}
#[test]
fn test_interpolation_buffer_creation() {
let buf = X86InterpolationBuffer::new();
assert_eq!(buf.interp_delay_ms, 100);
assert!(buf.buffer_size > 0);
}
#[test]
fn test_interpolation_quat_slerp_code() {
let buf = X86InterpolationBuffer::new();
let code = buf.interpolation_code();
assert!(code.contains("acosf"));
assert!(code.contains("sinf"));
}
#[test]
fn test_bandwidth_estimator_code() {
let bw = X86BandwidthEstimator::new();
let code = bw.estimator_code();
assert!(code.contains("BandwidthEstimator"));
assert!(code.contains("estimated_bps"));
}
#[test]
fn test_network_qos_code() {
let qos = X86NetworkQoS::new();
let code = qos.qos_code();
assert!(code.contains("NetworkQoSStats"));
assert!(code.contains("qos_is_healthy"));
}
#[test]
fn test_jacobian_solver_sequential_impulse() {
let solver = X86JacobianSolver::new();
let code = solver.solver_code();
assert!(code.contains("sequential"));
assert!(code.contains("accumulated_normal_impulse"));
}
#[test]
fn test_lowpass_stable() {
let fd = X86FilterDesigner::new(48000);
let (_b0, _b1, _b2, _a1, a2) = fd.lowpass_coeffs(200.0, 0.707);
assert!(a2.abs() < 1.0);
}
#[test]
fn test_radix4_code_has_butterflies() {
let fft = X86Radix4FFT::new(4096);
let code = fft.radix4_code();
assert!(code.contains("Radix-4"));
assert!(code.contains("w1r"));
}
#[test]
fn test_adsr_code() {
let adsr = X86ADSREnvelope::new();
let code = adsr.adsr_code();
assert!(code.contains("ADSRState"));
assert!(code.contains("adsr_process"));
assert!(code.contains("ATTACK_STAGE"));
}
#[test]
fn test_oscillator_bank_code() {
let bank = X86OscillatorBank::new();
let code = bank.oscillator_bank_code();
assert!(code.contains("OscVoice"));
assert!(code.contains("osc_bank_process"));
}
#[test]
fn test_additive_animation_with_pose() {
let mut anim = X86AdditiveAnimation::new();
anim.base_pose = vec![X86Mat4::identity()];
let mut skel = X86Skeleton::new();
skel.add_bone("root", None, X86Mat4::identity());
let result = anim.apply_additive(0.0, &skel);
assert_eq!(result.len(), 1);
}
#[test]
fn test_root_motion_extract() {
let rm = X86RootMotion::new();
let mut clip = X86AnimationClip::new("test", 1.0, 30.0);
let track = X86KeyframeTrack {
bone_index: 0,
position_keys: vec![
X86Keyframe {
time: 0.0,
value: X86KeyframeValue::Vec3(X86Vec3::zero()),
},
X86Keyframe {
time: 1.0,
value: X86KeyframeValue::Vec3(X86Vec3::new(10.0, 0.0, 0.0)),
},
],
rotation_keys: vec![],
scale_keys: vec![],
interpolation: X86KeyframeInterpolation::Linear,
};
clip.tracks.push(track);
let mut skel = X86Skeleton::new();
skel.add_bone("root", None, X86Mat4::identity());
let (delta_pos, _delta_rot) = rm.extract_delta(&clip, 0.0, 1.0, &skel);
assert!((delta_pos.x - 10.0).abs() < 0.01);
}
#[test]
fn test_animation_compressor_code() {
let comp = X86AnimationCompressor::new();
let code = comp.compression_code();
assert!(code.contains("compress_keyframe_track"));
}
#[test]
fn test_animation_compressor_no_panic() {
let comp = X86AnimationCompressor::new();
let track = X86KeyframeTrack {
bone_index: 0,
position_keys: vec![
X86Keyframe {
time: 0.0,
value: X86KeyframeValue::Vec3(X86Vec3::zero()),
},
X86Keyframe {
time: 1.0,
value: X86KeyframeValue::Vec3(X86Vec3::new(1.0, 0.0, 0.0)),
},
],
rotation_keys: vec![],
scale_keys: vec![],
interpolation: X86KeyframeInterpolation::Linear,
};
let compressed = comp.compress_track(&track);
assert!(compressed.position_keys.len() <= 2);
}
#[test]
fn test_phong_hlsl_shader() {
let r#gen =
X86ShaderProgramGenerator::new(X86ShaderLanguage::HLSL, X86ShaderModelVersion::SM60);
let code = r#gen.phong_shader();
assert!(code.contains("vs_main"));
assert!(code.contains("ps_main"));
assert!(code.contains("SV_POSITION"));
}
#[test]
fn test_phong_glsl_shader() {
let r#gen = X86ShaderProgramGenerator::new(
X86ShaderLanguage::GLSL,
X86ShaderModelVersion::Vulkan12,
);
let code = r#gen.phong_shader();
assert!(code.contains("#version 460"));
assert!(code.contains("inPosition"));
}
#[test]
fn test_post_process_tonemap() {
let r#gen = X86ShaderProgramGenerator::new(
X86ShaderLanguage::GLSL,
X86ShaderModelVersion::Vulkan12,
);
let code = r#gen.post_process_shader("tonemap");
assert!(code.contains("ACESFilm"));
}
#[test]
fn test_gpu_buffer_vulkan_code() {
let buf = X86GPUBuffer::new("testBuf", 1024, X86BufferUsage::Storage);
let code = buf.vulkan_create_code();
assert!(code.contains("VkBufferCreateInfo"));
assert!(code.contains("vkCreateBuffer"));
}
#[test]
fn test_gpu_buffer_d3d12_code() {
let buf = X86GPUBuffer::new("testBuf", 1024, X86BufferUsage::Vertex);
let code = buf.d3d12_create_code();
assert!(code.contains("D3D12_RESOURCE_DESC"));
assert!(code.contains("CreateCommittedResource"));
}
#[test]
fn test_vulkan_pipeline_cull_mode() {
let mut pb = X86VulkanPipelineBuilder::new();
pb.cull_mode = X86CullMode::None;
let code = pb.vulkan_pipeline_code();
assert!(code.contains("VK_CULL_MODE_NONE"));
}
#[test]
fn test_ecs_sparse_set_code() {
let ecs = X86ECSPatterns::new();
let code = ecs.sparse_set_pool_code();
assert!(code.contains("ComponentPool"));
assert!(code.contains("pool_add"));
assert!(code.contains("pool_remove"));
}
#[test]
fn test_obb_rotated_contains() {
let q = X86Quat::from_axis_angle(&X86Vec3::up(), std::f32::consts::PI * 0.25);
let obb = X86OBB::new(X86Vec3::zero(), X86Vec3::new(1.0, 1.0, 1.0), q);
assert!(obb.contains(&X86Vec3::zero()));
}
#[test]
fn test_obb_rotated_intersection() {
let q = X86Quat::from_axis_angle(&X86Vec3::up(), std::f32::consts::PI * 0.25);
let a = X86OBB::new(
X86Vec3::zero(),
X86Vec3::new(1.0, 1.0, 1.0),
X86Quat::identity(),
);
let b = X86OBB::new(X86Vec3::new(0.5, 0.5, 0.5), X86Vec3::new(1.0, 1.0, 1.0), q);
assert!(a.intersects_obb(&b));
}
#[test]
fn test_lerp_boundary() {
assert!((X86Interpolation::lerp(10.0, 20.0, 0.0) - 10.0).abs() < 0.001);
assert!((X86Interpolation::lerp(10.0, 20.0, 1.0) - 20.0).abs() < 0.001);
assert!((X86Interpolation::lerp(10.0, 20.0, -1.0) - 10.0).abs() < 0.001);
}
#[test]
fn test_smoothstep_boundary() {
assert!((X86Interpolation::smoothstep(0.0, 1.0, -1.0) - 0.0).abs() < 0.001);
assert!((X86Interpolation::smoothstep(0.0, 1.0, 2.0) - 1.0).abs() < 0.001);
}
#[test]
fn test_random_pcg_f32_range() {
let mut rng = X86GameRandom::pcg(42);
for _ in 0..1000 {
let v = rng.pcg_next_f32();
assert!(v >= 0.0 && v <= 1.0);
}
}
#[test]
fn test_random_xorshift_f32_range() {
let mut rng = X86GameRandom::xorshift128([99999, 88888]);
for _ in 0..1000 {
let v = rng.xorshift_next_f32();
assert!(v >= 0.0 && v <= 1.0);
}
}
#[test]
fn test_mat4_scale_uniform() {
let m = X86Mat4::scale(&X86Vec3::new(2.0, 2.0, 2.0));
let v = X86Vec3::new(1.0, 1.0, 1.0);
let r = m.transform_vec3(&v);
assert!((r.x - 2.0).abs() < 0.001);
assert!((r.y - 2.0).abs() < 0.001);
assert!((r.z - 2.0).abs() < 0.001);
}
#[test]
fn test_mat4_inverse_scale() {
let m = X86Mat4::scale(&X86Vec3::new(2.0, 3.0, 4.0));
let inv = m.inverse().unwrap();
assert!((inv.m[0][0] - 0.5).abs() < 0.001);
assert!((inv.m[1][1] - 1.0 / 3.0).abs() < 0.001);
}
#[test]
fn test_quat_mul_identity() {
let q = X86Quat::from_axis_angle(&X86Vec3::up(), 1.0);
let q_id = X86Quat::identity();
let result = q.mul(&q_id);
assert!((result.x - q.x).abs() < 0.001);
assert!((result.y - q.y).abs() < 0.001);
assert!((result.z - q.z).abs() < 0.001);
assert!((result.w - q.w).abs() < 0.001);
}
#[test]
fn test_quat_slerp_identity() {
let q = X86Quat::from_axis_angle(&X86Vec3::up(), 0.5);
let result = X86Quat::identity().slerp(&q, 0.0);
assert!((result.w - 1.0).abs() < 0.01);
}
#[test]
fn test_quat_nlerp_endpoints() {
let q1 = X86Quat::identity();
let q2 = X86Quat::from_axis_angle(&X86Vec3::new(1.0, 0.0, 0.0), std::f32::consts::PI * 0.5);
let result = q1.nlerp(&q2, 0.0);
let mag =
(result.x * result.x + result.y * result.y + result.z * result.z + result.w * result.w)
.sqrt();
assert!((mag - 1.0).abs() < 0.01);
}
#[test]
fn test_audio_ring_buffer_full() {
let mut rb = X86AudioRingBuffer::new(8);
assert_eq!(rb.available_write(), 7);
rb.advance_write(7);
assert_eq!(rb.available_write(), 0);
assert_eq!(rb.available_read(), 7);
}
#[test]
fn test_audio_ring_buffer_wrap_around() {
let mut rb = X86AudioRingBuffer::new(256);
rb.advance_write(200);
rb.advance_read(150);
assert_eq!(rb.available_read(), 50);
rb.advance_write(100);
assert!(rb.available_read() >= 50);
}
#[test]
fn test_sweep_and_prune_empty() {
let mut sap = X86SweepAndPrune::new();
let pairs = sap.find_pairs(&[]);
assert!(pairs.is_empty());
}
#[test]
fn test_sweep_and_prune_single() {
let mut sap = X86SweepAndPrune::new();
let aabbs = vec![(
0,
X86AABB::new(X86Vec3::zero(), X86Vec3::new(1.0, 1.0, 1.0)),
)];
let pairs = sap.find_pairs(&aabbs);
assert!(pairs.is_empty());
}
#[test]
fn test_bvh_empty() {
let bvh = X86BVH::new();
let results = bvh.query(&X86AABB::new(X86Vec3::zero(), X86Vec3::new(1.0, 1.0, 1.0)));
assert!(results.is_empty());
}
#[test]
fn test_spatial_grid_empty() {
let grid = X86SpatialGrid::new(1.0);
let results = grid.query(&X86AABB::new(X86Vec3::zero(), X86Vec3::new(1.0, 1.0, 1.0)));
assert!(results.is_empty());
}
#[test]
fn test_full_game_pipeline_all_systems() {
let games = X86Games::new().with_simd_level(X86GameSimdLevel::AVX2);
let flags = games.compile_flags();
assert!(flags.iter().any(|f| f.contains("avx2")));
assert!(flags.iter().any(|f| f.contains("fast-math")));
}
#[test]
fn test_all_sections_in_describe() {
let games = X86Games::default();
let desc = games.describe();
assert!(desc.contains("Math"));
assert!(desc.contains("Physics"));
assert!(desc.contains("Rendering"));
assert!(desc.contains("Animation"));
assert!(desc.contains("Audio"));
assert!(desc.contains("Networking"));
}
#[test]
fn test_compile_flags_dedup() {
let games = X86Games::default();
let flags = games.compile_flags();
let count = flags.iter().filter(|f| *f == "-msse4.2").count();
assert!(count <= 1);
}
#[test]
fn test_physics_engine_describe() {
let pe = X86GamePhysicsEngine::new(X86GameSimdLevel::default());
let desc = pe.describe();
assert!(desc.contains("gjk"));
assert!(desc.contains("simd"));
}
#[test]
fn test_fabrik_too_few_joints() {
let mut fabrik = X86FABRIK::new();
let mut joints = vec![X86Vec3::zero()];
let result = fabrik.solve(&mut joints, &[], &X86Vec3::new(1.0, 0.0, 0.0));
assert!(!result);
}
#[test]
fn test_anim_blend_empty() {
let blend = X86AnimationBlend::new();
let skel = X86Skeleton::new();
let poses = blend.sample(0.0, &skel);
assert!(poses.is_empty());
}
#[test]
fn test_game_loop_creation() {
let gl = X86GameLoop::new();
assert_eq!(gl.simulation_hz, 60);
assert!(gl.use_interpolation);
}
#[test]
fn test_game_loop_code() {
let gl = X86GameLoop::new();
let code = gl.game_loop_code();
assert!(code.contains("GameTimer"));
assert!(code.contains("fixed_update"));
assert!(code.contains("accumulator"));
}
#[test]
fn test_game_loop_interpolation_code() {
let gl = X86GameLoop::new();
let code = gl.interpolation_render_code();
assert!(code.contains("lerp_render"));
assert!(code.contains("interpolate_transform"));
}
#[test]
fn test_collision_manifold_default() {
let cm = X86CollisionManifold::new();
assert_eq!(cm.contact_count, 0);
}
#[test]
fn test_collision_manifold_response_code() {
let cm = X86CollisionManifold::new();
let code = cm.response_code();
assert!(code.contains("resolve_collision"));
assert!(code.contains("Baumgarte"));
assert!(code.contains("Friction impulse"));
}
#[test]
fn test_shadow_map_creation() {
let sm = X86ShadowMap::new();
assert_eq!(sm.resolution, 2048);
assert_eq!(sm.cascade_count, 4);
}
#[test]
fn test_shadow_map_shader() {
let sm = X86ShadowMap::new();
let code = sm.shadow_map_shader();
assert!(code.contains("CASCADE_COUNT"));
assert!(code.contains("sample_shadow_map"));
assert!(code.contains("PCF"));
}
#[test]
fn test_particle_system_creation() {
let ps = X86ParticleSystem::new();
assert_eq!(ps.max_particles, 10000);
assert!(ps.use_gpu_sim);
}
#[test]
fn test_particle_system_code() {
let ps = X86ParticleSystem::new();
let code = ps.particle_code();
assert!(code.contains("Particle"));
assert!(code.contains("particle_update"));
assert!(code.contains("particle_emit"));
assert!(code.contains("spread_angle"));
}
#[test]
fn test_input_system_creation() {
let is = X86InputSystem::new();
assert_eq!(is.max_actions, 256);
assert!(is.deadzone > 0.0);
}
#[test]
fn test_input_system_code() {
let is = X86InputSystem::new();
let code = is.input_code();
assert!(code.contains("InputManager"));
assert!(code.contains("input_begin_frame"));
assert!(code.contains("input_register_action"));
assert!(code.contains("ACTION_PRESSED"));
}
#[test]
fn test_all_component_defaults_constructible_v2() {
let _ = X86ReliableUDP::default();
let _ = X86InterpolationBuffer::default();
let _ = X86BandwidthEstimator::default();
let _ = X86NetworkQoS::default();
let _ = X86JacobianSolver::default();
let _ = X86FilterDesigner::new(48000);
let _ = X86Radix4FFT::new(4096);
let _ = X86AdditiveAnimation::default();
let _ = X86RootMotion::default();
let _ = X86VulkanPipelineBuilder::default();
let _ = X86ShaderProgramGenerator::default();
let _ = X86ADSREnvelope::default();
let _ = X86OscillatorBank::default();
let _ = X86AnimationCompressor::default();
let _ = X86ECSPatterns::default();
let _ = X86GameLoop::default();
let _ = X86CollisionManifold::default();
let _ = X86ShadowMap::default();
let _ = X86ParticleSystem::default();
let _ = X86InputSystem::default();
let _ = X86GPUBuffer::new("test", 64, X86BufferUsage::Uniform);
}
#[test]
fn test_describe_output_non_empty() {
let games = X86Games::default();
let desc = games.describe();
assert!(!desc.is_empty());
}
#[test]
fn test_linker_flags_non_empty_with_ray_tracing() {
let mut r = X86GameRendering::new(X86GameSimdLevel::default());
r.ray_tracing = true;
let flags = r.linker_flags();
assert!(!flags.is_empty());
}
#[test]
fn test_physics_engine_scalar_gjk_code() {
let pe = X86GamePhysicsEngine::new(X86GameSimdLevel::Scalar);
let code = pe.gjk_support_simd_code();
assert!(code.contains("gjk_support"));
assert!(code.contains("-INFINITY"));
}
#[test]
fn test_audio_dsp_header_complete() {
let dsp = X86GameAudioDSP::new(X86GameSimdLevel::SSE42);
let hdr = dsp.audio_dsp_header();
assert!(hdr.contains("sine_wave"));
assert!(hdr.contains("triangle_wave"));
assert!(hdr.contains("sawtooth_wave"));
assert!(hdr.contains("square_wave"));
assert!(hdr.contains("white_noise"));
assert!(hdr.contains("WavHeader"));
}
#[test]
fn test_engine_integration_defaults_disabled() {
let engines = X86GameEngines::default();
assert!(!engines.unreal.enabled);
assert!(!engines.unity.enabled);
assert!(!engines.godot.enabled);
assert!(!engines.custom.enabled);
}
#[test]
fn test_mat4_from_quat() {
let q = X86Quat::from_axis_angle(&X86Vec3::new(0.0, 1.0, 0.0), 0.0);
let m = X86Mat4::from_quat(&q);
assert!((m.m[0][0] - 1.0).abs() < 0.001);
assert!((m.m[1][1] - 1.0).abs() < 0.001);
assert!((m.m[2][2] - 1.0).abs() < 0.001);
}
#[test]
fn test_empty_convex_hull() {
let hull = X86ConvexHull::new(vec![X86Vec3::zero()]);
let support = hull.support_point(&X86Vec3::new(1.0, 0.0, 0.0));
assert!(support.x >= 0.0);
}
#[test]
fn test_ray_direction_normalized() {
let ray = X86Ray::new(X86Vec3::zero(), X86Vec3::new(3.0, 4.0, 0.0));
assert!((ray.direction.length() - 1.0).abs() < 0.001);
}
#[test]
fn test_obb_axes_orthogonal() {
let q = X86Quat::identity();
let obb = X86OBB::new(X86Vec3::zero(), X86Vec3::one(), q);
let axes = obb.axes();
assert!((axes[0].dot(&axes[1])).abs() < 0.001);
assert!((axes[1].dot(&axes[2])).abs() < 0.001);
assert!((axes[2].dot(&axes[0])).abs() < 0.001);
}
#[test]
fn test_rigid_body_mass_infinite() {
let mut body = X86RigidBody::new(X86Vec3::zero(), 0.0);
assert!(body.is_kinematic == false);
assert_eq!(body.inv_mass, 0.0);
body.integrate(1.0); }
#[test]
fn test_mat4_mul_non_identity() {
let t = X86Mat4::translate(&X86Vec3::new(5.0, 0.0, 0.0));
let s = X86Mat4::scale(&X86Vec3::new(2.0, 2.0, 2.0));
let ts = t.mul(&s);
assert!((ts.m[0][0] - 2.0).abs() < 0.001);
assert!((ts.m[0][3] - 5.0).abs() < 0.001);
}
#[test]
fn test_quat_slerp_endpoints() {
let q1 = X86Quat::identity();
let q2 = X86Quat::from_axis_angle(&X86Vec3::up(), std::f32::consts::PI * 0.5);
let result = q1.slerp(&q2, 0.0);
assert!((result.w - 1.0).abs() < 0.01);
let result = q1.slerp(&q2, 1.0);
assert!((result.x - q2.x).abs() < 0.01);
assert!((result.y - q2.y).abs() < 0.01);
assert!((result.z - q2.z).abs() < 0.01);
assert!((result.w - q2.w).abs() < 0.01);
}
#[test]
fn test_serialization_format() {
let ps = X86PacketSerializer::new();
assert!(matches!(ps.format, X86SerializationFormat::Binary));
}
#[test]
fn test_bitpacker_max_packet() {
let bp = X86BitPacker::new();
assert!(bp.max_packet_size > 0);
}
#[test]
fn test_client_server_defaults() {
let cs = X86ClientServer::new();
assert_eq!(cs.tick_rate, 60);
assert!(cs.timeout_ms > 0);
}
#[test]
fn test_all_enum_variants() {
assert!(matches!(X86GameSimdLevel::Scalar, X86GameSimdLevel::Scalar));
assert!(matches!(X86ShaderLanguage::HLSL, X86ShaderLanguage::HLSL));
assert!(matches!(X86ShaderTarget::SPIRV, X86ShaderTarget::SPIRV));
assert!(matches!(
X86PrimitiveTopology::TriangleList,
X86PrimitiveTopology::TriangleList
));
assert!(matches!(X86BufferUsage::Vertex, X86BufferUsage::Vertex));
assert!(matches!(
X86MemoryType::DeviceLocal,
X86MemoryType::DeviceLocal
));
}
}