Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Engine/Source/Applications/Editor/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ local module_name = 'Editor'

corvus_application_target(module_name)
add_deps('Core')
add_deps('Platform')
corvus_target_end()
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

#pragma once

#include "ExceptionHandler.hpp"

#include "Core/Containers/String.hpp"
#include "Core/Logging/LogChannel.hpp"
#include "Core/Utility/SourceLocation.hpp"
#include "Core/Utility/StringUtils.hpp"

struct FExceptionMetadata;
CORE_API DECLARE_LOG_CHANNEL_EXTERN(Assert)

namespace Assertion
Expand Down
4 changes: 2 additions & 2 deletions Engine/Source/Runtime/Core/Public/Core/CoreDefinitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
DEFAULT_MOVEABLE_PREFIX(Class,)

#define DEFAULT_COPY_MOVEABLE_PREFIX(Class, Prefix) \
DEFAULT_COPYABLE(Class, Prefix) \
DEFAULT_MOVEABLE(Class, Prefix)
DEFAULT_COPYABLE_PREFIX(Class, Prefix) \
DEFAULT_MOVEABLE_PREFIX(Class, Prefix)

#define INNER_APPEND(X, Y) X##Y
#define APPEND(X, Y) INNER_APPEND(X, Y)
Expand Down
181 changes: 181 additions & 0 deletions Engine/Source/Runtime/Platform/Private/Platform/CPUDetection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// RavenStorm Copyright @ 2025-2025

#include "Platform/CPUDetection.hpp"

#include "Core/Logging/LogChannel.hpp"
#include "Core/Logging/LogManager.hpp"

#include <Windows.h>

#include <utility>

#include "Core/Memory/Memory.hpp"

DEFINE_LOG_CHANNEL(CPUDetection, All)

namespace
{
struct FCPUIDResult
{
int32 EAX;
int32 EBX;
int32 ECX;
int32 EDX;
};

FCPUIDResult CallCPUID(const int32 FunctionId, const int32 SubFunctionId = 0)
{
FCPUIDResult Result;
int32 CPUInfo[4];
__cpuidex(CPUInfo, FunctionId, SubFunctionId);
Result.EAX = CPUInfo[0];
Result.EBX = CPUInfo[1];
Result.ECX = CPUInfo[2];
Result.EDX = CPUInfo[3];
return Result;
}
}

FCPUInfo FCPUDetection::CPUInfo = {};

void FCPUDetection::Initialize()
{
DetectVendor();
DetectBrand();
DetectCPUTopology();

CVLOG(LogCPUDetection, Info, "CPU: {}", CPUInfo.BrandString);
CVLOG(LogCPUDetection, Info, "\t- Vendor: {}", CPUInfo.VendorString);
CVLOG(LogCPUDetection, Info, "\t- Family: {}", CPUInfo.Family);
CVLOG(LogCPUDetection, Info, "\t- Model: {}", CPUInfo.Model);
CVLOG(LogCPUDetection, Info, "\t- Stepping: {}", CPUInfo.Stepping);
CVLOG(LogCPUDetection, Info, "\t- Physical Cores: {}, Logical Cores: {}", CPUInfo.PhysicalCores, CPUInfo.LogicalCores);
CVLOG(LogCPUDetection, Info, "\t- Logical Cores: {}", CPUInfo.LogicalCores);
CVLOG(LogCPUDetection, Info, "\t- Cache Line Size: {} bytes", CPUInfo.CacheLine);
CVLOG(LogCPUDetection, Info, "\t- L1 Cache: {} KB", CPUInfo.L1CacheSize / 1024);
CVLOG(LogCPUDetection, Info, "\t- L2 Cache: {} MB", CPUInfo.L2CacheSize / (1024 * 1024));
CVLOG(LogCPUDetection, Info, "\t- L3 Cache: {} MB", CPUInfo.L3CacheSize / (1024 * 1024));
}

FCPUInfo FCPUDetection::GetCPUInfo() noexcept
{
return CPUInfo;
}

void FCPUDetection::DetectVendor()
{
const FCPUIDResult Result = CallCPUID(0, 0);

char Vendor[13] = {};
*reinterpret_cast<int32*>(Vendor) = Result.EBX;
*reinterpret_cast<int32*>(Vendor + 4) = Result.EDX;
*reinterpret_cast<int32*>(Vendor + 8) = Result.ECX;
Vendor[12] = '\0';

CPUInfo.VendorString = FAnsiString(Vendor);
CPUInfo.IsIntel = CPUInfo.VendorString == "GenuineIntel";
CPUInfo.IsAMD = CPUInfo.VendorString == "AuthenticAMD";
}

void FCPUDetection::DetectBrand()
{
char Brand[49] = {};

const FCPUIDResult Result = CallCPUID(static_cast<int32>(0x80000000), 0);
if (Result.EAX >= static_cast<int32>(0x80000004))
{
const FCPUIDResult Brand0 = CallCPUID(static_cast<int32>(0x80000002), 0);
const FCPUIDResult Brand1 = CallCPUID(static_cast<int32>(0x80000003), 0);
const FCPUIDResult Brand2 = CallCPUID(static_cast<int32>(0x80000004), 0);

std::memcpy(Brand, &Brand0, 16);
std::memcpy(Brand + 16, &Brand1, 16);
std::memcpy(Brand + 32, &Brand2, 16);
Brand[48] = '\0';

// Trim leading spaces
char* Start = Brand;
while (*Start == ' ') ++Start;

CPUInfo.BrandString = FAnsiString(Start);
}
}

void FCPUDetection::DetectCPUTopology()
{
const FCPUIDResult Result1 = CallCPUID(1, 0);
CPUInfo.Family = ((Result1.EAX >> 8) & 0xF) + ((Result1.EAX >> 20) & 0xFF);
CPUInfo.Model = ((Result1.EAX >> 4) & 0xF) | ((Result1.EAX >> 12) & 0xF0);
CPUInfo.Stepping = Result1.EAX & 0xF;

SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
CPUInfo.LogicalCores = static_cast<int32>(SystemInfo.dwNumberOfProcessors);

DWORD BufferSize = 0;
GetLogicalProcessorInformation(nullptr, &BufferSize);
if (BufferSize > 0)
{
const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer = static_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>(FMemory::Allocate(BufferSize));
if (GetLogicalProcessorInformation(Buffer, &BufferSize))
{
const DWORD NumEntries = BufferSize / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
int32 PhysicalCores = 0;
int32 CacheLine = 0;
int32 L1CacheSize = 0;
int32 L2CacheSize = 0;
int32 L3CacheSize = 0;
for (DWORD Index = 0; Index < NumEntries; ++Index)
{
if (Buffer[Index].Relationship == RelationProcessorCore)
{
++PhysicalCores;
}
else if (Buffer[Index].Relationship == RelationCache)
{
if (const CACHE_DESCRIPTOR& Cache = Buffer[Index].Cache; Cache.Level == 1)
{
if (CacheLine == 0)
{
CacheLine = static_cast<int32>(Cache.LineSize);
}
if (Cache.Type == CacheData || Cache.Type == CacheUnified)
{
L1CacheSize += static_cast<int32>(Cache.Size);
}
else if (Cache.Type == CacheInstruction)
{
L1CacheSize += static_cast<int32>(Cache.Size);
}
}
else if (Cache.Level == 2)
{
L2CacheSize += static_cast<int32>(Cache.Size);
}
else if (Cache.Level == 3)
{
if (L3CacheSize == 0)
{
L3CacheSize = static_cast<int32>(Cache.Size);
}
}
}
}
CPUInfo.PhysicalCores = PhysicalCores;
CPUInfo.CacheLine = CacheLine > 0 ? CacheLine : 64;
CPUInfo.L1CacheSize = L1CacheSize;
CPUInfo.L2CacheSize = L2CacheSize;
CPUInfo.L3CacheSize = L3CacheSize;
}
FMemory::Free(Buffer);
}
else
{
CPUInfo.PhysicalCores = CPUInfo.LogicalCores;
CPUInfo.CacheLine = 64;
CPUInfo.L1CacheSize = 0;
CPUInfo.L2CacheSize = 0;
CPUInfo.L3CacheSize = 0;
}
CPUInfo.IsHyperThreaded = CPUInfo.LogicalCores > CPUInfo.PhysicalCores;
}
128 changes: 128 additions & 0 deletions Engine/Source/Runtime/Platform/Private/Platform/Platform.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// RavenStorm Copyright @ 2025-2025

#include "Platform/Platform.hpp"
#include "Core/Logging/LogManager.hpp"
#include "Platform/CPUDetection.hpp"

#include <Windows.h>

#include <VersionHelpers.h>

DEFINE_LOG_CHANNEL(Platform, All)

FSystemInfo FPlatform::SystemInfo = {};

void FPlatform::Initialize()
{
DetectOperatingSystem();
DetectComputerInfo();

CVLOG(LogPlatform, Info, "OS: {} ({})", SystemInfo.OSName, SystemInfo.OSVersion);
CVLOG(LogPlatform, Info, "\t- Build: {}", SystemInfo.OSBuildNumber);
CVLOG(LogPlatform, Info, "\t- Computer Name: {}", SystemInfo.ComputerName);

FCPUDetection::Initialize();
}

void FPlatform::Shutdown()
{
}

bool8 FPlatform::HasEnvVariable(const FString& VariableName) noexcept
{
return GetEnvironmentVariable(VariableName.c_str(), nullptr, 0) > 0;
}

FString FPlatform::GetEnvVariable(const FString& VariableName) noexcept
{
const DWORD BufferSize = GetEnvironmentVariable(VariableName.c_str(), nullptr, 0);
if (BufferSize == 0)
{
return {};
}
FString Result(BufferSize, '\0');
GetEnvironmentVariable(VariableName.c_str(), Result.data(), BufferSize);
return Result;
}

FString FPlatform::GetEnvVariable(const FString& VariableName, const FString& DefaultValue) noexcept
{
FString Value = GetEnvVariable(VariableName);
return Value.empty() ? DefaultValue : Value;
}

bool8 FPlatform::SetEnvVariable(const FString& VariableName, const FString& Value) noexcept
{
return SetEnvironmentVariable(VariableName.c_str(), Value.c_str()) != 0;
}

FCPUInfo FPlatform::GetCPUInfo() noexcept
{
return FCPUDetection::GetCPUInfo();
}

FSystemInfo FPlatform::GetSystemInfo() noexcept
{
return SystemInfo;
}

void FPlatform::DetectOperatingSystem()
{
using RtlGetVersionPtr = LONG(WINAPI*)(PRTL_OSVERSIONINFOW);

RTL_OSVERSIONINFOW VersionInfo = {};
VersionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);

if (const HMODULE NtDllModule = GetModuleHandleW(L"ntdll.dll"))
{
if (const auto RtlGetVersion = reinterpret_cast<RtlGetVersionPtr>(GetProcAddress(NtDllModule, "RtlGetVersion")))
{
RtlGetVersion(&VersionInfo);
}
}

const uint32 MajorVersion = VersionInfo.dwMajorVersion;
const uint32 MinorVersion = VersionInfo.dwMinorVersion;
const uint32 BuildNumber = VersionInfo.dwBuildNumber;

SystemInfo.WindowsVersion = DetermineWindowsVersion(MajorVersion, BuildNumber);
SystemInfo.OSName = GetWindowsVersionString(MajorVersion, BuildNumber);
SystemInfo.OSVersion = std::format("{}.{}.{}", MajorVersion, MinorVersion, BuildNumber);
SystemInfo.OSBuildNumber = std::format("{}", BuildNumber);
}

void FPlatform::DetectComputerInfo()
{
CHAR ComputerNameBuffer[MAX_COMPUTERNAME_LENGTH + 1];
DWORD ComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerName(ComputerNameBuffer, &ComputerNameSize))
{
SystemInfo.ComputerName = FString(ComputerNameBuffer);
}
}

EWindowsVersion FPlatform::DetermineWindowsVersion(const uint32 MajorVersion, const uint32 BuildNumber)
{
if (MajorVersion == 10)
{
if (BuildNumber >= 22000)
{
return EWindowsVersion::Windows11;
}
return EWindowsVersion::Windows10;
}
return EWindowsVersion::Unknown;
}

FString FPlatform::GetWindowsVersionString(const uint32 MajorVersion, const uint32 BuildNumber)
{
if (MajorVersion == 10)
{
if (BuildNumber >= 22000)
{
return "Windows 11";
}
return "Windows 10";
}
return "Windows (Unknown Version)";
}
Loading
Loading