Android update and small improvements
-fixed code do cross compiling to android -fixed build with GCC (workaround) -added little benchmark -several small fixes -updated meson build (demos building, working with GCC, LDC and DMD) -added some meson options -added ImGUI bind for OpenGL3
This commit is contained in:
parent
86edfa4a57
commit
66860b9042
30 changed files with 1358 additions and 173 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -9,4 +9,5 @@
|
||||||
!skeleton.html
|
!skeleton.html
|
||||||
!meson.build
|
!meson.build
|
||||||
!meson_options.txt
|
!meson_options.txt
|
||||||
!compile_wasm.py
|
!compile_wasm.py
|
||||||
|
!compile_android.py
|
||||||
78
compile_android.py
Normal file
78
compile_android.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import os
|
||||||
|
import ntpath
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def compile(sources, output):
|
||||||
|
files = []
|
||||||
|
# r=root, d=directories, f = files
|
||||||
|
for path in sources:
|
||||||
|
for r, d, f in os.walk(path):
|
||||||
|
for file in f:
|
||||||
|
if ntpath.basename(file) != 'win_dll.d':
|
||||||
|
filename, file_extension = os.path.splitext(file)
|
||||||
|
if file_extension == '.d' and filename != 'package':
|
||||||
|
files.append(os.path.join(r, file))
|
||||||
|
|
||||||
|
ldc_path = 'ldc'
|
||||||
|
if 'LDC' in os.environ:
|
||||||
|
ldc_path = os.environ['LDC']
|
||||||
|
|
||||||
|
ldc_cmd = ldc_path + ' ' + ldc_flags + '-lib -mtriple=armv7-none-linux-androideabi -fvisibility=hidden -betterC -oq -od=obj/ --singleobj --of=' + output + ' '
|
||||||
|
|
||||||
|
for path in sources:
|
||||||
|
ldc_cmd += '-I' + path + ' '
|
||||||
|
|
||||||
|
for path in import_paths:
|
||||||
|
ldc_cmd += '-I' + path + ' '
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
ldc_cmd += f + ' '
|
||||||
|
|
||||||
|
print(ldc_cmd)
|
||||||
|
|
||||||
|
if os.system(ldc_cmd):
|
||||||
|
exit(0)
|
||||||
|
print()
|
||||||
|
|
||||||
|
clean = 0
|
||||||
|
ldc_flags = ''
|
||||||
|
import_paths = ['source','tests']
|
||||||
|
build_tests = 0
|
||||||
|
|
||||||
|
for arg in sys.argv[1:]:
|
||||||
|
if(arg == '-release'):
|
||||||
|
ldc_flags += '-release '
|
||||||
|
elif(arg == '-enable-inlining'):
|
||||||
|
ldc_flags += '-enable-inlining '
|
||||||
|
elif(arg == '-O3'):
|
||||||
|
ldc_flags += '-O3 '
|
||||||
|
elif(arg == '-O2'):
|
||||||
|
ldc_flags += '-O2 '
|
||||||
|
elif(arg == '-O1'):
|
||||||
|
ldc_flags += '-O1 '
|
||||||
|
elif(arg == '-O0'):
|
||||||
|
ldc_flags += '-O0 '
|
||||||
|
elif(arg == '-Os'):
|
||||||
|
ldc_flags += '-Os '
|
||||||
|
elif(arg == '-Oz'):
|
||||||
|
ldc_flags += '-Oz '
|
||||||
|
elif(arg == '-g'):
|
||||||
|
ldc_flags += '-g '
|
||||||
|
elif(arg == '-opt'):
|
||||||
|
ldc_flags += '-release -enable-inlining -O3 '
|
||||||
|
else:
|
||||||
|
print('unknown argument: ' + arg)
|
||||||
|
exit()
|
||||||
|
|
||||||
|
compile(['source'], 'ecs.a')
|
||||||
|
|
||||||
|
#export LDC_LIBS=/path/to/your/ldc-build-runtime.tmp/lib/
|
||||||
|
CC = os.environ['NDK'] + '/toolchains/llvm/prebuilt/linux-x86_64/bin/clang'
|
||||||
|
TOOLCHAIN = os.environ['NDK'] + '/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64'
|
||||||
|
SYSROOT = os.environ['NDK'] + '/platforms/android-21/arch-arm'
|
||||||
|
LDC_LIBS = ''#os.environ['LDC_LIBS'] + '/libphobos2-ldc.a ' + os.environ['LDC_LIBS'] + '/libdruntime-ldc.a'
|
||||||
|
|
||||||
|
os.system(CC + ' -Wl,-soname,libecs.so -shared --sysroot=' + SYSROOT + ' obj/*.o ' + LDC_LIBS + ' -lgcc -gcc-toolchain ' + TOOLCHAIN +
|
||||||
|
' -no-canonical-prefixes -fuse-ld=bfd -target armv7-none-linux-androideabi -fvisibility=hidden \
|
||||||
|
-Wl,--gc-sections -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro \
|
||||||
|
-Wl,-z,now -mthumb -o libecs.so')
|
||||||
1
demos/.gitignore
vendored
1
demos/.gitignore
vendored
|
|
@ -14,4 +14,5 @@
|
||||||
!cimgui.bc
|
!cimgui.bc
|
||||||
!emscripten_shell.html
|
!emscripten_shell.html
|
||||||
!emscripten_multi_shell.html
|
!emscripten_multi_shell.html
|
||||||
|
!compile_android.py
|
||||||
.dub
|
.dub
|
||||||
91
demos/compile_android.py
Normal file
91
demos/compile_android.py
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import os
|
||||||
|
import ntpath
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def compile(sources, output):
|
||||||
|
files = []
|
||||||
|
# r=root, d=directories, f = files
|
||||||
|
for path in sources:
|
||||||
|
for r, d, f in os.walk(path):
|
||||||
|
for file in f:
|
||||||
|
if ntpath.basename(file) != 'win_dll.d':
|
||||||
|
filename, file_extension = os.path.splitext(file)
|
||||||
|
if file_extension == '.d':
|
||||||
|
files.append(os.path.join(r, file))
|
||||||
|
|
||||||
|
ldc_path = 'ldc'
|
||||||
|
if 'LDC' in os.environ:
|
||||||
|
ldc_path = os.environ['LDC']
|
||||||
|
|
||||||
|
ldc_cmd = ldc_path + ' ' + ldc_flags + '-lib -mtriple=armv7-none-linux-androideabi -fvisibility=hidden -betterC -oq -od=obj/ --singleobj --of=' + output + ' '
|
||||||
|
|
||||||
|
for path in sources:
|
||||||
|
ldc_cmd += '-I' + path + ' '
|
||||||
|
|
||||||
|
for path in import_paths:
|
||||||
|
ldc_cmd += '-I' + path + ' '
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
ldc_cmd += f + ' '
|
||||||
|
|
||||||
|
print(ldc_cmd)
|
||||||
|
|
||||||
|
if os.system(ldc_cmd):
|
||||||
|
print('some kind of error')
|
||||||
|
exit(0)
|
||||||
|
print()
|
||||||
|
|
||||||
|
clean = 0
|
||||||
|
ldc_flags = '--d-version=SDL_209 --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS '
|
||||||
|
#import_paths = ['source','tests']
|
||||||
|
import_paths = ['external','external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source']
|
||||||
|
build_tests = 0
|
||||||
|
|
||||||
|
for arg in sys.argv[1:]:
|
||||||
|
if(arg == '-release'):
|
||||||
|
ldc_flags += '-release '
|
||||||
|
elif(arg == '-enable-inlining'):
|
||||||
|
ldc_flags += '-enable-inlining '
|
||||||
|
elif(arg == '-O3'):
|
||||||
|
ldc_flags += '-O3 '
|
||||||
|
elif(arg == '-O2'):
|
||||||
|
ldc_flags += '-O2 '
|
||||||
|
elif(arg == '-O1'):
|
||||||
|
ldc_flags += '-O1 '
|
||||||
|
elif(arg == '-O0'):
|
||||||
|
ldc_flags += '-O0 '
|
||||||
|
elif(arg == '-Os'):
|
||||||
|
ldc_flags += '-Os '
|
||||||
|
elif(arg == '-Oz'):
|
||||||
|
ldc_flags += '-Oz '
|
||||||
|
elif(arg == '-g'):
|
||||||
|
ldc_flags += '-g '
|
||||||
|
elif(arg == '-opt'):
|
||||||
|
ldc_flags += '-release -enable-inlining -O3 '
|
||||||
|
else:
|
||||||
|
print('unknown argument: ' + arg)
|
||||||
|
exit()
|
||||||
|
|
||||||
|
#compile(['source'], 'ecs.a')
|
||||||
|
compile(['external/wasm_imports/bindbc/sdl'], 'build/bindbc-sdl.a')
|
||||||
|
compile(['utils/source'], 'build/utils.a')
|
||||||
|
compile(['external/sources/mmutils'], 'build/mmutils.a')
|
||||||
|
compile(['external/sources/glad'], 'build/glad.a')
|
||||||
|
compile(['external/android/bindbc'], 'build/bindbc.a')
|
||||||
|
compile(['source'], 'build/demo.a')
|
||||||
|
|
||||||
|
#compile(['external/wasm_imports/bindbc/sdl','utils/source','external/sources/mmutils','external/sources/glad'], 'build/asd.a')
|
||||||
|
|
||||||
|
#export LDC_LIBS=/path/to/your/ldc-build-runtime.tmp/lib/
|
||||||
|
CC = os.environ['NDK'] + '/toolchains/llvm/prebuilt/linux-x86_64/bin/clang'
|
||||||
|
TOOLCHAIN = os.environ['NDK'] + '/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64'
|
||||||
|
SYSROOT = os.environ['NDK'] + '/platforms/android-21/arch-arm'
|
||||||
|
#LDC_LIBS = os.environ['LDC_LIBS'] + '/libphobos2-ldc.a ' + os.environ['LDC_LIBS'] + '/libdruntime-ldc.a'
|
||||||
|
LDC_LIBS = ''
|
||||||
|
LIBS = '-L/platforms/android-21/arch-arm/usr/lib'
|
||||||
|
|
||||||
|
os.system(CC + ' -Wl,-soname,libdemos.so -shared --sysroot=' + SYSROOT + ' ../obj/*.o obj/*.o ' + LDC_LIBS + ' -lgcc -gcc-toolchain ' + TOOLCHAIN +
|
||||||
|
' -no-canonical-prefixes -fuse-ld=bfd -target armv7-none-linux-androideabi -fvisibility=hidden \
|
||||||
|
-Wl,--gc-sections -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro \
|
||||||
|
-Wl,-z,now -mthumb -lm -lc -Llibs/armeabi-v7a -lcimgui -o libdemos.so')
|
||||||
|
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
"libs-linux-x86_64": ["cimgui","SDL2","SDL2_image"],
|
"libs-linux-x86_64": ["cimgui","SDL2","SDL2_image"],
|
||||||
"lflags-linux-x86_64": ["-rpath=libs/linux/x64/","-Llibs/linux/x64/"],
|
"lflags-linux-x86_64": ["-rpath=libs/linux/x64/","-Llibs/linux/x64/"],
|
||||||
"dflags-ldc" : [
|
"dflags-ldc" : [
|
||||||
"--ffast-math"
|
"--ffast-math",
|
||||||
|
"-enable-cross-module-inlining"
|
||||||
],
|
],
|
||||||
"configurations" : [
|
"configurations" : [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
11
demos/external/android/bindbc/loader/package.d
vendored
Normal file
11
demos/external/android/bindbc/loader/package.d
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
// Copyright Michael D. Parker 2018.
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
module bindbc.loader;
|
||||||
|
|
||||||
|
public
|
||||||
|
import bindbc.loader.sharedlib,
|
||||||
|
bindbc.loader.system;
|
||||||
335
demos/external/android/bindbc/loader/sharedlib.d
vendored
Normal file
335
demos/external/android/bindbc/loader/sharedlib.d
vendored
Normal file
|
|
@ -0,0 +1,335 @@
|
||||||
|
|
||||||
|
// Copyright Michael D. Parker 2018.
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
module bindbc.loader.sharedlib;
|
||||||
|
|
||||||
|
import core.stdc.stdlib;
|
||||||
|
import core.stdc.string;
|
||||||
|
|
||||||
|
/// Handle to a shared library
|
||||||
|
struct SharedLib {
|
||||||
|
private void* _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Indicates an uninitialized or unassigned handle.
|
||||||
|
enum invalidHandle = SharedLib.init;
|
||||||
|
|
||||||
|
// Contains information about shared library and symbol load failures.
|
||||||
|
struct ErrorInfo {
|
||||||
|
private:
|
||||||
|
char[32] _error;
|
||||||
|
char[96] _message;
|
||||||
|
|
||||||
|
public @nogc nothrow @property:
|
||||||
|
/**
|
||||||
|
Returns the string "Missing Symbol" to indicate a symbol load failure, and
|
||||||
|
the name of a library to indicate a library load failure.
|
||||||
|
*/
|
||||||
|
const(char)* error() const { return _error.ptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a symbol name for symbol load failures, and a system-specific error
|
||||||
|
message for library load failures.
|
||||||
|
*/
|
||||||
|
const(char)* message() const { return _message.ptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private {
|
||||||
|
__gshared ErrorInfo[] _errors;
|
||||||
|
__gshared size_t _errorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow:
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an slice containing all errors that have been accumulated by the
|
||||||
|
`load` and `bindSymbol` functions since the last call to `resetErrors`.
|
||||||
|
*/
|
||||||
|
const(ErrorInfo)[] errors()
|
||||||
|
{
|
||||||
|
return _errors[0 .. _errorCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the total number of errors that have been accumulated by the
|
||||||
|
`load` and `bindSymbol` functions since the last call to `resetErrors`.
|
||||||
|
*/
|
||||||
|
size_t errorCount()
|
||||||
|
{
|
||||||
|
return _errorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the error count to 0 and erases all accumulated errors. This function
|
||||||
|
does not release any memory allocated for the error list.
|
||||||
|
*/
|
||||||
|
void resetErrors()
|
||||||
|
{
|
||||||
|
_errorCount = 0;
|
||||||
|
memset(_errors.ptr, 0, _errors.length * ErrorInfo.sizeof);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void freeErrors()
|
||||||
|
{
|
||||||
|
free(_errors.ptr);
|
||||||
|
_errors.length = _errorCount = 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads a symbol from a shared library and assigns it to a caller-supplied pointer.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
lib = a valid handle to a shared library loaded via the `load` function.
|
||||||
|
ptr = a pointer to a function or variable pointer whose declaration is
|
||||||
|
appropriate for the symbol being bound (it is up to the caller to
|
||||||
|
verify the types match).
|
||||||
|
symbolName = the name of the symbol to bind.
|
||||||
|
*/
|
||||||
|
void bindSymbol(SharedLib lib, void** ptr, const(char)* symbolName)
|
||||||
|
{
|
||||||
|
// Without this, DMD can hang in release builds
|
||||||
|
pragma(inline, false);
|
||||||
|
|
||||||
|
assert(lib._handle);
|
||||||
|
auto sym = loadSymbol(lib._handle, symbolName);
|
||||||
|
if(sym) {
|
||||||
|
*ptr = sym;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addErr("Missing Symbol", symbolName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Formats a symbol using the Windows stdcall mangling if necessary before passing it on to
|
||||||
|
bindSymbol.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
lib = a valid handle to a shared library loaded via the `load` function.
|
||||||
|
ptr = a pointer to a function or variable pointer whose declaration is
|
||||||
|
appropriate for the symbol being bound (it is up to the caller to
|
||||||
|
verify the types match).
|
||||||
|
symbolName = the name of the symbol to bind.
|
||||||
|
*/
|
||||||
|
void bindSymbol_stdcall(Func)(SharedLib lib, ref Func f, const(char)* symbolName)
|
||||||
|
{
|
||||||
|
import bindbc.loader.system : bindWindows, bind32;
|
||||||
|
|
||||||
|
static if(bindWindows && bind32) {
|
||||||
|
import core.stdc.stdio : snprintf;
|
||||||
|
import std.traits : ParameterTypeTuple;
|
||||||
|
|
||||||
|
uint paramSize(A...)(A args)
|
||||||
|
{
|
||||||
|
size_t sum = 0;
|
||||||
|
foreach(arg; args) {
|
||||||
|
sum += arg.sizeof;
|
||||||
|
|
||||||
|
// Align on 32-bit stack
|
||||||
|
if((sum & 3) != 0) {
|
||||||
|
sum += 4 - (sum & 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterTypeTuple!f params;
|
||||||
|
char[128] mangled;
|
||||||
|
snprintf(mangled.ptr, mangled.length, "_%s@%d", symbolName, paramSize(params));
|
||||||
|
symbolName = mangled.ptr;
|
||||||
|
}
|
||||||
|
bindSymbol(lib, cast(void**)&f, symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads a shared library from disk, using the system-specific API and search rules.
|
||||||
|
|
||||||
|
libName = the name of the library to load. May include the full or relative
|
||||||
|
path for the file.
|
||||||
|
*/
|
||||||
|
SharedLib load(const(char)* libName)
|
||||||
|
{
|
||||||
|
auto handle = loadLib(libName);
|
||||||
|
if(handle) return SharedLib(handle);
|
||||||
|
else {
|
||||||
|
addErr(libName, null);
|
||||||
|
return invalidHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Unloads a shared library from process memory.
|
||||||
|
|
||||||
|
Generally, it is not necessary to call this function at program exit, as the system will ensure
|
||||||
|
any shared libraries loaded by the process will be unloaded then. However, any loaded shared
|
||||||
|
libraries that are no longer needed by the program during runtime, such as those that are part
|
||||||
|
of a "hot swap" mechanism, should be unloaded to free up resources.
|
||||||
|
*/
|
||||||
|
void unload(ref SharedLib lib) {
|
||||||
|
if(lib._handle) {
|
||||||
|
unloadLib(lib._handle);
|
||||||
|
lib = invalidHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void allocErrs() {
|
||||||
|
size_t newSize = _errorCount == 0 ? 16 : _errors.length * 2;
|
||||||
|
auto errs = cast(ErrorInfo*)malloc(ErrorInfo.sizeof * newSize);
|
||||||
|
if(!errs) exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
if(_errorCount > 0) {
|
||||||
|
memcpy(errs, _errors.ptr, ErrorInfo.sizeof * _errors.length);
|
||||||
|
free(_errors.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_errors = errs[0 .. newSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
void addErr(const(char)* errstr, const(char)* message)
|
||||||
|
{
|
||||||
|
if(_errors.length == 0 || _errorCount >= _errors.length) {
|
||||||
|
allocErrs();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pinfo = &_errors[_errorCount];
|
||||||
|
strcpy(pinfo._error.ptr, errstr);
|
||||||
|
|
||||||
|
if(message) {
|
||||||
|
strncpy(pinfo._message.ptr, message, pinfo._message.length);
|
||||||
|
pinfo._message[pinfo._message.length - 1] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sysError(pinfo._message.ptr, pinfo._message.length);
|
||||||
|
}
|
||||||
|
++_errorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
{
|
||||||
|
import core.sys.windows.windows;
|
||||||
|
extern(Windows) @nogc nothrow alias pSetDLLDirectory = BOOL function(const(char)*);
|
||||||
|
pSetDLLDirectory setDLLDirectory;
|
||||||
|
|
||||||
|
void* loadLib(const(char)* name)
|
||||||
|
{
|
||||||
|
return LoadLibraryA(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unloadLib(void* lib)
|
||||||
|
{
|
||||||
|
FreeLibrary(lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* loadSymbol(void* lib, const(char)* symbolName)
|
||||||
|
{
|
||||||
|
return GetProcAddress(lib, symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysError(char* buf, size_t len)
|
||||||
|
{
|
||||||
|
char* msgBuf;
|
||||||
|
enum uint langID = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
|
||||||
|
|
||||||
|
FormatMessageA(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
null,
|
||||||
|
GetLastError(),
|
||||||
|
langID,
|
||||||
|
cast(char*)&msgBuf,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
if(msgBuf) {
|
||||||
|
strncpy(buf, msgBuf, len);
|
||||||
|
buf[len - 1] = 0;
|
||||||
|
LocalFree(msgBuf);
|
||||||
|
}
|
||||||
|
else strncpy(buf, "Unknown Error\0", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adds a path to the default search path on Windows, replacing the path set in a previous
|
||||||
|
call to the same function.
|
||||||
|
|
||||||
|
Any path added to this function will be added to the default DLL search path as documented at
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setdlldirectoryw.
|
||||||
|
|
||||||
|
Generally, when loading DLLs on a path that is not on the search path, e.g., from a subdirectory
|
||||||
|
of the application, the path should be prepended to the DLL name passed to the load function,
|
||||||
|
e.g., "dlls\\SDL2.dll". If `setCustomLoaderSearchPath(".\\dlls")` is called first, then the subdirectory
|
||||||
|
will become part of the DLL search path and the path may be omitted from the load function. (Be
|
||||||
|
aware that ".\\dlls" is relative to the current working directory, which may not be the application
|
||||||
|
directory, so the path should be built appropriately.)
|
||||||
|
|
||||||
|
Some DLLs may depend on other DLLs, perhaps even attempting to load them dynamically at run time
|
||||||
|
(e.g., SDL2_image only loads dependencies such as libpng if it is initialized at run time with
|
||||||
|
PNG support). In this case, if the DLL and its dependencies are placed in a subdirectory and
|
||||||
|
loaded as e.g., "dlls\\SDL2_image.dll", then it will not be able to find its dependencies; the
|
||||||
|
system loader will look for them on the regular DLL search path. When that happens, the solution
|
||||||
|
is to call `setCustomLoaderSearchPath` with the subdirectory before initializing the library.
|
||||||
|
|
||||||
|
Calling this function with `null` as the argument will reset the default search path.
|
||||||
|
|
||||||
|
When the function returns `false`, the relevant `ErrorInfo` is added to the global error list and can
|
||||||
|
be retrieved by looping through the array returned by the `errors` function.
|
||||||
|
|
||||||
|
When placing DLLs in a subdirectory of the application, it should be considered good practice to
|
||||||
|
call `setCustomLoaderSearchPath` to ensure all DLLs load properly. It should also be considered good
|
||||||
|
practice to reset the default search path once all DLLs are loaded.
|
||||||
|
|
||||||
|
This function is only available on Windows, so any usage of it should be preceded with
|
||||||
|
`version(Windows)`.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
path = the path to add to the DLL search path, or `null` to reset the default.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
`true` if the path was successfully added to the DLL search path, otherwise `false`.
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
bool setCustomLoaderSearchPath(const(char)* path)
|
||||||
|
{
|
||||||
|
if(!setDLLDirectory) {
|
||||||
|
auto lib = load("Kernel32.dll");
|
||||||
|
if(lib == invalidHandle) return false;
|
||||||
|
lib.bindSymbol(cast(void**)&setDLLDirectory, "SetDllDirectoryA");
|
||||||
|
if(!setDLLDirectory) return false;
|
||||||
|
}
|
||||||
|
return setDLLDirectory(path) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else version(Posix) {
|
||||||
|
import core.sys.posix.dlfcn;
|
||||||
|
|
||||||
|
void* loadLib(const(char)* name)
|
||||||
|
{
|
||||||
|
return dlopen(name, RTLD_NOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unloadLib(void* lib)
|
||||||
|
{
|
||||||
|
dlclose(lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* loadSymbol(void* lib, const(char)* symbolName)
|
||||||
|
{
|
||||||
|
return dlsym(lib, symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysError(char* buf, size_t len)
|
||||||
|
{
|
||||||
|
const (char)* msg = dlerror();
|
||||||
|
strncpy(buf, msg != null ? msg : "Unknown Error", len);
|
||||||
|
buf[len - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else static assert(0, "bindbc-loader is not implemented on this platform.");
|
||||||
55
demos/external/android/bindbc/loader/system.d
vendored
Normal file
55
demos/external/android/bindbc/loader/system.d
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
// Copyright Michael D. Parker 2018.
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
module bindbc.loader.system;
|
||||||
|
|
||||||
|
static if((void*).sizeof == 8) {
|
||||||
|
enum bind64 = true;
|
||||||
|
enum bind32 = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enum bind64 = false;
|
||||||
|
enum bind32 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
version(Windows) enum bindWindows = true;
|
||||||
|
else enum bindWindows = false;
|
||||||
|
|
||||||
|
version(OSX) enum bindMac = true;
|
||||||
|
else enum bindMac = false;
|
||||||
|
|
||||||
|
version(linux) enum bindLinux = true;
|
||||||
|
else enum bindLinux = false;
|
||||||
|
|
||||||
|
version(Posix) enum bindPosix = true;
|
||||||
|
else enum bindPosix = false;
|
||||||
|
|
||||||
|
version(Android) enum bindAndroid = true;
|
||||||
|
else enum bindAndroid = false;
|
||||||
|
|
||||||
|
enum bindIOS = false;
|
||||||
|
enum bindWinRT = false;
|
||||||
|
|
||||||
|
version(FreeBSD) {
|
||||||
|
enum bindBSD = true;
|
||||||
|
enum bindFreeBSD = true;
|
||||||
|
enum bindOpenBSD = false;
|
||||||
|
}
|
||||||
|
else version(OpenBSD) {
|
||||||
|
enum bindBSD = true;
|
||||||
|
enum bindFreeBSD = false;
|
||||||
|
enum bindOpenBSD = true;
|
||||||
|
}
|
||||||
|
else version(BSD) {
|
||||||
|
enum bindBSD = true;
|
||||||
|
enum bindFreeBSD = false;
|
||||||
|
enum bindOpenBSD = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enum bindBSD = false;
|
||||||
|
enum bindFreeBSD = false;
|
||||||
|
enum bindOpenBSD = false;
|
||||||
|
}
|
||||||
15
demos/external/sources/mmutils/thread_pool.d
vendored
15
demos/external/sources/mmutils/thread_pool.d
vendored
|
|
@ -201,6 +201,21 @@ void instructionPause()
|
||||||
static assert(0);
|
static assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else version (Android)
|
||||||
|
{
|
||||||
|
version(LDC)
|
||||||
|
{
|
||||||
|
import ldc.attributes;
|
||||||
|
@optStrategy("none")
|
||||||
|
static void nop()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
else static assert(0);
|
||||||
|
}
|
||||||
else version(WebAssembly)
|
else version(WebAssembly)
|
||||||
{
|
{
|
||||||
version(LDC)
|
version(LDC)
|
||||||
|
|
|
||||||
12
demos/external/wasm_imports/bindbc/sdl/dynload.d
vendored
12
demos/external/wasm_imports/bindbc/sdl/dynload.d
vendored
|
|
@ -14,8 +14,8 @@ import bindbc.sdl.config,
|
||||||
bindbc.sdl.bind;
|
bindbc.sdl.bind;
|
||||||
|
|
||||||
private {
|
private {
|
||||||
SharedLib lib;
|
__gshared SharedLib lib;
|
||||||
SDLSupport loadedVersion;
|
__gshared SDLSupport loadedVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unloadSDL()
|
void unloadSDL()
|
||||||
|
|
@ -664,14 +664,14 @@ SDLSupport loadSDL(const(char)* libName)
|
||||||
lib.bindSymbol(cast(void**)&SDL_HasColorKey, "SDL_HasColorKey");
|
lib.bindSymbol(cast(void**)&SDL_HasColorKey, "SDL_HasColorKey");
|
||||||
lib.bindSymbol(cast(void**)&SDL_GetDisplayOrientation, "SDL_GetDisplayOrientation");
|
lib.bindSymbol(cast(void**)&SDL_GetDisplayOrientation, "SDL_GetDisplayOrientation");
|
||||||
|
|
||||||
version(linux) {
|
version(Android) {
|
||||||
lib.bindSymbol(cast(void**)&SDL_LinuxSetThreadPriority, "SDL_LinuxSetThreadPriority");
|
|
||||||
}
|
|
||||||
else version(Android) {
|
|
||||||
lib.bindSymbol(cast(void**)&SDL_IsChromebook, "SDL_IsChromebook");
|
lib.bindSymbol(cast(void**)&SDL_IsChromebook, "SDL_IsChromebook");
|
||||||
lib.bindSymbol(cast(void**)&SDL_IsDeXMode, "SDL_IsDeXMode");
|
lib.bindSymbol(cast(void**)&SDL_IsDeXMode, "SDL_IsDeXMode");
|
||||||
lib.bindSymbol(cast(void**)&SDL_AndroidBackButton, "SDL_AndroidBackButton");
|
lib.bindSymbol(cast(void**)&SDL_AndroidBackButton, "SDL_AndroidBackButton");
|
||||||
}
|
}
|
||||||
|
else version(linux) {
|
||||||
|
lib.bindSymbol(cast(void**)&SDL_LinuxSetThreadPriority, "SDL_LinuxSetThreadPriority");
|
||||||
|
}
|
||||||
|
|
||||||
if(errorCount() != errCount) return SDLSupport.badLibrary;
|
if(errorCount() != errCount) return SDLSupport.badLibrary;
|
||||||
else loadedVersion = SDLSupport.sdl209;
|
else loadedVersion = SDLSupport.sdl209;
|
||||||
|
|
|
||||||
|
|
@ -229,8 +229,8 @@ else {
|
||||||
}
|
}
|
||||||
|
|
||||||
private {
|
private {
|
||||||
SharedLib lib;
|
__gshared SharedLib lib;
|
||||||
SDLImageSupport loadedVersion;
|
__gshared SDLImageSupport loadedVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unloadSDLImage()
|
void unloadSDLImage()
|
||||||
|
|
|
||||||
BIN
demos/libs/armeabi-v7a/libcimgui.so
Executable file
BIN
demos/libs/armeabi-v7a/libcimgui.so
Executable file
Binary file not shown.
|
|
@ -203,12 +203,10 @@ void mainLoop(void* arg)
|
||||||
temp_fps = 0;
|
temp_fps = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event))
|
||||||
{
|
{
|
||||||
version(WebAssembly)ImGui_ImplSDL2_ProcessEvent(&event);
|
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||||
else ImGui_ImplSDL2_ProcessEvent(&event);
|
|
||||||
if(launcher.event)launcher.event(&event);
|
if(launcher.event)launcher.event(&event);
|
||||||
if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)) {
|
if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)) {
|
||||||
quit();
|
quit();
|
||||||
|
|
@ -278,7 +276,8 @@ void mainLoop(void* arg)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGuiImplOpenGL2NewFrame();
|
//ImGuiImplOpenGL2NewFrame();
|
||||||
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
ImGuiImplSDL2NewFrame(launcher.window);
|
ImGuiImplSDL2NewFrame(launcher.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -632,7 +631,9 @@ void mainLoop(void* arg)
|
||||||
|
|
||||||
igRender();
|
igRender();
|
||||||
version(WebAssembly)ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
|
version(WebAssembly)ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
|
||||||
else ImGuiImplOpenGL2RenderDrawData(igGetDrawData());
|
else version(Android)ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
|
||||||
|
else ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
|
||||||
|
//ImGuiImplOpenGL2RenderDrawData(igGetDrawData());
|
||||||
|
|
||||||
//launcher.renderer.clear();
|
//launcher.renderer.clear();
|
||||||
//launcher.renderer.present();
|
//launcher.renderer.present();
|
||||||
|
|
@ -652,15 +653,48 @@ void quit()
|
||||||
version(WebAssembly)emscripten_cancel_main_loop();
|
version(WebAssembly)emscripten_cancel_main_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
version(Android)
|
||||||
{
|
{
|
||||||
|
export extern (C) int SDL_main(int argc, char** args)
|
||||||
|
{
|
||||||
|
return app_main(argc,args);
|
||||||
|
}
|
||||||
|
|
||||||
|
import ldc.attributes;
|
||||||
|
|
||||||
|
extern (C) __gshared
|
||||||
|
{
|
||||||
|
@section(".tdata")
|
||||||
|
int _tlsstart = 0;
|
||||||
|
@section(".tcommon")
|
||||||
|
int _tlsend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extern (C) int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
return app_main(argc,argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int app_main(int argc, char** argv)
|
||||||
|
//int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
version(BindSDL_Static){}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loadSDL();
|
||||||
|
loadSDLImage();
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||||
{
|
{
|
||||||
printf("SDL could not initialize! SDL_Error: %s", SDL_GetError());
|
printf("SDL could not initialize! SDL_Error: %s", SDL_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_version sdl_version;
|
SDL_version sdl_version;
|
||||||
SDL_GetVersion(&sdl_version);
|
SDL_GetVersion(&sdl_version);
|
||||||
printf("SDL version: %u.%u.%u\n",cast(uint)sdl_version.major,cast(uint)sdl_version.minor,cast(uint)sdl_version.patch);
|
printf("SDL version: %u.%u.%u\n",cast(uint)sdl_version.major,cast(uint)sdl_version.minor,cast(uint)sdl_version.patch);
|
||||||
|
|
@ -692,6 +726,21 @@ int main(int argc, char** argv)
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else version(Android)
|
||||||
|
{
|
||||||
|
//gladLoadGL();
|
||||||
|
gladLoadGLES2(x => SDL_GL_GetProcAddress(x));
|
||||||
|
if(!ImGuiImplSDL2InitForOpenGL(launcher.window,launcher.gl_context))
|
||||||
|
{
|
||||||
|
printf("ImGui initialization failed!");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if(!ImGui_ImplOpenGL3_Init("#version 100"))
|
||||||
|
{
|
||||||
|
printf("ImGui OpenGL initialization failed!");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gladLoadGL();
|
gladLoadGL();
|
||||||
|
|
@ -700,13 +749,14 @@ int main(int argc, char** argv)
|
||||||
printf("ImGui initialization failed!");
|
printf("ImGui initialization failed!");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if(!ImGuiImplOpenGL2Init())
|
//if(!ImGuiImplOpenGL2Init())
|
||||||
|
if(!ImGui_ImplOpenGL3_Init("#version 120"))
|
||||||
{
|
{
|
||||||
printf("ImGui OpenGL initialization failed!");
|
printf("ImGui OpenGL initialization failed!");
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFontConfig* config = ImFontConfig_ImFontConfig();
|
ImFontConfig* config = ImFontConfig_ImFontConfig();
|
||||||
ImGuiIO* io = igGetIO();
|
ImGuiIO* io = igGetIO();
|
||||||
const ushort* font_ranges = ImFontAtlas_GetGlyphRangesDefault(io.Fonts);
|
const ushort* font_ranges = ImFontAtlas_GetGlyphRangesDefault(io.Fonts);
|
||||||
|
|
|
||||||
|
|
@ -1392,7 +1392,7 @@ struct UpgradeCollisionSystem
|
||||||
if(space_invaders.shoot_grid.test(id, data.location[i], cast(ubyte)(0xFF)))
|
if(space_invaders.shoot_grid.test(id, data.location[i], cast(ubyte)(0xFF)))
|
||||||
{
|
{
|
||||||
Entity* entity = launcher.manager.getEntity(id);
|
Entity* entity = launcher.manager.getEntity(id);
|
||||||
if(entity.hasComponent(CShip.component_id))
|
if(entity && entity.hasComponent(CShip.component_id))
|
||||||
{
|
{
|
||||||
launcher.manager.sendEvent(id, EUpgrade());
|
launcher.manager.sendEvent(id, EUpgrade());
|
||||||
launcher.manager.removeEntity(data.entity[i].id);
|
launcher.manager.removeEntity(data.entity[i].id);
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,17 @@ struct ECSJobUpdater
|
||||||
//pool.unregistExternalThread(thread_data);
|
//pool.unregistExternalThread(thread_data);
|
||||||
if(jobs)Mallocator.dispose(jobs);
|
if(jobs)Mallocator.dispose(jobs);
|
||||||
version(WebAssembly)pthread_key_delete(tls_key);
|
version(WebAssembly)pthread_key_delete(tls_key);
|
||||||
|
else version(Android)pthread_key_delete(tls_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
version(WebAssembly)
|
version(WebAssembly)
|
||||||
{
|
{
|
||||||
__gshared pthread_key_t tls_key;
|
__gshared pthread_key_t tls_key;
|
||||||
}
|
}
|
||||||
|
else version(Android)
|
||||||
|
{
|
||||||
|
__gshared pthread_key_t tls_key;
|
||||||
|
}
|
||||||
else static uint thread_id = 0;
|
else static uint thread_id = 0;
|
||||||
|
|
||||||
ThreadPool pool;
|
ThreadPool pool;
|
||||||
|
|
@ -105,6 +110,7 @@ struct ECSJobUpdater
|
||||||
void onCreate(uint threads_count)
|
void onCreate(uint threads_count)
|
||||||
{
|
{
|
||||||
version(WebAssembly)pthread_key_create(&tls_key, null);
|
version(WebAssembly)pthread_key_create(&tls_key, null);
|
||||||
|
else version(Android)pthread_key_create(&tls_key, null);
|
||||||
|
|
||||||
pool.initialize();
|
pool.initialize();
|
||||||
thread_data = pool.registerExternalThread();
|
thread_data = pool.registerExternalThread();
|
||||||
|
|
@ -116,6 +122,7 @@ struct ECSJobUpdater
|
||||||
uint getThreadID() @nogc nothrow
|
uint getThreadID() @nogc nothrow
|
||||||
{
|
{
|
||||||
version(WebAssembly)return cast(int)pthread_getspecific(tls_key);
|
version(WebAssembly)return cast(int)pthread_getspecific(tls_key);
|
||||||
|
else version(Android)return cast(int)pthread_getspecific(tls_key);
|
||||||
else return thread_id;
|
else return thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,6 +207,11 @@ struct ECSJobUpdater
|
||||||
}
|
}
|
||||||
else job.execute();
|
else job.execute();
|
||||||
}
|
}
|
||||||
|
else version(Android)
|
||||||
|
{
|
||||||
|
pthread_setspecific(tls_key, cast(void*)th_data.threadId);
|
||||||
|
job.execute();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
updater.thread_id = th_data.threadId;
|
updater.thread_id = th_data.threadId;
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,13 @@
|
||||||
"../external/sources"
|
"../external/sources"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindbc-sdl":"0.13.0",
|
"bindbc-sdl":"0.19.0",
|
||||||
"ecs":{"path":"../../"}
|
"ecs":{"path":"../../"}
|
||||||
},
|
},
|
||||||
"versions": [
|
"versions": [
|
||||||
"BindSDL_Image",
|
"BindSDL_Image",
|
||||||
"SDL_2010"
|
"SDL_2010"
|
||||||
],
|
],
|
||||||
|
|
||||||
"configurations" : [
|
"configurations" : [
|
||||||
{
|
{
|
||||||
"name" : "default",
|
"name" : "default",
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,12 @@ module ecs_utils.gfx.buffer;
|
||||||
|
|
||||||
import bubel.ecs.std;
|
import bubel.ecs.std;
|
||||||
|
|
||||||
import glad.gl.gl;
|
//import glad.gl.gl;
|
||||||
import glad.gl.gles2;
|
//import glad.gl.gles2;
|
||||||
|
|
||||||
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
|
else import glad.gl.gl;
|
||||||
|
|
||||||
extern(C):
|
extern(C):
|
||||||
|
|
||||||
|
|
@ -64,13 +68,13 @@ struct Buffer
|
||||||
void map(BindTarget target) nothrow
|
void map(BindTarget target) nothrow
|
||||||
{
|
{
|
||||||
bind(target);
|
bind(target);
|
||||||
data.map_ptr = glMapBuffer(target,GL_WRITE_ONLY);
|
version(Android){}else data.map_ptr = glMapBuffer(target,GL_WRITE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void map(uint offset, uint size, BindTarget target, uint flags = MapFlagBits.write | MapFlagBits.flush_explict | MapFlagBits.invalidate_buffer) nothrow
|
void map(uint offset, uint size, BindTarget target, uint flags = MapFlagBits.write | MapFlagBits.flush_explict | MapFlagBits.invalidate_buffer) nothrow
|
||||||
{
|
{
|
||||||
bind(target);
|
bind(target);
|
||||||
data.map_ptr = glMapBufferRange(target,offset,size,flags);
|
version(Android){}else data.map_ptr = glMapBufferRange(target,offset,size,flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush(uint offset, uint size, BindTarget target) nothrow
|
void flush(uint offset, uint size, BindTarget target) nothrow
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import bubel.ecs.std;
|
||||||
|
|
||||||
import ecs_utils.gfx.shader;
|
import ecs_utils.gfx.shader;
|
||||||
|
|
||||||
import glad.gl.gl;
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
|
else import glad.gl.gl;
|
||||||
|
|
||||||
//import mutils.serializer.json;
|
//import mutils.serializer.json;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import bubel.ecs.std;
|
||||||
|
|
||||||
import ecs_utils.gfx.buffer;
|
import ecs_utils.gfx.buffer;
|
||||||
|
|
||||||
import glad.gl.gl;
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
|
else import glad.gl.gl;
|
||||||
//import mutils.serializer.json;
|
//import mutils.serializer.json;
|
||||||
|
|
||||||
extern(C):
|
extern(C):
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import ecs_utils.math.vector;
|
||||||
import bubel.ecs.block_allocator;
|
import bubel.ecs.block_allocator;
|
||||||
import bubel.ecs.vector;
|
import bubel.ecs.vector;
|
||||||
version(WebAssembly)import glad.gl.gles2;
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
else import glad.gl.gl;
|
else import glad.gl.gl;
|
||||||
|
|
||||||
version = ver1;
|
version = ver1;
|
||||||
|
|
@ -637,6 +638,7 @@ struct Renderer
|
||||||
if(threads[thread_id].block.items >= VertexBlock.max_items)
|
if(threads[thread_id].block.items >= VertexBlock.max_items)
|
||||||
{
|
{
|
||||||
//pushBlock(threads[thread_id].block);
|
//pushBlock(threads[thread_id].block);
|
||||||
|
prepared_items += threads[thread_id].block.items;
|
||||||
threads[thread_id].blocks.add(threads[thread_id].block);
|
threads[thread_id].blocks.add(threads[thread_id].block);
|
||||||
threads[thread_id].block = getBlock();
|
threads[thread_id].block = getBlock();
|
||||||
}
|
}
|
||||||
|
|
@ -667,6 +669,10 @@ struct Renderer
|
||||||
{
|
{
|
||||||
glDepthRangef(0,1);
|
glDepthRangef(0,1);
|
||||||
}
|
}
|
||||||
|
else version(Android)
|
||||||
|
{
|
||||||
|
glDepthRangef(0,1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glDepthRange(0,1);
|
glDepthRange(0,1);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ import bindbc.sdl;
|
||||||
|
|
||||||
import bubel.ecs.std;
|
import bubel.ecs.std;
|
||||||
|
|
||||||
import glad.gl.gl;
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
|
else import glad.gl.gl;
|
||||||
|
|
||||||
//version = ver1;
|
//version = ver1;
|
||||||
|
|
||||||
|
|
@ -67,10 +69,12 @@ struct Shader
|
||||||
}
|
}
|
||||||
|
|
||||||
version(WebAssembly)const char* glsl = "#version 100\n";
|
version(WebAssembly)const char* glsl = "#version 100\n";
|
||||||
|
else version(Android)const char* glsl = "#version 100\n";
|
||||||
else const char* glsl = "#version 330\n";
|
else const char* glsl = "#version 330\n";
|
||||||
const char* buffer = data.code.ptr;
|
const char* buffer = data.code.ptr;
|
||||||
char* ver;
|
char* ver;
|
||||||
version(WebAssembly)ver = cast(char*)"#define ver1 1\n#define GLES\n".ptr;
|
version(WebAssembly)ver = cast(char*)"#define ver1 1\n#define GLES\n".ptr;
|
||||||
|
else version(Android)ver = cast(char*)"#define ver1 1\n#define GLES\n".ptr;
|
||||||
else ver = cast(char*)"#define ver1 1\n".ptr;
|
else ver = cast(char*)"#define ver1 1\n".ptr;
|
||||||
/*switch(__ecs_used_technique)
|
/*switch(__ecs_used_technique)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import bubel.ecs.std;
|
||||||
|
|
||||||
import ecs_utils.math.vector;
|
import ecs_utils.math.vector;
|
||||||
|
|
||||||
import glad.gl.gl;
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
|
else import glad.gl.gl;
|
||||||
|
|
||||||
extern(C):
|
extern(C):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ else :
|
||||||
|
|
||||||
import bindbc.sdl;
|
import bindbc.sdl;
|
||||||
|
|
||||||
import glad.gl.gl;
|
version(WebAssembly)import glad.gl.gles2;
|
||||||
|
else version(Android)import glad.gl.gles2;
|
||||||
|
else import glad.gl.gl;
|
||||||
|
|
||||||
import cimgui.cimgui;
|
import cimgui.cimgui;
|
||||||
|
|
||||||
|
|
@ -210,7 +212,7 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
||||||
|
|
||||||
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
|
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
|
||||||
// The function is only supported from SDL 2.0.4 (released Jan 2016)
|
// The function is only supported from SDL 2.0.4 (released Jan 2016)
|
||||||
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
|
bool any_mouse_button_down = ImGui.IsAnyMouseDown();
|
||||||
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
|
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
|
||||||
//#else*/
|
//#else*/
|
||||||
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
|
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
|
||||||
|
|
@ -291,10 +293,11 @@ void ImGuiImplSDL2NewFrame(SDL_Window* window)
|
||||||
int w, h;
|
int w, h;
|
||||||
int display_w, display_h;
|
int display_w, display_h;
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
// SDL_GL_GetDrawableSize(window, &display_w, &display_h); FIXME: you see
|
||||||
io.DisplaySize = ImVec2(cast(float)w, cast(float)h);
|
io.DisplaySize = ImVec2(cast(float)w, cast(float)h);
|
||||||
if (w > 0 && h > 0)
|
// if (w > 0 && h > 0)
|
||||||
io.DisplayFramebufferScale = ImVec2(cast(float)display_w / w, cast(float)display_h / h);
|
// io.DisplayFramebufferScale = ImVec2(cast(float)display_w / w, cast(float)display_h / h);
|
||||||
|
io.DisplayFramebufferScale = ImVec2(1,1);
|
||||||
|
|
||||||
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||||
frequency = SDL_GetPerformanceFrequency();
|
frequency = SDL_GetPerformanceFrequency();
|
||||||
|
|
@ -310,89 +313,460 @@ void ImGuiImplSDL2NewFrame(SDL_Window* window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__gshared GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
|
||||||
|
__gshared char[32] g_GlslVersionString = ""; // Specified by user or detected based on compile time GL settings.
|
||||||
|
//__gshared GLuint g_FontTexture = 0;
|
||||||
|
__gshared GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||||
|
__gshared int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location
|
||||||
|
__gshared int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
|
||||||
|
__gshared uint g_VboHandle = 0, g_ElementsHandle = 0;
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ImGuiImplOpenGL2Init()
|
|
||||||
{
|
{
|
||||||
// Setup back-end capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO* io = igGetIO();
|
ImGuiIO* io = igGetIO();
|
||||||
io.BackendRendererName = "imgui_impl_opengl2";
|
io.BackendRendererName = "imgui_impl_opengl3";
|
||||||
|
|
||||||
|
|
||||||
|
// Store GLSL version string so we can refer to it later in case we recreate shaders.
|
||||||
|
// Note: GLSL version is NOT the same as GL version. Leave this to null if unsure.
|
||||||
|
/*#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
|
if (glsl_version == null)
|
||||||
|
glsl_version = "#version 100";
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||||
|
if (glsl_version == null)
|
||||||
|
glsl_version = "#version 300 es";
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
if (glsl_version == null)
|
||||||
|
glsl_version = "#version 150";
|
||||||
|
#else
|
||||||
|
if (glsl_version == null)
|
||||||
|
glsl_version = "#version 130";
|
||||||
|
#endif
|
||||||
|
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString));*/
|
||||||
|
//const (char)*glsl_version = "#version 100";
|
||||||
|
import core.stdc.string;
|
||||||
|
strcpy(g_GlslVersionString.ptr, glsl_version);
|
||||||
|
strcat(g_GlslVersionString.ptr, "\n");
|
||||||
|
|
||||||
|
// Dummy construct to make it easily visible in the IDE and debugger which GL loader has been selected.
|
||||||
|
// The code actually never uses the 'gl_loader' variable! It is only here so you can read it!
|
||||||
|
// If auto-detection fails or doesn't select the same GL loader file as used by your application,
|
||||||
|
// you are likely to get a crash below.
|
||||||
|
// You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
|
||||||
|
/*const char* gl_loader = "Unknown";
|
||||||
|
IM_UNUSED(gl_loader);
|
||||||
|
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||||
|
gl_loader = "GL3W";
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
|
||||||
|
gl_loader = "GLEW";
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
|
||||||
|
gl_loader = "GLAD";
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
|
||||||
|
gl_loader = "glbinding2";
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
|
||||||
|
gl_loader = "glbinding3";
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
|
||||||
|
gl_loader = "custom";
|
||||||
|
#else
|
||||||
|
gl_loader = "none";
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
// Make a dummy GL call (we don't actually need the result)
|
||||||
|
// IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code.
|
||||||
|
// Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above.
|
||||||
|
/*GLint current_texture;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);*/
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiImplOpenGL2Shutdown()
|
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
|
||||||
{
|
{
|
||||||
ImGuiImplOpenGL2DestroyDeviceObjects();
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiImplOpenGL2NewFrame()
|
|
||||||
{
|
|
||||||
if (!g_FontTexture)
|
|
||||||
ImGuiImplOpenGL2CreateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGuiImplOpenGL2SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
|
|
||||||
{
|
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
//glDisable(GL_LIGHTING);
|
|
||||||
//glDisable(GL_COLOR_MATERIAL);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
// #ifdef GL_POLYGON_MODE
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
// #endif
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
|
|
||||||
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
|
||||||
// you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function:
|
bool clip_origin_lower_left = true;
|
||||||
// GLint last_program;
|
// #if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
|
||||||
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
// GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin);
|
||||||
// glUseProgram(0);
|
// if (current_clip_origin == GL_UPPER_LEFT)
|
||||||
// ImGui_ImplOpenGL2_RenderDrawData(...);
|
// clip_origin_lower_left = false;
|
||||||
// glUseProgram(last_program)
|
// #endif
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
// Setup viewport, orthographic projection matrix
|
||||||
// Our visible imgui space lies from draw_data.DisplayPos (top left) to draw_data.DisplayPos+data_data.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
// Our visible imgui space lies from draw_data.DisplayPos (top left) to draw_data.DisplayPos+data_data.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||||
glViewport(0, 0, cast(GLsizei)fb_width, cast(GLsizei)fb_height);
|
glViewport(0, 0, cast(GLsizei)fb_width, cast(GLsizei)fb_height);
|
||||||
glMatrixMode(GL_PROJECTION);
|
float L = draw_data.DisplayPos.x;
|
||||||
glPushMatrix();
|
float R = draw_data.DisplayPos.x + draw_data.DisplaySize.x;
|
||||||
glLoadIdentity();
|
float T = draw_data.DisplayPos.y;
|
||||||
glOrtho(draw_data.DisplayPos.x, draw_data.DisplayPos.x + draw_data.DisplaySize.x, draw_data.DisplayPos.y + draw_data.DisplaySize.y, draw_data.DisplayPos.y, -1.0f, +1.0f);
|
float B = draw_data.DisplayPos.y + draw_data.DisplaySize.y;
|
||||||
glMatrixMode(GL_MODELVIEW);
|
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
|
||||||
glPushMatrix();
|
const float[4][4] ortho_projection =
|
||||||
glLoadIdentity();
|
[
|
||||||
|
[ 2.0f/(R-L), 0.0f, 0.0f, 0.0f ],
|
||||||
|
[ 0.0f, 2.0f/(T-B), 0.0f, 0.0f ],
|
||||||
|
[ 0.0f, 0.0f, -1.0f, 0.0f ],
|
||||||
|
[ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f ],
|
||||||
|
];
|
||||||
|
glUseProgram(g_ShaderHandle);
|
||||||
|
glUniform1i(g_AttribLocationTex, 0);
|
||||||
|
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||||
|
// #ifdef GL_SAMPLER_BINDING
|
||||||
|
// glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// (void)vertex_array_object;
|
||||||
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
|
// glBindVertexArray(vertex_array_object);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// Bind vertex/index buffers and setup attributes for ImDrawVert
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationVtxPos);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationVtxUV);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationVtxColor);
|
||||||
|
glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, ImDrawVert.sizeof, cast(GLvoid*)ImDrawVert.pos.offsetof);
|
||||||
|
glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, ImDrawVert.sizeof, cast(GLvoid*)ImDrawVert.uv.offsetof);
|
||||||
|
glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, ImDrawVert.sizeof, cast(GLvoid*)ImDrawVert.col.offsetof);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenGL2 Render function.
|
|
||||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
void ImGui_ImplOpenGL3_Shutdown()
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
{
|
||||||
void ImGuiImplOpenGL2RenderDrawData(ImDrawData* draw_data)
|
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_NewFrame()
|
||||||
|
{
|
||||||
|
if (!g_ShaderHandle)
|
||||||
|
ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
// Backup GL state
|
||||||
|
GLint last_texture, last_array_buffer;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
|
// GLint last_vertex_array;
|
||||||
|
// glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// Parse GLSL version string
|
||||||
|
import core.stdc.stdio;
|
||||||
|
int glsl_version = 130;
|
||||||
|
sscanf(g_GlslVersionString.ptr, "#version %d", &glsl_version);
|
||||||
|
|
||||||
|
const GLchar* vertex_shader_glsl_120 =
|
||||||
|
"uniform mat4 ProjMtx;\n
|
||||||
|
attribute vec2 Position;\n
|
||||||
|
attribute vec2 UV;\n
|
||||||
|
attribute vec4 Color;\n
|
||||||
|
varying vec2 Frag_UV;\n
|
||||||
|
varying vec4 Frag_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Frag_UV = UV;\n
|
||||||
|
Frag_Color = Color;\n
|
||||||
|
gl_Position = ProjMtx * vec4(Position.xy,0,1);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* vertex_shader_glsl_130 =
|
||||||
|
"uniform mat4 ProjMtx;\n
|
||||||
|
in vec2 Position;\n
|
||||||
|
in vec2 UV;\n
|
||||||
|
in vec4 Color;\n
|
||||||
|
out vec2 Frag_UV;\n
|
||||||
|
out vec4 Frag_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Frag_UV = UV;\n
|
||||||
|
Frag_Color = Color;\n
|
||||||
|
gl_Position = ProjMtx * vec4(Position.xy,0,1);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* vertex_shader_glsl_300_es =
|
||||||
|
"precision mediump float;\n
|
||||||
|
layout (location = 0) in vec2 Position;\n
|
||||||
|
layout (location = 1) in vec2 UV;\n
|
||||||
|
layout (location = 2) in vec4 Color;\n
|
||||||
|
uniform mat4 ProjMtx;\n
|
||||||
|
out vec2 Frag_UV;\n
|
||||||
|
out vec4 Frag_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Frag_UV = UV;\n
|
||||||
|
Frag_Color = Color;\n
|
||||||
|
gl_Position = ProjMtx * vec4(Position.xy,0,1);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* vertex_shader_glsl_410_core =
|
||||||
|
"layout (location = 0) in vec2 Position;\n
|
||||||
|
layout (location = 1) in vec2 UV;\n
|
||||||
|
layout (location = 2) in vec4 Color;\n
|
||||||
|
uniform mat4 ProjMtx;\n
|
||||||
|
out vec2 Frag_UV;\n
|
||||||
|
out vec4 Frag_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Frag_UV = UV;\n
|
||||||
|
Frag_Color = Color;\n
|
||||||
|
gl_Position = ProjMtx * vec4(Position.xy,0,1);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* fragment_shader_glsl_120 =
|
||||||
|
"#ifdef GL_ES\n
|
||||||
|
precision mediump float;\n
|
||||||
|
#endif\n
|
||||||
|
uniform sampler2D Texture;\n
|
||||||
|
varying vec2 Frag_UV;\n
|
||||||
|
varying vec4 Frag_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* fragment_shader_glsl_130 =
|
||||||
|
"uniform sampler2D Texture;\n
|
||||||
|
in vec2 Frag_UV;\n
|
||||||
|
in vec4 Frag_Color;\n
|
||||||
|
out vec4 Out_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* fragment_shader_glsl_300_es =
|
||||||
|
"precision mediump float;\n
|
||||||
|
uniform sampler2D Texture;\n
|
||||||
|
in vec2 Frag_UV;\n
|
||||||
|
in vec4 Frag_Color;\n
|
||||||
|
layout (location = 0) out vec4 Out_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
const GLchar* fragment_shader_glsl_410_core =
|
||||||
|
"in vec2 Frag_UV;\n
|
||||||
|
in vec4 Frag_Color;\n
|
||||||
|
uniform sampler2D Texture;\n
|
||||||
|
layout (location = 0) out vec4 Out_Color;\n
|
||||||
|
void main()\n
|
||||||
|
{\n
|
||||||
|
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
// Select shaders matching our GLSL versions
|
||||||
|
const (char)* vertex_shader = null;
|
||||||
|
const (char)* fragment_shader = null;
|
||||||
|
if (glsl_version < 130)
|
||||||
|
{
|
||||||
|
vertex_shader = vertex_shader_glsl_120;
|
||||||
|
fragment_shader = fragment_shader_glsl_120;
|
||||||
|
}
|
||||||
|
else if (glsl_version >= 410)
|
||||||
|
{
|
||||||
|
vertex_shader = vertex_shader_glsl_410_core;
|
||||||
|
fragment_shader = fragment_shader_glsl_410_core;
|
||||||
|
}
|
||||||
|
else if (glsl_version == 300)
|
||||||
|
{
|
||||||
|
vertex_shader = vertex_shader_glsl_300_es;
|
||||||
|
fragment_shader = fragment_shader_glsl_300_es;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertex_shader = vertex_shader_glsl_130;
|
||||||
|
fragment_shader = fragment_shader_glsl_130;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create shaders
|
||||||
|
const (char)*[2] vertex_shader_with_version = [ g_GlslVersionString.ptr, vertex_shader ];
|
||||||
|
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
glShaderSource(g_VertHandle, 2, vertex_shader_with_version.ptr, null);
|
||||||
|
glCompileShader(g_VertHandle);
|
||||||
|
CheckShader(g_VertHandle, "vertex shader");
|
||||||
|
|
||||||
|
const (char)*[2] fragment_shader_with_version = [ g_GlslVersionString.ptr, fragment_shader ];
|
||||||
|
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(g_FragHandle, 2, fragment_shader_with_version.ptr, null);
|
||||||
|
glCompileShader(g_FragHandle);
|
||||||
|
CheckShader(g_FragHandle, "fragment shader");
|
||||||
|
|
||||||
|
g_ShaderHandle = glCreateProgram();
|
||||||
|
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||||
|
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||||
|
glLinkProgram(g_ShaderHandle);
|
||||||
|
CheckProgram(g_ShaderHandle, "shader program");
|
||||||
|
|
||||||
|
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||||
|
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||||
|
g_AttribLocationVtxPos = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||||
|
g_AttribLocationVtxUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||||
|
g_AttribLocationVtxColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||||
|
|
||||||
|
// Create buffers
|
||||||
|
glGenBuffers(1, &g_VboHandle);
|
||||||
|
glGenBuffers(1, &g_ElementsHandle);
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||||
|
|
||||||
|
// Restore modified GL state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
|
// glBindVertexArray(last_vertex_array);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||||
|
{
|
||||||
|
if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; }
|
||||||
|
if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; }
|
||||||
|
if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); }
|
||||||
|
if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); }
|
||||||
|
if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; }
|
||||||
|
if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; }
|
||||||
|
if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; }
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckShader(GLuint handle, const char* desc)
|
||||||
|
{
|
||||||
|
GLint status = 0, log_length = 0;
|
||||||
|
glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
|
||||||
|
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
|
/*if (cast(GLboolean)status == GL_FALSE)
|
||||||
|
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);
|
||||||
|
if (log_length > 1)
|
||||||
|
{
|
||||||
|
ImVector<char> buf;
|
||||||
|
buf.resize(cast(int)(log_length + 1));
|
||||||
|
glGetShaderInfoLog(handle, log_length, null, cast(GLchar*)buf.begin());
|
||||||
|
fprintf(stderr, "%s\n", buf.begin());
|
||||||
|
}*/
|
||||||
|
return cast(GLboolean)status == GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you get an error please report on GitHub. You may try different GL context version or GLSL version.
|
||||||
|
static bool CheckProgram(GLuint handle, const char* desc)
|
||||||
|
{
|
||||||
|
GLint status = 0, log_length = 0;
|
||||||
|
glGetProgramiv(handle, GL_LINK_STATUS, &status);
|
||||||
|
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
|
/*if (cast(GLboolean)status == GL_FALSE)
|
||||||
|
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString);
|
||||||
|
if (log_length > 1)
|
||||||
|
{
|
||||||
|
ImVector<char> buf;
|
||||||
|
buf.resize(cast(int)(log_length + 1));
|
||||||
|
glGetProgramInfoLog(handle, log_length, null, cast(GLchar*)buf.begin());
|
||||||
|
fprintf(stderr, "%s\n", buf.begin());
|
||||||
|
}*/
|
||||||
|
return cast(GLboolean)status == GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
||||||
|
{
|
||||||
|
// Build texture atlas
|
||||||
|
ImGuiIO* io = igGetIO();
|
||||||
|
ubyte* pixels;
|
||||||
|
int width, height, bpp;
|
||||||
|
|
||||||
|
ImFontAtlas_GetTexDataAsRGBA32(io.Fonts,&pixels, &width, &height, &bpp);
|
||||||
|
//io.Fonts.GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||||
|
|
||||||
|
// Upload texture to graphics system
|
||||||
|
GLint last_texture;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGenTextures(1, &g_FontTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
// #ifdef GL_UNPACK_ROW_LENGTH
|
||||||
|
// glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
// #endif
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
|
||||||
|
// Store our identifier
|
||||||
|
io.Fonts.TexID = cast(ImTextureID)cast(sizediff_t)g_FontTexture;
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_DestroyFontsTexture()
|
||||||
|
{
|
||||||
|
if (g_FontTexture)
|
||||||
|
{
|
||||||
|
ImGuiIO* io = igGetIO();
|
||||||
|
glDeleteTextures(1, &g_FontTexture);
|
||||||
|
io.Fonts.TexID = null;
|
||||||
|
g_FontTexture = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
int fb_width = cast(int)(draw_data.DisplaySize.x * draw_data.FramebufferScale.x);
|
int fb_width = cast(int)(draw_data.DisplaySize.x * draw_data.FramebufferScale.x);
|
||||||
int fb_height = cast(int)(draw_data.DisplaySize.y * draw_data.FramebufferScale.y);
|
int fb_height = cast(int)(draw_data.DisplaySize.y * draw_data.FramebufferScale.y);
|
||||||
if (fb_width == 0 || fb_height == 0)
|
if (fb_width <= 0 || fb_height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Backup GL state
|
// Backup GL state
|
||||||
|
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, cast(GLint*)&last_active_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
GLint[2] last_polygon_mode; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode.ptr);
|
// #ifdef GL_SAMPLER_BINDING
|
||||||
|
// GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
||||||
|
// #endif
|
||||||
|
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
|
// GLint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object);
|
||||||
|
// #endif
|
||||||
|
// #ifdef GL_POLYGON_MODE
|
||||||
|
// GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||||
|
// #endif
|
||||||
GLint[4] last_viewport; glGetIntegerv(GL_VIEWPORT, last_viewport.ptr);
|
GLint[4] last_viewport; glGetIntegerv(GL_VIEWPORT, last_viewport.ptr);
|
||||||
GLint[4] last_scissor_box; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box.ptr);
|
GLint[4] last_scissor_box; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box.ptr);
|
||||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, cast(GLint*)&last_blend_src_rgb);
|
||||||
|
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, cast(GLint*)&last_blend_dst_rgb);
|
||||||
|
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, cast(GLint*)&last_blend_src_alpha);
|
||||||
|
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, cast(GLint*)&last_blend_dst_alpha);
|
||||||
|
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, cast(GLint*)&last_blend_equation_rgb);
|
||||||
|
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, cast(GLint*)&last_blend_equation_alpha);
|
||||||
|
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||||
|
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||||
|
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
// Setup desired GL state
|
// Setup desired GL state
|
||||||
ImGuiImplOpenGL2SetupRenderState(draw_data, fb_width, fb_height);
|
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
|
||||||
|
// The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
|
||||||
|
GLuint vertex_array_object = 0;
|
||||||
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
|
// glGenVertexArrays(1, &vertex_array_object);
|
||||||
|
// #endif
|
||||||
|
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||||
|
|
||||||
// Will project scissor/clipping rectangles into framebuffer space
|
// Will project scissor/clipping rectangles into framebuffer space
|
||||||
ImVec2 clip_off = draw_data.DisplayPos; // (0,0) unless using multi-viewports
|
ImVec2 clip_off = draw_data.DisplayPos; // (0,0) unless using multi-viewports
|
||||||
|
|
@ -401,23 +775,22 @@ void ImGuiImplOpenGL2RenderDrawData(ImDrawData* draw_data)
|
||||||
// Render command lists
|
// Render command lists
|
||||||
for (int n = 0; n < draw_data.CmdListsCount; n++)
|
for (int n = 0; n < draw_data.CmdListsCount; n++)
|
||||||
{
|
{
|
||||||
ImDrawList* cmd_list = draw_data.CmdLists[n];
|
const ImDrawList* cmd_list = draw_data.CmdLists[n];
|
||||||
ImDrawVert* vtx_buffer = cmd_list.VtxBuffer.Data;
|
|
||||||
ImDrawIdx* idx_buffer = cmd_list.IdxBuffer.Data;
|
// Upload vertex/index buffers
|
||||||
glVertexPointer(2, GL_FLOAT, ImDrawVert.sizeof, cast(const GLvoid*)(cast(const char*)vtx_buffer + ImDrawVert.pos.offsetof));
|
glBufferData(GL_ARRAY_BUFFER, cast(GLsizeiptr)cmd_list.VtxBuffer.Size * ImDrawVert.sizeof, cast(const GLvoid*)cmd_list.VtxBuffer.Data, GL_STREAM_DRAW);
|
||||||
glTexCoordPointer(2, GL_FLOAT, ImDrawVert.sizeof, cast(const GLvoid*)(cast(const char*)vtx_buffer + ImDrawVert.uv.offsetof));
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, cast(GLsizeiptr)cmd_list.IdxBuffer.Size * ImDrawIdx.sizeof, cast(const GLvoid*)cmd_list.IdxBuffer.Data, GL_STREAM_DRAW);
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, ImDrawVert.sizeof, cast(const GLvoid*)(cast(const char*)vtx_buffer + ImDrawVert.col.offsetof));
|
|
||||||
|
|
||||||
for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
|
for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
|
||||||
{
|
{
|
||||||
const ImDrawCmd* pcmd = &cmd_list.CmdBuffer.Data[cmd_i];
|
const ImDrawCmd* pcmd = &cmd_list.CmdBuffer.Data[cmd_i];
|
||||||
if (pcmd.UserCallback)
|
if (pcmd.UserCallback != null)
|
||||||
{
|
{
|
||||||
// User callback, registered via ImDrawList::AddCallback()
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||||
/*if (pcmd.UserCallback == &ImDrawCallback_ResetRenderState)
|
// if (pcmd.UserCallback == ImDrawCallback_ResetRenderState)
|
||||||
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
|
// ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||||
else*/
|
// else
|
||||||
pcmd.UserCallback(cmd_list, pcmd);
|
pcmd.UserCallback(cmd_list, pcmd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -435,74 +808,43 @@ void ImGuiImplOpenGL2RenderDrawData(ImDrawData* draw_data)
|
||||||
glScissor(cast(int)clip_rect.x, cast(int)(fb_height - clip_rect.w), cast(int)(clip_rect.z - clip_rect.x), cast(int)(clip_rect.w - clip_rect.y));
|
glScissor(cast(int)clip_rect.x, cast(int)(fb_height - clip_rect.w), cast(int)(clip_rect.z - clip_rect.x), cast(int)(clip_rect.w - clip_rect.y));
|
||||||
|
|
||||||
// Bind texture, Draw
|
// Bind texture, Draw
|
||||||
glBindTexture(GL_TEXTURE_2D, cast(GLuint)pcmd.TextureId);
|
glBindTexture(GL_TEXTURE_2D, cast(GLuint)cast(sizediff_t)pcmd.TextureId);
|
||||||
glDrawElements(GL_TRIANGLES, cast(GLsizei)pcmd.ElemCount, ImDrawIdx.sizeof == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
// #if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||||
|
// if (g_GlVersion >= 320)
|
||||||
|
// glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd.ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd.IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd.VtxOffset);
|
||||||
|
// else
|
||||||
|
// #endif
|
||||||
|
glDrawElements(GL_TRIANGLES, cast(GLsizei)pcmd.ElemCount, ImDrawIdx.sizeof == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, cast(void*)cast(sizediff_t)(pcmd.IdxOffset * ImDrawIdx.sizeof));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx_buffer += pcmd.ElemCount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy the temporary VAO
|
||||||
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
|
// glDeleteVertexArrays(1, &vertex_array_object);
|
||||||
|
// #endif
|
||||||
|
|
||||||
// Restore modified GL state
|
// Restore modified GL state
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
glUseProgram(last_program);
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
// #ifdef GL_SAMPLER_BINDING
|
||||||
glBindTexture(GL_TEXTURE_2D, cast(GLuint)last_texture);
|
// glBindSampler(0, last_sampler);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
// #endif
|
||||||
glPopMatrix();
|
glActiveTexture(last_active_texture);
|
||||||
glMatrixMode(GL_PROJECTION);
|
// #ifndef IMGUI_IMPL_OPENGL_ES2
|
||||||
glPopMatrix();
|
// glBindVertexArray(last_vertex_array_object);
|
||||||
glPopAttrib();
|
// #endif
|
||||||
glPolygonMode(GL_FRONT, cast(GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, cast(GLenum)last_polygon_mode[1]);
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
||||||
|
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
||||||
|
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
||||||
|
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
||||||
|
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||||
|
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||||
|
// #ifdef GL_POLYGON_MODE
|
||||||
|
// glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
||||||
|
// #endif
|
||||||
glViewport(last_viewport[0], last_viewport[1], cast(GLsizei)last_viewport[2], cast(GLsizei)last_viewport[3]);
|
glViewport(last_viewport[0], last_viewport[1], cast(GLsizei)last_viewport[2], cast(GLsizei)last_viewport[3]);
|
||||||
glScissor(last_scissor_box[0], last_scissor_box[1], cast(GLsizei)last_scissor_box[2], cast(GLsizei)last_scissor_box[3]);
|
glScissor(last_scissor_box[0], last_scissor_box[1], cast(GLsizei)last_scissor_box[2], cast(GLsizei)last_scissor_box[3]);
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiImplOpenGL2CreateFontsTexture()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO* io = igGetIO();
|
|
||||||
ubyte* pixels;
|
|
||||||
int width, height;
|
|
||||||
int bpp;
|
|
||||||
ImFontAtlas_GetTexDataAsRGBA32(io.Fonts, &pixels, &width, &height, &bpp); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
|
||||||
GLint last_texture;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &g_FontTexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
||||||
|
|
||||||
// Store our identifier
|
|
||||||
io.Fonts.TexID = cast(ImTextureID)g_FontTexture;
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiImplOpenGL2DestroyFontsTexture()
|
|
||||||
{
|
|
||||||
if (g_FontTexture)
|
|
||||||
{
|
|
||||||
ImGuiIO* io = igGetIO();
|
|
||||||
glDeleteTextures(1, &g_FontTexture);
|
|
||||||
io.Fonts.TexID = null;
|
|
||||||
g_FontTexture = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiImplOpenGL2CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
return ImGuiImplOpenGL2CreateFontsTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiImplOpenGL2DestroyDeviceObjects()
|
|
||||||
{
|
|
||||||
ImGuiImplOpenGL2DestroyFontsTexture();
|
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +58,15 @@ version(D_BetterC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(Android)
|
||||||
|
{
|
||||||
|
alias pthread_key_t = uint;
|
||||||
|
|
||||||
|
extern (C) int pthread_key_create(pthread_key_t *, void* function(void *)) @nogc nothrow;
|
||||||
|
extern (C) int pthread_key_delete(pthread_key_t) @nogc nothrow;
|
||||||
|
extern (C) void* pthread_getspecific(pthread_key_t) @nogc nothrow;
|
||||||
|
extern (C) int pthread_setspecific(pthread_key_t, const void *) @nogc nothrow;
|
||||||
|
}
|
||||||
|
|
||||||
version(WebAssembly)
|
version(WebAssembly)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
35
meson.build
35
meson.build
|
|
@ -23,6 +23,8 @@ tests_src = [
|
||||||
]
|
]
|
||||||
|
|
||||||
betterC_opt = get_option('betterC')
|
betterC_opt = get_option('betterC')
|
||||||
|
BuildDemos_opt = get_option('BuildDemos')
|
||||||
|
LTO_otp = get_option('LTO')
|
||||||
|
|
||||||
comp = meson.get_compiler('d')
|
comp = meson.get_compiler('d')
|
||||||
|
|
||||||
|
|
@ -31,16 +33,41 @@ comp_id = comp.get_id()
|
||||||
args = []
|
args = []
|
||||||
link_args = []
|
link_args = []
|
||||||
|
|
||||||
|
if comp_id == 'gcc'
|
||||||
|
args += '-pthread'
|
||||||
|
link_args += '-pthread'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if LTO_otp
|
||||||
|
if comp_id == 'gcc'
|
||||||
|
args += '-flto'
|
||||||
|
link_args += '-flto'
|
||||||
|
elif comp_id == 'llvm'
|
||||||
|
args += '-flto=thin'
|
||||||
|
link_args += '-flto=thin'
|
||||||
|
else
|
||||||
|
message('LTO don\'t work with DMD')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
if betterC_opt
|
if betterC_opt
|
||||||
args += '-betterC'
|
if comp_id == 'gcc'
|
||||||
link_args += '-betterC'
|
args += ['-flto','-fno-druntime']
|
||||||
|
link_args += ['-flto','-fno-druntime']
|
||||||
|
else
|
||||||
|
args += '-betterC'
|
||||||
|
link_args += '-betterC'
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
inc = include_directories('source/')
|
inc = include_directories('source/')
|
||||||
tests_inc = include_directories('source/')
|
tests_inc = include_directories('source/')
|
||||||
|
|
||||||
ecs_lib = shared_library('ecs', src, include_directories : [tests_inc, inc], d_args: args, link_args: link_args)
|
ecs_lib = library('ecs', src, include_directories : [tests_inc, inc], d_args: args, link_args: link_args)
|
||||||
|
|
||||||
executable('tests', tests_src, include_directories : [tests_inc, inc], d_args: args, link_args: link_args, link_with: ecs_lib)
|
executable('tests', tests_src, include_directories : [tests_inc, inc], d_args: args, link_args: link_args, link_with: ecs_lib)
|
||||||
|
|
||||||
|
if BuildDemos_opt
|
||||||
|
subdir('demos/utils')
|
||||||
|
subdir('demos')
|
||||||
|
endif
|
||||||
|
|
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
option('betterC', type: 'boolean', value: false)
|
option('betterC', type: 'boolean', value: false)
|
||||||
|
option('BuildDemos', type: 'boolean', value: false)
|
||||||
|
option('LTO', type: 'boolean', value: false)
|
||||||
|
|
@ -15,7 +15,7 @@ struct IDManager
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
Get new ID.
|
Get new ID.
|
||||||
*/
|
*/
|
||||||
pragma(inline, false) EntityID getNewID() nothrow @nogc
|
EntityID getNewID() nothrow @nogc
|
||||||
{
|
{
|
||||||
int current = m_stack_top.atomicOp!"-="(1) + 1;
|
int current = m_stack_top.atomicOp!"-="(1) + 1;
|
||||||
if (current < 0)
|
if (current < 0)
|
||||||
|
|
|
||||||
|
|
@ -906,7 +906,8 @@ export struct EntityManager
|
||||||
input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
|
input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
|
||||||
}//*/
|
}//*/
|
||||||
|
|
||||||
static foreach (iii, comp_info; components_info.req)
|
///FIXME: should be "components_info.req()" but it's not compile with GCC
|
||||||
|
static foreach (iii, comp_info; components_info.m_req[0 .. components_info.m_req_counter])
|
||||||
{
|
{
|
||||||
__traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
|
__traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
|
||||||
Sys.EntitiesData, comp_info.name)))*)(
|
Sys.EntitiesData, comp_info.name)))*)(
|
||||||
|
|
@ -914,7 +915,7 @@ export struct EntityManager
|
||||||
.. entities_count];
|
.. entities_count];
|
||||||
}
|
}
|
||||||
|
|
||||||
static foreach (iii, comp_info; components_info.optional)
|
static foreach (iii, comp_info; components_info.m_optional[0 .. components_info.m_optional_counter])
|
||||||
{
|
{
|
||||||
if (system.m_optional_components[iii] < info.deltas.length
|
if (system.m_optional_components[iii] < info.deltas.length
|
||||||
&& info.deltas[system.m_optional_components[iii]] != 0)
|
&& info.deltas[system.m_optional_components[iii]] != 0)
|
||||||
|
|
@ -1344,9 +1345,9 @@ export struct EntityManager
|
||||||
"Can't call function with system which hasn't EntitesData structure.");
|
"Can't call function with system which hasn't EntitesData structure.");
|
||||||
static assert(__traits(hasMember, Sys, "onUpdate"),
|
static assert(__traits(hasMember, Sys, "onUpdate"),
|
||||||
"Can't call function with system which hasn't onUpdate function callback.");
|
"Can't call function with system which hasn't onUpdate function callback.");
|
||||||
static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate),
|
// static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate),
|
||||||
functionAttributes!(s.onUpdate)) == typeof(&s.onUpdate)),
|
// functionAttributes!(s.onUpdate)) == typeof(&s.onUpdate)),
|
||||||
"Function must match system update function.");
|
// "Function must match system update function."); FIXME: It's lead to crash on android build
|
||||||
static assert(__traits(hasMember, Sys, "system_id"), "Sys must be system type.");
|
static assert(__traits(hasMember, Sys, "system_id"), "Sys must be system type.");
|
||||||
|
|
||||||
System* system = getSystem(Sys.system_id);
|
System* system = getSystem(Sys.system_id);
|
||||||
|
|
@ -3105,7 +3106,7 @@ export struct EntityManager
|
||||||
// has_work |= removeEntities();
|
// has_work |= removeEntities();
|
||||||
has_work |= updateEvents();
|
has_work |= updateEvents();
|
||||||
|
|
||||||
//id_manager.optimize();
|
id_manager.optimize();
|
||||||
has_work |= updateBlocks();
|
has_work |= updateBlocks();
|
||||||
has_work |= changeEntities();
|
has_work |= changeEntities();
|
||||||
has_work |= removeEntities();
|
has_work |= removeEntities();
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ else version (D_BetterC)
|
||||||
{
|
{
|
||||||
private const uint max_alloca = 10000;
|
private const uint max_alloca = 10000;
|
||||||
private __gshared byte[max_alloca] alloca_array;
|
private __gshared byte[max_alloca] alloca_array;
|
||||||
private uint alloca_pos = 0;
|
private __gshared uint alloca_pos = 0;
|
||||||
export extern (C) void* __alloca(size_t length) @nogc nothrow
|
export extern (C) void* __alloca(size_t length) @nogc nothrow
|
||||||
{
|
{
|
||||||
if (alloca_pos + length > max_alloca)
|
if (alloca_pos + length > max_alloca)
|
||||||
|
|
@ -158,7 +158,32 @@ static struct Mallocator
|
||||||
|
|
||||||
static if (__traits(isPOD, T))
|
static if (__traits(isPOD, T))
|
||||||
{
|
{
|
||||||
static immutable T init = T.init;
|
__gshared immutable T init = T.init;
|
||||||
|
|
||||||
|
foreach (i; 0 .. ret.length)
|
||||||
|
{
|
||||||
|
memcpy(&ret[i], &init, T.sizeof);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static import std.conv;
|
||||||
|
|
||||||
|
foreach (i; 0 .. ret.length)
|
||||||
|
{
|
||||||
|
std.conv.emplace(&ret[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static T[] alignMakeArray(T)(size_t length, size_t alignment) nothrow @nogc
|
||||||
|
{
|
||||||
|
T[] ret = (cast(T*) alignAlloc(T.sizeof * length, alignment))[0 .. length];
|
||||||
|
|
||||||
|
static if (__traits(isPOD, T))
|
||||||
|
{
|
||||||
|
__gshared immutable T init = T.init;
|
||||||
|
|
||||||
foreach (i; 0 .. ret.length)
|
foreach (i; 0 .. ret.length)
|
||||||
{
|
{
|
||||||
|
|
@ -206,7 +231,7 @@ static struct Mallocator
|
||||||
|
|
||||||
static if (__traits(isPOD, T))
|
static if (__traits(isPOD, T))
|
||||||
{
|
{
|
||||||
static immutable T init = T.init;
|
__gshared immutable T init = T.init;
|
||||||
memcpy(ret, &init, T.sizeof);
|
memcpy(ret, &init, T.sizeof);
|
||||||
}
|
}
|
||||||
else static if (is(T == struct))
|
else static if (is(T == struct))
|
||||||
|
|
|
||||||
111
tests/tests.d
111
tests/tests.d
|
|
@ -93,6 +93,13 @@ struct TestEvent2
|
||||||
float a;
|
float a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct CPosition
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
}
|
||||||
|
|
||||||
static struct TestComp
|
static struct TestComp
|
||||||
{
|
{
|
||||||
mixin ECS.Component; //__gshared ushort component_id;
|
mixin ECS.Component; //__gshared ushort component_id;
|
||||||
|
|
@ -186,6 +193,52 @@ static struct TestComp5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EverySystem
|
||||||
|
{
|
||||||
|
mixin ECS.System;
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
uint length;
|
||||||
|
Entity[] entity;
|
||||||
|
CPosition[] pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i;0..data.length)
|
||||||
|
{
|
||||||
|
data.pos[i].x++;
|
||||||
|
data.pos[i].y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iterate(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i;0..data.length)
|
||||||
|
{
|
||||||
|
data.pos[i].x++;
|
||||||
|
data.pos[i].y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i;0..data.length)
|
||||||
|
{
|
||||||
|
gEM.removeEntity(data.entity[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addOne(EntitiesData data)
|
||||||
|
{
|
||||||
|
foreach(i;0..data.length)
|
||||||
|
{
|
||||||
|
gEM.addComponents(data.entity[i].id, TestComp2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ChangeTestSystem
|
struct ChangeTestSystem
|
||||||
{
|
{
|
||||||
mixin ECS.System!16; //__gshared ushort system_id;
|
mixin ECS.System!16; //__gshared ushort system_id;
|
||||||
|
|
@ -648,6 +701,7 @@ else:
|
||||||
gEM.registerComponent!TestComp;
|
gEM.registerComponent!TestComp;
|
||||||
gEM.registerComponent!TestComp3;
|
gEM.registerComponent!TestComp3;
|
||||||
gEM.registerComponent!TestComp5;
|
gEM.registerComponent!TestComp5;
|
||||||
|
gEM.registerComponent!CPosition;
|
||||||
|
|
||||||
gEM.registerEvent!TestEvent;
|
gEM.registerEvent!TestEvent;
|
||||||
gEM.registerEvent!TestEvent2;
|
gEM.registerEvent!TestEvent2;
|
||||||
|
|
@ -669,6 +723,7 @@ else:
|
||||||
gEM.registerSystem!EmptySystem(2);
|
gEM.registerSystem!EmptySystem(2);
|
||||||
gEM.registerSystem!EmptyEventSystem(2);
|
gEM.registerSystem!EmptyEventSystem(2);
|
||||||
gEM.registerSystem!EventSystem(2);
|
gEM.registerSystem!EventSystem(2);
|
||||||
|
gEM.registerSystem!EverySystem(0);
|
||||||
//gEM.registerSystem!TestSystemWithHighPriority(100);
|
//gEM.registerSystem!TestSystemWithHighPriority(100);
|
||||||
//gEM.registerSystem!TestSystem2(0);
|
//gEM.registerSystem!TestSystem2(0);
|
||||||
gEM.endRegister();
|
gEM.endRegister();
|
||||||
|
|
@ -693,6 +748,62 @@ else:
|
||||||
//dur = (MonoTime.currTime - time).total!"usecs";
|
//dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
//writeln("Template allocating: ", dur, " usecs");
|
//writeln("Template allocating: ", dur, " usecs");
|
||||||
printf("Template allocating: %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
printf("Template allocating: %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
|
||||||
|
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
ushort[1] empty_ids = [CPosition.component_id];
|
||||||
|
EntityTemplate* tmpl_empty = gEM.allocateTemplate(empty_ids);
|
||||||
|
|
||||||
|
gEM.commit();
|
||||||
|
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
|
||||||
|
foreach(i;0..4_000_000)gEM.addEntity(tmpl_empty);
|
||||||
|
gEM.commit();
|
||||||
|
foreach(i;0..4_000_000)gEM.addEntity(tmpl_empty);
|
||||||
|
gEM.commit();
|
||||||
|
foreach(i;0..2_000_000)gEM.addEntity(tmpl_empty);
|
||||||
|
gEM.commit();
|
||||||
|
|
||||||
|
printf("Adding 1M entities: %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
|
||||||
|
gEM.commit();
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
gEM.callEntitiesFunction!EverySystem(&gEM.getSystem!EverySystem().iterate);
|
||||||
|
printf("Iterate 1M entities: %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
|
||||||
|
gEM.begin();
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
gEM.update();
|
||||||
|
printf("Iterate 1M entities (update): %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
gEM.end();
|
||||||
|
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
gEM.callEntitiesFunction!EverySystem(&gEM.getSystem!EverySystem().free);
|
||||||
|
gEM.commit();
|
||||||
|
printf("Deleting 1M entities: %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
|
||||||
|
foreach(i;0..4_000_000)gEM.addEntity(tmpl_empty);
|
||||||
|
gEM.commit();
|
||||||
|
foreach(i;0..4_000_000)gEM.addEntity(tmpl_empty);
|
||||||
|
gEM.commit();
|
||||||
|
foreach(i;0..2_000_000)gEM.addEntity(tmpl_empty);
|
||||||
|
gEM.commit();
|
||||||
|
|
||||||
|
printf("Adding 1M entities (prealloc): %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
|
||||||
|
gEM.commit();
|
||||||
|
time = Time.getUSecTime();
|
||||||
|
gEM.callEntitiesFunction!EverySystem(&gEM.getSystem!EverySystem().addOne);
|
||||||
|
gEM.commit();
|
||||||
|
printf("Adding 1M component: %f usecs\n", cast(float)(Time.getUSecTime() - time));
|
||||||
|
|
||||||
|
gEM.commit();
|
||||||
|
gEM.callEntitiesFunction!EverySystem(&gEM.getSystem!EverySystem().free);
|
||||||
|
gEM.commit();
|
||||||
|
|
||||||
time = Time.getUSecTime();
|
time = Time.getUSecTime();
|
||||||
|
|
||||||
EntityID entity;
|
EntityID entity;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue