feat: added context and utility headers
This commit is contained in:
186
include/fxn/context.hpp
Normal file
186
include/fxn/context.hpp
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <atomic>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace fxn
|
||||||
|
{
|
||||||
|
struct Vector2
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vector3
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vector4
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NativeContext
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct scrVector3
|
||||||
|
{
|
||||||
|
alignas(8) float x;
|
||||||
|
alignas(8) float y;
|
||||||
|
alignas(8) float z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alignas(16) scrVector3N
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* m_ReturnBuffer;
|
||||||
|
std::uint32_t m_ArgumentCount;
|
||||||
|
void* m_Arguments;
|
||||||
|
std::uint32_t m_DataCount;
|
||||||
|
|
||||||
|
struct VectorSpace
|
||||||
|
{
|
||||||
|
scrVector3 *outVectors[4];
|
||||||
|
scrVector3N inVectors[4];
|
||||||
|
} m_VectorSpace;
|
||||||
|
|
||||||
|
scrVector3 m_Vectors[4];
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAX_ARGUMENTS = 32,
|
||||||
|
ARGUMENT_SIZE = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
std::uint8_t m_Stack[MAX_ARGUMENTS * ARGUMENT_SIZE];
|
||||||
|
std::uint64_t m_NativeHash;
|
||||||
|
std::atomic_bool m_Executed;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline NativeContext()
|
||||||
|
: m_ReturnBuffer(nullptr), m_ArgumentCount(0), m_Arguments(nullptr), m_DataCount(0), m_NativeHash(0), m_VectorSpace{}, m_Vectors{}, m_Stack{}, m_Executed(false)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < sizeof(m_Stack); i++)
|
||||||
|
{
|
||||||
|
m_Stack[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Arguments = &m_Stack;
|
||||||
|
m_ReturnBuffer = &m_Stack;
|
||||||
|
|
||||||
|
m_ArgumentCount = 0;
|
||||||
|
m_DataCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NativeContext(std::uint64_t hash)
|
||||||
|
: NativeContext()
|
||||||
|
{
|
||||||
|
m_NativeHash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
inline void PushArgument(const T& arg)
|
||||||
|
{
|
||||||
|
if (m_ArgumentCount >= MAX_ARGUMENTS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Exceeded maximum number of arguments.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (sizeof(T) < ARGUMENT_SIZE)
|
||||||
|
{
|
||||||
|
// Zero out the memory to avoid garbage values
|
||||||
|
*reinterpret_cast<std::uintptr_t*>(m_Stack + (m_ArgumentCount * ARGUMENT_SIZE)) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*reinterpret_cast<T*>(m_Stack + (m_ArgumentCount * ARGUMENT_SIZE)) = arg;
|
||||||
|
m_ArgumentCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void PushArgument<Vector3>(const Vector3& arg)
|
||||||
|
{
|
||||||
|
PushArgument(arg.x);
|
||||||
|
PushArgument(arg.y);
|
||||||
|
PushArgument(arg.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<typename R>
|
||||||
|
inline R GetResult()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<R*>(m_ReturnBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline Vector3 GetResult<Vector3>()
|
||||||
|
{
|
||||||
|
scrVector3* vec = reinterpret_cast<scrVector3*>(m_ReturnBuffer);
|
||||||
|
return Vector3{ vec->x, vec->y, vec->z };
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline std::uint64_t GetNativeHash() const
|
||||||
|
{
|
||||||
|
return m_NativeHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::uint32_t GetArgumentCount() const
|
||||||
|
{
|
||||||
|
return m_ArgumentCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* GetArguments() const
|
||||||
|
{
|
||||||
|
return m_Arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsExecuted() const
|
||||||
|
{
|
||||||
|
return m_Executed.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetExecuted(bool executed)
|
||||||
|
{
|
||||||
|
m_Executed.store(executed, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline void SetVectorResults()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_DataCount; i++)
|
||||||
|
{
|
||||||
|
auto outVector = m_VectorSpace.outVectors[i];
|
||||||
|
const auto& inVector = m_VectorSpace.inVectors[i];
|
||||||
|
|
||||||
|
outVector->x = inVector.x;
|
||||||
|
outVector->y = inVector.y;
|
||||||
|
outVector->z = inVector.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline const T& GetArgument(std::size_t index) const
|
||||||
|
{
|
||||||
|
if (index >= m_ArgumentCount)
|
||||||
|
{
|
||||||
|
throw std::out_of_range("Argument index out of range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto functionData = reinterpret_cast<uintptr_t*>(m_Arguments);
|
||||||
|
return *reinterpret_cast<T*>(&functionData[index]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
29
include/fxn/utility.hpp
Normal file
29
include/fxn/utility.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string_view>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace fxn
|
||||||
|
{
|
||||||
|
inline constexpr char ToLower(const char c) noexcept
|
||||||
|
{
|
||||||
|
return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr unsigned int HashString(std::string_view str) noexcept
|
||||||
|
{
|
||||||
|
std::uint32_t hash = 0;
|
||||||
|
|
||||||
|
for (char ch : str)
|
||||||
|
{
|
||||||
|
hash += ToLower(ch);
|
||||||
|
hash += (hash << 10);
|
||||||
|
hash ^= (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
hash += (hash << 3);
|
||||||
|
hash ^= (hash >> 11);
|
||||||
|
hash += (hash << 15);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user