Skip to content

Commit

Permalink
Add memory counter via an ndll (thank you raylib for windows.h confli…
Browse files Browse the repository at this point in the history
…cts)
  • Loading branch information
Vortex2Oblivion committed Dec 26, 2024
1 parent d6c6f63 commit e62c3ce
Show file tree
Hide file tree
Showing 12 changed files with 362 additions and 13 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
test/bin/cpp/*
.vscode/
.zed/

ndlls/*/bin
ndlls/*/obj

!test/bin/cpp/images/
!test/bin/cpp/sound/
1 change: 1 addition & 0 deletions build_ndlls.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lime rebuild ndlls/memory windows
2 changes: 1 addition & 1 deletion extraParams.hxml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
--macro raylib.macros.GlobalMetadata.run()
--macro raylib.macros.GlobalMetadata.run()
34 changes: 23 additions & 11 deletions haxelib.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
{
"name": "flixel-raylib",
"url" : "https://github.com/Vortex2Oblivion/flixel-raylib",
"license": "MIT",
"tags": ["flixel", "haxeflixel", "bindings", "raylib", "game", "development"],
"description": "Rewrite of flixel with a raylib backend.",
"version": "1.0.0",
"releasenote": "",
"contributors": ["Vortex"],
"dependencies": {"hxcpp": ""},
"classPath": "src"
}
"name": "flixel-raylib",
"url": "https://github.com/Vortex2Oblivion/flixel-raylib",
"license": "MIT",
"tags": [
"flixel",
"haxeflixel",
"bindings",
"raylib",
"game",
"development"
],
"description": "Rewrite of flixel with a raylib backend.",
"version": "1.0.0",
"releasenote": "",
"contributors": [
"Vortex"
],
"dependencies": {
"hxcpp": "",
"lime": ""
},
"classPath": "src"
}
160 changes: 160 additions & 0 deletions ndlls/memory/common/ExternalInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#ifndef STATIC_LINK
#define IMPLEMENT_API
#endif

#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX)
#define NEKO_COMPATIBLE
#endif

#if defined(HX_WINDOWS)
#include <windows.h>
#include <dwmapi.h>

#pragma comment(lib, "Dwmapi")
#endif


#include <hx/CFFI.h>
#include <hx/CFFIPrime.h>
#include "memory.h"


// Helpers
inline bool val_is_raw_object(value inVal) { return val_type(inVal)==valtObject; }
inline bool val_is_enum(value inVal) { return val_type(inVal)==valtEnum; }
inline bool val_is_class(value inVal) { return val_type(inVal)==valtClass; }

// Allocating:
// alloc_null() == generate haxe null / or use val_null
// alloc_bool(bool) == generate haxe bool
// alloc_int(int) == generate haxe int
// alloc_float(double) == generate haxe float
// alloc_empty_object() == generate haxe anon obj
// alloc_string(const char *) == generate haxe string
// alloc_array(int) == generate haxe array with a size

// Getting:
// val_int(value) == get int from haxe object
// val_bool(value) == get bool from haxe object
// val_float(value) == get double from haxe object
// val_string(value) == get const char * from haxe object

// Checking
// val_is_null(value) == checks if the value is null
// val_is_int(value) == checks if the value is int
// val_is_bool(value) == checks if the value is bool
// val_is_float(value) == checks if the value is float
// val_is_string(value) == checks if the value is string
// val_is_function(value) == checks if the value is function
// val_is_array(value) == checks if the value is array
// val_is_abstract(value) == checks if the value is abstract? unsure
// val_is_kind(value, vkind) == checks if the value is kind? unsure
// val_is_number(value) == checks if the value is int or float
// val_is_object(value) == checks if the value is int or float
// val_is_raw_object(value) == checks if the value is an anon obj (Custom)
// val_is_enum(value) == checks if the value is enum (Custom)
// val_is_class(value) == checks if the value is class (Custom)

// Arrays:
// val_array_size(value) == get length of array
// val_array_i(value, int) == get item from index from array, you need to use the val_ functions to prepare the value
// val_array_set_i(value, int, value) == set item at index in array, you need to use alloc_ function to prepare the value
// val_array_set_size(value, int) == sets the length of the array
// val_array_push(value, value) == pushes a value to an array, you need to use the val_ functions to prepare the value
// alloc_array(int) == idk what the int does

// Functions:
// you need to use the val_ functions to prepare the values
// add o before the call function (val_ocall0) to call a object field, and add an int value for the field, unsure what this is for
// val_call0(value) == call haxe function with 0 args
// val_call1(value, value) == call haxe function with 1 args
// val_call2(value, value, value) == call haxe function with 2 args
// val_call3(value, value, value, value) == call haxe function with 3 args
// val_callN(value, value*, int) == calls haxe function with n args, based on the int and the array, Usage below

/*
int num_args = 4;
value *args = new value[num_args];
args[0] = alloc_bool(false);
args[1] = alloc_bool(true);
args[2] = alloc_int(5);
args[3] = alloc_int(15);
value result = val_callN(root->get(), args, num_args);
*/

// Objects
// idk it uses an int for the field i have no clue
// tho theres val_field_name(field) no clue how this is used
// setting a field: alloc_field(value, val_id(val_string(value)), value);
// setting a field with cstring: alloc_field(value, val_id(const char*), value);
// getting a field: val_field(value, val_id(val_string(value)));
// getting a field with cstring: val_field(value, val_id(const char*));
// TODO: finish this

// Misc:
// val_gc(value, c++ func) == sets a finalizer for a object, warning very limited, trying to allocate haxe memory crashes
// val_fun_nargs(value) == get total args of function, -1 for Reflect.makeVarArgs
// val_strlen(value) == get length of string

// Check https://github.com/HaxeFoundation/hxcpp/blob/master/src/hx/CFFI.cpp for the code, and more functions

// Defining functions for the ndll:
// the prefix isnt needed it can completely just be set_window_transparent if you want
// n can be from 0 to 15
// DEFINE_PRIMEn(function) == define function that returns
// DEFINE_PRIMEnv(function) == define void function

// FYI: if the type is bool or int or double (haxe float) then it does the conversion automatically

#if defined(HX_WINDOWS)

static value get_memory_usage() {
return alloc_float(getCurrentRSS());
}
DEFINE_PRIME0 (get_memory_usage);

static value get_memory_peak() {
return alloc_float(getPeakRSS());
}
DEFINE_PRIME0 (get_memory_peak);

#else

static value get_memory_usage () {
return alloc_float(0);
}
DEFINE_PRIME0 (get_memory_usage);

static value get_memory_peak () {
return alloc_float(0);
}
DEFINE_PRIME0 (get_memory_peak)

#endif

// Examples
/*
static value memory_sample_method (value inputValue) {
int returnValue = val_int(inputValue);
return alloc_int(returnValue);
}
DEFINE_PRIME1 (memory_sample_method);
static void memory_sample_method_void (value inputValue) {
int returnValue = val_int(inputValue);
}
DEFINE_PRIME1v (memory_sample_method_void);
*/



extern "C" void memory_main () {

val_int(0); // Fix Neko init

}
DEFINE_ENTRY_POINT (memory_main);



extern "C" int memory_register_prims () { return 0; }
114 changes: 114 additions & 0 deletions ndlls/memory/common/memory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Author: David Robert Nadeau
* Site: http://NadeauSoftware.com/
* License: Creative Commons Attribution 3.0 Unported License
* http://creativecommons.org/licenses/by/3.0/deed.en_US
*/

#if defined(_WIN32)
#include <windows.h>
#include <psapi.h>

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/resource.h>

#if defined(__APPLE__) && defined(__MACH__)
#include <mach/mach.h>

#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
#include <fcntl.h>
#include <procfs.h>

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
#include <stdio.h>

#endif

#else
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
#endif

/**
* Returns the peak (maximum so far) resident set size (physical
* memory use) measured in bytes, or zero if the value cannot be
* determined on this OS.
*/
size_t getPeakRSS()
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
return (size_t)info.PeakWorkingSetSize;

#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
/* AIX and Solaris ------------------------------------------ */
struct psinfo psinfo;
int fd = -1;
if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
return (size_t)0L; /* Can't open? */
if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo))
{
close(fd);
return (size_t)0L; /* Can't read? */
}
close(fd);
return (size_t)(psinfo.pr_rssize * 1024L);

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
/* BSD, Linux, and OSX -------------------------------------- */
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
#if defined(__APPLE__) && defined(__MACH__)
return (size_t)rusage.ru_maxrss;
#else
return (size_t)(rusage.ru_maxrss * 1024L);
#endif

#else
/* Unknown OS ----------------------------------------------- */
return (size_t)0L; /* Unsupported. */
#endif
}

/**
* Returns the current resident set size (physical memory use) measured
* in bytes, or zero if the value cannot be determined on this OS.
*/
size_t getCurrentRSS()
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
return (size_t)info.WorkingSetSize;

#elif defined(__APPLE__) && defined(__MACH__)
/* OSX ------------------------------------------------------ */
struct mach_task_basic_info info;
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
(task_info_t)&info, &infoCount) != KERN_SUCCESS)
return (size_t)0L; /* Can't access? */
return (size_t)info.resident_size;

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
/* Linux ---------------------------------------------------- */
long rss = 0L;
FILE *fp = NULL;
if ((fp = fopen("/proc/self/statm", "r")) == NULL)
return (size_t)0L; /* Can't open? */
if (fscanf(fp, "%*s%ld", &rss) != 1)
{
fclose(fp);
return (size_t)0L; /* Can't read? */
}
fclose(fp);
return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE);

#else
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
return (size_t)0L; /* Unsupported. */
#endif
}
3 changes: 3 additions & 0 deletions src/Build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,7 @@
<flag value="OpenGL" />
</target>
</section>


<copyFile name="memory.ndll" from="${haxelib:flixel-raylib}/ndlls/memory/bin/Windows64" toolId="exe" />
</xml>
5 changes: 4 additions & 1 deletion src/flixel/FlxG.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package flixel;

import flixel.util.FlxMemory;
import flixel.FlxCamera;
import flixel.system.frontEnds.CameraFrontEnd;
import flixel.system.frontEnds.SoundFrontEnd;
Expand Down Expand Up @@ -41,8 +42,10 @@ class FlxG {
return getFrameTime();
}

@:allow(flixel.FlxGame.new) static function init(game:FlxGame, width:Int, height:Int) {
@:allow(flixel.FlxGame.new)
static function init(game:FlxGame, width:Int, height:Int) {
Log.trace = (v:Dynamic, ?infos:PosInfos) -> untyped __cpp__("std::cout << {0}", '${Log.formatOutput(v, infos)}\n');
FlxMemory.init();
initialWidth = width;
initialHeight = height;
cameras.reset();
Expand Down
6 changes: 6 additions & 0 deletions src/flixel/FlxGame.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package flixel;

import flixel.util.FlxStringUtil;
import flixel.util.FlxMemory;
import raylib.Colors;
//import external.memory.Memory;

class FlxGame {
public function new(gameWidth:Int = 0, gameHeight:Int = 0, initialState:FlxState, updateFramerate:Int = 60) {
initWindow(gameWidth, gameHeight, "FlxProject");
Expand All @@ -25,6 +30,7 @@ class FlxGame {
}
}
drawFPS(1, 1);
drawText("\n"+FlxStringUtil.formatBytes(FlxMemory.getMemory()) +" / " + FlxStringUtil.formatBytes(FlxMemory.getPeakMemory()), 1, 1, 20, Colors.LIME);
endDrawing();
}
closeAudioDevice();
Expand Down
11 changes: 11 additions & 0 deletions src/flixel/math/FlxMath.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package flixel.math;

class FlxMath {
public static function roundDecimal(value:Float, precision:Int):Float {
var mult:Float = 1;
for (i in 0...precision) {
mult *= 10;
}
return Math.fround(value * mult) / mult;
}
}
Loading

0 comments on commit e62c3ce

Please sign in to comment.