From 56087c6cbae641dbbf83188e44adc899cd79b285 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 28 Aug 2025 00:50:15 +0100 Subject: [PATCH 01/76] Remove redundant file dialog string conversions No need to iterate through the whole string to find the length, just to see if it is empty. --- project/include/ui/FileDialog.h | 30 +++- project/src/ExternalInterface.cpp | 222 ++++++------------------- project/src/ui/FileDialog.cpp | 266 +++++++----------------------- 3 files changed, 133 insertions(+), 385 deletions(-) diff --git a/project/include/ui/FileDialog.h b/project/include/ui/FileDialog.h index 4a310b3198..cb96863ee4 100644 --- a/project/include/ui/FileDialog.h +++ b/project/include/ui/FileDialog.h @@ -13,10 +13,30 @@ namespace lime { public: - static std::wstring* OpenDirectory (std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); - static std::wstring* OpenFile (std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); - static void OpenFiles (std::vector* files, std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); - static std::wstring* SaveFile (std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); +#ifdef HX_WINDOWS + using char_t = wchar_t; +#else + using char_t = char; +#endif + + static const char_t* OpenDirectory(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); + static const char_t* OpenFile(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); + + // Use actual string view once we can use c++17 + class string_view { + public: + string_view(const char_t* c_str, size_t length) : c_str(c_str), length(length) {} + + const char_t* data() const { return c_str; } + const size_t size() const { return length; } + + private: + const char_t* c_str; + size_t length; + }; + + static std::vector OpenFiles(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); + static const char_t* SaveFile(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); }; @@ -24,4 +44,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 1718f4aa00..c5f7e2d36c 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -203,66 +203,51 @@ namespace lime { } - std::wstring* hxstring_to_wstring (HxString val) { - - if (val.c_str ()) { - - #ifdef HX_WINDOWS - return new std::wstring (hxs_wchar (val, nullptr)); - #else - const std::string _val (hxs_utf8 (val, nullptr)); - return new std::wstring (_val.begin (), _val.end ()); - #endif - - } else { - - return 0; - - } - - } - - - std::wstring* hxstring_to_wstring (hl_vstring* val) { + #ifdef HX_WINDOWS + #define hxs_to_fd_str(str) hxs_wchar(str, nullptr) + #define alloc_from_fd_str(str) alloc_wstring(str) + #define alloc_from_fd_str_len(str, len) alloc_wstring_len(str, len) + static const FileDialog::char_t* hl_vstring_to_fd_str (hl_vstring* val) { if (val) { - - std::string _val = std::string (hl_to_utf8 (val->bytes)); - #ifdef HX_WINDOWS - std::wstring_convert> converter; - return new std::wstring (converter.from_bytes (_val)); - #else - return new std::wstring (_val.begin (), _val.end ()); - #endif - - } else { - - return 0; - + return val->bytes; } + return nullptr; + } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src, size_t length) { + // copy first, since hl_to_utf8 has no length parameter, and hl_utf16_to_utf8 is not exposed + FileDialog::char_t* utf16 = (FileDialog::char_t*)hl_copy_bytes((vbyte*)src, (length + 1) * sizeof(FileDialog::char_t)); + utf16[length] = L'\0'; + return (vbyte*)hl_to_utf8(utf16); } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src) { + return (vbyte*)hl_to_utf8((uchar*)src); + } - value wstring_to_value (std::wstring* val) { + #else + #define hxs_to_fd_str(str) hxs_utf8(str, nullptr) + #define alloc_from_fd_str(str) alloc_string(str) + #define alloc_from_fd_str_len(str, len) alloc_string_len(str, len) + static const FileDialog::char_t* hl_vstring_to_fd_str (hl_vstring* val) { if (val) { - - #ifdef HX_WINDOWS - return alloc_wstring (val->c_str ()); - #else - std::string _val = std::string (val->begin (), val->end ()); - return alloc_string (_val.c_str ()); - #endif - - } else { - - return 0; - + return hl_to_utf8 (val->bytes); } + return nullptr; + } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src, size_t length) { + vbyte* result = hl_copy_bytes((vbyte*)src, length + 1); + result[length] = '\0'; + return result; } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src) { + return hl_fd_str_to_utf8_bytes(src, std::strlen(src)); + } + #endif value lime_application_create () { @@ -764,25 +749,11 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const FileDialog::char_t* path = FileDialog::OpenDirectory (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); if (path) { - value _path = wstring_to_value (path); - delete path; - return _path; - - } else { - - return alloc_null (); + return alloc_from_fd_str (path); } @@ -797,25 +768,11 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const FileDialog::char_t* path = FileDialog::OpenDirectory (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); if (path) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; - - } else { - - return NULL; + return hl_fd_str_to_utf8_bytes(path); } @@ -830,25 +787,11 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const FileDialog::char_t* path = FileDialog::OpenFile (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); if (path) { - value _path = wstring_to_value (path); - delete path; - return _path; - - } else { - - return alloc_null (); + return alloc_from_fd_str (path); } @@ -863,25 +806,11 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const FileDialog::char_t* path = FileDialog::OpenFile (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); if (path) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; - - } else { - - return NULL; + return hl_fd_str_to_utf8_bytes (path); } @@ -896,24 +825,15 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::vector files; - - FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); + auto files = FileDialog::OpenFiles (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); value result = alloc_array (files.size ()); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - for (int i = 0; i < files.size (); i++) { - value _file = wstring_to_value (files[i]); - val_array_set_i (result, i, _file); - delete files[i]; + auto file_str = files[i]; + + value file = alloc_from_fd_str_len (file_str.data(), file_str.size()); + val_array_set_i (result, i, file); } @@ -930,24 +850,14 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::vector files; - - FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); + auto files = FileDialog::OpenFiles (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, files.size ()); vbyte** resultData = hl_aptr (result, vbyte*); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - for (int i = 0; i < files.size (); i++) { - *resultData++ = hl_wstring_to_utf8_bytes (*files[i]); - delete files[i]; + auto file_str = files[i]; + *resultData++ = hl_fd_str_to_utf8_bytes (file_str.data(), file_str.size()); } @@ -964,25 +874,11 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const FileDialog::char_t* path = FileDialog::SaveFile (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); if (path) { - value _path = wstring_to_value (path); - delete path; - return _path; - - } else { - - return alloc_null (); + return alloc_from_fd_str (path); } @@ -997,25 +893,11 @@ namespace lime { #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const FileDialog::char_t* path = FileDialog::SaveFile (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); if (path) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; - - } else { - - return NULL; + return hl_fd_str_to_utf8_bytes (path); } diff --git a/project/src/ui/FileDialog.cpp b/project/src/ui/FileDialog.cpp index b4ce57fdd1..b740102696 100644 --- a/project/src/ui/FileDialog.cpp +++ b/project/src/ui/FileDialog.cpp @@ -6,298 +6,144 @@ #include +#ifdef HX_WINDOWS +#define tinyfd_selectFolderDialog tinyfd_selectFolderDialogW +#define tinyfd_openFileDialog tinyfd_openFileDialogW +#define tinyfd_saveFileDialog tinyfd_saveFileDialogW -namespace lime { - - - std::string* wstring_to_string (std::wstring* source) { +#define FD_STR(str) L##str +#else +#define FD_STR(str) str +#endif - if (!source) return NULL; +using char_t = lime::FileDialog::char_t; +using string_t = std::basic_string; - int size = std::wcslen (source->c_str ()); - char* temp = (char*)malloc (size + 1); - std::wcstombs (temp, source->c_str (), size); - temp[size] = '\0'; - - std::string* data = new std::string (temp); - free (temp); - return data; +namespace lime { + static bool is_null_or_empty (const char_t* str) { + return str == nullptr || str[0] == 0; } - - std::wstring* FileDialog::OpenDirectory (std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { + const char_t* FileDialog::OpenDirectory (const char_t* title, const char_t* filter, const char_t* defaultPath) { // TODO: Filter? - #ifdef HX_WINDOWS - - const wchar_t* path = tinyfd_selectFolderDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0); - - if (path && std::wcslen(path) > 0) { - - std::wstring* _path = new std::wstring (path); - return _path; - - } - - #else - - std::string* _title = wstring_to_string (title); - //std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); - - const char* path = tinyfd_selectFolderDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL); - - if (_title) delete _title; - //if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const char_t* path = tinyfd_selectFolderDialog(title, defaultPath); - if (path && std::strlen(path) > 0) { + if (!is_null_or_empty(path)) { - std::string _path = std::string (path); - std::wstring* __path = new std::wstring (_path.begin (), _path.end ()); - return __path; + return path; } - #endif - return 0; } - std::wstring* FileDialog::OpenFile (std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { - - #ifdef HX_WINDOWS + const char_t* FileDialog::OpenFile (const char_t* title, const char_t* filter, const char_t* defaultPath) { - std::vector filters_vec; + std::vector filters_vec; if (filter) { - std::wstring temp (L"*."); - std::wstring line; - std::wstringstream ss(*filter); - while(std::getline(ss, line, L',')) { + string_t temp(FD_STR("*.")); + string_t line; + std::basic_stringstream ss(filter); + while(std::getline(ss, line, FD_STR(','))) { filters_vec.push_back(temp + line); } } const int numFilters = filter ? filters_vec.size() : 1; - const wchar_t **filters = new const wchar_t*[numFilters]; + const char_t **filters = new const char_t*[numFilters]; if (filter && numFilters > 0) { for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + filters[index] = const_cast(filters_vec[index].c_str()); } } else { filters[0] = NULL; } - const wchar_t* path = tinyfd_openFileDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0, filter ? numFilters : 0, filter ? filters : NULL, NULL, 0); + const char_t* path = tinyfd_openFileDialog (title, defaultPath, filter ? numFilters : 0, filter ? filters : NULL, NULL, 0); delete[] filters; - if (path && std::wcslen(path) > 0) { + if (!is_null_or_empty(path)) { - std::wstring* _path = new std::wstring (path); - return _path; + return path; } - #else - - std::string* _title = wstring_to_string (title); - std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); - - std::vector filters_vec; - if (_filter) { - std::string line; - std::stringstream ss(*_filter); - while(std::getline(ss, line, ',')) { - line.insert (0, "*."); - filters_vec.push_back(line); - } - } - - const int numFilters = _filter ? filters_vec.size() : 1; - const char **filters = new const char*[numFilters]; - if (_filter && numFilters > 0) { - for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); - } - } else { - filters[0] = NULL; - } - - const char* path = tinyfd_openFileDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL, _filter ? numFilters : 0, _filter ? filters : NULL, NULL, 0); - - delete[] filters; - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - - if (path && std::strlen(path) > 0) { - - std::string _path = std::string (path); - std::wstring* __path = new std::wstring (_path.begin (), _path.end ()); - return __path; - - } - - #endif - return 0; } - void FileDialog::OpenFiles (std::vector* files, std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { - - std::wstring* __paths = 0; - - #ifdef HX_WINDOWS + std::vector FileDialog::OpenFiles (const char_t* title, const char_t* filter, const char_t* defaultPath) { + std::vector files; - std::vector filters_vec; + std::vector filters_vec; if (filter) { - std::wstring temp (L"*."); - std::wstring line; - std::wstringstream ss(*filter); - while(std::getline(ss, line, L',')) { + string_t temp(FD_STR("*.")); + string_t line; + std::basic_stringstream ss(filter); + while(std::getline(ss, line, FD_STR(','))) { filters_vec.push_back(temp + line); } } const int numFilters = filter ? filters_vec.size() : 1; - const wchar_t **filters = new const wchar_t*[numFilters]; + const char_t **filters = new const char_t*[numFilters]; if (filter && numFilters > 0) { for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + filters[index] = const_cast(filters_vec[index].c_str()); } } else { filters[0] = NULL; } - const wchar_t* paths = tinyfd_openFileDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0, filter ? numFilters : 0, filter ? filters : NULL, NULL, 1); + const char_t* paths = tinyfd_openFileDialog (title, defaultPath, filter ? numFilters : 0, filter ? filters : NULL, NULL, 1); delete[] filters; - if (paths) { + if (!is_null_or_empty(paths)) { - __paths = new std::wstring (paths); + char_t sep = FD_STR('|'); - } - - #else - - std::string* _title = wstring_to_string (title); - std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); + const char_t* start = paths, + * cur = paths; - std::vector filters_vec; - if (_filter) { - std::string line; - std::stringstream ss(*_filter); - while(std::getline(ss, line, ',')) { - line.insert (0, "*."); - filters_vec.push_back(line); - } - } + while (*cur) { + if (*cur == sep) { + files.emplace_back(start, cur - start); + start = cur + 1; + } - const int numFilters = _filter ? filters_vec.size() : 1; - const char **filters = new const char*[numFilters]; - if (_filter && numFilters > 0) { - for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + cur++; } - } else { - filters[0] = NULL; - } - - const char* paths = tinyfd_openFileDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL, _filter ? numFilters : 0, _filter ? filters : NULL, NULL, 1); - delete[] filters; - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - - if (paths) { - - std::string _paths = std::string (paths); - __paths = new std::wstring (_paths.begin (), _paths.end ()); + files.emplace_back(start, cur - start); } - #endif - - if (__paths) { - - std::wstring sep = L"|"; - - std::size_t start = 0, end = 0; - - while ((end = __paths->find (sep, start)) != std::wstring::npos) { - - files->push_back (new std::wstring (__paths->substr (start, end - start).c_str ())); - start = end + 1; - - } - - files->push_back (new std::wstring (__paths->substr (start).c_str ())); - - } + return files; } - std::wstring* FileDialog::SaveFile (std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { - - #ifdef HX_WINDOWS + const char_t* FileDialog::SaveFile (const char_t* title, const char_t* filter, const char_t* defaultPath) { - std::wstring temp (L"*."); - const wchar_t* filters[] = { filter ? (temp + *filter).c_str () : NULL }; + string_t temp(FD_STR("*.")); + const char_t* filters[] = { filter ? (temp + *filter).c_str () : NULL }; - const wchar_t* path = tinyfd_saveFileDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0, filter ? 1 : 0, filter ? filters : NULL, NULL); + const char_t* path = tinyfd_saveFileDialog (title, defaultPath, filter ? 1 : 0, filter ? filters : NULL, NULL); - if (path && std::wcslen(path) > 0) { + if (!is_null_or_empty(path)) { - std::wstring* _path = new std::wstring (path); - return _path; + return path; } - #else - - std::string* _title = wstring_to_string (title); - std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); - - const char* filters[] = { NULL }; - - if (_filter) { - - _filter->insert (0, "*."); - filters[0] = _filter->c_str (); - - } - - const char* path = tinyfd_saveFileDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL, _filter ? 1 : 0, _filter ? filters : NULL, NULL); - - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - - if (path && std::strlen(path) > 0) { - - std::string _path = std::string (path); - std::wstring* __path = new std::wstring (_path.begin (), _path.end ()); - return __path; - - } - - #endif - return 0; } From 4613c72d2172f9fbb0cd505c6c1c81b7047a23e2 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Sat, 20 Dec 2025 02:06:21 +0000 Subject: [PATCH 02/76] Add comment about file dialog string ownership --- project/include/ui/FileDialog.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/project/include/ui/FileDialog.h b/project/include/ui/FileDialog.h index cb96863ee4..aa087a0b67 100644 --- a/project/include/ui/FileDialog.h +++ b/project/include/ui/FileDialog.h @@ -9,6 +9,8 @@ namespace lime { + // Functions in this class return pointers to externally owned memory, which will be reused automatically + // for future dialogs and should not be freed. class FileDialog { public: From 918ca9f5676db25f2792ee728837baefbd91cf8b Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Mon, 12 Jan 2026 13:45:35 +0000 Subject: [PATCH 03/76] Remove unneeded const --- project/include/ui/FileDialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/include/ui/FileDialog.h b/project/include/ui/FileDialog.h index aa087a0b67..1adf918f7b 100644 --- a/project/include/ui/FileDialog.h +++ b/project/include/ui/FileDialog.h @@ -30,7 +30,7 @@ namespace lime { string_view(const char_t* c_str, size_t length) : c_str(c_str), length(length) {} const char_t* data() const { return c_str; } - const size_t size() const { return length; } + size_t size() const { return length; } private: const char_t* c_str; From 20b47866c3c19ccd105634b8681dc54dfd7544b0 Mon Sep 17 00:00:00 2001 From: Joseph Cloutier Date: Thu, 14 May 2026 16:37:43 -0400 Subject: [PATCH 04/76] Fix asset embedding regression. Originally, this check happened _in addition to_ copying the asset to `targetPath`. I incorrectly made it run instead, which would mean the asset never got copied. The copy seems to be mostly redundant, but having a valid `sourcePath` means `getAssetData()` and `getPackedAssetData()` can return more information. --- src/lime/tools/PlatformTarget.hx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lime/tools/PlatformTarget.hx b/src/lime/tools/PlatformTarget.hx index d616a2e352..fc5dc2a20f 100644 --- a/src/lime/tools/PlatformTarget.hx +++ b/src/lime/tools/PlatformTarget.hx @@ -222,18 +222,16 @@ class PlatformTarget System.mkdir(Path.directory(path)); AssetHelper.copyAsset(asset, path, project.templateContext); } - else if (asset.embed == true) + else { - if (asset.sourcePath == "") + if (asset.embed == true && asset.sourcePath == "") { var path = Path.combine(embedDirectory, asset.targetPath); System.mkdir(Path.directory(path)); AssetHelper.copyAsset(asset, path); asset.sourcePath = path; } - } - else - { + var path = Path.combine(assetDirectory, asset.targetPath); System.mkdir(Path.directory(path)); AssetHelper.copyAssetIfNewer(asset, path); From c2ed6a0b9d36b5ba5351404601f42bfac205a9b8 Mon Sep 17 00:00:00 2001 From: Joseph Cloutier Date: Thu, 14 May 2026 16:46:47 -0400 Subject: [PATCH 05/76] Use `copyProjectAssets()` in `WebAssemblyPlatform`. Now copying directly into the application directory rather than _obj/assets_. Everything else here is the same. --- tools/platforms/WebAssemblyPlatform.hx | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tools/platforms/WebAssemblyPlatform.hx b/tools/platforms/WebAssemblyPlatform.hx index dbf8ad19f4..420594e8bc 100644 --- a/tools/platforms/WebAssemblyPlatform.hx +++ b/tools/platforms/WebAssemblyPlatform.hx @@ -447,21 +447,7 @@ class WebAssemblyPlatform extends PlatformTarget // ProjectHelper.recursiveSmartCopyTemplate(project, "webassembly/cpp", targetDirectory + "/obj", context); ProjectHelper.recursiveSmartCopyTemplate(project, "cpp/static", targetDirectory + "/obj", context); - for (asset in project.assets) - { - var path = Path.combine(destination, asset.targetPath); - - if (asset.type == AssetType.TEMPLATE) - { - System.mkdir(Path.directory(path)); - AssetHelper.copyAsset(asset, path, context); - } - else - { - System.mkdir(Path.directory(path)); - AssetHelper.copyAsset(asset, path, context); - } - } + copyProjectAssets(destination); } @ignore public override function install():Void {} From 919232a237870e4c7a7db5bb6190a4eaf7de967b Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 19 May 2026 22:07:19 -0400 Subject: [PATCH 06/76] Add an experimental Vulkan backend This adds a native Vulkan context, wires it through the SDL backend, and exposes the bootstrap pieces needed to create an instance and surface from Lime. --- docs/ImportAll.hx | 7 + project/Build.xml | 10 + project/include/graphics/vulkan/VKRenderer.h | 160 ++ project/include/ui/Window.h | 18 +- project/src/ExternalInterface.cpp | 1093 +++++++++++ project/src/backend/sdl/SDLWindow.cpp | 225 ++- project/src/backend/sdl/SDLWindow.h | 7 + project/src/graphics/vulkan/VKRenderer.cpp | 1739 +++++++++++++++++ .../_internal/backend/native/NativeCFFI.hx | 169 ++ .../_internal/backend/native/NativeWindow.hx | 15 +- src/lime/graphics/RenderContext.hx | 7 + src/lime/graphics/RenderContextType.hx | 5 + src/lime/graphics/VulkanRenderContext.hx | 190 ++ src/lime/graphics/vulkan/VK.hx | 154 ++ src/lime/graphics/vulkan/VKInstance.hx | 112 ++ src/lime/graphics/vulkan/VKPhysicalDevice.hx | 87 + src/lime/graphics/vulkan/VKQueueFamilyInfo.hx | 42 + src/lime/graphics/vulkan/VKRenderer.hx | 147 ++ src/lime/graphics/vulkan/VKSurface.hx | 52 + 19 files changed, 4194 insertions(+), 45 deletions(-) create mode 100644 project/include/graphics/vulkan/VKRenderer.h create mode 100644 project/src/graphics/vulkan/VKRenderer.cpp create mode 100644 src/lime/graphics/VulkanRenderContext.hx create mode 100644 src/lime/graphics/vulkan/VK.hx create mode 100644 src/lime/graphics/vulkan/VKInstance.hx create mode 100644 src/lime/graphics/vulkan/VKPhysicalDevice.hx create mode 100644 src/lime/graphics/vulkan/VKQueueFamilyInfo.hx create mode 100644 src/lime/graphics/vulkan/VKRenderer.hx create mode 100644 src/lime/graphics/vulkan/VKSurface.hx diff --git a/docs/ImportAll.hx b/docs/ImportAll.hx index e0039724f6..ba022480ee 100644 --- a/docs/ImportAll.hx +++ b/docs/ImportAll.hx @@ -58,6 +58,13 @@ import lime.graphics.PixelFormat; import lime.graphics.RenderContext; import lime.graphics.RenderContextAttributes; import lime.graphics.RenderContextType; +import lime.graphics.VulkanRenderContext; +import lime.graphics.vulkan.VK; +import lime.graphics.vulkan.VKRenderer; +import lime.graphics.vulkan.VKInstance; +import lime.graphics.vulkan.VKPhysicalDevice; +import lime.graphics.vulkan.VKQueueFamilyInfo; +import lime.graphics.vulkan.VKSurface; import lime.graphics.WebGL2RenderContext; import lime.graphics.WebGLRenderContext; import lime.math.ARGB; diff --git a/project/Build.xml b/project/Build.xml index ef9bc7458d..a1a5b48d2c 100755 --- a/project/Build.xml +++ b/project/Build.xml @@ -35,10 +35,14 @@ + + + + @@ -59,6 +63,10 @@ + + + + @@ -236,6 +244,7 @@ + @@ -270,6 +279,7 @@ + diff --git a/project/include/graphics/vulkan/VKRenderer.h b/project/include/graphics/vulkan/VKRenderer.h new file mode 100644 index 0000000000..ae2b0b8f69 --- /dev/null +++ b/project/include/graphics/vulkan/VKRenderer.h @@ -0,0 +1,160 @@ +#ifndef LIME_GRAPHICS_VULKAN_VKRENDERER_H +#define LIME_GRAPHICS_VULKAN_VKRENDERER_H + +#include +#include +#include +#include +#include + + +namespace lime { + + + class VulkanRenderer { + + public: + + explicit VulkanRenderer (Window* window); + ~VulkanRenderer (); + + bool ClearOverlay (); + bool Create (const char* applicationName); + void Destroy (); + bool Render (float red, float green, float blue, float alpha); + bool Resize (); + bool SetOverlay (const unsigned char* data, int width, int height, int x, int y); + + inline const std::string& GetInfo () const { return info; } + inline const std::string& GetLastError () const { return lastError; } + + private: + + bool CreateCommandBuffers (); + bool CreateCommandPool (); + bool CreateDevice (); + bool CreateFramebuffers (); + bool CreateImageViews (); + bool CreateInstance (const char* applicationName); + bool CreateOverlayBuffer (size_t requiredSize); + bool CreateRenderPass (); + bool CreateSurface (); + bool CreateSwapchain (); + bool CreateSwapchainResources (); + bool CreateSyncObjects (); + void DestroyOverlayResources (); + void DestroySwapchainResources (); + uint32_t FindMemoryType (uint32_t typeFilter, VkMemoryPropertyFlags properties); + bool LoadDeviceProcs (); + bool LoadGlobalProcs (); + bool LoadInstanceProcs (); + bool PickPhysicalDevice (); + bool RecordCommandBuffer (uint32_t imageIndex, float red, float green, float blue, float alpha); + bool RecreateSwapchain (); + void SetError (const std::string& value); + + Window* window; + std::string info; + std::string lastError; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + PFN_vkAllocateMemory vkAllocateMemory; + PFN_vkBindBufferMemory vkBindBufferMemory; + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; + PFN_vkCreateBuffer vkCreateBuffer; + PFN_vkCreateDevice vkCreateDevice; + PFN_vkCreateFence vkCreateFence; + PFN_vkCreateFramebuffer vkCreateFramebuffer; + PFN_vkCreateImageView vkCreateImageView; + PFN_vkCreateInstance vkCreateInstance; + PFN_vkCreateRenderPass vkCreateRenderPass; + PFN_vkCreateSemaphore vkCreateSemaphore; + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; + PFN_vkCreateCommandPool vkCreateCommandPool; + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; + PFN_vkBeginCommandBuffer vkBeginCommandBuffer; + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; + PFN_vkCmdEndRenderPass vkCmdEndRenderPass; + PFN_vkDestroyCommandPool vkDestroyCommandPool; + PFN_vkDestroyBuffer vkDestroyBuffer; + PFN_vkDestroyDevice vkDestroyDevice; + PFN_vkDestroyFence vkDestroyFence; + PFN_vkDestroyFramebuffer vkDestroyFramebuffer; + PFN_vkDestroyImageView vkDestroyImageView; + PFN_vkDestroyInstance vkDestroyInstance; + PFN_vkDestroyRenderPass vkDestroyRenderPass; + PFN_vkDestroySemaphore vkDestroySemaphore; + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; + PFN_vkDeviceWaitIdle vkDeviceWaitIdle; + PFN_vkEndCommandBuffer vkEndCommandBuffer; + PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; + PFN_vkFreeMemory vkFreeMemory; + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; + PFN_vkGetDeviceQueue vkGetDeviceQueue; + PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; + PFN_vkMapMemory vkMapMemory; + PFN_vkQueuePresentKHR vkQueuePresentKHR; + PFN_vkQueueSubmit vkQueueSubmit; + PFN_vkResetCommandPool vkResetCommandPool; + PFN_vkResetFences vkResetFences; + PFN_vkUnmapMemory vkUnmapMemory; + PFN_vkWaitForFences vkWaitForFences; + + VkInstance instance; + VkSurfaceKHR surface; + VkPhysicalDevice physicalDevice; + VkPhysicalDeviceProperties physicalDeviceProperties; + VkDevice device; + VkQueue queue; + uint32_t queueFamilyIndex; + VkSwapchainKHR swapchain; + VkFormat swapchainFormat; + VkPresentModeKHR swapchainPresentMode; + int requestedVSyncMode; + VkExtent2D swapchainExtent; + VkRenderPass renderPass; + VkCommandPool commandPool; + VkSemaphore imageAvailableSemaphore; + VkSemaphore renderFinishedSemaphore; + VkFence inFlightFence; + VkBuffer overlayBuffer; + VkDeviceMemory overlayBufferMemory; + bool portabilityEnumerationSupported; + bool portabilitySubsetSupported; + bool swapchainDirty; + size_t overlayBufferCapacity; + unsigned char* overlayMappedData; + uint32_t overlayWidth; + uint32_t overlayHeight; + int overlayX; + int overlayY; + bool overlayEnabled; + + std::vector instanceExtensions; + std::vector deviceExtensions; + std::vector swapchainImages; + std::vector swapchainImageViews; + std::vector framebuffers; + std::vector commandBuffers; + + }; + + +} + + +#endif diff --git a/project/include/ui/Window.h b/project/include/ui/Window.h index 04321be0b2..8af2651c4a 100644 --- a/project/include/ui/Window.h +++ b/project/include/ui/Window.h @@ -11,8 +11,13 @@ #include #include #include +#include #include +#ifdef CreateWindow +#undef CreateWindow +#endif + namespace lime { @@ -68,7 +73,17 @@ namespace lime { virtual bool SetAlwaysOnTop (bool alwaysOnTop) = 0; virtual void WarpMouse (int x, int y) = 0; virtual int GetVSyncInterval () const { return 0; } + virtual int GetRequestedVSyncMode () const { return 0; } virtual double GetRefreshRate () const { return 60.0; } + virtual uint64_t CreateVulkanSurface (uintptr_t instance) { return 0; } + virtual void GetVulkanDrawableSize (int* width, int* height) { + + if (width) *width = 0; + if (height) *height = 0; + + } + virtual bool GetVulkanInstanceExtensions (unsigned int* count, const char** names) { return false; } + virtual void* GetVulkanInstanceProcAddr () { return 0; } Application* currentApplication; int flags; @@ -98,7 +113,8 @@ namespace lime { WINDOW_FLAG_MINIMIZED = 0x00002000, WINDOW_FLAG_MAXIMIZED = 0x00004000, WINDOW_FLAG_ALWAYS_ON_TOP = 0x00008000, - WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000 + WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000, + WINDOW_FLAG_VULKAN = 0x00020000 }; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 0fcb20e6e7..4fc72f7cc3 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -16,6 +16,9 @@ #include #include #include +#ifdef LIME_VULKAN +#include +#endif #include #include #include @@ -57,6 +60,7 @@ #include #include +#include #ifdef LIME_SDL_SOUND #include @@ -67,6 +71,178 @@ DEFINE_KIND (k_finalizer); namespace lime { + static std::string lastVulkanRendererError; + static std::string lastVKError; + + + static uint64_t CombineVulkanHandle (int high, int low) { + + return ((uint64_t)(uint32_t)high << 32) | (uint32_t)low; + + } + + + static value CreateVulkanHandleValue (uint64_t handleValue) { + + value result = alloc_empty_object (); + alloc_field (result, val_id ("low"), alloc_int ((int32_t)(handleValue & 0xFFFFFFFFULL))); + alloc_field (result, val_id ("high"), alloc_int ((int32_t)(handleValue >> 32))); + return result; + + } + + + static vdynamic* HLCreateVulkanHandleValue (uint64_t handleValue) { + + const int id_low = hl_hash_utf8 ("low"); + const int id_high = hl_hash_utf8 ("high"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_seti (result, id_low, &hlt_i32, (int32_t)(handleValue & 0xFFFFFFFFULL)); + hl_dyn_seti (result, id_high, &hlt_i32, (int32_t)(handleValue >> 32)); + return result; + + } + + +#ifdef LIME_VULKAN + static VkSurfaceKHR UInt64ToVulkanSurface (uint64_t value) { + + return (VkSurfaceKHR)value; + + } + + + static bool CreateManagedVulkanInstance (Window* targetWindow, const char* applicationName, VkInstance* outInstance) { + + if (!targetWindow || !outInstance) { + + lastVKError = "Missing Vulkan window or output instance"; + return false; + + } + + *outInstance = VK_NULL_HANDLE; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; + + } + + PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkCreateInstance"); + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties = + (PFN_vkEnumerateInstanceExtensionProperties)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"); + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion = + (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkEnumerateInstanceVersion"); + + if (!vkCreateInstance || !vkEnumerateInstanceExtensionProperties) { + + lastVKError = "Missing required Vulkan global functions"; + return false; + + } + + unsigned int requiredExtensionCount = 0; + if (!targetWindow->GetVulkanInstanceExtensions (&requiredExtensionCount, 0)) { + + lastVKError = "Failed to query required Vulkan window extensions"; + return false; + + } + + std::vector requiredExtensions (requiredExtensionCount); + if (requiredExtensionCount > 0 && !targetWindow->GetVulkanInstanceExtensions (&requiredExtensionCount, requiredExtensions.data ())) { + + lastVKError = "Failed to fetch required Vulkan window extensions"; + return false; + + } + + std::vector instanceExtensions; + for (size_t i = 0; i < requiredExtensions.size (); ++i) { + + instanceExtensions.push_back (requiredExtensions[i]); + + } + + bool portabilityEnumerationSupported = false; + uint32_t availableExtensionCount = 0; + if (vkEnumerateInstanceExtensionProperties (0, &availableExtensionCount, 0) == VK_SUCCESS && availableExtensionCount > 0) { + + std::vector availableExtensions (availableExtensionCount); + if (vkEnumerateInstanceExtensionProperties (0, &availableExtensionCount, availableExtensions.data ()) == VK_SUCCESS) { + + for (size_t i = 0; i < availableExtensions.size (); ++i) { + + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + if (strcmp (availableExtensions[i].extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) { + + portabilityEnumerationSupported = true; + + } + #endif + + } + + } + + } + + if (portabilityEnumerationSupported) { + + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + instanceExtensions.push_back (VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + #endif + + } + + uint32_t instanceVersion = VK_API_VERSION_1_0; + if (vkEnumerateInstanceVersion) { + + vkEnumerateInstanceVersion (&instanceVersion); + + } + + VkApplicationInfo applicationInfo; + memset (&applicationInfo, 0, sizeof (applicationInfo)); + applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + applicationInfo.pApplicationName = applicationName ? applicationName : "Lime"; + applicationInfo.pEngineName = "Lime"; + applicationInfo.applicationVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.engineVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.apiVersion = instanceVersion >= VK_API_VERSION_1_0 ? VK_API_VERSION_1_0 : instanceVersion; + + VkInstanceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &applicationInfo; + createInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size (); + createInfo.ppEnabledExtensionNames = instanceExtensions.empty () ? 0 : instanceExtensions.data (); + + #ifdef VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR + if (portabilityEnumerationSupported) { + + createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + + } + #endif + + VkResult result = vkCreateInstance (&createInfo, 0, outInstance); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateInstance failed"; + return false; + + } + + lastVKError.clear (); + return true; + + } +#endif + void gc_application (value handle) { @@ -3533,6 +3709,889 @@ namespace lime { } + value lime_window_get_vulkan_instance_extensions (value window) { + + Window* targetWindow = (Window*)val_data (window); + unsigned int count = 0; + + if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + + return alloc_array (0); + + } + + std::vector names (count); + if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + + return alloc_array (0); + + } + + value result = alloc_array (count); + + for (unsigned int i = 0; i < count; ++i) { + + val_array_set_i (result, i, alloc_string (names[i])); + + } + + return result; + + } + + + HL_PRIM hl_varray* HL_NAME(hl_window_get_vulkan_instance_extensions) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + unsigned int count = 0; + + if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + + return hl_alloc_array (&hlt_bytes, 0); + + } + + std::vector names (count); + if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + + return hl_alloc_array (&hlt_bytes, 0); + + } + + hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, count); + vbyte** resultData = hl_aptr (result, vbyte*); + + for (unsigned int i = 0; i < count; ++i) { + + *resultData++ = hl_copy_bytes ((const vbyte*)names[i], (int)std::strlen (names[i]) + 1); + + } + + return result; + + } + + + value lime_window_get_vulkan_drawable_size (value window) { + + Window* targetWindow = (Window*)val_data (window); + int width = 0; + int height = 0; + targetWindow->GetVulkanDrawableSize (&width, &height); + + value result = alloc_empty_object (); + alloc_field (result, val_id ("width"), alloc_int (width)); + alloc_field (result, val_id ("height"), alloc_int (height)); + return result; + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_drawable_size) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + int width = 0; + int height = 0; + targetWindow->GetVulkanDrawableSize (&width, &height); + + const int id_width = hl_hash_utf8 ("width"); + const int id_height = hl_hash_utf8 ("height"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj(); + hl_dyn_seti (result, id_width, &hlt_i32, width); + hl_dyn_seti (result, id_height, &hlt_i32, height); + return result; + + } + + + value lime_window_get_vulkan_instance_proc_addr (value window) { + + Window* targetWindow = (Window*)val_data (window); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_instance_proc_addr) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + + } + + + value lime_window_create_vulkan_surface (value window, int instanceHigh, int instanceLow) { + + Window* targetWindow = (Window*)val_data (window); + uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + + if (!surface) { + + return alloc_null (); + + } + + return CreateVulkanHandleValue (surface); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_create_vulkan_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + + Window* targetWindow = (Window*)window->ptr; + uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + + if (!surface) { + + return 0; + + } + + return HLCreateVulkanHandleValue (surface); + + } + + + value lime_vk_create_instance (value window, HxString applicationName) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = VK_NULL_HANDLE; + + if (!CreateManagedVulkanInstance (targetWindow, applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0, &instance)) { + + return alloc_null (); + + } + + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_instance) (HL_CFFIPointer* window, hl_vstring* applicationName) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = VK_NULL_HANDLE; + const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + + if (!CreateManagedVulkanInstance (targetWindow, applicationNameUTF8, &instance)) { + + return 0; + + } + + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_instance (value window, int instanceHigh, int instanceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); + if (vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_instance) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); + if (vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + void lime_vk_destroy_surface (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + if (!surface) return; + + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); + if (vkDestroySurfaceKHR) { + + vkDestroySurfaceKHR (instance, surface, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + if (!surface) return; + + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); + if (vkDestroySurfaceKHR) { + + vkDestroySurfaceKHR (instance, surface, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_physical_devices (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + + if (!targetWindow || !instance) { + + lastVKError = "Missing Vulkan window or instance"; + return alloc_null (); + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return alloc_null (); + + } + + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, + "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, + "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan instance functions"; + return alloc_null (); + + } + + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices failed"; + return alloc_null (); + + } + + value devices = alloc_array (deviceCount); + if (deviceCount == 0) { + + lastVKError.clear (); + return devices; + + } + + std::vector physicalDevices (deviceCount); + result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + return alloc_null (); + + } + + const int id_handle = val_id ("handle"); + const int id_name = val_id ("name"); + const int id_apiVersion = val_id ("apiVersion"); + const int id_driverVersion = val_id ("driverVersion"); + const int id_vendorID = val_id ("vendorID"); + const int id_deviceID = val_id ("deviceID"); + const int id_deviceType = val_id ("deviceType"); + const int id_queueFamilies = val_id ("queueFamilies"); + + const int id_index = val_id ("index"); + const int id_flags = val_id ("flags"); + const int id_queueCount = val_id ("queueCount"); + const int id_timestampValidBits = val_id ("timestampValidBits"); + const int id_supportsGraphics = val_id ("supportsGraphics"); + const int id_supportsCompute = val_id ("supportsCompute"); + const int id_supportsTransfer = val_id ("supportsTransfer"); + const int id_supportsPresent = val_id ("supportsPresent"); + + for (uint32_t i = 0; i < deviceCount; ++i) { + + VkPhysicalDeviceProperties properties; + memset (&properties, 0, sizeof (properties)); + vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); + std::vector queueFamilies (queueFamilyCount); + if (queueFamilyCount > 0) { + + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + + } + + value queueFamilyArray = alloc_array (queueFamilyCount); + + for (uint32_t q = 0; q < queueFamilyCount; ++q) { + + VkBool32 supportsPresent = VK_FALSE; + if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + + vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + + } + + value queueFamilyObject = alloc_empty_object (); + alloc_field (queueFamilyObject, id_index, alloc_int (q)); + alloc_field (queueFamilyObject, id_flags, alloc_int (queueFamilies[q].queueFlags)); + alloc_field (queueFamilyObject, id_queueCount, alloc_int (queueFamilies[q].queueCount)); + alloc_field (queueFamilyObject, id_timestampValidBits, alloc_int (queueFamilies[q].timestampValidBits)); + alloc_field (queueFamilyObject, id_supportsGraphics, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsCompute, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsTransfer, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsPresent, alloc_bool (supportsPresent != VK_FALSE)); + val_array_set_i (queueFamilyArray, q, queueFamilyObject); + + } + + value deviceObject = alloc_empty_object (); + alloc_field (deviceObject, id_handle, CreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); + alloc_field (deviceObject, id_name, alloc_string (properties.deviceName)); + alloc_field (deviceObject, id_apiVersion, alloc_int (properties.apiVersion)); + alloc_field (deviceObject, id_driverVersion, alloc_int (properties.driverVersion)); + alloc_field (deviceObject, id_vendorID, alloc_int (properties.vendorID)); + alloc_field (deviceObject, id_deviceID, alloc_int (properties.deviceID)); + alloc_field (deviceObject, id_deviceType, alloc_int (properties.deviceType)); + alloc_field (deviceObject, id_queueFamilies, queueFamilyArray); + val_array_set_i (devices, i, deviceObject); + + } + + lastVKError.clear (); + return devices; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_array (0); +#endif + + } + + + HL_PRIM hl_varray* HL_NAME(hl_vk_get_physical_devices) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + + if (!targetWindow || !instance) { + + lastVKError = "Missing Vulkan window or instance"; + return 0; + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return 0; + + } + + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, + "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, + "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan instance functions"; + return 0; + + } + + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices failed"; + return 0; + + } + + hl_varray* devices = (hl_varray*)hl_alloc_array (&hlt_dynobj, deviceCount); + if (deviceCount == 0) { + + lastVKError.clear (); + return devices; + + } + + std::vector physicalDevices (deviceCount); + result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + return 0; + + } + + vdynamic** deviceData = hl_aptr (devices, vdynamic*); + + const int id_handle = hl_hash_utf8 ("handle"); + const int id_name = hl_hash_utf8 ("name"); + const int id_apiVersion = hl_hash_utf8 ("apiVersion"); + const int id_driverVersion = hl_hash_utf8 ("driverVersion"); + const int id_vendorID = hl_hash_utf8 ("vendorID"); + const int id_deviceID = hl_hash_utf8 ("deviceID"); + const int id_deviceType = hl_hash_utf8 ("deviceType"); + const int id_queueFamilies = hl_hash_utf8 ("queueFamilies"); + + const int id_index = hl_hash_utf8 ("index"); + const int id_flags = hl_hash_utf8 ("flags"); + const int id_queueCount = hl_hash_utf8 ("queueCount"); + const int id_timestampValidBits = hl_hash_utf8 ("timestampValidBits"); + const int id_supportsGraphics = hl_hash_utf8 ("supportsGraphics"); + const int id_supportsCompute = hl_hash_utf8 ("supportsCompute"); + const int id_supportsTransfer = hl_hash_utf8 ("supportsTransfer"); + const int id_supportsPresent = hl_hash_utf8 ("supportsPresent"); + + for (uint32_t i = 0; i < deviceCount; ++i) { + + VkPhysicalDeviceProperties properties; + memset (&properties, 0, sizeof (properties)); + vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); + std::vector queueFamilies (queueFamilyCount); + if (queueFamilyCount > 0) { + + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + + } + + hl_varray* queueFamilyArray = (hl_varray*)hl_alloc_array (&hlt_dynobj, queueFamilyCount); + vdynamic** queueFamilyData = hl_aptr (queueFamilyArray, vdynamic*); + + for (uint32_t q = 0; q < queueFamilyCount; ++q) { + + VkBool32 supportsPresent = VK_FALSE; + if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + + vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + + } + + vdynamic* queueFamilyObject = (vdynamic*)hl_alloc_dynobj (); + *queueFamilyData++ = queueFamilyObject; + hl_dyn_seti (queueFamilyObject, id_index, &hlt_i32, q); + hl_dyn_seti (queueFamilyObject, id_flags, &hlt_i32, queueFamilies[q].queueFlags); + hl_dyn_seti (queueFamilyObject, id_queueCount, &hlt_i32, queueFamilies[q].queueCount); + hl_dyn_seti (queueFamilyObject, id_timestampValidBits, &hlt_i32, queueFamilies[q].timestampValidBits); + hl_dyn_seti (queueFamilyObject, id_supportsGraphics, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsCompute, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsTransfer, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsPresent, &hlt_bool, supportsPresent != VK_FALSE); + + } + + vdynamic* deviceObject = (vdynamic*)hl_alloc_dynobj (); + *deviceData++ = deviceObject; + hl_dyn_setp (deviceObject, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); + hl_dyn_setp (deviceObject, id_name, &hlt_bytes, hl_copy_bytes ((const vbyte*)properties.deviceName, (int)std::strlen (properties.deviceName) + 1)); + hl_dyn_seti (deviceObject, id_apiVersion, &hlt_i32, properties.apiVersion); + hl_dyn_seti (deviceObject, id_driverVersion, &hlt_i32, properties.driverVersion); + hl_dyn_seti (deviceObject, id_vendorID, &hlt_i32, properties.vendorID); + hl_dyn_seti (deviceObject, id_deviceID, &hlt_i32, properties.deviceID); + hl_dyn_seti (deviceObject, id_deviceType, &hlt_i32, properties.deviceType); + hl_dyn_setp (deviceObject, id_queueFamilies, &hlt_array, queueFamilyArray); + + } + + lastVKError.clear (); + return devices; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return (hl_varray*)hl_alloc_array (&hlt_dynobj, 0); +#endif + + } + + + value lime_vk_get_last_error () { + + return alloc_string (lastVKError.c_str ()); + + } + + + HL_PRIM vbyte* HL_NAME(hl_vk_get_last_error) () { + + return hl_copy_bytes ((const vbyte*)lastVKError.c_str (), (int)lastVKError.size () + 1); + + } + + +#ifdef LIME_VULKAN + value lime_vulkan_renderer_create (value window, HxString applicationName) { + + Window* targetWindow = (Window*)val_data (window); + VulkanRenderer* renderer = new VulkanRenderer (targetWindow); + + if (!renderer->Create (applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0)) { + + lastVulkanRendererError = renderer->GetLastError (); + delete renderer; + return alloc_null (); + + } + + lastVulkanRendererError.clear (); + return CFFIPointer (renderer); + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_vulkan_renderer_create) (HL_CFFIPointer* window, hl_vstring* applicationName) { + + Window* targetWindow = (Window*)window->ptr; + VulkanRenderer* renderer = new VulkanRenderer (targetWindow); + const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + + if (!renderer->Create (applicationNameUTF8)) { + + lastVulkanRendererError = renderer->GetLastError (); + delete renderer; + return 0; + + } + + lastVulkanRendererError.clear (); + return HLCFFIPointer (renderer); + + } + + + void lime_vulkan_renderer_destroy (value handle) { + + if (val_is_null (handle)) return; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + delete renderer; + + } + + + HL_PRIM void HL_NAME(hl_vulkan_renderer_destroy) (HL_CFFIPointer* handle) { + + if (!handle || !handle->ptr) return; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + handle->ptr = 0; + delete renderer; + + } + + + value lime_vulkan_renderer_get_info (value handle) { + + if (val_is_null (handle)) return alloc_string (""); + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + return alloc_string (renderer->GetInfo ().c_str ()); + + } + + + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_info) (HL_CFFIPointer* handle) { + + if (!handle || !handle->ptr) return 0; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + return hl_copy_bytes ((const vbyte*)renderer->GetInfo ().c_str (), (int)renderer->GetInfo ().size () + 1); + + } + + + value lime_vulkan_renderer_get_last_error () { + + return alloc_string (lastVulkanRendererError.c_str ()); + + } + + + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { + + return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); + + } + + + bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { + + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + Bytes data (bytes); + bool result = renderer->SetOverlay (data.b, width, height, x, y); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_set_overlay) (HL_CFFIPointer* handle, Bytes* bytes, int width, int height, int x, int y) { + + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->SetOverlay (bytes ? bytes->b : 0, width, height, x, y); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + bool lime_vulkan_renderer_clear_overlay (value handle) { + + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->ClearOverlay (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_clear_overlay) (HL_CFFIPointer* handle) { + + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->ClearOverlay (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + bool lime_vulkan_renderer_render (value handle, double red, double green, double blue, double alpha) { + + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->Render (red, green, blue, alpha); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_render) (HL_CFFIPointer* handle, double red, double green, double blue, double alpha) { + + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->Render (red, green, blue, alpha); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + bool lime_vulkan_renderer_resize (value handle) { + + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->Resize (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_resize) (HL_CFFIPointer* handle) { + + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->Resize (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } +#else + value lime_vulkan_renderer_create (value window, HxString applicationName) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return alloc_null (); + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_vulkan_renderer_create) (HL_CFFIPointer* window, hl_vstring* applicationName) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return 0; + + } + + + void lime_vulkan_renderer_destroy (value handle) {} + + + HL_PRIM void HL_NAME(hl_vulkan_renderer_destroy) (HL_CFFIPointer* handle) {} + + + value lime_vulkan_renderer_get_info (value handle) { + + return alloc_string (""); + + } + + + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_info) (HL_CFFIPointer* handle) { + + return hl_copy_bytes ((const vbyte*)"", 1); + + } + + + value lime_vulkan_renderer_get_last_error () { + + return alloc_string (lastVulkanRendererError.c_str ()); + + } + + + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { + + return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); + + } + + + bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_set_overlay) (HL_CFFIPointer* handle, Bytes* bytes, int width, int height, int x, int y) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + bool lime_vulkan_renderer_clear_overlay (value handle) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_clear_overlay) (HL_CFFIPointer* handle) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + bool lime_vulkan_renderer_render (value handle, double red, double green, double blue, double alpha) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_render) (HL_CFFIPointer* handle, double red, double green, double blue, double alpha) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + bool lime_vulkan_renderer_resize (value handle) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_resize) (HL_CFFIPointer* handle) { + + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; + + } +#endif + + int lime_window_get_display (value window) { Window* targetWindow = (Window*)val_data (window); @@ -4297,6 +5356,7 @@ namespace lime { DEFINE_PRIME1v (lime_window_focus); DEFINE_PRIME1 (lime_window_get_context); DEFINE_PRIME1 (lime_window_get_context_type); + DEFINE_PRIME3 (lime_window_create_vulkan_surface); DEFINE_PRIME1 (lime_window_get_display); DEFINE_PRIME1 (lime_window_get_display_mode); DEFINE_PRIME1 (lime_window_get_height); @@ -4304,6 +5364,22 @@ namespace lime { DEFINE_PRIME1 (lime_window_get_mouse_lock); DEFINE_PRIME1 (lime_window_get_scale); DEFINE_PRIME1 (lime_window_get_text_input_enabled); + DEFINE_PRIME1 (lime_window_get_vulkan_drawable_size); + DEFINE_PRIME1 (lime_window_get_vulkan_instance_extensions); + DEFINE_PRIME1 (lime_window_get_vulkan_instance_proc_addr); + DEFINE_PRIME2 (lime_vk_create_instance); + DEFINE_PRIME3v (lime_vk_destroy_instance); + DEFINE_PRIME5v (lime_vk_destroy_surface); + DEFINE_PRIME5 (lime_vk_get_physical_devices); + DEFINE_PRIME0 (lime_vk_get_last_error); + DEFINE_PRIME2 (lime_vulkan_renderer_create); + DEFINE_PRIME1v (lime_vulkan_renderer_destroy); + DEFINE_PRIME1 (lime_vulkan_renderer_get_info); + DEFINE_PRIME0 (lime_vulkan_renderer_get_last_error); + DEFINE_PRIME6 (lime_vulkan_renderer_set_overlay); + DEFINE_PRIME1 (lime_vulkan_renderer_clear_overlay); + DEFINE_PRIME5 (lime_vulkan_renderer_render); + DEFINE_PRIME1 (lime_vulkan_renderer_resize); DEFINE_PRIME1 (lime_window_get_width); DEFINE_PRIME1 (lime_window_get_x); DEFINE_PRIME1 (lime_window_get_y); @@ -4496,6 +5572,7 @@ namespace lime { DEFINE_HL_PRIM (_VOID, hl_window_focus, _TCFFIPOINTER); DEFINE_HL_PRIM (_F64, hl_window_get_context, _TCFFIPOINTER); DEFINE_HL_PRIM (_BYTES, hl_window_get_context_type, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_window_create_vulkan_surface, _TCFFIPOINTER _I32 _I32); DEFINE_HL_PRIM (_I32, hl_window_get_display, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_window_get_display_mode, _TCFFIPOINTER _TDISPLAYMODE); DEFINE_HL_PRIM (_I32, hl_window_get_height, _TCFFIPOINTER); @@ -4503,6 +5580,22 @@ namespace lime { DEFINE_HL_PRIM (_BOOL, hl_window_get_mouse_lock, _TCFFIPOINTER); DEFINE_HL_PRIM (_F64, hl_window_get_scale, _TCFFIPOINTER); DEFINE_HL_PRIM (_BOOL, hl_window_get_text_input_enabled, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_window_get_vulkan_drawable_size, _TCFFIPOINTER); + DEFINE_HL_PRIM (_ARR, hl_window_get_vulkan_instance_extensions, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_window_get_vulkan_instance_proc_addr, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_vk_create_instance, _TCFFIPOINTER _STRING); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_instance, _TCFFIPOINTER _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_surface, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_ARR, hl_vk_get_physical_devices, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BYTES, hl_vk_get_last_error, _NO_ARG); + DEFINE_HL_PRIM (_TCFFIPOINTER, hl_vulkan_renderer_create, _TCFFIPOINTER _STRING); + DEFINE_HL_PRIM (_VOID, hl_vulkan_renderer_destroy, _TCFFIPOINTER); + DEFINE_HL_PRIM (_BYTES, hl_vulkan_renderer_get_info, _TCFFIPOINTER); + DEFINE_HL_PRIM (_BYTES, hl_vulkan_renderer_get_last_error, _NO_ARG); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_set_overlay, _TCFFIPOINTER _TBYTES _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_clear_overlay, _TCFFIPOINTER); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_render, _TCFFIPOINTER _F64 _F64 _F64 _F64); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_resize, _TCFFIPOINTER); DEFINE_HL_PRIM (_I32, hl_window_get_width, _TCFFIPOINTER); DEFINE_HL_PRIM (_I32, hl_window_get_x, _TCFFIPOINTER); DEFINE_HL_PRIM (_I32, hl_window_get_y, _TCFFIPOINTER); diff --git a/project/src/backend/sdl/SDLWindow.cpp b/project/src/backend/sdl/SDLWindow.cpp index 07cd39693b..9686ae6894 100644 --- a/project/src/backend/sdl/SDLWindow.cpp +++ b/project/src/backend/sdl/SDLWindow.cpp @@ -199,6 +199,7 @@ namespace lime { sdlTexture = 0; sdlRenderer = 0; context = 0; + useVulkan = (flags & WINDOW_FLAG_VULKAN) != 0; contextWidth = 0; contextHeight = 0; @@ -242,7 +243,15 @@ namespace lime { if (flags & WINDOW_FLAG_HARDWARE) { - sdlWindowFlags |= SDL_WINDOW_OPENGL; + if (useVulkan) { + + sdlWindowFlags |= SDL_WINDOW_VULKAN; + + } else { + + sdlWindowFlags |= SDL_WINDOW_OPENGL; + + } if (flags & WINDOW_FLAG_ALLOW_HIGHDPI) { @@ -250,61 +259,65 @@ namespace lime { } - #if defined (HX_WINDOWS) && defined (NATIVE_TOOLKIT_SDL_ANGLE) - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_SetHint (SDL_HINT_VIDEO_WIN_D3DCOMPILER, "d3dcompiler_47.dll"); - #endif + if (!useVulkan) { - #if defined (RASPBERRYPI) - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengles2"); - #endif + #if defined (HX_WINDOWS) && defined (NATIVE_TOOLKIT_SDL_ANGLE) + SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_SetHint (SDL_HINT_VIDEO_WIN_D3DCOMPILER, "d3dcompiler_47.dll"); + #endif - #if defined (IPHONE) || defined (APPLETV) - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3); - #endif + #if defined (RASPBERRYPI) + SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengles2"); + #endif + + #if defined (IPHONE) || defined (APPLETV) + SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3); + #endif - if (flags & WINDOW_FLAG_DEPTH_BUFFER) { + if (flags & WINDOW_FLAG_DEPTH_BUFFER) { - SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 32 - (flags & WINDOW_FLAG_STENCIL_BUFFER) ? 8 : 0); + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 32 - (flags & WINDOW_FLAG_STENCIL_BUFFER) ? 8 : 0); - } + } - if (flags & WINDOW_FLAG_STENCIL_BUFFER) { + if (flags & WINDOW_FLAG_STENCIL_BUFFER) { - SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8); - } + } - if (flags & WINDOW_FLAG_HW_AA_HIRES) { + if (flags & WINDOW_FLAG_HW_AA_HIRES) { - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 4); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 4); - } else if (flags & WINDOW_FLAG_HW_AA) { + } else if (flags & WINDOW_FLAG_HW_AA) { - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 2); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 2); - } + } - if (flags & WINDOW_FLAG_COLOR_DEPTH_32_BIT) { + if (flags & WINDOW_FLAG_COLOR_DEPTH_32_BIT) { - SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8); - } else { + } else { - SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 6); - SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 6); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); + + } } @@ -313,7 +326,7 @@ namespace lime { sdlWindow = SDL_CreateWindow (title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, sdlWindowFlags); #if defined (IPHONE) || defined (APPLETV) - if (sdlWindow && !SDL_GL_CreateContext (sdlWindow)) { + if (!useVulkan && sdlWindow && !SDL_GL_CreateContext (sdlWindow)) { SDL_DestroyWindow (sdlWindow); SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); @@ -362,7 +375,7 @@ namespace lime { int sdlRendererFlags = 0; - if (flags & WINDOW_FLAG_HARDWARE) { + if ((flags & WINDOW_FLAG_HARDWARE) && !useVulkan) { sdlRendererFlags |= SDL_RENDERER_ACCELERATED; @@ -430,7 +443,7 @@ namespace lime { } - if (!context) { + if (!context && !useVulkan) { sdlRendererFlags &= ~SDL_RENDERER_ACCELERATED; sdlRendererFlags &= ~SDL_RENDERER_PRESENTVSYNC; @@ -441,7 +454,7 @@ namespace lime { } - if (context || sdlRenderer) { + if (context || sdlRenderer || useVulkan) { ((SDLApplication*)currentApplication)->RegisterWindow (this); @@ -558,6 +571,12 @@ namespace lime { void SDLWindow::ContextFlip () { + if (useVulkan) { + + return; + + } + if (context && !sdlRenderer) { SDL_GL_SwapWindow (sdlWindow); @@ -578,6 +597,13 @@ namespace lime { } + int SDLWindow::GetRequestedVSyncMode () const { + + return requestedVSyncMode; + + } + + double SDLWindow::GetRefreshRate () const { if (!sdlWindow) { @@ -605,6 +631,72 @@ namespace lime { } + uint64_t SDLWindow::CreateVulkanSurface (uintptr_t instance) { + + if (!useVulkan || !instance) { + + return 0; + + } + + SDL_vulkanSurface surface = 0; + if (SDL_Vulkan_CreateSurface (sdlWindow, (SDL_vulkanInstance)instance, &surface) != SDL_TRUE) { + + return 0; + + } + + #if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + return (uint64_t)(uintptr_t)surface; + #else + return (uint64_t)surface; + #endif + + } + + + void SDLWindow::GetVulkanDrawableSize (int* width, int* height) { + + if (!useVulkan) { + + if (width) *width = 0; + if (height) *height = 0; + return; + + } + + SDL_Vulkan_GetDrawableSize (sdlWindow, width, height); + + } + + + bool SDLWindow::GetVulkanInstanceExtensions (unsigned int* count, const char** names) { + + if (!useVulkan) { + + if (count) *count = 0; + return false; + + } + + return SDL_Vulkan_GetInstanceExtensions (sdlWindow, count, names) == SDL_TRUE; + + } + + + void* SDLWindow::GetVulkanInstanceProcAddr () { + + if (!useVulkan) { + + return 0; + + } + + return SDL_Vulkan_GetVkGetInstanceProcAddr (); + + } + + void* SDLWindow::ContextLock (bool useCFFIValue) { if (sdlRenderer) { @@ -692,6 +784,12 @@ namespace lime { void SDLWindow::ContextMakeCurrent () { + if (useVulkan) { + + return; + + } + if (sdlWindow && context) { SDL_GL_MakeCurrent (sdlWindow, context); @@ -723,6 +821,12 @@ namespace lime { void* SDLWindow::GetContext () { + if (useVulkan) { + + return sdlWindow; + + } + return context; } @@ -730,6 +834,12 @@ namespace lime { const char* SDLWindow::GetContextType () { + if (useVulkan) { + + return "vulkan"; + + } + if (context) { return "opengl"; @@ -1333,6 +1443,35 @@ namespace lime { requestedVSyncMode = vsyncMode; activeSwapInterval = 0; + if (useVulkan) { + + switch (vsyncMode) { + + case 1: + activeSwapInterval = 1; + flags |= WINDOW_FLAG_VSYNC; + break; + + case 2: + activeSwapInterval = -1; + flags |= WINDOW_FLAG_VSYNC; + break; + + case 3: + activeSwapInterval = 1; + flags |= WINDOW_FLAG_VSYNC; + break; + + default: + flags &= ~WINDOW_FLAG_VSYNC; + break; + + } + + return; + + } + if (!sdlWindow || !context || sdlRenderer) { flags &= ~WINDOW_FLAG_VSYNC; diff --git a/project/src/backend/sdl/SDLWindow.h b/project/src/backend/sdl/SDLWindow.h index 51cd02403a..9c3c20fddd 100644 --- a/project/src/backend/sdl/SDLWindow.h +++ b/project/src/backend/sdl/SDLWindow.h @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -62,7 +63,12 @@ namespace lime { virtual bool SetVisible (bool visible); virtual void WarpMouse (int x, int y); virtual int GetVSyncInterval () const; + virtual int GetRequestedVSyncMode () const; virtual double GetRefreshRate () const; + virtual uint64_t CreateVulkanSurface (uintptr_t instance); + virtual void GetVulkanDrawableSize (int* width, int* height); + virtual bool GetVulkanInstanceExtensions (unsigned int* count, const char** names); + virtual void* GetVulkanInstanceProcAddr (); SDL_Renderer* sdlRenderer; SDL_Texture* sdlTexture; SDL_Window* sdlWindow; @@ -74,6 +80,7 @@ namespace lime { int contextHeight; int contextWidth; int requestedVSyncMode; + bool useVulkan; }; diff --git a/project/src/graphics/vulkan/VKRenderer.cpp b/project/src/graphics/vulkan/VKRenderer.cpp new file mode 100644 index 0000000000..dfe41d9553 --- /dev/null +++ b/project/src/graphics/vulkan/VKRenderer.cpp @@ -0,0 +1,1739 @@ +#include + +#include +#include + +#include +#include +#include +#include + + +namespace lime { + + + static const char* VulkanResultToString (VkResult result) { + + switch (result) { + + case VK_SUCCESS: return "VK_SUCCESS"; + case VK_NOT_READY: return "VK_NOT_READY"; + case VK_TIMEOUT: return "VK_TIMEOUT"; + case VK_EVENT_SET: return "VK_EVENT_SET"; + case VK_EVENT_RESET: return "VK_EVENT_RESET"; + case VK_INCOMPLETE: return "VK_INCOMPLETE"; + case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR"; + case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR"; + default: return "VK_RESULT_UNKNOWN"; + + } + + } + + + static std::string FormatVulkanVersion (uint32_t version) { + + std::ostringstream result; + result << VK_API_VERSION_MAJOR (version) << "." << VK_API_VERSION_MINOR (version) << "." << VK_API_VERSION_PATCH (version); + return result.str (); + + } + + + static const char* VulkanPresentModeToString (VkPresentModeKHR mode) { + + switch (mode) { + + case VK_PRESENT_MODE_IMMEDIATE_KHR: return "immediate"; + case VK_PRESENT_MODE_MAILBOX_KHR: return "mailbox"; + case VK_PRESENT_MODE_FIFO_KHR: return "fifo"; + #ifdef VK_PRESENT_MODE_FIFO_RELAXED_KHR + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "fifo-relaxed"; + #endif + default: return "unknown"; + + } + + } + + + static VkPresentModeKHR ChoosePresentMode (const std::vector& presentModes, int requestedVSyncMode) { + + bool hasImmediate = false; + bool hasMailbox = false; + bool hasFifo = false; + bool hasFifoRelaxed = false; + + for (size_t i = 0; i < presentModes.size (); ++i) { + + switch (presentModes[i]) { + + case VK_PRESENT_MODE_IMMEDIATE_KHR: + hasImmediate = true; + break; + + case VK_PRESENT_MODE_MAILBOX_KHR: + hasMailbox = true; + break; + + case VK_PRESENT_MODE_FIFO_KHR: + hasFifo = true; + break; + + #ifdef VK_PRESENT_MODE_FIFO_RELAXED_KHR + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: + hasFifoRelaxed = true; + break; + #endif + + default: + break; + + } + + } + + switch (requestedVSyncMode) { + + case 0: + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + break; + + case 2: + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + #ifdef VK_PRESENT_MODE_FIFO_RELAXED_KHR + if (hasFifoRelaxed) return VK_PRESENT_MODE_FIFO_RELAXED_KHR; + #endif + break; + + case 3: + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + break; + + default: + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + break; + + } + + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + return VK_PRESENT_MODE_FIFO_KHR; + + } + + + VulkanRenderer::VulkanRenderer (Window* window) + : window (window), + vkGetInstanceProcAddr (0), + vkGetDeviceProcAddr (0), + vkAllocateMemory (0), + vkBindBufferMemory (0), + vkCmdCopyBufferToImage (0), + vkCmdPipelineBarrier (0), + vkCreateBuffer (0), + vkCreateDevice (0), + vkCreateFence (0), + vkCreateFramebuffer (0), + vkCreateImageView (0), + vkCreateInstance (0), + vkCreateRenderPass (0), + vkCreateSemaphore (0), + vkCreateSwapchainKHR (0), + vkCreateCommandPool (0), + vkAllocateCommandBuffers (0), + vkAcquireNextImageKHR (0), + vkBeginCommandBuffer (0), + vkCmdBeginRenderPass (0), + vkCmdEndRenderPass (0), + vkDestroyCommandPool (0), + vkDestroyBuffer (0), + vkDestroyDevice (0), + vkDestroyFence (0), + vkDestroyFramebuffer (0), + vkDestroyImageView (0), + vkDestroyInstance (0), + vkDestroyRenderPass (0), + vkDestroySemaphore (0), + vkDestroySurfaceKHR (0), + vkDestroySwapchainKHR (0), + vkDeviceWaitIdle (0), + vkEndCommandBuffer (0), + vkEnumerateDeviceExtensionProperties (0), + vkFreeMemory (0), + vkGetBufferMemoryRequirements (0), + vkEnumerateInstanceExtensionProperties (0), + vkEnumerateInstanceVersion (0), + vkEnumeratePhysicalDevices (0), + vkGetDeviceQueue (0), + vkGetPhysicalDeviceMemoryProperties (0), + vkGetPhysicalDeviceProperties (0), + vkGetPhysicalDeviceQueueFamilyProperties (0), + vkGetPhysicalDeviceSurfaceCapabilitiesKHR (0), + vkGetPhysicalDeviceSurfaceFormatsKHR (0), + vkGetPhysicalDeviceSurfacePresentModesKHR (0), + vkGetPhysicalDeviceSurfaceSupportKHR (0), + vkGetSwapchainImagesKHR (0), + vkMapMemory (0), + vkQueuePresentKHR (0), + vkQueueSubmit (0), + vkResetCommandPool (0), + vkResetFences (0), + vkUnmapMemory (0), + vkWaitForFences (0), + instance (VK_NULL_HANDLE), + surface (VK_NULL_HANDLE), + physicalDevice (VK_NULL_HANDLE), + device (VK_NULL_HANDLE), + queue (VK_NULL_HANDLE), + queueFamilyIndex (0), + swapchain (VK_NULL_HANDLE), + swapchainFormat (VK_FORMAT_UNDEFINED), + swapchainPresentMode (VK_PRESENT_MODE_FIFO_KHR), + requestedVSyncMode (0), + renderPass (VK_NULL_HANDLE), + commandPool (VK_NULL_HANDLE), + imageAvailableSemaphore (VK_NULL_HANDLE), + renderFinishedSemaphore (VK_NULL_HANDLE), + inFlightFence (VK_NULL_HANDLE), + overlayBuffer (VK_NULL_HANDLE), + overlayBufferMemory (VK_NULL_HANDLE), + portabilityEnumerationSupported (false), + portabilitySubsetSupported (false), + swapchainDirty (false), + overlayBufferCapacity (0), + overlayMappedData (0), + overlayWidth (0), + overlayHeight (0), + overlayX (0), + overlayY (0), + overlayEnabled (false) { + + memset (&physicalDeviceProperties, 0, sizeof (physicalDeviceProperties)); + memset (&swapchainExtent, 0, sizeof (swapchainExtent)); + + } + + + VulkanRenderer::~VulkanRenderer () { + + Destroy (); + + } + + + bool VulkanRenderer::Create (const char* applicationName) { + + Destroy (); + lastError.clear (); + info.clear (); + + if (!window) { + + SetError ("Vulkan renderer creation failed: missing window"); + return false; + + } + + if (SDL_Vulkan_LoadLibrary (NULL) != 0) { + + SetError (std::string ("SDL_Vulkan_LoadLibrary failed: ") + SDL_GetError ()); + return false; + + } + + if (!LoadGlobalProcs ()) { + + return false; + + } + + if (!CreateInstance (applicationName)) return false; + if (!LoadInstanceProcs ()) return false; + if (!CreateSurface ()) return false; + if (!PickPhysicalDevice ()) return false; + if (!CreateDevice ()) return false; + if (!LoadDeviceProcs ()) return false; + vkGetDeviceQueue (device, queueFamilyIndex, 0, &queue); + if (!CreateSwapchainResources ()) return false; + if (!CreateSyncObjects ()) return false; + + std::ostringstream result; + result << physicalDeviceProperties.deviceName << " | Vulkan " << FormatVulkanVersion (physicalDeviceProperties.apiVersion) + << " | present " << VulkanPresentModeToString (swapchainPresentMode); + info = result.str (); + return true; + + } + + + bool VulkanRenderer::ClearOverlay () { + + overlayEnabled = false; + overlayWidth = 0; + overlayHeight = 0; + overlayX = 0; + overlayY = 0; + lastError.clear (); + return true; + + } + + + void VulkanRenderer::Destroy () { + + if (device && vkDeviceWaitIdle) { + + vkDeviceWaitIdle (device); + + } + + if (device && vkDestroyFence && inFlightFence) { + + vkDestroyFence (device, inFlightFence, 0); + inFlightFence = VK_NULL_HANDLE; + + } + + if (device && vkDestroySemaphore && renderFinishedSemaphore) { + + vkDestroySemaphore (device, renderFinishedSemaphore, 0); + renderFinishedSemaphore = VK_NULL_HANDLE; + + } + + if (device && vkDestroySemaphore && imageAvailableSemaphore) { + + vkDestroySemaphore (device, imageAvailableSemaphore, 0); + imageAvailableSemaphore = VK_NULL_HANDLE; + + } + + DestroyOverlayResources (); + DestroySwapchainResources (); + + if (device && vkDestroyDevice) { + + vkDestroyDevice (device, 0); + device = VK_NULL_HANDLE; + + } + + queue = VK_NULL_HANDLE; + physicalDevice = VK_NULL_HANDLE; + memset (&physicalDeviceProperties, 0, sizeof (physicalDeviceProperties)); + + if (surface && vkDestroySurfaceKHR && instance) { + + vkDestroySurfaceKHR (instance, surface, 0); + surface = VK_NULL_HANDLE; + + } + + if (instance && vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + instance = VK_NULL_HANDLE; + + } + + instanceExtensions.clear (); + deviceExtensions.clear (); + portabilityEnumerationSupported = false; + portabilitySubsetSupported = false; + swapchainDirty = false; + swapchainFormat = VK_FORMAT_UNDEFINED; + swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; + requestedVSyncMode = 0; + memset (&swapchainExtent, 0, sizeof (swapchainExtent)); + + } + + + bool VulkanRenderer::Render (float red, float green, float blue, float alpha) { + + if (!device) { + + SetError ("Vulkan renderer is not initialized"); + return false; + + } + + int currentRequestedVSyncMode = window ? window->GetRequestedVSyncMode () : 0; + if (swapchainDirty || !swapchain || swapchainExtent.width == 0 || swapchainExtent.height == 0 || currentRequestedVSyncMode != requestedVSyncMode) { + + if (!RecreateSwapchain ()) { + + return false; + + } + + } + + if (!swapchain || swapchainExtent.width == 0 || swapchainExtent.height == 0) { + + return true; + + } + + VkResult result = vkWaitForFences (device, 1, &inFlightFence, VK_TRUE, UINT64_MAX); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkWaitForFences failed: ") + VulkanResultToString (result)); + return false; + + } + + uint32_t imageIndex = 0; + result = vkAcquireNextImageKHR (device, swapchain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) { + + return RecreateSwapchain (); + + } + + if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + + SetError (std::string ("vkAcquireNextImageKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkResetFences (device, 1, &inFlightFence); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkResetFences failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkResetCommandPool (device, commandPool, 0); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkResetCommandPool failed: ") + VulkanResultToString (result)); + return false; + + } + + if (!RecordCommandBuffer (imageIndex, red, green, blue, alpha)) { + + return false; + + } + + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = &imageAvailableSemaphore; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = &renderFinishedSemaphore; + + result = vkQueueSubmit (queue, 1, &submitInfo, inFlightFence); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkQueueSubmit failed: ") + VulkanResultToString (result)); + return false; + + } + + VkPresentInfoKHR presentInfo; + memset (&presentInfo, 0, sizeof (presentInfo)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = &renderFinishedSemaphore; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + presentInfo.pImageIndices = &imageIndex; + + result = vkQueuePresentKHR (queue, &presentInfo); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { + + return RecreateSwapchain (); + + } + + if (result != VK_SUCCESS) { + + SetError (std::string ("vkQueuePresentKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::Resize () { + + return RecreateSwapchain (); + + } + + + bool VulkanRenderer::SetOverlay (const unsigned char* data, int width, int height, int x, int y) { + + if (!data || width <= 0 || height <= 0) { + + return ClearOverlay (); + + } + + size_t requiredSize = (size_t)width * (size_t)height * 4; + if (!CreateOverlayBuffer (requiredSize)) { + + return false; + + } + + memcpy (overlayMappedData, data, requiredSize); + + overlayWidth = (uint32_t)width; + overlayHeight = (uint32_t)height; + overlayX = x; + overlayY = y; + overlayEnabled = true; + lastError.clear (); + return true; + + } + + + bool VulkanRenderer::CreateCommandBuffers () { + + commandBuffers.clear (); + + if (swapchainImages.empty ()) { + + SetError ("Cannot allocate Vulkan command buffers without swapchain images"); + return false; + + } + + commandBuffers.resize (swapchainImages.size (), VK_NULL_HANDLE); + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocateInfo.commandBufferCount = (uint32_t)commandBuffers.size (); + + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, commandBuffers.data ()); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkAllocateCommandBuffers failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateCommandPool () { + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateCommandPool failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateDevice () { + + const float queuePriority = 1.0f; + + VkDeviceQueueCreateInfo queueCreateInfo; + memset (&queueCreateInfo, 0, sizeof (queueCreateInfo)); + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamilyIndex; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + + deviceExtensions.clear (); + deviceExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + if (portabilitySubsetSupported) { + + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + deviceExtensions.push_back (VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + #endif + + } + + VkDeviceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.queueCreateInfoCount = 1; + createInfo.pQueueCreateInfos = &queueCreateInfo; + createInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size (); + createInfo.ppEnabledExtensionNames = deviceExtensions.data (); + + VkResult result = vkCreateDevice (physicalDevice, &createInfo, 0, &device); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateDevice failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateFramebuffers () { + + framebuffers.clear (); + framebuffers.resize (swapchainImageViews.size (), VK_NULL_HANDLE); + + for (size_t i = 0; i < swapchainImageViews.size (); ++i) { + + VkImageView attachments[] = { swapchainImageViews[i] }; + VkFramebufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = 1; + createInfo.pAttachments = attachments; + createInfo.width = swapchainExtent.width; + createInfo.height = swapchainExtent.height; + createInfo.layers = 1; + + VkResult result = vkCreateFramebuffer (device, &createInfo, 0, &framebuffers[i]); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateFramebuffer failed: ") + VulkanResultToString (result)); + return false; + + } + + } + + return true; + + } + + + bool VulkanRenderer::CreateImageViews () { + + swapchainImageViews.clear (); + swapchainImageViews.resize (swapchainImages.size (), VK_NULL_HANDLE); + + for (size_t i = 0; i < swapchainImages.size (); ++i) { + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = swapchainImages[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = swapchainFormat; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + VkResult result = vkCreateImageView (device, &createInfo, 0, &swapchainImageViews[i]); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateImageView failed: ") + VulkanResultToString (result)); + return false; + + } + + } + + return true; + + } + + + bool VulkanRenderer::CreateInstance (const char* applicationName) { + + instanceExtensions.clear (); + + unsigned int requiredExtensionCount = 0; + if (!window->GetVulkanInstanceExtensions (&requiredExtensionCount, 0)) { + + SetError ("Failed to query required Vulkan window extensions"); + return false; + + } + + std::vector requiredExtensions (requiredExtensionCount); + if (requiredExtensionCount > 0 && !window->GetVulkanInstanceExtensions (&requiredExtensionCount, requiredExtensions.data ())) { + + SetError ("Failed to fetch required Vulkan window extensions"); + return false; + + } + + for (size_t i = 0; i < requiredExtensions.size (); ++i) { + + instanceExtensions.push_back (requiredExtensions[i]); + + } + + uint32_t availableCount = 0; + if (vkEnumerateInstanceExtensionProperties && + vkEnumerateInstanceExtensionProperties (0, &availableCount, 0) == VK_SUCCESS && availableCount > 0) { + + std::vector availableExtensions (availableCount); + if (vkEnumerateInstanceExtensionProperties (0, &availableCount, availableExtensions.data ()) == VK_SUCCESS) { + + for (size_t i = 0; i < availableExtensions.size (); ++i) { + + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + if (strcmp (availableExtensions[i].extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) { + + portabilityEnumerationSupported = true; + + } + #endif + + } + + } + + } + + if (portabilityEnumerationSupported) { + + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + instanceExtensions.push_back (VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + #endif + + } + + uint32_t instanceVersion = VK_API_VERSION_1_0; + if (vkEnumerateInstanceVersion) { + + vkEnumerateInstanceVersion (&instanceVersion); + + } + + VkApplicationInfo applicationInfo; + memset (&applicationInfo, 0, sizeof (applicationInfo)); + applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + applicationInfo.pApplicationName = applicationName ? applicationName : "Lime Vulkan Sample"; + applicationInfo.pEngineName = "Lime"; + applicationInfo.applicationVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.engineVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.apiVersion = instanceVersion >= VK_API_VERSION_1_0 ? VK_API_VERSION_1_0 : instanceVersion; + + VkInstanceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &applicationInfo; + createInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size (); + createInfo.ppEnabledExtensionNames = instanceExtensions.empty () ? 0 : instanceExtensions.data (); + + #ifdef VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR + if (portabilityEnumerationSupported) { + + createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + + } + #endif + + VkResult result = vkCreateInstance (&createInfo, 0, &instance); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateInstance failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateOverlayBuffer (size_t requiredSize) { + + if (!device) { + + SetError ("Cannot create Vulkan overlay buffer before device initialization"); + return false; + + } + + if (requiredSize == 0) { + + DestroyOverlayResources (); + return true; + + } + + if (overlayBuffer != VK_NULL_HANDLE && overlayMappedData && overlayBufferCapacity >= requiredSize) { + + return true; + + } + + DestroyOverlayResources (); + + VkBufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.size = requiredSize; + createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkResult result = vkCreateBuffer (device, &createInfo, 0, &overlayBuffer); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateBuffer failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + VkMemoryRequirements memoryRequirements; + memset (&memoryRequirements, 0, sizeof (memoryRequirements)); + vkGetBufferMemoryRequirements (device, overlayBuffer, &memoryRequirements); + + VkMemoryAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = memoryRequirements.size; + allocateInfo.memoryTypeIndex = FindMemoryType ( + memoryRequirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + ); + if (allocateInfo.memoryTypeIndex == UINT32_MAX) { + + return false; + + } + + result = vkAllocateMemory (device, &allocateInfo, 0, &overlayBufferMemory); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkAllocateMemory failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + result = vkBindBufferMemory (device, overlayBuffer, overlayBufferMemory, 0); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkBindBufferMemory failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + void* mappedData = 0; + result = vkMapMemory (device, overlayBufferMemory, 0, allocateInfo.allocationSize, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + SetError (std::string ("vkMapMemory failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + overlayMappedData = (unsigned char*)mappedData; + overlayBufferCapacity = requiredSize; + return true; + + } + + + bool VulkanRenderer::CreateRenderPass () { + + VkAttachmentDescription colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.format = swapchainFormat; + colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorAttachmentRef; + memset (&colorAttachmentRef, 0, sizeof (colorAttachmentRef)); + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass; + memset (&subpass, 0, sizeof (subpass)); + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + + VkSubpassDependency dependency; + memset (&dependency, 0, sizeof (dependency)); + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + createInfo.attachmentCount = 1; + createInfo.pAttachments = &colorAttachment; + createInfo.subpassCount = 1; + createInfo.pSubpasses = &subpass; + createInfo.dependencyCount = 1; + createInfo.pDependencies = &dependency; + + VkResult result = vkCreateRenderPass (device, &createInfo, 0, &renderPass); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateRenderPass failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateSurface () { + + uint64_t nativeSurface = window->CreateVulkanSurface ((uintptr_t)instance); + if (!nativeSurface) { + + SetError ("Failed to create Vulkan surface from Lime window"); + return false; + + } + + surface = (VkSurfaceKHR)(uintptr_t)nativeSurface; + return true; + + } + + + bool VulkanRenderer::CreateSwapchain () { + + VkSurfaceCapabilitiesKHR capabilities; + memset (&capabilities, 0, sizeof (capabilities)); + VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (physicalDevice, surface, &capabilities); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + uint32_t formatCount = 0; + result = vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, 0); + if (result != VK_SUCCESS || formatCount == 0) { + + SetError ("Failed to query Vulkan surface formats"); + return false; + + } + + std::vector formats (formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, formats.data ()); + + VkSurfaceFormatKHR surfaceFormat = formats[0]; + for (size_t i = 0; i < formats.size (); ++i) { + + if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + + surfaceFormat = formats[i]; + break; + + } + + } + + uint32_t presentModeCount = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, 0); + std::vector presentModes (presentModeCount > 0 ? presentModeCount : 1, VK_PRESENT_MODE_FIFO_KHR); + if (presentModeCount > 0) { + + vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, presentModes.data ()); + + } + + int currentRequestedVSyncMode = window ? window->GetRequestedVSyncMode () : 0; + VkPresentModeKHR presentMode = ChoosePresentMode (presentModes, currentRequestedVSyncMode); + + int drawableWidth = 0; + int drawableHeight = 0; + window->GetVulkanDrawableSize (&drawableWidth, &drawableHeight); + if (drawableWidth <= 0 || drawableHeight <= 0) { + + swapchainExtent.width = 0; + swapchainExtent.height = 0; + swapchainDirty = true; + return true; + + } + + if (capabilities.currentExtent.width != UINT32_MAX) { + + swapchainExtent = capabilities.currentExtent; + + } else { + + swapchainExtent.width = (uint32_t)(std::max) ((int)capabilities.minImageExtent.width, + (std::min) (drawableWidth, (int)capabilities.maxImageExtent.width)); + swapchainExtent.height = (uint32_t)(std::max) ((int)capabilities.minImageExtent.height, + (std::min) (drawableHeight, (int)capabilities.maxImageExtent.height)); + + } + + uint32_t imageCount = capabilities.minImageCount + 1; + if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) { + + imageCount = capabilities.maxImageCount; + + } + + VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + const VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR + }; + + for (size_t i = 0; i < sizeof (compositeAlphaFlags) / sizeof (compositeAlphaFlags[0]); ++i) { + + if (capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) { + + compositeAlpha = compositeAlphaFlags[i]; + break; + + } + + } + + VkSwapchainCreateInfoKHR createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = swapchainExtent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.preTransform = capabilities.currentTransform; + createInfo.compositeAlpha = compositeAlpha; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = VK_NULL_HANDLE; + + result = vkCreateSwapchainKHR (device, &createInfo, 0, &swapchain); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateSwapchainKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + swapchainFormat = surfaceFormat.format; + swapchainPresentMode = presentMode; + requestedVSyncMode = currentRequestedVSyncMode; + swapchainDirty = false; + + uint32_t swapchainImageCount = 0; + result = vkGetSwapchainImagesKHR (device, swapchain, &swapchainImageCount, 0); + if (result != VK_SUCCESS || swapchainImageCount == 0) { + + SetError ("Failed to query Vulkan swapchain images"); + return false; + + } + + swapchainImages.resize (swapchainImageCount); + result = vkGetSwapchainImagesKHR (device, swapchain, &swapchainImageCount, swapchainImages.data ()); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkGetSwapchainImagesKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateSwapchainResources () { + + if (!CreateSwapchain ()) return false; + if (swapchainExtent.width == 0 || swapchainExtent.height == 0) return true; + if (!CreateImageViews ()) return false; + if (!CreateRenderPass ()) return false; + if (!CreateCommandPool ()) return false; + if (!CreateFramebuffers ()) return false; + if (!CreateCommandBuffers ()) return false; + return true; + + } + + + bool VulkanRenderer::CreateSyncObjects () { + + VkSemaphoreCreateInfo semaphoreInfo; + memset (&semaphoreInfo, 0, sizeof (semaphoreInfo)); + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fenceInfo; + memset (&fenceInfo, 0, sizeof (fenceInfo)); + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + VkResult result = vkCreateSemaphore (device, &semaphoreInfo, 0, &imageAvailableSemaphore); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateSemaphore failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkCreateSemaphore (device, &semaphoreInfo, 0, &renderFinishedSemaphore); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateSemaphore failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkCreateFence (device, &fenceInfo, 0, &inFlightFence); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateFence failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + void VulkanRenderer::DestroyOverlayResources () { + + overlayEnabled = false; + overlayWidth = 0; + overlayHeight = 0; + overlayX = 0; + overlayY = 0; + + if (device && overlayBufferMemory && overlayMappedData && vkUnmapMemory) { + + vkUnmapMemory (device, overlayBufferMemory); + overlayMappedData = 0; + + } + + if (device && vkDestroyBuffer && overlayBuffer) { + + vkDestroyBuffer (device, overlayBuffer, 0); + overlayBuffer = VK_NULL_HANDLE; + + } + + if (device && vkFreeMemory && overlayBufferMemory) { + + vkFreeMemory (device, overlayBufferMemory, 0); + overlayBufferMemory = VK_NULL_HANDLE; + + } + + overlayMappedData = 0; + overlayBufferCapacity = 0; + + } + + + void VulkanRenderer::DestroySwapchainResources () { + + commandBuffers.clear (); + + if (device && vkDestroyCommandPool && commandPool) { + + vkDestroyCommandPool (device, commandPool, 0); + commandPool = VK_NULL_HANDLE; + + } + + for (size_t i = 0; i < framebuffers.size (); ++i) { + + if (framebuffers[i] && device && vkDestroyFramebuffer) { + + vkDestroyFramebuffer (device, framebuffers[i], 0); + + } + + } + + framebuffers.clear (); + + if (device && vkDestroyRenderPass && renderPass) { + + vkDestroyRenderPass (device, renderPass, 0); + renderPass = VK_NULL_HANDLE; + + } + + for (size_t i = 0; i < swapchainImageViews.size (); ++i) { + + if (swapchainImageViews[i] && device && vkDestroyImageView) { + + vkDestroyImageView (device, swapchainImageViews[i], 0); + + } + + } + + swapchainImageViews.clear (); + swapchainImages.clear (); + + if (device && vkDestroySwapchainKHR && swapchain) { + + vkDestroySwapchainKHR (device, swapchain, 0); + swapchain = VK_NULL_HANDLE; + + } + + } + + + uint32_t VulkanRenderer::FindMemoryType (uint32_t typeFilter, VkMemoryPropertyFlags properties) { + + VkPhysicalDeviceMemoryProperties memoryProperties; + memset (&memoryProperties, 0, sizeof (memoryProperties)); + vkGetPhysicalDeviceMemoryProperties (physicalDevice, &memoryProperties); + + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) { + + if ((typeFilter & (1u << i)) && + (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { + + return i; + + } + + } + + SetError ("Failed to find a compatible Vulkan memory type"); + return UINT32_MAX; + + } + + + bool VulkanRenderer::LoadDeviceProcs () { + + if (!vkGetDeviceProcAddr) { + + SetError ("Missing vkGetDeviceProcAddr"); + return false; + + } + + #define LIME_LOAD_DEVICE_PROC(name) \ + name = (PFN_##name)vkGetDeviceProcAddr (device, #name); \ + if (!name) { SetError (std::string ("Missing Vulkan device proc: ") + #name); return false; } + + LIME_LOAD_DEVICE_PROC (vkAllocateMemory); + LIME_LOAD_DEVICE_PROC (vkAcquireNextImageKHR); + LIME_LOAD_DEVICE_PROC (vkAllocateCommandBuffers); + LIME_LOAD_DEVICE_PROC (vkBeginCommandBuffer); + LIME_LOAD_DEVICE_PROC (vkBindBufferMemory); + LIME_LOAD_DEVICE_PROC (vkCmdCopyBufferToImage); + LIME_LOAD_DEVICE_PROC (vkCmdBeginRenderPass); + LIME_LOAD_DEVICE_PROC (vkCmdEndRenderPass); + LIME_LOAD_DEVICE_PROC (vkCmdPipelineBarrier); + LIME_LOAD_DEVICE_PROC (vkCreateBuffer); + LIME_LOAD_DEVICE_PROC (vkCreateCommandPool); + LIME_LOAD_DEVICE_PROC (vkCreateFence); + LIME_LOAD_DEVICE_PROC (vkCreateFramebuffer); + LIME_LOAD_DEVICE_PROC (vkCreateImageView); + LIME_LOAD_DEVICE_PROC (vkCreateRenderPass); + LIME_LOAD_DEVICE_PROC (vkCreateSemaphore); + LIME_LOAD_DEVICE_PROC (vkCreateSwapchainKHR); + LIME_LOAD_DEVICE_PROC (vkDestroyCommandPool); + LIME_LOAD_DEVICE_PROC (vkDestroyBuffer); + LIME_LOAD_DEVICE_PROC (vkDestroyDevice); + LIME_LOAD_DEVICE_PROC (vkDestroyFence); + LIME_LOAD_DEVICE_PROC (vkDestroyFramebuffer); + LIME_LOAD_DEVICE_PROC (vkDestroyImageView); + LIME_LOAD_DEVICE_PROC (vkDestroyRenderPass); + LIME_LOAD_DEVICE_PROC (vkDestroySemaphore); + LIME_LOAD_DEVICE_PROC (vkDestroySwapchainKHR); + LIME_LOAD_DEVICE_PROC (vkDeviceWaitIdle); + LIME_LOAD_DEVICE_PROC (vkEndCommandBuffer); + LIME_LOAD_DEVICE_PROC (vkFreeMemory); + LIME_LOAD_DEVICE_PROC (vkGetBufferMemoryRequirements); + LIME_LOAD_DEVICE_PROC (vkGetSwapchainImagesKHR); + LIME_LOAD_DEVICE_PROC (vkMapMemory); + LIME_LOAD_DEVICE_PROC (vkQueuePresentKHR); + LIME_LOAD_DEVICE_PROC (vkQueueSubmit); + LIME_LOAD_DEVICE_PROC (vkResetCommandPool); + LIME_LOAD_DEVICE_PROC (vkResetFences); + LIME_LOAD_DEVICE_PROC (vkUnmapMemory); + LIME_LOAD_DEVICE_PROC (vkWaitForFences); + + #undef LIME_LOAD_DEVICE_PROC + + return true; + + } + + + bool VulkanRenderer::LoadGlobalProcs () { + + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)window->GetVulkanInstanceProcAddr (); + + if (!vkGetInstanceProcAddr) { + + SetError ("SDL did not expose vkGetInstanceProcAddr"); + return false; + + } + + #define LIME_LOAD_GLOBAL_PROC(name) \ + name = (PFN_##name)vkGetInstanceProcAddr (VK_NULL_HANDLE, #name); \ + if (!name) { SetError (std::string ("Missing Vulkan global proc: ") + #name); return false; } + + LIME_LOAD_GLOBAL_PROC (vkCreateInstance); + LIME_LOAD_GLOBAL_PROC (vkEnumerateInstanceExtensionProperties); + vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkEnumerateInstanceVersion"); + + #undef LIME_LOAD_GLOBAL_PROC + + return true; + + } + + + bool VulkanRenderer::LoadInstanceProcs () { + + #define LIME_LOAD_INSTANCE_PROC(name) \ + name = (PFN_##name)vkGetInstanceProcAddr (instance, #name); \ + if (!name) { SetError (std::string ("Missing Vulkan instance proc: ") + #name); return false; } + + LIME_LOAD_INSTANCE_PROC (vkCreateDevice); + LIME_LOAD_INSTANCE_PROC (vkDestroyInstance); + LIME_LOAD_INSTANCE_PROC (vkDestroySurfaceKHR); + LIME_LOAD_INSTANCE_PROC (vkEnumerateDeviceExtensionProperties); + LIME_LOAD_INSTANCE_PROC (vkEnumeratePhysicalDevices); + LIME_LOAD_INSTANCE_PROC (vkGetDeviceProcAddr); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceMemoryProperties); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceProperties); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceQueueFamilyProperties); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfaceFormatsKHR); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfacePresentModesKHR); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfaceSupportKHR); + LIME_LOAD_INSTANCE_PROC (vkGetDeviceQueue); + + #undef LIME_LOAD_INSTANCE_PROC + + return true; + + } + + + bool VulkanRenderer::PickPhysicalDevice () { + + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + if (result != VK_SUCCESS || deviceCount == 0) { + + SetError ("No Vulkan physical devices were found"); + return false; + + } + + std::vector physicalDevices (deviceCount); + vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + for (size_t deviceIndex = 0; deviceIndex < physicalDevices.size (); ++deviceIndex) { + + VkPhysicalDevice candidate = physicalDevices[deviceIndex]; + + uint32_t extensionCount = 0; + vkEnumerateDeviceExtensionProperties (candidate, 0, &extensionCount, 0); + std::vector extensions (extensionCount); + if (extensionCount > 0) { + + vkEnumerateDeviceExtensionProperties (candidate, 0, &extensionCount, extensions.data ()); + + } + + bool hasSwapchain = false; + bool hasPortabilitySubset = false; + + for (size_t i = 0; i < extensions.size (); ++i) { + + if (strcmp (extensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) { + + hasSwapchain = true; + + } + + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + if (strcmp (extensions[i].extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) { + + hasPortabilitySubset = true; + + } + #endif + + } + + if (!hasSwapchain) { + + continue; + + } + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (candidate, &queueFamilyCount, 0); + if (queueFamilyCount == 0) { + + continue; + + } + + std::vector queueFamilies (queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties (candidate, &queueFamilyCount, queueFamilies.data ()); + + for (uint32_t queueIndex = 0; queueIndex < queueFamilyCount; ++queueIndex) { + + VkBool32 supportsPresent = VK_FALSE; + vkGetPhysicalDeviceSurfaceSupportKHR (candidate, queueIndex, surface, &supportsPresent); + + if ((queueFamilies[queueIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) && supportsPresent) { + + physicalDevice = candidate; + queueFamilyIndex = queueIndex; + portabilitySubsetSupported = hasPortabilitySubset; + vkGetPhysicalDeviceProperties (physicalDevice, &physicalDeviceProperties); + return true; + + } + + } + + } + + SetError ("Failed to find a Vulkan physical device with graphics and present support"); + return false; + + } + + + bool VulkanRenderer::RecordCommandBuffer (uint32_t imageIndex, float red, float green, float blue, float alpha) { + + if (imageIndex >= commandBuffers.size () || imageIndex >= framebuffers.size ()) { + + SetError ("Invalid Vulkan swapchain image index"); + return false; + + } + + VkCommandBuffer commandBuffer = commandBuffers[imageIndex]; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkBeginCommandBuffer failed: ") + VulkanResultToString (result)); + return false; + + } + + VkClearValue clearValue; + clearValue.color.float32[0] = red; + clearValue.color.float32[1] = green; + clearValue.color.float32[2] = blue; + clearValue.color.float32[3] = alpha; + + VkRenderPassBeginInfo renderPassInfo; + memset (&renderPassInfo, 0, sizeof (renderPassInfo)); + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassInfo.renderPass = renderPass; + renderPassInfo.framebuffer = framebuffers[imageIndex]; + renderPassInfo.renderArea.offset.x = 0; + renderPassInfo.renderArea.offset.y = 0; + renderPassInfo.renderArea.extent = swapchainExtent; + renderPassInfo.clearValueCount = 1; + renderPassInfo.pClearValues = &clearValue; + + vkCmdBeginRenderPass (commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdEndRenderPass (commandBuffer); + + uint32_t copyWidth = overlayWidth; + uint32_t copyHeight = overlayHeight; + int copyX = overlayX; + int copyY = overlayY; + VkDeviceSize bufferOffset = 0; + bool hasOverlayCopy = overlayEnabled && overlayBuffer && overlayMappedData && overlayWidth > 0 && overlayHeight > 0; + + if (hasOverlayCopy) { + + if (copyX < 0) { + + uint32_t clipped = (uint32_t)(-copyX); + if (clipped >= copyWidth) { + + hasOverlayCopy = false; + + } else { + + bufferOffset += (VkDeviceSize)clipped * 4; + copyWidth -= clipped; + copyX = 0; + + } + + } + + if (hasOverlayCopy && copyY < 0) { + + uint32_t clipped = (uint32_t)(-copyY); + if (clipped >= copyHeight) { + + hasOverlayCopy = false; + + } else { + + bufferOffset += (VkDeviceSize)clipped * (VkDeviceSize)overlayWidth * 4; + copyHeight -= clipped; + copyY = 0; + + } + + } + + if (hasOverlayCopy && + (copyX >= (int)swapchainExtent.width || copyY >= (int)swapchainExtent.height)) { + + hasOverlayCopy = false; + + } + + if (hasOverlayCopy && (uint32_t)copyX + copyWidth > swapchainExtent.width) { + + copyWidth = swapchainExtent.width - (uint32_t)copyX; + + } + + if (hasOverlayCopy && (uint32_t)copyY + copyHeight > swapchainExtent.height) { + + copyHeight = swapchainExtent.height - (uint32_t)copyY; + + } + + hasOverlayCopy = hasOverlayCopy && copyWidth > 0 && copyHeight > 0; + + } + + VkImageMemoryBarrier imageBarrier; + memset (&imageBarrier, 0, sizeof (imageBarrier)); + imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageBarrier.image = swapchainImages[imageIndex]; + imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBarrier.subresourceRange.baseMipLevel = 0; + imageBarrier.subresourceRange.levelCount = 1; + imageBarrier.subresourceRange.baseArrayLayer = 0; + imageBarrier.subresourceRange.layerCount = 1; + + if (hasOverlayCopy) { + + imageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + + vkCmdPipelineBarrier ( + commandBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, 0, + 0, 0, + 1, &imageBarrier + ); + + VkBufferImageCopy copyRegion; + memset (©Region, 0, sizeof (copyRegion)); + copyRegion.bufferOffset = bufferOffset; + copyRegion.bufferRowLength = overlayWidth; + copyRegion.bufferImageHeight = overlayHeight; + copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.imageSubresource.mipLevel = 0; + copyRegion.imageSubresource.baseArrayLayer = 0; + copyRegion.imageSubresource.layerCount = 1; + copyRegion.imageOffset.x = copyX; + copyRegion.imageOffset.y = copyY; + copyRegion.imageOffset.z = 0; + copyRegion.imageExtent.width = copyWidth; + copyRegion.imageExtent.height = copyHeight; + copyRegion.imageExtent.depth = 1; + + vkCmdCopyBufferToImage (commandBuffer, overlayBuffer, swapchainImages[imageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); + + imageBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageBarrier.dstAccessMask = 0; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + vkCmdPipelineBarrier ( + commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, 0, + 0, 0, + 1, &imageBarrier + ); + + } else { + + imageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageBarrier.dstAccessMask = 0; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + vkCmdPipelineBarrier ( + commandBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, 0, + 0, 0, + 1, &imageBarrier + ); + + } + + result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkEndCommandBuffer failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::RecreateSwapchain () { + + if (!device) { + + return false; + + } + + int drawableWidth = 0; + int drawableHeight = 0; + window->GetVulkanDrawableSize (&drawableWidth, &drawableHeight); + if (drawableWidth <= 0 || drawableHeight <= 0) { + + if (swapchain || !swapchainImages.empty () || !swapchainImageViews.empty () || !framebuffers.empty () || !commandBuffers.empty () || commandPool || renderPass) { + + if (vkDeviceWaitIdle (device) != VK_SUCCESS) { + + SetError ("vkDeviceWaitIdle failed while suspending the swapchain"); + return false; + + } + + DestroySwapchainResources (); + + } + + swapchainExtent.width = 0; + swapchainExtent.height = 0; + swapchainDirty = true; + lastError.clear (); + return true; + + } + + if (vkDeviceWaitIdle (device) != VK_SUCCESS) { + + SetError ("vkDeviceWaitIdle failed during swapchain recreation"); + return false; + + } + + DestroySwapchainResources (); + if (!CreateSwapchainResources ()) { + + swapchainDirty = true; + return false; + + } + + swapchainDirty = (swapchain == VK_NULL_HANDLE || swapchainExtent.width == 0 || swapchainExtent.height == 0); + lastError.clear (); + return true; + + } + + + void VulkanRenderer::SetError (const std::string& value) { + + lastError = value; + + } + + +} diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index fe8bb2cb41..7db7353e27 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -328,6 +328,8 @@ class NativeCFFI @:cffi private static function lime_window_get_context_type(handle:Dynamic):Dynamic; + @:cffi private static function lime_window_create_vulkan_surface(handle:Dynamic, instanceHigh:Int, instanceLow:Int):Dynamic; + @:cffi private static function lime_window_get_display(handle:Dynamic):Int; @:cffi private static function lime_window_get_display_mode(handle:Dynamic):Dynamic; @@ -344,6 +346,38 @@ class NativeCFFI @:cffi private static function lime_window_get_text_input_enabled(handle:Dynamic):Bool; + @:cffi private static function lime_window_get_vulkan_drawable_size(handle:Dynamic):Dynamic; + + @:cffi private static function lime_window_get_vulkan_instance_extensions(handle:Dynamic):Array; + + @:cffi private static function lime_window_get_vulkan_instance_proc_addr(handle:Dynamic):Dynamic; + + @:cffi private static function lime_vk_create_instance(handle:Dynamic, applicationName:String):Dynamic; + + @:cffi private static function lime_vk_destroy_instance(handle:Dynamic, instanceHigh:Int, instanceLow:Int):Void; + + @:cffi private static function lime_vk_destroy_surface(handle:Dynamic, instanceHigh:Int, instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Void; + + @:cffi private static function lime_vk_get_physical_devices(handle:Dynamic, instanceHigh:Int, instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Dynamic; + + @:cffi private static function lime_vk_get_last_error():Dynamic; + + @:cffi private static function lime_vulkan_renderer_create(handle:Dynamic, applicationName:String):CFFIPointer; + + @:cffi private static function lime_vulkan_renderer_destroy(handle:Dynamic):Void; + + @:cffi private static function lime_vulkan_renderer_get_info(handle:Dynamic):Dynamic; + + @:cffi private static function lime_vulkan_renderer_get_last_error():Dynamic; + + @:cffi private static function lime_vulkan_renderer_set_overlay(handle:Dynamic, bytes:Dynamic, width:Int, height:Int, x:Int, y:Int):Bool; + + @:cffi private static function lime_vulkan_renderer_clear_overlay(handle:Dynamic):Bool; + + @:cffi private static function lime_vulkan_renderer_render(handle:Dynamic, red:Float, green:Float, blue:Float, alpha:Float):Bool; + + @:cffi private static function lime_vulkan_renderer_resize(handle:Dynamic):Bool; + @:cffi private static function lime_window_get_width(handle:Dynamic):Int; @:cffi private static function lime_window_get_x(handle:Dynamic):Int; @@ -633,6 +667,8 @@ class NativeCFFI private static var lime_window_get_context = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_context", "od", false)); private static var lime_window_get_context_type = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_get_context_type", "oo", false)); + private static var lime_window_create_vulkan_surface = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_create_vulkan_surface", "oiio", false)); private static var lime_window_get_display = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_display", "oi", false)); private static var lime_window_get_display_mode = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_get_display_mode", "oo", false)); @@ -644,6 +680,38 @@ class NativeCFFI private static var lime_window_get_scale = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_scale", "od", false)); private static var lime_window_get_text_input_enabled = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_window_get_text_input_enabled", "ob", false)); + private static var lime_window_get_vulkan_drawable_size = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_get_vulkan_drawable_size", "oo", false)); + private static var lime_window_get_vulkan_instance_extensions = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_get_vulkan_instance_extensions", "oo", false)); + private static var lime_window_get_vulkan_instance_proc_addr = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_get_vulkan_instance_proc_addr", "oo", false)); + private static var lime_vk_create_instance = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_instance", "oso", false)); + private static var lime_vk_destroy_instance = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_instance", "oiiv", false)); + private static var lime_vk_destroy_surface = new cpp.CallableInt->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_surface", "oiiiiv", false)); + private static var lime_vk_get_physical_devices = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_physical_devices", "oiiiio", false)); + private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_last_error", "o", false)); + private static var lime_vulkan_renderer_create = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_create", "oso", false)); + private static var lime_vulkan_renderer_destroy = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_destroy", "ov", false)); + private static var lime_vulkan_renderer_get_info = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_get_info", "oo", false)); + private static var lime_vulkan_renderer_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_get_last_error", "o", false)); + private static var lime_vulkan_renderer_set_overlay = new cpp.Callablecpp.Object->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_set_overlay", "ooiiiib", false)); + private static var lime_vulkan_renderer_clear_overlay = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_clear_overlay", "ob", false)); + private static var lime_vulkan_renderer_render = new cpp.CallableFloat->Float->Float->Float->Bool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_render", "oddddb", false)); + private static var lime_vulkan_renderer_resize = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_resize", "ob", false)); private static var lime_window_get_width = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_width", "oi", false)); private static var lime_window_get_x = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_x", "oi", false)); private static var lime_window_get_y = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_y", "oi", false)); @@ -831,6 +899,7 @@ class NativeCFFI private static var lime_window_focus = CFFI.load("lime", "lime_window_focus", 1); private static var lime_window_get_context = CFFI.load("lime", "lime_window_get_context", 1); private static var lime_window_get_context_type = CFFI.load("lime", "lime_window_get_context_type", 1); + private static var lime_window_create_vulkan_surface = CFFI.load("lime", "lime_window_create_vulkan_surface", 3); private static var lime_window_get_display = CFFI.load("lime", "lime_window_get_display", 1); private static var lime_window_get_display_mode = CFFI.load("lime", "lime_window_get_display_mode", 1); private static var lime_window_get_height = CFFI.load("lime", "lime_window_get_height", 1); @@ -839,6 +908,22 @@ class NativeCFFI private static var lime_window_get_opacity = CFFI.load("lime", "lime_window_get_opacity", 1); private static var lime_window_get_scale = CFFI.load("lime", "lime_window_get_scale", 1); private static var lime_window_get_text_input_enabled = CFFI.load("lime", "lime_window_get_text_input_enabled", 1); + private static var lime_window_get_vulkan_drawable_size = CFFI.load("lime", "lime_window_get_vulkan_drawable_size", 1); + private static var lime_window_get_vulkan_instance_extensions = CFFI.load("lime", "lime_window_get_vulkan_instance_extensions", 1); + private static var lime_window_get_vulkan_instance_proc_addr = CFFI.load("lime", "lime_window_get_vulkan_instance_proc_addr", 1); + private static var lime_vk_create_instance = CFFI.load("lime", "lime_vk_create_instance", 2); + private static var lime_vk_destroy_instance = CFFI.load("lime", "lime_vk_destroy_instance", 3); + private static var lime_vk_destroy_surface = CFFI.load("lime", "lime_vk_destroy_surface", 5); + private static var lime_vk_get_physical_devices = CFFI.load("lime", "lime_vk_get_physical_devices", 5); + private static var lime_vk_get_last_error = CFFI.load("lime", "lime_vk_get_last_error", 0); + private static var lime_vulkan_renderer_create = CFFI.load("lime", "lime_vulkan_renderer_create", 2); + private static var lime_vulkan_renderer_destroy = CFFI.load("lime", "lime_vulkan_renderer_destroy", 1); + private static var lime_vulkan_renderer_get_info = CFFI.load("lime", "lime_vulkan_renderer_get_info", 1); + private static var lime_vulkan_renderer_get_last_error = CFFI.load("lime", "lime_vulkan_renderer_get_last_error", 0); + private static var lime_vulkan_renderer_set_overlay = CFFI.load("lime", "lime_vulkan_renderer_set_overlay", 6); + private static var lime_vulkan_renderer_clear_overlay = CFFI.load("lime", "lime_vulkan_renderer_clear_overlay", 1); + private static var lime_vulkan_renderer_render = CFFI.load("lime", "lime_vulkan_renderer_render", 5); + private static var lime_vulkan_renderer_resize = CFFI.load("lime", "lime_vulkan_renderer_resize", 1); private static var lime_window_get_width = CFFI.load("lime", "lime_window_get_width", 1); private static var lime_window_get_x = CFFI.load("lime", "lime_window_get_x", 1); private static var lime_window_get_y = CFFI.load("lime", "lime_window_get_y", 1); @@ -1431,6 +1516,12 @@ class NativeCFFI return null; } + @:hlNative("lime", "hl_window_create_vulkan_surface") private static function lime_window_create_vulkan_surface(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int):Dynamic + { + return null; + } + @:hlNative("lime", "hl_window_get_display") private static function lime_window_get_display(handle:CFFIPointer):Int { return 0; @@ -1463,6 +1554,84 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_window_get_vulkan_drawable_size") private static function lime_window_get_vulkan_drawable_size(handle:CFFIPointer):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_window_get_vulkan_instance_extensions") private static function lime_window_get_vulkan_instance_extensions( + handle:CFFIPointer):hl.NativeArray + { + return null; + } + + @:hlNative("lime", "hl_window_get_vulkan_instance_proc_addr") private static function lime_window_get_vulkan_instance_proc_addr(handle:CFFIPointer):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_create_instance") private static function lime_vk_create_instance(handle:CFFIPointer, applicationName:String):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_instance") private static function lime_vk_destroy_instance(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_destroy_surface") private static function lime_vk_destroy_surface(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_physical_devices") private static function lime_vk_get_physical_devices(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_get_last_error") private static function lime_vk_get_last_error():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_vulkan_renderer_create") private static function lime_vulkan_renderer_create(handle:CFFIPointer, + applicationName:String):CFFIPointer + { + return null; + } + + @:hlNative("lime", "hl_vulkan_renderer_destroy") private static function lime_vulkan_renderer_destroy(handle:CFFIPointer):Void {} + + @:hlNative("lime", "hl_vulkan_renderer_get_info") private static function lime_vulkan_renderer_get_info(handle:CFFIPointer):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_vulkan_renderer_get_last_error") private static function lime_vulkan_renderer_get_last_error():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_vulkan_renderer_set_overlay") private static function lime_vulkan_renderer_set_overlay(handle:CFFIPointer, + bytes:hl.Bytes, width:Int, height:Int, x:Int, y:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vulkan_renderer_clear_overlay") private static function lime_vulkan_renderer_clear_overlay(handle:CFFIPointer):Bool + { + return false; + } + + @:hlNative("lime", "hl_vulkan_renderer_render") private static function lime_vulkan_renderer_render(handle:CFFIPointer, red:Float, green:Float, + blue:Float, alpha:Float):Bool + { + return false; + } + + @:hlNative("lime", "hl_vulkan_renderer_resize") private static function lime_vulkan_renderer_resize(handle:CFFIPointer):Bool + { + return false; + } + @:hlNative("lime", "hl_window_get_width") private static function lime_window_get_width(handle:CFFIPointer):Int { return 0; diff --git a/src/lime/_internal/backend/native/NativeWindow.hx b/src/lime/_internal/backend/native/NativeWindow.hx index 0f6028a296..3da3ec90e2 100644 --- a/src/lime/_internal/backend/native/NativeWindow.hx +++ b/src/lime/_internal/backend/native/NativeWindow.hx @@ -14,6 +14,7 @@ import lime.graphics.Image; import lime.graphics.ImageBuffer; import lime.graphics.OpenGLRenderContext; import lime.graphics.RenderContext; +import lime.graphics.VulkanRenderContext; import lime.math.Rectangle; import lime.math.Vector2; import lime.system.CFFI; @@ -79,9 +80,13 @@ class NativeWindow contextAttributes.vsync = (resolvedVSyncMode != VSyncMode.Off); #if (cairo || (!lime_opengl && !lime_opengles)) - contextAttributes.type = CAIRO; + if (!Reflect.hasField(contextAttributes, "type") || contextAttributes.type != VULKAN) + { + contextAttributes.type = CAIRO; + } #end if (Reflect.hasField(contextAttributes, "type") && contextAttributes.type == CAIRO) contextAttributes.hardware = false; + if (Reflect.hasField(contextAttributes, "type") && contextAttributes.type == VULKAN) contextAttributes.hardware = true; if (Reflect.hasField(attributes, "allowHighDPI") && attributes.allowHighDPI) flags |= cast WindowFlags.WINDOW_FLAG_ALLOW_HIGHDPI; if (Reflect.hasField(attributes, "alwaysOnTop") && attributes.alwaysOnTop) flags |= cast WindowFlags.WINDOW_FLAG_ALWAYS_ON_TOP; @@ -106,6 +111,7 @@ class NativeWindow if (contextAttributes.depth) flags |= cast WindowFlags.WINDOW_FLAG_DEPTH_BUFFER; if (contextAttributes.hardware) flags |= cast WindowFlags.WINDOW_FLAG_HARDWARE; + if (Reflect.hasField(contextAttributes, "type") && contextAttributes.type == VULKAN) flags |= cast WindowFlags.WINDOW_FLAG_VULKAN; if (contextAttributes.stencil) flags |= cast WindowFlags.WINDOW_FLAG_STENCIL_BUFFER; if (contextAttributes.vsync) flags |= cast WindowFlags.WINDOW_FLAG_VSYNC; @@ -156,6 +162,12 @@ class NativeWindow { GL.context = gl; } + case "vulkan": + useHardware = true; + contextAttributes.hardware = true; + context.vulkan = new VulkanRenderContext(handle); + context.type = VULKAN; + context.version = Reflect.hasField(contextAttributes, "version") && contextAttributes.version != null ? contextAttributes.version : ""; default: useHardware = false; @@ -742,4 +754,5 @@ class NativeWindow var WINDOW_FLAG_MAXIMIZED = 0x00004000; var WINDOW_FLAG_ALWAYS_ON_TOP = 0x00008000; var WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000; + var WINDOW_FLAG_VULKAN = 0x00020000; } diff --git a/src/lime/graphics/RenderContext.hx b/src/lime/graphics/RenderContext.hx index 4443ffee9b..d269542e76 100644 --- a/src/lime/graphics/RenderContext.hx +++ b/src/lime/graphics/RenderContext.hx @@ -86,6 +86,13 @@ class RenderContext #if (!lime_doc_gen || native || (js && html5)) public var webgl2(default, null):WebGL2RenderContext; #end + + /** + Access to the current Vulkan render API bootstrap helpers, if available + **/ + #if (!lime_doc_gen || native) + public var vulkan(default, null):VulkanRenderContext; + #end public var window(default, null):Window; @:noCompletion private function new() {} diff --git a/src/lime/graphics/RenderContextType.hx b/src/lime/graphics/RenderContextType.hx index 8dddd1aa48..6b0fa93ff7 100644 --- a/src/lime/graphics/RenderContextType.hx +++ b/src/lime/graphics/RenderContextType.hx @@ -40,6 +40,11 @@ package lime.graphics; **/ var WEBGL = "webgl"; + /** + Describes a Vulkan render context + **/ + var VULKAN = "vulkan"; + /** Describes a custom render context **/ diff --git a/src/lime/graphics/VulkanRenderContext.hx b/src/lime/graphics/VulkanRenderContext.hx new file mode 100644 index 0000000000..a33494aa6a --- /dev/null +++ b/src/lime/graphics/VulkanRenderContext.hx @@ -0,0 +1,190 @@ +package lime.graphics; + +import haxe.Int64; +import lime.graphics.vulkan.VKRenderer; +import lime.math.Vector2; +import lime.system.CFFI; +import lime.system.CFFIPointer; + +#if hl +import hl.Bytes as HLBytes; +import hl.NativeArray; +#end +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +/** + The `VulkanRenderContext` exposes native Vulkan window bootstrap helpers when + Vulkan is the render context type of the current `Window`. + + Lime does not provide Vulkan API bindings or manage swapchains for you. + Instead, this context focuses on the window-specific pieces an external + Vulkan layer needs: + + - required instance extensions for the current window + - the current drawable size in pixels + - Vulkan surface creation for an existing `VkInstance` + - access to `vkGetInstanceProcAddr` +**/ +@:access(lime._internal.backend.native.NativeCFFI) +class VulkanRenderContext +{ + public var type(default, null):RenderContextType; + public var version(default, null):String; + + private var __windowHandle:CFFIPointer; + + @:allow(lime._internal.backend.native.NativeWindow) + private function new(windowHandle:CFFIPointer) + { + __windowHandle = windowHandle; + type = VULKAN; + version = ""; + } + + /** + Creates a Vulkan surface for the current window using an existing + `VkInstance` handle, or an object that exposes a `get()` method returning + that handle. + **/ + public function createSurface(instance:Dynamic):Int64 + { + var surfaceData:Dynamic = null; + + #if (!macro && lime_cffi) + var instanceHandle = __resolveHandle(instance); + if (instanceHandle.high != 0 || instanceHandle.low != 0) + { + surfaceData = NativeCFFI.lime_window_create_vulkan_surface(__windowHandle, instanceHandle.high, instanceHandle.low); + } + #end + + if (surfaceData != null) + { + return Int64.make(surfaceData.high, surfaceData.low); + } + + return Int64.ofInt(0); + } + + /** + Gets the current drawable size in pixels for the Vulkan surface. + **/ + public function getDrawableSize(result:Vector2 = null):Vector2 + { + if (result == null) result = new Vector2(); + + #if (!macro && lime_cffi) + var size:Dynamic = NativeCFFI.lime_window_get_vulkan_drawable_size(__windowHandle); + if (size != null) + { + result.x = size.width; + result.y = size.height; + return result; + } + #end + + result.x = 0; + result.y = 0; + return result; + } + + /** + Returns the list of Vulkan instance extensions required to create a + surface for this window. + **/ + public function getInstanceExtensions():Array + { + #if (!macro && lime_cffi) + #if hl + var bytes:NativeArray = cast NativeCFFI.lime_window_get_vulkan_instance_extensions(__windowHandle); + if (bytes != null) + { + var extensions = new Array(); + for (i in 0...bytes.length) + { + extensions[i] = CFFI.stringValue(bytes[i]); + } + return extensions; + } + #else + var extensions:Array = cast NativeCFFI.lime_window_get_vulkan_instance_extensions(__windowHandle); + if (extensions != null) + { + return extensions; + } + #end + #end + + return []; + } + + /** + Returns the native address of SDL's `vkGetInstanceProcAddr` function. + **/ + public function getInstanceProcAddr():Int64 + { + #if (!macro && lime_cffi) + var handleData:Dynamic = NativeCFFI.lime_window_get_vulkan_instance_proc_addr(__windowHandle); + if (handleData != null) + { + return Int64.make(handleData.high, handleData.low); + } + #end + + return Int64.ofInt(0); + } + + /** + Creates a minimal Vulkan swapchain renderer for the current window. + + This is intentionally narrow and currently only exposes clear-and-present + rendering so we can validate Lime's Vulkan window path end-to-end. + The renderer respects the current Lime `vsyncMode` preference when it + chooses a swapchain present mode. + **/ + public function createRenderer(applicationName:String = "Lime"):VKRenderer + { + #if (!macro && lime_cffi) + var handle = NativeCFFI.lime_vulkan_renderer_create(__windowHandle, applicationName); + if (handle != null) + { + return new VKRenderer(handle); + } + #end + + return null; + } + + private static function __resolveHandle(value:Dynamic):Int64 + { + if (value == null) return Int64.ofInt(0); + + var high:Dynamic = Reflect.field(value, "high"); + var low:Dynamic = Reflect.field(value, "low"); + if (high != null && low != null) + { + return Int64.make(high, low); + } + + switch (Type.typeof(value)) + { + case TInt: + return Int64.ofInt(cast value); + default: + } + + var getField = Reflect.field(value, "get"); + if (getField != null) + { + try + { + return __resolveHandle(Reflect.callMethod(value, getField, [])); + } + catch (e:Dynamic) {} + } + + return Int64.ofInt(0); + } +} diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx new file mode 100644 index 0000000000..54e9b17032 --- /dev/null +++ b/src/lime/graphics/vulkan/VK.hx @@ -0,0 +1,154 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.graphics.VulkanRenderContext; +import lime.system.CFFI; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + Entry point for Lime's lightweight Vulkan bootstrap helpers. + + This API is intentionally smaller than `lime.graphics.opengl.GL`. It focuses + on the native window/bootstrap work needed to get a Vulkan app started while + Lime's wider Vulkan surface continues to grow. +**/ +class VK +{ + /** + Creates a managed `VkInstance` for the current Lime Vulkan window. + **/ + public static function createInstance(context:VulkanRenderContext, applicationName:String = "Lime"):VKInstance + { + if (context == null) + { + return null; + } + + #if (!macro && lime_cffi) + var handleData:Dynamic = NativeCFFI.lime_vk_create_instance(context.__windowHandle, applicationName); + if (handleData != null) + { + var handle = __makeHandle(handleData); + if (!__isZero(handle)) + { + return new VKInstance(context, handle); + } + } + #end + + return null; + } + + /** + Returns the last bootstrap-layer Vulkan error surfaced by Lime. + **/ + public static function getLastError():String + { + #if (!macro && lime_cffi) + var value:Dynamic = NativeCFFI.lime_vk_get_last_error(); + if (value != null) + { + return CFFI.stringValue(value); + } + #end + + return ""; + } + + /** + Picks a preferred physical device from an enumerated device list. + This currently prefers graphics-capable devices, optionally requiring + present support, and favors discrete GPUs by default. + **/ + public static function pickPhysicalDevice(devices:Array, requirePresent:Bool = false, + preferDiscrete:Bool = true):VKPhysicalDevice + { + if (devices == null || devices.length == 0) + { + return null; + } + + var bestDevice:VKPhysicalDevice = null; + var bestScore = -1; + + for (device in devices) + { + var score = __scorePhysicalDevice(device, requirePresent, preferDiscrete); + if (score > bestScore) + { + bestScore = score; + bestDevice = device; + } + } + + return bestDevice; + } + + public static inline function versionString(version:Int):String + { + var major = version >>> 22; + var minor = (version >>> 12) & 0x3FF; + var patch = version & 0xFFF; + return major + "." + minor + "." + patch; + } + + @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKInstance) + @:allow(lime.graphics.vulkan.VKPhysicalDevice) + private static function __makeHandle(value:Dynamic):Int64 + { + if (value == null) + { + return Int64.ofInt(0); + } + + return Int64.make(value.high, value.low); + } + + @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKInstance) + private static inline function __isZero(handle:Int64):Bool + { + return handle.high == 0 && handle.low == 0; + } + + private static function __scorePhysicalDevice(device:VKPhysicalDevice, requirePresent:Bool, preferDiscrete:Bool):Int + { + if (device == null || !device.hasQueueFamily(true, requirePresent)) + { + return -1; + } + + var score = 0; + + switch (device.deviceType) + { + case 2: + score += preferDiscrete ? 400 : 250; + case 1: + score += preferDiscrete ? 300 : 400; + case 3: + score += 150; + case 4: + score += 100; + default: + score += 50; + } + + var primaryQueue = device.getQueueFamily(true, requirePresent); + if (primaryQueue != null) + { + score += primaryQueue.queueCount * 2; + if (primaryQueue.supportsTransfer) score += 4; + if (primaryQueue.supportsCompute) score += 2; + } + + score += device.queueFamilies.length; + return score; + } +} diff --git a/src/lime/graphics/vulkan/VKInstance.hx b/src/lime/graphics/vulkan/VKInstance.hx new file mode 100644 index 0000000000..de6a9af7c5 --- /dev/null +++ b/src/lime/graphics/vulkan/VKInstance.hx @@ -0,0 +1,112 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.graphics.VulkanRenderContext; +import lime.system.CFFI; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A lightweight managed `VkInstance` wrapper created through `VK.createInstance`. +**/ +class VKInstance +{ + public var context(default, null):VulkanRenderContext; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VK) + private function new(context:VulkanRenderContext, handle:Int64) + { + this.context = context; + this.handle = handle; + } + + /** + Creates a `VKSurface` for the current window using this instance. + **/ + public function createSurface(contextOverride:VulkanRenderContext = null):VKSurface + { + var activeContext = (contextOverride != null) ? contextOverride : context; + + if (activeContext == null || VK.__isZero(handle)) + { + return null; + } + + #if (!macro && lime_cffi) + var surfaceData:Dynamic = NativeCFFI.lime_window_create_vulkan_surface(activeContext.__windowHandle, handle.high, handle.low); + if (surfaceData != null) + { + return new VKSurface(activeContext, this, surfaceData.high, surfaceData.low); + } + #end + + return null; + } + + /** + Destroys the managed `VkInstance`. + **/ + public function dispose():Void + { + #if (!macro && lime_cffi) + if (context != null && !VK.__isZero(handle)) + { + NativeCFFI.lime_vk_destroy_instance(context.__windowHandle, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + /** + Enumerates physical devices visible to this instance. If a surface is + provided, queue family presentation support is populated for that surface. + **/ + public function enumeratePhysicalDevices(surface:VKSurface = null):Array + { + var devices = new Array(); + + if (context == null || VK.__isZero(handle)) + { + return devices; + } + + #if (!macro && lime_cffi) + var result:Dynamic = NativeCFFI.lime_vk_get_physical_devices(context.__windowHandle, handle.high, handle.low, surface != null ? surface.high : 0, + surface != null ? surface.low : 0); + + if (result != null) + { + var length:Int = untyped result.length; + for (i in 0...length) + { + devices.push(new VKPhysicalDevice(this, untyped result[i])); + } + } + #end + + return devices; + } + + /** + Selects a preferred physical device using Lime's lightweight heuristics. + **/ + public function pickPhysicalDevice(surface:VKSurface = null, preferDiscrete:Bool = true):VKPhysicalDevice + { + return VK.pickPhysicalDevice(enumeratePhysicalDevices(surface), surface != null && surface.isValid(), preferDiscrete); + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx new file mode 100644 index 0000000000..47d1b5b214 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -0,0 +1,87 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.system.CFFI; + +/** + Describes a Vulkan physical device discovered through a `VKInstance`. +**/ +class VKPhysicalDevice +{ + public var instance(default, null):VKInstance; + public var handle(default, null):Int64; + public var name(default, null):String; + public var apiVersion(default, null):Int; + public var apiVersionString(default, null):String; + public var driverVersion(default, null):Int; + public var vendorID(default, null):Int; + public var deviceID(default, null):Int; + public var deviceType(default, null):Int; + public var deviceTypeName(default, null):String; + public var isDiscrete(default, null):Bool; + public var supportsPresent(default, null):Bool; + public var queueFamilies(default, null):Array; + + @:allow(lime.graphics.vulkan.VKInstance) + private function new(instance:VKInstance, data:Dynamic) + { + this.instance = instance; + handle = VK.__makeHandle(data.handle); + name = (data.name != null) ? CFFI.stringValue(data.name) : ""; + apiVersion = data.apiVersion; + apiVersionString = VK.versionString(apiVersion); + driverVersion = data.driverVersion; + vendorID = data.vendorID; + deviceID = data.deviceID; + deviceType = data.deviceType; + deviceTypeName = switch (deviceType) + { + case 1: "integrated-gpu"; + case 2: "discrete-gpu"; + case 3: "virtual-gpu"; + case 4: "cpu"; + default: "other"; + } + isDiscrete = (deviceType == 2); + supportsPresent = false; + + queueFamilies = []; + var rawQueueFamilies:Dynamic = data.queueFamilies; + if (rawQueueFamilies != null) + { + var length:Int = untyped rawQueueFamilies.length; + for (i in 0...length) + { + var queueFamily = new VKQueueFamilyInfo(untyped rawQueueFamilies[i]); + queueFamilies.push(queueFamily); + if (queueFamily.supportsPresent) + { + supportsPresent = true; + } + } + } + } + + /** + Returns the first queue family that matches the requested capabilities. + **/ + public function getQueueFamily(requireGraphics:Bool = true, requirePresent:Bool = false, requireCompute:Bool = false, + requireTransfer:Bool = false):VKQueueFamilyInfo + { + for (queueFamily in queueFamilies) + { + if (queueFamily.matches(requireGraphics, requirePresent, requireCompute, requireTransfer)) + { + return queueFamily; + } + } + + return null; + } + + public inline function hasQueueFamily(requireGraphics:Bool = true, requirePresent:Bool = false, requireCompute:Bool = false, + requireTransfer:Bool = false):Bool + { + return getQueueFamily(requireGraphics, requirePresent, requireCompute, requireTransfer) != null; + } +} diff --git a/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx b/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx new file mode 100644 index 0000000000..d8df278384 --- /dev/null +++ b/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx @@ -0,0 +1,42 @@ +package lime.graphics.vulkan; + +/** + Describes one queue family on a Vulkan physical device. +**/ +class VKQueueFamilyInfo +{ + public var index(default, null):Int; + public var flags(default, null):Int; + public var queueCount(default, null):Int; + public var timestampValidBits(default, null):Int; + public var supportsGraphics(default, null):Bool; + public var supportsCompute(default, null):Bool; + public var supportsTransfer(default, null):Bool; + public var supportsPresent(default, null):Bool; + + @:allow(lime.graphics.vulkan.VKPhysicalDevice) + private function new(data:Dynamic) + { + index = data.index; + flags = data.flags; + queueCount = data.queueCount; + timestampValidBits = data.timestampValidBits; + supportsGraphics = data.supportsGraphics; + supportsCompute = data.supportsCompute; + supportsTransfer = data.supportsTransfer; + supportsPresent = data.supportsPresent; + } + + /** + Checks whether this queue family satisfies a requested capability set. + **/ + public inline function matches(requireGraphics:Bool = false, requirePresent:Bool = false, requireCompute:Bool = false, + requireTransfer:Bool = false):Bool + { + if (requireGraphics && !supportsGraphics) return false; + if (requirePresent && !supportsPresent) return false; + if (requireCompute && !supportsCompute) return false; + if (requireTransfer && !supportsTransfer) return false; + return true; + } +} diff --git a/src/lime/graphics/vulkan/VKRenderer.hx b/src/lime/graphics/vulkan/VKRenderer.hx new file mode 100644 index 0000000000..374c7c53d4 --- /dev/null +++ b/src/lime/graphics/vulkan/VKRenderer.hx @@ -0,0 +1,147 @@ +package lime.graphics.vulkan; + +import lime.graphics.Image; +import lime.system.CFFI; +import lime.system.CFFIPointer; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A minimal managed Vulkan swapchain renderer exposed by Lime for validation + and sample work. This is intentionally narrower than Lime's GL API surface. +**/ +class VKRenderer +{ + public var info(get, never):String; + public var isValid(get, never):Bool; + public var lastError(get, never):String; + + private var __handle:CFFIPointer; + private var __info:String; + + @:allow(lime.graphics.VulkanRenderContext) + private function new(handle:CFFIPointer) + { + __handle = handle; + __info = ""; + + #if (!macro && lime_cffi) + if (__handle != null) + { + refreshInfo(); + } + #end + } + + public function dispose():Void + { + #if (!macro && lime_cffi) + if (__handle != null) + { + NativeCFFI.lime_vulkan_renderer_destroy(__handle); + __handle = null; + } + #end + } + + public function render(red:Float, green:Float, blue:Float, alpha:Float = 1.0):Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + return NativeCFFI.lime_vulkan_renderer_render(__handle, red, green, blue, alpha); + } + #end + + return false; + } + + public function refreshInfo():String + { + #if (!macro && lime_cffi) + if (__handle != null) + { + var value:Dynamic = NativeCFFI.lime_vulkan_renderer_get_info(__handle); + __info = (value != null) ? CFFI.stringValue(value) : ""; + } + #end + + return __info; + } + + public function setOverlayImage(image:Image, x:Int, y:Int):Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + if (image == null) + { + return NativeCFFI.lime_vulkan_renderer_clear_overlay(__handle); + } + + if (image.buffer != null && image.width > 0 && image.height > 0) + { + return NativeCFFI.lime_vulkan_renderer_set_overlay(__handle, image.data.toBytes(), image.width, image.height, x, y); + } + } + #end + + return false; + } + + public function clearOverlay():Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + return NativeCFFI.lime_vulkan_renderer_clear_overlay(__handle); + } + #end + + return false; + } + + public function resize():Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + return NativeCFFI.lime_vulkan_renderer_resize(__handle); + } + #end + + return false; + } + + public static function getLastError():String + { + #if (!macro && lime_cffi) + var value:Dynamic = NativeCFFI.lime_vulkan_renderer_get_last_error(); + if (value != null) + { + return CFFI.stringValue(value); + } + #end + + return ""; + } + + private inline function get_info():String + { + return __info; + } + + private inline function get_isValid():Bool + { + return __handle != null; + } + + private inline function get_lastError():String + { + return getLastError(); + } +} diff --git a/src/lime/graphics/vulkan/VKSurface.hx b/src/lime/graphics/vulkan/VKSurface.hx new file mode 100644 index 0000000000..6abd8988fb --- /dev/null +++ b/src/lime/graphics/vulkan/VKSurface.hx @@ -0,0 +1,52 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.graphics.VulkanRenderContext; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A lightweight managed `VkSurfaceKHR` wrapper for the current Lime window. +**/ +class VKSurface +{ + public var context(default, null):VulkanRenderContext; + public var instance(default, null):VKInstance; + public var high(default, null):Int; + public var low(default, null):Int; + + @:allow(lime.graphics.vulkan.VKInstance) + private function new(context:VulkanRenderContext, instance:VKInstance, high:Int, low:Int) + { + this.context = context; + this.instance = instance; + this.high = high; + this.low = low; + } + + public function dispose():Void + { + #if (!macro && lime_cffi) + if (context != null && instance != null && instance.isValid() && (high != 0 || low != 0)) + { + NativeCFFI.lime_vk_destroy_surface(context.__windowHandle, instance.handle.high, instance.handle.low, high, low); + high = 0; + low = 0; + } + #end + } + + public inline function isValid():Bool + { + return high != 0 || low != 0; + } + + public inline function toInt64():Int64 + { + return Int64.make(high, low); + } +} From df371a3a08b04bce533eaad452b7e6c828e4a575 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 19 May 2026 22:08:03 -0400 Subject: [PATCH 07/76] Hook the Vulkan backend into project config and CI This makes Vulkan selectable from project.xml and adds a small smoke test in CI so the new backend stays covered. --- .github/workflows/main.yml | 63 +++++++++++- README.md | 5 + src/lime/tools/ProjectXMLParser.hx | 3 + src/lime/tools/WindowData.hx | 2 + templates/haxe/ApplicationMain.hx | 2 +- tests/vulkan-smoke/Source/Main.hx | 152 +++++++++++++++++++++++++++++ tests/vulkan-smoke/project.xml | 14 +++ 7 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 tests/vulkan-smoke/Source/Main.hx create mode 100644 tests/vulkan-smoke/project.xml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 857907b35e..e7c87e1f36 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -182,6 +182,65 @@ jobs: lime create SimpleAudio -verbose -nocolor lime build SimpleAudio linux -release -verbose -nocolor + vulkan-smoke: + runs-on: ubuntu-22.04 + steps: + + - uses: actions/checkout@v6 + with: + submodules: true + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev mesa-vulkan-drivers xvfb + + - uses: krdlab/setup-haxe@v2 + with: + haxe-version: ${{ env.HAXE_VERSION }} + + - name: Set HAXEPATH + run: | + echo "HAXEPATH=$HAXE_STD_PATH/.." >> $GITHUB_ENV + + - name: Install Haxe dependencies + run: | + curl --output ../hxcpp-4.3.45.zip --location https://github.com/HaxeFoundation/hxcpp/releases/download/v4.3.45/hxcpp-4.3.45.zip + haxelib --global update haxelib --quiet + haxelib install ../hxcpp-4.3.45.zip --quiet + haxelib install format --quiet + haxelib install hxp --quiet + haxelib install utest --quiet + + - name: Rebuild Lime tools + run: | + haxelib dev lime ${{ github.workspace }} + haxelib run lime rebuild tools -nocolor -verbose -nocffi + haxelib run lime setup -alias -y -nocffi + + - name: Rebuild Lime (Linux Vulkan) + run: | + lime rebuild linux -64 -release -nocolor -verbose -nocffi -D lime-vulkan + + - name: Build Vulkan smoke test app + working-directory: tests/vulkan-smoke + run: | + lime build linux -release -verbose -nocolor + + - name: Run Vulkan smoke test app + working-directory: tests/vulkan-smoke + run: | + xvfb-run -a Export/linux/bin/LimeVulkanSmoke + + - name: Install samples + run: | + haxelib git lime-samples https://github.com/openfl/lime-samples --quiet + + - name: Build HelloWorld Vulkan sample + run: | + lime create HelloWorld -verbose -nocolor + lime build HelloWorld linux -release -verbose -nocolor -D lime-vulkan --window-render-type=vulkan + macos: runs-on: macos-14 steps: @@ -536,7 +595,7 @@ jobs: lime build SimpleAudio ios -release -nosign -verbose -nocolor -eval package-haxelib: - needs: [linux, macos, windows, android, ios] + needs: [linux, vulkan-smoke, macos, windows, android, ios] runs-on: ubuntu-22.04 steps: @@ -996,7 +1055,7 @@ jobs: notify: runs-on: ubuntu-22.04 - needs: [package-haxelib, docs, android, flash-samples, air-samples, hashlink-samples, hashlinkc-samples, html5-samples, ios, linux, macos, neko-samples, windows] + needs: [package-haxelib, docs, android, flash-samples, air-samples, hashlink-samples, hashlinkc-samples, html5-samples, ios, linux, vulkan-smoke, macos, neko-samples, windows] if: ${{ github.repository == 'openfl/lime' && github.event_name != 'pull_request' }} steps: - name: Notify Discord diff --git a/README.md b/README.md index c6803fb1a5..a703f9140a 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,13 @@ Lime does not include a renderer, but exposes the current context: * DOM * Flash * GL + * Vulkan The GL context is based upon the WebGL standard, implemented for both OpenGL and OpenGL ES as needed. +Native Vulkan support currently focuses on window/bootstrap helpers and a minimal validation renderer for backend verification, not a full high-level renderer. +The native Vulkan bootstrap and validation renderer are currently opt-in and require building Lime with the `lime-vulkan` define plus Vulkan headers available to the native toolchain. +To request a Vulkan window, use the standard `RenderContextType.VULKAN` context selection, set `` in project XML, or use `--window-render-type=vulkan`. +The in-repo `tests/vulkan-smoke` project is used as the current Vulkan CI smoke app. Lime provides a unified audio API, but also provides access to OpenAL for advanced audio on native targets. diff --git a/src/lime/tools/ProjectXMLParser.hx b/src/lime/tools/ProjectXMLParser.hx index 876d59d1c3..63ca4d5bb6 100644 --- a/src/lime/tools/ProjectXMLParser.hx +++ b/src/lime/tools/ProjectXMLParser.hx @@ -1984,6 +1984,9 @@ class ProjectXMLParser extends HXProject case "parameters", "title": Reflect.setField(windows[id], name, Std.string(value)); + case "render-type", "context-type": + Reflect.setField(windows[id], "renderType", Std.string(value).toLowerCase()); + case "allow-high-dpi": Reflect.setField(windows[id], "allowHighDPI", value == "true"); diff --git a/src/lime/tools/WindowData.hx b/src/lime/tools/WindowData.hx index df74318d29..92f101feb1 100644 --- a/src/lime/tools/WindowData.hx +++ b/src/lime/tools/WindowData.hx @@ -19,6 +19,7 @@ abstract WindowData({ @:optional var allowHighDPI:Bool; @:optional var alwaysOnTop:Bool; @:optional var antialiasing:Int; + @:optional var renderType:String; @:optional var orientation:Orientation; @:optional var allowShaders:Bool; @:optional var requireShaders:Bool; @@ -53,6 +54,7 @@ abstract WindowData({ allowHighDPI: false, alwaysOnTop: false, antialiasing: 0, + renderType: null, orientation: Orientation.AUTO, allowShaders: false, requireShaders: false, diff --git a/templates/haxe/ApplicationMain.hx b/templates/haxe/ApplicationMain.hx index 422fbcb030..2fadafabb0 100644 --- a/templates/haxe/ApplicationMain.hx +++ b/templates/haxe/ApplicationMain.hx @@ -62,7 +62,7 @@ import ::APP_MAIN::; depth: ::depthBuffer::, hardware: ::hardware::, stencil: ::stencilBuffer::, - type: null, + type: ::if renderType::"::renderType::"::else::null::end::, vsync: ::vsync:: }; diff --git a/tests/vulkan-smoke/Source/Main.hx b/tests/vulkan-smoke/Source/Main.hx new file mode 100644 index 0000000000..ff2e2a7fe8 --- /dev/null +++ b/tests/vulkan-smoke/Source/Main.hx @@ -0,0 +1,152 @@ +package; + +import haxe.Int64; +import haxe.Timer; +import lime.app.Application; +import lime.graphics.RenderContext; +import lime.graphics.RenderContextType; +import lime.graphics.VulkanRenderContext; +import lime.graphics.vulkan.VK; +import lime.graphics.vulkan.VKRenderer; +import lime.system.System; + +class Main extends Application +{ + private var renderer:VKRenderer; + private var finished:Bool; + + public function new() + { + super(); + } + + override public function onWindowCreate():Void + { + super.onWindowCreate(); + + if (window == null) + { + fail("Missing primary window"); + return; + } + + if (window.context == null || window.context.type != RenderContextType.VULKAN || window.context.vulkan == null) + { + fail("Primary window was not created with a Vulkan context"); + return; + } + + var context = window.context.vulkan; + validateBootstrap(context); + + renderer = context.createRenderer("LimeVulkanSmoke"); + if (renderer == null || !renderer.isValid) + { + fail("Failed to create Vulkan renderer: " + VKRenderer.getLastError()); + } + } + + override public function render(context:RenderContext):Void + { + super.render(context); + + if (finished || renderer == null) + { + return; + } + + if (!renderer.render(0.125, 0.25, 0.5, 1.0)) + { + fail("Failed to render Vulkan frame: " + renderer.lastError); + return; + } + + finished = true; + Timer.delay(complete, 50); + } + + private function validateBootstrap(context:VulkanRenderContext):Void + { + var extensions = context.getInstanceExtensions(); + if (extensions == null || extensions.length == 0) + { + fail("No Vulkan instance extensions were reported"); + return; + } + + var procAddr = context.getInstanceProcAddr(); + if (!isNonZero(procAddr)) + { + fail("vkGetInstanceProcAddr was not available"); + return; + } + + var instance = VK.createInstance(context, "LimeVulkanSmoke"); + if (instance == null || !instance.isValid()) + { + fail("Failed to create Vulkan instance: " + VK.getLastError()); + return; + } + + var surface = instance.createSurface(); + if (surface == null || !surface.isValid()) + { + instance.dispose(); + fail("Failed to create Vulkan surface"); + return; + } + + var devices = instance.enumeratePhysicalDevices(surface); + if (devices.length == 0) + { + surface.dispose(); + instance.dispose(); + fail("No Vulkan physical devices were enumerated"); + return; + } + + var device = instance.pickPhysicalDevice(surface); + if (device == null || !device.hasQueueFamily(true, true)) + { + surface.dispose(); + instance.dispose(); + fail("No present-capable graphics queue family was found"); + return; + } + + surface.dispose(); + instance.dispose(); + } + + private function complete():Void + { + if (renderer != null) + { + renderer.dispose(); + renderer = null; + } + + if (window != null) + { + window.close(); + } + } + + private function fail(message:String):Void + { + trace("Vulkan smoke failed: " + message); + + if (renderer != null) + { + renderer.dispose(); + renderer = null; + } + + System.exit(1); + } + + private static inline function isNonZero(value:Int64):Bool + { + return value.high != 0 || value.low != 0; + } +} diff --git a/tests/vulkan-smoke/project.xml b/tests/vulkan-smoke/project.xml new file mode 100644 index 0000000000..4752ae8640 --- /dev/null +++ b/tests/vulkan-smoke/project.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + From aec24419f4a44e458ed9fe0c8c0c5b8b1aed8a8f Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 19 May 2026 22:16:02 -0400 Subject: [PATCH 08/76] Fix Vulkan docs on non-CFFI targets Guard the Vulkan helper imports so the doc builds can compile these types on flash and html5 as well as native targets. --- src/lime/graphics/VulkanRenderContext.hx | 8 ++++++-- src/lime/graphics/vulkan/VK.hx | 2 ++ src/lime/graphics/vulkan/VKInstance.hx | 1 - src/lime/graphics/vulkan/VKPhysicalDevice.hx | 4 +++- src/lime/graphics/vulkan/VKRenderer.hx | 8 ++++++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/lime/graphics/VulkanRenderContext.hx b/src/lime/graphics/VulkanRenderContext.hx index a33494aa6a..f56636b8b4 100644 --- a/src/lime/graphics/VulkanRenderContext.hx +++ b/src/lime/graphics/VulkanRenderContext.hx @@ -3,8 +3,12 @@ package lime.graphics; import haxe.Int64; import lime.graphics.vulkan.VKRenderer; import lime.math.Vector2; +#if (!lime_doc_gen || lime_cffi) import lime.system.CFFI; +#end +#if (!lime_doc_gen || lime_cffi) import lime.system.CFFIPointer; +#end #if hl import hl.Bytes as HLBytes; @@ -33,10 +37,10 @@ class VulkanRenderContext public var type(default, null):RenderContextType; public var version(default, null):String; - private var __windowHandle:CFFIPointer; + private var __windowHandle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end; @:allow(lime._internal.backend.native.NativeWindow) - private function new(windowHandle:CFFIPointer) + private function new(windowHandle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end) { __windowHandle = windowHandle; type = VULKAN; diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx index 54e9b17032..4f5359eecc 100644 --- a/src/lime/graphics/vulkan/VK.hx +++ b/src/lime/graphics/vulkan/VK.hx @@ -2,7 +2,9 @@ package lime.graphics.vulkan; import haxe.Int64; import lime.graphics.VulkanRenderContext; +#if (!lime_doc_gen || lime_cffi) import lime.system.CFFI; +#end #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; diff --git a/src/lime/graphics/vulkan/VKInstance.hx b/src/lime/graphics/vulkan/VKInstance.hx index de6a9af7c5..71d4e079a3 100644 --- a/src/lime/graphics/vulkan/VKInstance.hx +++ b/src/lime/graphics/vulkan/VKInstance.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import lime.graphics.VulkanRenderContext; -import lime.system.CFFI; #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx index 47d1b5b214..1edb88aec4 100644 --- a/src/lime/graphics/vulkan/VKPhysicalDevice.hx +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -1,7 +1,9 @@ package lime.graphics.vulkan; import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) import lime.system.CFFI; +#end /** Describes a Vulkan physical device discovered through a `VKInstance`. @@ -27,7 +29,7 @@ class VKPhysicalDevice { this.instance = instance; handle = VK.__makeHandle(data.handle); - name = (data.name != null) ? CFFI.stringValue(data.name) : ""; + name = (data.name != null) ? #if (!lime_doc_gen || lime_cffi) CFFI.stringValue(data.name) #else cast data.name #end : ""; apiVersion = data.apiVersion; apiVersionString = VK.versionString(apiVersion); driverVersion = data.driverVersion; diff --git a/src/lime/graphics/vulkan/VKRenderer.hx b/src/lime/graphics/vulkan/VKRenderer.hx index 374c7c53d4..d736b84299 100644 --- a/src/lime/graphics/vulkan/VKRenderer.hx +++ b/src/lime/graphics/vulkan/VKRenderer.hx @@ -1,8 +1,12 @@ package lime.graphics.vulkan; import lime.graphics.Image; +#if (!lime_doc_gen || lime_cffi) import lime.system.CFFI; +#end +#if (!lime_doc_gen || lime_cffi) import lime.system.CFFIPointer; +#end #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; @@ -20,11 +24,11 @@ class VKRenderer public var isValid(get, never):Bool; public var lastError(get, never):String; - private var __handle:CFFIPointer; + private var __handle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end; private var __info:String; @:allow(lime.graphics.VulkanRenderContext) - private function new(handle:CFFIPointer) + private function new(handle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end) { __handle = handle; __info = ""; From ff8ad734074c4c964b8b25fb317ee06bbbc29b14 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 19 May 2026 22:49:35 -0400 Subject: [PATCH 09/76] Restore frame timing for directly-created windows --- src/lime/app/Application.hx | 1 + src/lime/ui/Window.hx | 1 + 2 files changed, 2 insertions(+) diff --git a/src/lime/app/Application.hx b/src/lime/app/Application.hx index 10d128991e..7c617d01d1 100644 --- a/src/lime/app/Application.hx +++ b/src/lime/app/Application.hx @@ -868,6 +868,7 @@ class Application extends Module return __vsyncMode; } + @:allow(lime.ui.Window) @:noCompletion private function __seedFrameConfiguration(attributes:WindowAttributes):Void { if (__frameConfigured) diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index 4a25da753c..b53f65b2af 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -238,6 +238,7 @@ class Window __minimized = Reflect.hasField(__attributes, "minimized") ? __attributes.minimized : false; id = -1; __backend = new WindowBackend(this); + if (id != -1 && application != null) application.__seedFrameConfiguration(__attributes); #if windows var mappings = [ "8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", From 7dfdf49548528a83100dfebbaaaab69507ac7cb3 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 19 May 2026 23:08:14 -0400 Subject: [PATCH 10/76] Fix Vulkan smoke coverage on Linux --- .github/workflows/main.yml | 7 +++++-- .../lib/custom/sdl/include/SDL_config_linux.h | 3 +++ project/src/backend/sdl/SDLWindow.cpp | 11 ++++++++++- .../_internal/backend/native/NativeCFFI.hx | 2 +- .../_internal/backend/native/NativeWindow.hx | 18 ++++++++++-------- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e7c87e1f36..7965bbfae6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -193,7 +193,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev mesa-vulkan-drivers xvfb + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libx11-xcb1 libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev mesa-vulkan-drivers xvfb - uses: krdlab/setup-haxe@v2 with: @@ -230,7 +230,10 @@ jobs: - name: Run Vulkan smoke test app working-directory: tests/vulkan-smoke run: | - xvfb-run -a Export/linux/bin/LimeVulkanSmoke + if [ -f /usr/share/vulkan/icd.d/lvp_icd.x86_64.json ]; then + export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json + fi + SDL_AUDIODRIVER=dummy xvfb-run -a Export/linux/bin/LimeVulkanSmoke - name: Install samples run: | diff --git a/project/lib/custom/sdl/include/SDL_config_linux.h b/project/lib/custom/sdl/include/SDL_config_linux.h index fc5213ebc9..54a9fe5b30 100644 --- a/project/lib/custom/sdl/include/SDL_config_linux.h +++ b/project/lib/custom/sdl/include/SDL_config_linux.h @@ -308,6 +308,9 @@ /* #undef SDL_VIDEO_OPENGL_OSMESA */ /* #undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC */ +/* Enable Vulkan support */ +#define SDL_VIDEO_VULKAN 1 + /* Enable system power support */ #define SDL_POWER_LINUX 1 /* #undef SDL_POWER_WINDOWS */ diff --git a/project/src/backend/sdl/SDLWindow.cpp b/project/src/backend/sdl/SDLWindow.cpp index 9686ae6894..522556fcf8 100644 --- a/project/src/backend/sdl/SDLWindow.cpp +++ b/project/src/backend/sdl/SDLWindow.cpp @@ -1578,7 +1578,16 @@ namespace lime { Window* CreateWindow (Application* application, int width, int height, int flags, const char* title) { - return new SDLWindow (application, width, height, flags, title); + SDLWindow* window = new SDLWindow (application, width, height, flags, title); + + if (!window->sdlWindow) { + + delete window; + return 0; + + } + + return window; } diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index 7db7353e27..f6adb901ec 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -920,7 +920,7 @@ class NativeCFFI private static var lime_vulkan_renderer_destroy = CFFI.load("lime", "lime_vulkan_renderer_destroy", 1); private static var lime_vulkan_renderer_get_info = CFFI.load("lime", "lime_vulkan_renderer_get_info", 1); private static var lime_vulkan_renderer_get_last_error = CFFI.load("lime", "lime_vulkan_renderer_get_last_error", 0); - private static var lime_vulkan_renderer_set_overlay = CFFI.load("lime", "lime_vulkan_renderer_set_overlay", 6); + private static var lime_vulkan_renderer_set_overlay = CFFI.load("lime", "lime_vulkan_renderer_set_overlay", -1); private static var lime_vulkan_renderer_clear_overlay = CFFI.load("lime", "lime_vulkan_renderer_clear_overlay", 1); private static var lime_vulkan_renderer_render = CFFI.load("lime", "lime_vulkan_renderer_render", 5); private static var lime_vulkan_renderer_resize = CFFI.load("lime", "lime_vulkan_renderer_resize", 1); diff --git a/src/lime/_internal/backend/native/NativeWindow.hx b/src/lime/_internal/backend/native/NativeWindow.hx index 3da3ec90e2..ecadbb89c1 100644 --- a/src/lime/_internal/backend/native/NativeWindow.hx +++ b/src/lime/_internal/backend/native/NativeWindow.hx @@ -121,17 +121,19 @@ class NativeWindow #if (!macro && lime_cffi) handle = NativeCFFI.lime_window_create(parent.application.__backend.handle, width, height, flags, title); - if (handle != null) + if (handle == null) { - parent.__width = NativeCFFI.lime_window_get_width(handle); + return; + } - parent.__height = NativeCFFI.lime_window_get_height(handle); - parent.__x = NativeCFFI.lime_window_get_x(handle); - parent.__y = NativeCFFI.lime_window_get_y(handle); - parent.__hidden = (Reflect.hasField(attributes, "hidden") && attributes.hidden); + parent.__width = NativeCFFI.lime_window_get_width(handle); - parent.id = NativeCFFI.lime_window_get_id(handle); - } + parent.__height = NativeCFFI.lime_window_get_height(handle); + parent.__x = NativeCFFI.lime_window_get_x(handle); + parent.__y = NativeCFFI.lime_window_get_y(handle); + parent.__hidden = (Reflect.hasField(attributes, "hidden") && attributes.hidden); + + parent.id = NativeCFFI.lime_window_get_id(handle); parent.__scale = NativeCFFI.lime_window_get_scale(handle); var context = new RenderContext(); From 35d97de87fa2ec76dc714a45c08cc9fbfd876daf Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 20 May 2026 19:34:05 -0400 Subject: [PATCH 11/76] Wire up Vulkan devices and command buffers Add the first logical device, queue, command pool, command buffer, fence, and semaphore wrappers for Lime's Vulkan API. Back them with native CFFI calls and exercise the path in the Vulkan smoke test. Keep the deeper Vulkan primitives behind lime-vulkan so regular Lime apps do not resolve Vulkan-only bindings during startup. --- docs/ImportAll.hx | 6 + project/src/ExternalInterface.cpp | 1473 +++++++++++++++++ .../_internal/backend/native/NativeCFFI.hx | 219 +++ src/lime/graphics/VulkanRenderContext.hx | 13 +- src/lime/graphics/vulkan/VK.hx | 63 +- src/lime/graphics/vulkan/VKCommandBuffer.hx | 96 ++ src/lime/graphics/vulkan/VKCommandPool.hx | 93 ++ src/lime/graphics/vulkan/VKDevice.hx | 134 ++ src/lime/graphics/vulkan/VKFence.hx | 78 + src/lime/graphics/vulkan/VKPhysicalDevice.hx | 37 + src/lime/graphics/vulkan/VKQueue.hx | 75 + src/lime/graphics/vulkan/VKRenderer.hx | 6 +- src/lime/graphics/vulkan/VKSemaphore.hx | 47 + tests/vulkan-smoke/Source/Main.hx | 108 ++ 14 files changed, 2432 insertions(+), 16 deletions(-) create mode 100644 src/lime/graphics/vulkan/VKCommandBuffer.hx create mode 100644 src/lime/graphics/vulkan/VKCommandPool.hx create mode 100644 src/lime/graphics/vulkan/VKDevice.hx create mode 100644 src/lime/graphics/vulkan/VKFence.hx create mode 100644 src/lime/graphics/vulkan/VKQueue.hx create mode 100644 src/lime/graphics/vulkan/VKSemaphore.hx diff --git a/docs/ImportAll.hx b/docs/ImportAll.hx index ba022480ee..cd1be55208 100644 --- a/docs/ImportAll.hx +++ b/docs/ImportAll.hx @@ -60,10 +60,16 @@ import lime.graphics.RenderContextAttributes; import lime.graphics.RenderContextType; import lime.graphics.VulkanRenderContext; import lime.graphics.vulkan.VK; +import lime.graphics.vulkan.VKCommandBuffer; +import lime.graphics.vulkan.VKCommandPool; +import lime.graphics.vulkan.VKDevice; +import lime.graphics.vulkan.VKFence; import lime.graphics.vulkan.VKRenderer; import lime.graphics.vulkan.VKInstance; import lime.graphics.vulkan.VKPhysicalDevice; +import lime.graphics.vulkan.VKQueue; import lime.graphics.vulkan.VKQueueFamilyInfo; +import lime.graphics.vulkan.VKSemaphore; import lime.graphics.vulkan.VKSurface; import lime.graphics.WebGL2RenderContext; import lime.graphics.WebGLRenderContext; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 4fc72f7cc3..7bab73d4a4 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -241,6 +241,259 @@ namespace lime { return true; } + + + static std::vector GetVulkanDeviceExtensions (value extensions) { + + std::vector deviceExtensions; + + if (val_is_null (extensions)) { + + deviceExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + return deviceExtensions; + + } + + int length = val_array_size (extensions); + for (int i = 0; i < length; ++i) { + + value extension = val_array_i (extensions, i); + if (!val_is_null (extension)) { + + deviceExtensions.push_back (val_string (extension)); + + } + + } + + return deviceExtensions; + + } + + + static std::vector GetHLVulkanDeviceExtensions (hl_varray* extensions) { + + std::vector deviceExtensions; + + if (!extensions) { + + deviceExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + return deviceExtensions; + + } + + int length = extensions->size; + hl_vstring** extensionData = hl_aptr (extensions, hl_vstring*); + + for (int i = 0; i < length; ++i) { + + hl_vstring* extension = *extensionData++; + if (extension) { + + deviceExtensions.push_back (hl_to_utf8 ((const uchar*)extension->bytes)); + + } + + } + + return deviceExtensions; + + } + + + static PFN_vkVoidFunction GetManagedVulkanDeviceProc (Window* targetWindow, VkInstance instance, VkDevice device, const char* name) { + + if (!targetWindow || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return 0; + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return 0; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return 0; + + } + + PFN_vkVoidFunction proc = vkGetDeviceProcAddr (device, name); + if (!proc) { + + lastVKError = std::string ("Missing Vulkan device function: ") + name; + return 0; + + } + + return proc; + + } + + + static bool CreateManagedVulkanDevice (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, + const std::vector& requestedExtensions, VkDevice* outDevice, VkQueue* outQueue) { + + if (!targetWindow || !instance || !physicalDevice || !outDevice || !outQueue) { + + lastVKError = "Missing Vulkan instance, physical device, or output device"; + return false; + + } + + *outDevice = VK_NULL_HANDLE; + *outQueue = VK_NULL_HANDLE; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; + + } + + PFN_vkCreateDevice vkCreateDevice = (PFN_vkCreateDevice)vkGetInstanceProcAddr (instance, "vkCreateDevice"); + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties = + (PFN_vkEnumerateDeviceExtensionProperties)vkGetInstanceProcAddr (instance, "vkEnumerateDeviceExtensionProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + + if (!vkCreateDevice || !vkGetDeviceProcAddr || !vkEnumerateDeviceExtensionProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan device creation functions"; + return false; + + } + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevice, &queueFamilyCount, 0); + if (queueFamilyIndex >= queueFamilyCount) { + + lastVKError = "Invalid Vulkan queue family index"; + return false; + + } + + float queuePriority = 1.0f; + VkDeviceQueueCreateInfo queueCreateInfo; + memset (&queueCreateInfo, 0, sizeof (queueCreateInfo)); + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamilyIndex; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + + std::vector deviceExtensions; + for (size_t i = 0; i < requestedExtensions.size (); ++i) { + + deviceExtensions.push_back (requestedExtensions[i].c_str ()); + + } + + if (!requestedExtensions.empty ()) { + + uint32_t extensionCount = 0; + VkResult extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, 0); + if (extensionResult != VK_SUCCESS) { + + lastVKError = "Could not enumerate Vulkan device extensions"; + return false; + + } + + std::vector availableExtensions (extensionCount); + if (extensionCount > 0) { + + extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, availableExtensions.data ()); + if (extensionResult != VK_SUCCESS) { + + lastVKError = "Could not enumerate Vulkan device extensions"; + return false; + + } + + } + + for (size_t i = 0; i < requestedExtensions.size (); ++i) { + + bool extensionSupported = false; + + for (size_t e = 0; e < availableExtensions.size (); ++e) { + + if (strcmp (availableExtensions[e].extensionName, requestedExtensions[i].c_str ()) == 0) { + + extensionSupported = true; + break; + + } + + } + + if (!extensionSupported) { + + lastVKError = std::string ("Vulkan physical device does not support ") + requestedExtensions[i]; + return false; + + } + + } + + } + + VkPhysicalDeviceFeatures deviceFeatures; + memset (&deviceFeatures, 0, sizeof (deviceFeatures)); + + VkDeviceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.queueCreateInfoCount = 1; + createInfo.pQueueCreateInfos = &queueCreateInfo; + createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size (); + createInfo.ppEnabledExtensionNames = deviceExtensions.empty () ? 0 : deviceExtensions.data (); + + VkResult result = vkCreateDevice (physicalDevice, &createInfo, 0, outDevice); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateDevice failed"; + return false; + + } + + PFN_vkGetDeviceQueue vkGetDeviceQueue = (PFN_vkGetDeviceQueue)vkGetDeviceProcAddr (*outDevice, "vkGetDeviceQueue"); + if (!vkGetDeviceQueue) { + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (*outDevice, "vkDestroyDevice"); + if (vkDestroyDevice) vkDestroyDevice (*outDevice, 0); + *outDevice = VK_NULL_HANDLE; + lastVKError = "Missing Vulkan device queue function"; + return false; + + } + + vkGetDeviceQueue (*outDevice, queueFamilyIndex, 0, outQueue); + if (!*outQueue) { + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (*outDevice, "vkDestroyDevice"); + if (vkDestroyDevice) vkDestroyDevice (*outDevice, 0); + *outDevice = VK_NULL_HANDLE; + lastVKError = "Failed to get Vulkan device queue"; + return false; + + } + + lastVKError.clear (); + return true; + + } #endif @@ -4284,6 +4537,1188 @@ namespace lime { } + value lime_vk_create_device (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int queueFamilyIndex, + value extensions) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + std::vector deviceExtensions = GetVulkanDeviceExtensions (extensions); + VkDevice device = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + + return alloc_null (); + + } + + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); + alloc_field (result, val_id ("queue"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); + alloc_field (result, val_id ("queueFamilyIndex"), alloc_int (queueFamilyIndex)); + return result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int queueFamilyIndex, hl_varray* extensions) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + std::vector deviceExtensions = GetHLVulkanDeviceExtensions (extensions); + VkDevice device = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + + return 0; + + } + + const int id_handle = hl_hash_utf8 ("handle"); + const int id_queue = hl_hash_utf8 ("queue"); + const int id_queueFamilyIndex = hl_hash_utf8 ("queueFamilyIndex"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); + hl_dyn_setp (result, id_queue, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); + hl_dyn_seti (result, id_queueFamilyIndex, &hlt_i32, queueFamilyIndex); + return result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_device (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + if (deviceHigh == 0 && deviceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) return; + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); + if (vkDestroyDevice) { + + vkDestroyDevice (device, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + if (deviceHigh == 0 && deviceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) return; + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); + if (vkDestroyDevice) { + + vkDestroyDevice (device, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_device_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); + if (!vkDeviceWaitIdle) { + + lastVKError = "Missing Vulkan device wait idle function"; + return false; + + } + + VkResult result = vkDeviceWaitIdle (device); + if (result != VK_SUCCESS) { + + lastVKError = "vkDeviceWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_device_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); + if (!vkDeviceWaitIdle) { + + lastVKError = "Missing Vulkan device wait idle function"; + return false; + + } + + VkResult result = vkDeviceWaitIdle (device); + if (result != VK_SUCCESS) { + + lastVKError = "vkDeviceWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_queue_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device || !queue) { + + lastVKError = "Missing Vulkan window, instance, device, or queue"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); + if (!vkQueueWaitIdle) { + + lastVKError = "Missing Vulkan queue wait idle function"; + return false; + + } + + VkResult result = vkQueueWaitIdle (queue); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_queue_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device || !queue) { + + lastVKError = "Missing Vulkan window, instance, device, or queue"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); + if (!vkQueueWaitIdle) { + + lastVKError = "Missing Vulkan queue wait idle function"; + return false; + + } + + VkResult result = vkQueueWaitIdle (queue); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueFamilyIndex, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateCommandPool"); + if (!vkCreateCommandPool) return alloc_null (); + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = flags; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool commandPool = VK_NULL_HANDLE; + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateCommandPool failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueFamilyIndex, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateCommandPool"); + if (!vkCreateCommandPool) return 0; + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = flags; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool commandPool = VK_NULL_HANDLE; + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateCommandPool failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow) { + +#ifdef LIME_VULKAN + if (commandPoolHigh == 0 && commandPoolLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyCommandPool"); + if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow) { + +#ifdef LIME_VULKAN + if (commandPoolHigh == 0 && commandPoolLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyCommandPool"); + if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_reset_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandPool"); + if (!vkResetCommandPool) return false; + + VkResult result = vkResetCommandPool (device, commandPool, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandPool"); + if (!vkResetCommandPool) return false; + + VkResult result = vkResetCommandPool (device, commandPool, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_allocate_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int level) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAllocateCommandBuffers"); + if (!vkAllocateCommandBuffers) return alloc_null (); + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = (VkCommandBufferLevel)level; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateCommandBuffers failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandPoolHigh, int commandPoolLow, int level) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAllocateCommandBuffers"); + if (!vkAllocateCommandBuffers) return 0; + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = (VkCommandBufferLevel)level; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateCommandBuffers failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_free_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + if (commandBufferHigh == 0 && commandBufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkFreeCommandBuffers"); + if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_free_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + if (commandBufferHigh == 0 && commandBufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkFreeCommandBuffers"); + if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_begin_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBeginCommandBuffer"); + if (!vkBeginCommandBuffer) return false; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = flags; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + lastVKError = "vkBeginCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_begin_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBeginCommandBuffer"); + if (!vkBeginCommandBuffer) return false; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = flags; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + lastVKError = "vkBeginCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_end_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkEndCommandBuffer"); + if (!vkEndCommandBuffer) return false; + + VkResult result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkEndCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_end_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkEndCommandBuffer"); + if (!vkEndCommandBuffer) return false; + + VkResult result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkEndCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_reset_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandBuffer"); + if (!vkResetCommandBuffer) return false; + + VkResult result = vkResetCommandBuffer (commandBuffer, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandBuffer"); + if (!vkResetCommandBuffer) return false; + + VkResult result = vkResetCommandBuffer (commandBuffer, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSemaphore"); + if (!vkCreateSemaphore) return alloc_null (); + + VkSemaphoreCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkSemaphore semaphore = VK_NULL_HANDLE; + VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSemaphore failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSemaphore"); + if (!vkCreateSemaphore) return 0; + + VkSemaphoreCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkSemaphore semaphore = VK_NULL_HANDLE; + VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSemaphore failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int semaphoreHigh, + int semaphoreLow) { + +#ifdef LIME_VULKAN + if (semaphoreHigh == 0 && semaphoreLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySemaphore"); + if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int semaphoreHigh, int semaphoreLow) { + +#ifdef LIME_VULKAN + if (semaphoreHigh == 0 && semaphoreLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySemaphore"); + if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); + if (!vkCreateFence) return alloc_null (); + + VkFenceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + createInfo.flags = flags; + + VkFence fence = VK_NULL_HANDLE; + VkResult result = vkCreateFence (device, &createInfo, 0, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFence failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); + if (!vkCreateFence) return 0; + + VkFenceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + createInfo.flags = flags; + + VkFence fence = VK_NULL_HANDLE; + VkResult result = vkCreateFence (device, &createInfo, 0, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFence failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + if (fenceHigh == 0 && fenceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); + if (vkDestroyFence) vkDestroyFence (device, fence, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow) { + +#ifdef LIME_VULKAN + if (fenceHigh == 0 && fenceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); + if (vkDestroyFence) vkDestroyFence (device, fence, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_wait_for_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow, + int timeoutHigh, int timeoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); + if (!vkWaitForFences) return false; + + VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); + if (result != VK_SUCCESS) { + + lastVKError = "vkWaitForFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_wait_for_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow, int timeoutHigh, int timeoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); + if (!vkWaitForFences) return false; + + VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); + if (result != VK_SUCCESS) { + + lastVKError = "vkWaitForFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_reset_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); + if (!vkResetFences) return false; + + VkResult result = vkResetFences (device, 1, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); + if (!vkResetFences) return false; + + VkResult result = vkResetFences (device, 1, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_queue_submit (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow, + int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueSubmit failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_queue_submit) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueSubmit failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vk_get_last_error () { return alloc_string (lastVKError.c_str ()); @@ -5371,6 +6806,25 @@ namespace lime { DEFINE_PRIME3v (lime_vk_destroy_instance); DEFINE_PRIME5v (lime_vk_destroy_surface); DEFINE_PRIME5 (lime_vk_get_physical_devices); + DEFINE_PRIME7 (lime_vk_create_device); + DEFINE_PRIME5v (lime_vk_destroy_device); + DEFINE_PRIME5 (lime_vk_device_wait_idle); + DEFINE_PRIME7 (lime_vk_queue_wait_idle); + DEFINE_PRIME7 (lime_vk_create_command_pool); + DEFINE_PRIME7v (lime_vk_destroy_command_pool); + DEFINE_PRIME8 (lime_vk_reset_command_pool); + DEFINE_PRIME8 (lime_vk_allocate_command_buffer); + DEFINE_PRIME9v (lime_vk_free_command_buffer); + DEFINE_PRIME8 (lime_vk_begin_command_buffer); + DEFINE_PRIME7 (lime_vk_end_command_buffer); + DEFINE_PRIME8 (lime_vk_reset_command_buffer); + DEFINE_PRIME5 (lime_vk_create_semaphore); + DEFINE_PRIME7v (lime_vk_destroy_semaphore); + DEFINE_PRIME6 (lime_vk_create_fence); + DEFINE_PRIME7v (lime_vk_destroy_fence); + DEFINE_PRIME9 (lime_vk_wait_for_fence); + DEFINE_PRIME7 (lime_vk_reset_fence); + DEFINE_PRIME11 (lime_vk_queue_submit); DEFINE_PRIME0 (lime_vk_get_last_error); DEFINE_PRIME2 (lime_vulkan_renderer_create); DEFINE_PRIME1v (lime_vulkan_renderer_destroy); @@ -5587,6 +7041,25 @@ namespace lime { DEFINE_HL_PRIM (_VOID, hl_vk_destroy_instance, _TCFFIPOINTER _I32 _I32); DEFINE_HL_PRIM (_VOID, hl_vk_destroy_surface, _TCFFIPOINTER _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_ARR, hl_vk_get_physical_devices, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_device, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_device, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_device_wait_idle, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_queue_wait_idle, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_command_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_command_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_command_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_allocate_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_free_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_begin_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_end_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_semaphore, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_semaphore, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_wait_for_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_queue_submit, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_BYTES, hl_vk_get_last_error, _NO_ARG); DEFINE_HL_PRIM (_TCFFIPOINTER, hl_vulkan_renderer_create, _TCFFIPOINTER _STRING); DEFINE_HL_PRIM (_VOID, hl_vulkan_renderer_destroy, _TCFFIPOINTER); diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index f6adb901ec..b9abfcc40a 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -360,6 +360,62 @@ class NativeCFFI @:cffi private static function lime_vk_get_physical_devices(handle:Dynamic, instanceHigh:Int, instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Dynamic; + #if lime_vulkan + @:cffi private static function lime_vk_create_device(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, + queueFamilyIndex:Int, extensions:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_device(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Void; + + @:cffi private static function lime_vk_device_wait_idle(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Bool; + + @:cffi private static function lime_vk_queue_wait_idle(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, + queueLow:Int):Bool; + + @:cffi private static function lime_vk_create_command_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + queueFamilyIndex:Int, flags:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_command_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int):Void; + + @:cffi private static function lime_vk_reset_command_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_allocate_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int, level:Int):Dynamic; + + @:cffi private static function lime_vk_free_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Void; + + @:cffi private static function lime_vk_begin_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_end_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int):Bool; + + @:cffi private static function lime_vk_reset_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_create_semaphore(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_semaphore(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + semaphoreHigh:Int, semaphoreLow:Int):Void; + + @:cffi private static function lime_vk_create_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + flags:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, + fenceLow:Int):Void; + + @:cffi private static function lime_vk_wait_for_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + fenceHigh:Int, fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool; + + @:cffi private static function lime_vk_reset_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, + fenceLow:Int):Bool; + + @:cffi private static function lime_vk_queue_submit(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, + queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, fenceLow:Int):Bool; + #end + @:cffi private static function lime_vk_get_last_error():Dynamic; @:cffi private static function lime_vulkan_renderer_create(handle:Dynamic, applicationName:String):CFFIPointer; @@ -694,6 +750,46 @@ class NativeCFFI "lime_vk_destroy_surface", "oiiiiv", false)); private static var lime_vk_get_physical_devices = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_physical_devices", "oiiiio", false)); + #if lime_vulkan + private static var lime_vk_create_device = new cpp.CallableInt->Int->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_device", "oiiiiioo", false)); + private static var lime_vk_destroy_device = new cpp.CallableInt->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_device", "oiiiiv", false)); + private static var lime_vk_device_wait_idle = new cpp.CallableInt->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_device_wait_idle", "oiiiib", false)); + private static var lime_vk_queue_wait_idle = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_queue_wait_idle", "oiiiiiib", false)); + private static var lime_vk_create_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_command_pool", "oiiiiiio", false)); + private static var lime_vk_destroy_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_command_pool", "oiiiiiiv", false)); + private static var lime_vk_reset_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_command_pool", "oiiiiiiib", false)); + private static var lime_vk_allocate_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_allocate_command_buffer", "oiiiiiiio", false)); + private static var lime_vk_free_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_free_command_buffer", "oiiiiiiiiv", false)); + private static var lime_vk_begin_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_begin_command_buffer", "oiiiiiiib", false)); + private static var lime_vk_end_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_end_command_buffer", "oiiiiiib", false)); + private static var lime_vk_reset_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_command_buffer", "oiiiiiiib", false)); + private static var lime_vk_create_semaphore = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_semaphore", "oiiiio", false)); + private static var lime_vk_destroy_semaphore = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_semaphore", "oiiiiiiv", false)); + private static var lime_vk_create_fence = new cpp.CallableInt->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_fence", "oiiiiio", false)); + private static var lime_vk_destroy_fence = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_fence", "oiiiiiiv", false)); + private static var lime_vk_wait_for_fence = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_wait_for_fence", "oiiiiiiiib", false)); + private static var lime_vk_reset_fence = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_fence", "oiiiiiib", false)); + private static var lime_vk_queue_submit = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_queue_submit", "oiiiiiiiiiib", false)); + #end private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_last_error", "o", false)); private static var lime_vulkan_renderer_create = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", @@ -915,6 +1011,27 @@ class NativeCFFI private static var lime_vk_destroy_instance = CFFI.load("lime", "lime_vk_destroy_instance", 3); private static var lime_vk_destroy_surface = CFFI.load("lime", "lime_vk_destroy_surface", 5); private static var lime_vk_get_physical_devices = CFFI.load("lime", "lime_vk_get_physical_devices", 5); + #if lime_vulkan + private static var lime_vk_create_device = CFFI.load("lime", "lime_vk_create_device", -1); + private static var lime_vk_destroy_device = CFFI.load("lime", "lime_vk_destroy_device", 5); + private static var lime_vk_device_wait_idle = CFFI.load("lime", "lime_vk_device_wait_idle", 5); + private static var lime_vk_queue_wait_idle = CFFI.load("lime", "lime_vk_queue_wait_idle", -1); + private static var lime_vk_create_command_pool = CFFI.load("lime", "lime_vk_create_command_pool", -1); + private static var lime_vk_destroy_command_pool = CFFI.load("lime", "lime_vk_destroy_command_pool", -1); + private static var lime_vk_reset_command_pool = CFFI.load("lime", "lime_vk_reset_command_pool", -1); + private static var lime_vk_allocate_command_buffer = CFFI.load("lime", "lime_vk_allocate_command_buffer", -1); + private static var lime_vk_free_command_buffer = CFFI.load("lime", "lime_vk_free_command_buffer", -1); + private static var lime_vk_begin_command_buffer = CFFI.load("lime", "lime_vk_begin_command_buffer", -1); + private static var lime_vk_end_command_buffer = CFFI.load("lime", "lime_vk_end_command_buffer", -1); + private static var lime_vk_reset_command_buffer = CFFI.load("lime", "lime_vk_reset_command_buffer", -1); + private static var lime_vk_create_semaphore = CFFI.load("lime", "lime_vk_create_semaphore", 5); + private static var lime_vk_destroy_semaphore = CFFI.load("lime", "lime_vk_destroy_semaphore", -1); + private static var lime_vk_create_fence = CFFI.load("lime", "lime_vk_create_fence", -1); + private static var lime_vk_destroy_fence = CFFI.load("lime", "lime_vk_destroy_fence", -1); + private static var lime_vk_wait_for_fence = CFFI.load("lime", "lime_vk_wait_for_fence", -1); + private static var lime_vk_reset_fence = CFFI.load("lime", "lime_vk_reset_fence", -1); + private static var lime_vk_queue_submit = CFFI.load("lime", "lime_vk_queue_submit", -1); + #end private static var lime_vk_get_last_error = CFFI.load("lime", "lime_vk_get_last_error", 0); private static var lime_vulkan_renderer_create = CFFI.load("lime", "lime_vulkan_renderer_create", 2); private static var lime_vulkan_renderer_destroy = CFFI.load("lime", "lime_vulkan_renderer_destroy", 1); @@ -1587,6 +1704,108 @@ class NativeCFFI return null; } + #if lime_vulkan + @:hlNative("lime", "hl_vk_create_device") private static function lime_vk_create_device(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + physicalDeviceHigh:Int, physicalDeviceLow:Int, queueFamilyIndex:Int, extensions:hl.NativeArray):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_device") private static function lime_vk_destroy_device(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_device_wait_idle") private static function lime_vk_device_wait_idle(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_queue_wait_idle") private static function lime_vk_queue_wait_idle(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_command_pool") private static function lime_vk_create_command_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueFamilyIndex:Int, flags:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_command_pool") private static function lime_vk_destroy_command_pool(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int):Void {} + + @:hlNative("lime", "hl_vk_reset_command_pool") private static function lime_vk_reset_command_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_allocate_command_buffer") private static function lime_vk_allocate_command_buffer(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, level:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_free_command_buffer") private static function lime_vk_free_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Void {} + + @:hlNative("lime", "hl_vk_begin_command_buffer") private static function lime_vk_begin_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_end_command_buffer") private static function lime_vk_end_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_reset_command_buffer") private static function lime_vk_reset_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_semaphore") private static function lime_vk_create_semaphore(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_semaphore") private static function lime_vk_destroy_semaphore(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, semaphoreHigh:Int, semaphoreLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_fence") private static function lime_vk_create_fence(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, flags:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_fence") private static function lime_vk_destroy_fence(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_wait_for_fence") private static function lime_vk_wait_for_fence(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_reset_fence") private static function lime_vk_reset_fence(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_queue_submit") private static function lime_vk_queue_submit(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, + fenceLow:Int):Bool + { + return false; + } + #end + @:hlNative("lime", "hl_vk_get_last_error") private static function lime_vk_get_last_error():hl.Bytes { return null; diff --git a/src/lime/graphics/VulkanRenderContext.hx b/src/lime/graphics/VulkanRenderContext.hx index f56636b8b4..39e2e3c1b6 100644 --- a/src/lime/graphics/VulkanRenderContext.hx +++ b/src/lime/graphics/VulkanRenderContext.hx @@ -22,14 +22,15 @@ import lime._internal.backend.native.NativeCFFI; The `VulkanRenderContext` exposes native Vulkan window bootstrap helpers when Vulkan is the render context type of the current `Window`. - Lime does not provide Vulkan API bindings or manage swapchains for you. - Instead, this context focuses on the window-specific pieces an external - Vulkan layer needs: + This context owns the window-specific pieces of Lime's Vulkan API: - required instance extensions for the current window - the current drawable size in pixels - Vulkan surface creation for an existing `VkInstance` - access to `vkGetInstanceProcAddr` + + Use `lime.graphics.vulkan.VK` and related classes for the broader Vulkan API + surface as it grows. **/ @:access(lime._internal.backend.native.NativeCFFI) class VulkanRenderContext @@ -141,10 +142,10 @@ class VulkanRenderContext } /** - Creates a minimal Vulkan swapchain renderer for the current window. + Creates Lime's validation Vulkan swapchain renderer for the current window. - This is intentionally narrow and currently only exposes clear-and-present - rendering so we can validate Lime's Vulkan window path end-to-end. + This renderer exists for smoke tests and samples while the public `VK` + surface grows into the full rendering API. The renderer respects the current Lime `vsyncMode` preference when it chooses a swapchain present mode. **/ diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx index 4f5359eecc..24cc8b32e3 100644 --- a/src/lime/graphics/vulkan/VK.hx +++ b/src/lime/graphics/vulkan/VK.hx @@ -13,14 +13,49 @@ import lime._internal.backend.native.NativeCFFI; @:access(lime.graphics.VulkanRenderContext) @:access(lime._internal.backend.native.NativeCFFI) /** - Entry point for Lime's lightweight Vulkan bootstrap helpers. + Entry point for Lime's Vulkan API surface. - This API is intentionally smaller than `lime.graphics.opengl.GL`. It focuses - on the native window/bootstrap work needed to get a Vulkan app started while - Lime's wider Vulkan surface continues to grow. + Like `lime.graphics.opengl.GL`, this class is the public place for low-level + graphics API access. Vulkan is explicit by design, so the API is organized + around handles and lifecycle objects instead of GL-style global state. **/ class VK { + public static inline var SUCCESS = 0; + public static inline var NOT_READY = 1; + public static inline var TIMEOUT = 2; + public static inline var EVENT_SET = 3; + public static inline var EVENT_RESET = 4; + public static inline var INCOMPLETE = 5; + + public static inline var KHR_SWAPCHAIN_EXTENSION_NAME = "VK_KHR_swapchain"; + + public static inline var PHYSICAL_DEVICE_TYPE_OTHER = 0; + public static inline var PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1; + public static inline var PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2; + public static inline var PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3; + public static inline var PHYSICAL_DEVICE_TYPE_CPU = 4; + + public static inline var QUEUE_GRAPHICS_BIT = 0x00000001; + public static inline var QUEUE_COMPUTE_BIT = 0x00000002; + public static inline var QUEUE_TRANSFER_BIT = 0x00000004; + public static inline var QUEUE_SPARSE_BINDING_BIT = 0x00000008; + + public static inline var COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001; + public static inline var COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002; + public static inline var COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004; + + public static inline var COMMAND_BUFFER_LEVEL_PRIMARY = 0; + public static inline var COMMAND_BUFFER_LEVEL_SECONDARY = 1; + + public static inline var COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001; + public static inline var COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002; + public static inline var COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004; + + public static inline var COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001; + + public static inline var FENCE_CREATE_SIGNALED_BIT = 0x00000001; + /** Creates a managed `VkInstance` for the current Lime Vulkan window. **/ @@ -100,8 +135,14 @@ class VK } @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKCommandBuffer) + @:allow(lime.graphics.vulkan.VKCommandPool) + @:allow(lime.graphics.vulkan.VKDevice) + @:allow(lime.graphics.vulkan.VKFence) @:allow(lime.graphics.vulkan.VKInstance) @:allow(lime.graphics.vulkan.VKPhysicalDevice) + @:allow(lime.graphics.vulkan.VKQueue) + @:allow(lime.graphics.vulkan.VKSemaphore) private static function __makeHandle(value:Dynamic):Int64 { if (value == null) @@ -113,7 +154,13 @@ class VK } @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKCommandBuffer) + @:allow(lime.graphics.vulkan.VKCommandPool) + @:allow(lime.graphics.vulkan.VKDevice) + @:allow(lime.graphics.vulkan.VKFence) @:allow(lime.graphics.vulkan.VKInstance) + @:allow(lime.graphics.vulkan.VKQueue) + @:allow(lime.graphics.vulkan.VKSemaphore) private static inline function __isZero(handle:Int64):Bool { return handle.high == 0 && handle.low == 0; @@ -130,13 +177,13 @@ class VK switch (device.deviceType) { - case 2: + case PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: score += preferDiscrete ? 400 : 250; - case 1: + case PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: score += preferDiscrete ? 300 : 400; - case 3: + case PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: score += 150; - case 4: + case PHYSICAL_DEVICE_TYPE_CPU: score += 100; default: score += 50; diff --git a/src/lime/graphics/vulkan/VKCommandBuffer.hx b/src/lime/graphics/vulkan/VKCommandBuffer.hx new file mode 100644 index 0000000000..685ecfe448 --- /dev/null +++ b/src/lime/graphics/vulkan/VKCommandBuffer.hx @@ -0,0 +1,96 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan command buffer allocated from a `VKCommandPool`. +**/ +class VKCommandBuffer +{ + public var device(get, never):VKDevice; + public var handle(default, null):Int64; + public var level(default, null):Int; + public var pool(default, null):VKCommandPool; + + @:allow(lime.graphics.vulkan.VKCommandPool) + private function new(pool:VKCommandPool, handle:Int64, level:Int) + { + this.pool = pool; + this.handle = handle; + this.level = level; + } + + public function begin(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && pool != null && pool.device != null && pool.device.isValid()) + { + return NativeCFFI.lime_vk_begin_command_buffer(pool.device.instance.context.__windowHandle, pool.device.instance.handle.high, + pool.device.instance.handle.low, pool.device.handle.high, pool.device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } + + public function dispose():Void + { + if (pool != null) + { + pool.free(this); + } + } + + public function end():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && pool != null && pool.device != null && pool.device.isValid()) + { + return NativeCFFI.lime_vk_end_command_buffer(pool.device.instance.context.__windowHandle, pool.device.instance.handle.high, + pool.device.instance.handle.low, pool.device.handle.high, pool.device.handle.low, handle.high, handle.low); + } + #end + + return false; + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && pool != null && pool.device != null && pool.device.isValid()) + { + return NativeCFFI.lime_vk_reset_command_buffer(pool.device.instance.context.__windowHandle, pool.device.instance.handle.high, + pool.device.instance.handle.low, pool.device.handle.high, pool.device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } + + @:allow(lime.graphics.vulkan.VKCommandPool) + private function __invalidate():Void + { + handle = Int64.ofInt(0); + } + + private inline function get_device():VKDevice + { + return (pool != null) ? pool.device : null; + } +} diff --git a/src/lime/graphics/vulkan/VKCommandPool.hx b/src/lime/graphics/vulkan/VKCommandPool.hx new file mode 100644 index 0000000000..a95be9ee2e --- /dev/null +++ b/src/lime/graphics/vulkan/VKCommandPool.hx @@ -0,0 +1,93 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan command pool created from a `VKDevice`. +**/ +class VKCommandPool +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var queueFamilyIndex(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, queueFamilyIndex:Int, handle:Int64) + { + this.device = device; + this.queueFamilyIndex = queueFamilyIndex; + this.handle = handle; + } + + public function allocateCommandBuffer(level:Int = VK.COMMAND_BUFFER_LEVEL_PRIMARY):VKCommandBuffer + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_allocate_command_buffer(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, level); + var commandBufferHandle = VK.__makeHandle(data); + if (!VK.__isZero(commandBufferHandle)) + { + return new VKCommandBuffer(this, commandBufferHandle, level); + } + } + #end + + return null; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_command_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_reset_command_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } + + @:allow(lime.graphics.vulkan.VKCommandBuffer) + private function free(commandBuffer:VKCommandBuffer):Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (commandBuffer != null && commandBuffer.isValid() && isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_free_command_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low); + commandBuffer.__invalidate(); + } + #end + } +} diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx new file mode 100644 index 0000000000..dbcdd331aa --- /dev/null +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -0,0 +1,134 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A logical Vulkan device created from a `VKPhysicalDevice`. +**/ +class VKDevice +{ + public var extensions(default, null):Array; + public var graphicsQueue(default, null):VKQueue; + public var handle(default, null):Int64; + public var instance(default, null):VKInstance; + public var physicalDevice(default, null):VKPhysicalDevice; + public var queueFamily(default, null):VKQueueFamilyInfo; + + @:allow(lime.graphics.vulkan.VKPhysicalDevice) + private function new(physicalDevice:VKPhysicalDevice, queueFamily:VKQueueFamilyInfo, extensions:Array, data:Dynamic) + { + this.physicalDevice = physicalDevice; + this.instance = physicalDevice.instance; + this.queueFamily = queueFamily; + this.extensions = extensions.copy(); + handle = VK.__makeHandle(data.handle); + graphicsQueue = new VKQueue(this, VK.__makeHandle(data.queue), data.queueFamilyIndex, 0); + } + + public function createCommandPool(queueFamily:VKQueueFamilyInfo = null, flags:Int = VK.COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT):VKCommandPool + { + if (queueFamily == null) + { + queueFamily = this.queueFamily; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && queueFamily != null) + { + var data:Dynamic = NativeCFFI.lime_vk_create_command_pool(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, queueFamily.index, flags); + var commandPoolHandle = VK.__makeHandle(data); + if (!VK.__isZero(commandPoolHandle)) + { + return new VKCommandPool(this, queueFamily.index, commandPoolHandle); + } + } + #end + + return null; + } + + public function createFence(signaled:Bool = false):VKFence + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var flags = signaled ? VK.FENCE_CREATE_SIGNALED_BIT : 0; + var data:Dynamic = NativeCFFI.lime_vk_create_fence(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, flags); + var fenceHandle = VK.__makeHandle(data); + if (!VK.__isZero(fenceHandle)) + { + return new VKFence(this, fenceHandle); + } + } + #end + + return null; + } + + public function createSemaphore():VKSemaphore + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_semaphore(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low); + var semaphoreHandle = VK.__makeHandle(data); + if (!VK.__isZero(semaphoreHandle)) + { + return new VKSemaphore(this, semaphoreHandle); + } + } + #end + + return null; + } + + /** + Destroys the logical device. All resources created from the device should + be destroyed before calling this method. + **/ + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + NativeCFFI.lime_vk_destroy_device(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + graphicsQueue = null; + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + /** + Blocks until the logical device has completed all submitted work. + **/ + public function waitIdle():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + return NativeCFFI.lime_vk_device_wait_idle(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, handle.low); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKFence.hx b/src/lime/graphics/vulkan/VKFence.hx new file mode 100644 index 0000000000..6fd009ac1f --- /dev/null +++ b/src/lime/graphics/vulkan/VKFence.hx @@ -0,0 +1,78 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan fence used for CPU/GPU synchronization. +**/ +class VKFence +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_fence(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_reset_fence(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + return false; + } + + public function wait(timeout:Int64):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_wait_for_fence(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, timeout.high, timeout.low); + } + #end + + return false; + } + + public function waitForever():Bool + { + return wait(Int64.make(-1, -1)); + } +} diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx index 1edb88aec4..7958b2ce5a 100644 --- a/src/lime/graphics/vulkan/VKPhysicalDevice.hx +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -3,8 +3,11 @@ package lime.graphics.vulkan; import haxe.Int64; #if (!lime_doc_gen || lime_cffi) import lime.system.CFFI; +import lime._internal.backend.native.NativeCFFI; #end +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) /** Describes a Vulkan physical device discovered through a `VKInstance`. **/ @@ -64,6 +67,40 @@ class VKPhysicalDevice } } + /** + Creates a logical device with one queue from the requested queue family. + If no queue family is provided, Lime selects a graphics-capable family + that can present to the current surface when that data is available. + **/ + public function createDevice(queueFamily:VKQueueFamilyInfo = null, extensions:Array = null):VKDevice + { + if (queueFamily == null) + { + queueFamily = getQueueFamily(true, supportsPresent); + } + + if (extensions == null) + { + extensions = [VK.KHR_SWAPCHAIN_EXTENSION_NAME]; + } + + if (queueFamily == null || instance == null || instance.context == null || !instance.isValid()) + { + return null; + } + + #if (!macro && lime_cffi && lime_vulkan) + var data:Dynamic = NativeCFFI.lime_vk_create_device(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, queueFamily.index, extensions); + if (data != null) + { + return new VKDevice(this, queueFamily, extensions, data); + } + #end + + return null; + } + /** Returns the first queue family that matches the requested capabilities. **/ diff --git a/src/lime/graphics/vulkan/VKQueue.hx b/src/lime/graphics/vulkan/VKQueue.hx new file mode 100644 index 0000000000..9f6e62cb09 --- /dev/null +++ b/src/lime/graphics/vulkan/VKQueue.hx @@ -0,0 +1,75 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan queue retrieved from a `VKDevice`. +**/ +class VKQueue +{ + public var device(default, null):VKDevice; + public var familyIndex(default, null):Int; + public var handle(default, null):Int64; + public var index(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, familyIndex:Int, index:Int) + { + this.device = device; + this.handle = handle; + this.familyIndex = familyIndex; + this.index = index; + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + /** + Submits one command buffer to this queue. A fence may be provided to track + completion from the CPU. + **/ + public function submit(commandBuffer:VKCommandBuffer, fence:VKFence = null):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && commandBuffer != null && commandBuffer.isValid()) + { + var fenceHigh = (fence != null && fence.isValid()) ? fence.handle.high : 0; + var fenceLow = (fence != null && fence.isValid()) ? fence.handle.low : 0; + + return NativeCFFI.lime_vk_queue_submit(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low, fenceHigh, fenceLow); + } + #end + + return false; + } + + /** + Blocks until this queue has completed all submitted work. + **/ + public function waitIdle():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_queue_wait_idle(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKRenderer.hx b/src/lime/graphics/vulkan/VKRenderer.hx index d736b84299..d3b70e3023 100644 --- a/src/lime/graphics/vulkan/VKRenderer.hx +++ b/src/lime/graphics/vulkan/VKRenderer.hx @@ -15,8 +15,10 @@ import lime._internal.backend.native.NativeCFFI; @:access(lime.graphics.VulkanRenderContext) @:access(lime._internal.backend.native.NativeCFFI) /** - A minimal managed Vulkan swapchain renderer exposed by Lime for validation - and sample work. This is intentionally narrower than Lime's GL API surface. + Lime's managed Vulkan validation renderer. + + This is useful for smoke tests and samples, but application renderers should + build on `VK` handles such as `VKInstance`, `VKDevice`, and `VKQueue`. **/ class VKRenderer { diff --git a/src/lime/graphics/vulkan/VKSemaphore.hx b/src/lime/graphics/vulkan/VKSemaphore.hx new file mode 100644 index 0000000000..4128be555b --- /dev/null +++ b/src/lime/graphics/vulkan/VKSemaphore.hx @@ -0,0 +1,47 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan semaphore used for GPU/GPU synchronization. +**/ +class VKSemaphore +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_semaphore(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/tests/vulkan-smoke/Source/Main.hx b/tests/vulkan-smoke/Source/Main.hx index ff2e2a7fe8..24986fcb43 100644 --- a/tests/vulkan-smoke/Source/Main.hx +++ b/tests/vulkan-smoke/Source/Main.hx @@ -114,6 +114,114 @@ class Main extends Application return; } + var queueFamily = device.getQueueFamily(true, true); + var logicalDevice = device.createDevice(queueFamily); + if (logicalDevice == null || !logicalDevice.isValid() || logicalDevice.graphicsQueue == null || !logicalDevice.graphicsQueue.isValid()) + { + surface.dispose(); + instance.dispose(); + fail("Failed to create Vulkan logical device: " + VK.getLastError()); + return; + } + + if (!logicalDevice.graphicsQueue.waitIdle()) + { + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to wait for Vulkan graphics queue: " + VK.getLastError()); + return; + } + + var semaphore = logicalDevice.createSemaphore(); + if (semaphore == null || !semaphore.isValid()) + { + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to create Vulkan semaphore: " + VK.getLastError()); + return; + } + + var commandPool = logicalDevice.createCommandPool(queueFamily); + if (commandPool == null || !commandPool.isValid()) + { + semaphore.dispose(); + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to create Vulkan command pool: " + VK.getLastError()); + return; + } + + var commandBuffer = commandPool.allocateCommandBuffer(); + if (commandBuffer == null || !commandBuffer.isValid()) + { + commandPool.dispose(); + semaphore.dispose(); + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to allocate Vulkan command buffer: " + VK.getLastError()); + return; + } + + if (!commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) || !commandBuffer.end()) + { + commandBuffer.dispose(); + commandPool.dispose(); + semaphore.dispose(); + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to record Vulkan command buffer: " + VK.getLastError()); + return; + } + + var fence = logicalDevice.createFence(); + if (fence == null || !fence.isValid()) + { + commandBuffer.dispose(); + commandPool.dispose(); + semaphore.dispose(); + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to create Vulkan fence: " + VK.getLastError()); + return; + } + + if (!logicalDevice.graphicsQueue.submit(commandBuffer, fence) || !fence.waitForever() || !fence.reset()) + { + fence.dispose(); + commandBuffer.dispose(); + commandPool.dispose(); + semaphore.dispose(); + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to submit Vulkan command buffer: " + VK.getLastError()); + return; + } + + if (!logicalDevice.waitIdle()) + { + fence.dispose(); + commandBuffer.dispose(); + commandPool.dispose(); + semaphore.dispose(); + logicalDevice.dispose(); + surface.dispose(); + instance.dispose(); + fail("Failed to wait for Vulkan logical device: " + VK.getLastError()); + return; + } + + fence.dispose(); + commandBuffer.dispose(); + commandPool.dispose(); + semaphore.dispose(); + logicalDevice.dispose(); surface.dispose(); instance.dispose(); } From 780cb40fe8923634111ec23e972abec19dde93f0 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 21 May 2026 00:58:04 -0400 Subject: [PATCH 12/76] Fix HashLink Vulkan signatures Match the HashLink declarations for Vulkan device enumeration and renderer overlays to the signatures exported by the native hdll. --- src/lime/_internal/backend/native/NativeCFFI.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index b9abfcc40a..a33d5fa464 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -1699,7 +1699,7 @@ class NativeCFFI instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Void {} @:hlNative("lime", "hl_vk_get_physical_devices") private static function lime_vk_get_physical_devices(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Dynamic + instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):hl.NativeArray { return null; } @@ -1830,7 +1830,7 @@ class NativeCFFI } @:hlNative("lime", "hl_vulkan_renderer_set_overlay") private static function lime_vulkan_renderer_set_overlay(handle:CFFIPointer, - bytes:hl.Bytes, width:Int, height:Int, x:Int, y:Int):Bool + bytes:Bytes, width:Int, height:Int, x:Int, y:Int):Bool { return false; } From 251cb31ee2c8aa0f1210f1dfa7f73c68a503f5bd Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 22 May 2026 01:57:54 -0400 Subject: [PATCH 13/76] Add Vulkan types, swapchain & helper bindings Introduce comprehensive Vulkan bindings and runtime helpers across Haxe and native code. Updated docs/ImportAll.hx to expose many new lime.graphics.vulkan types. Added numerous Haxe VK* classes and shader SPIR-V assets for the vulkan-smoke test. Major changes in project/src/ExternalInterface.cpp: include , robust device extension enumeration and VK_KHR_portability_subset handling, helpers for choosing present modes, creating/destroying managed swapchains, querying swapchain images and surface formats, finding memory types, and conversion helpers between native Vulkan structs and Haxe/HL values. Also cleaned up existing garbage collectors and added utility functions for array conversions. Tests updated to include Vulkan smoke test assets and project configuration. --- docs/ImportAll.hx | 24 +- project/src/ExternalInterface.cpp | 10825 +++++++++++----- .../_internal/backend/native/NativeCFFI.hx | 670 + src/lime/graphics/vulkan/VK.hx | 274 + src/lime/graphics/vulkan/VKAcquireResult.hx | 22 + src/lime/graphics/vulkan/VKBuffer.hx | 123 + src/lime/graphics/vulkan/VKCommandBuffer.hx | 235 + src/lime/graphics/vulkan/VKDescriptorPool.hx | 62 + .../graphics/vulkan/VKDescriptorPoolSize.hx | 13 + src/lime/graphics/vulkan/VKDescriptorSet.hx | 73 + .../graphics/vulkan/VKDescriptorSetLayout.hx | 44 + .../vulkan/VKDescriptorSetLayoutBinding.hx | 17 + src/lime/graphics/vulkan/VKDevice.hx | 382 + src/lime/graphics/vulkan/VKDeviceMemory.hx | 85 + src/lime/graphics/vulkan/VKFramebuffer.hx | 50 + .../graphics/vulkan/VKGraphicsPipelineInfo.hx | 77 + src/lime/graphics/vulkan/VKImage.hx | 165 + src/lime/graphics/vulkan/VKImageView.hx | 55 + .../graphics/vulkan/VKMemoryRequirements.hx | 32 + src/lime/graphics/vulkan/VKPipeline.hx | 46 + src/lime/graphics/vulkan/VKPipelineCache.hx | 44 + src/lime/graphics/vulkan/VKPipelineLayout.hx | 44 + src/lime/graphics/vulkan/VKQueue.hx | 42 + src/lime/graphics/vulkan/VKRenderPass.hx | 50 + src/lime/graphics/vulkan/VKSampler.hx | 44 + src/lime/graphics/vulkan/VKShaderModule.hx | 44 + src/lime/graphics/vulkan/VKSwapchain.hx | 140 + src/lime/graphics/vulkan/VKVertexAttribute.hx | 17 + src/lime/graphics/vulkan/VKVertexBinding.hx | 15 + .../vulkan-smoke/Assets/shaders/cube.frag.spv | Bin 0 -> 668 bytes .../vulkan-smoke/Assets/shaders/cube.vert.spv | Bin 0 -> 1456 bytes .../vulkan-smoke/Assets/shaders/quad.frag.spv | Bin 0 -> 660 bytes .../vulkan-smoke/Assets/shaders/quad.vert.spv | Bin 0 -> 1116 bytes tests/vulkan-smoke/Source/Main.hx | 883 +- tests/vulkan-smoke/project.xml | 1 + 35 files changed, 11594 insertions(+), 3004 deletions(-) create mode 100644 src/lime/graphics/vulkan/VKAcquireResult.hx create mode 100644 src/lime/graphics/vulkan/VKBuffer.hx create mode 100644 src/lime/graphics/vulkan/VKDescriptorPool.hx create mode 100644 src/lime/graphics/vulkan/VKDescriptorPoolSize.hx create mode 100644 src/lime/graphics/vulkan/VKDescriptorSet.hx create mode 100644 src/lime/graphics/vulkan/VKDescriptorSetLayout.hx create mode 100644 src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx create mode 100644 src/lime/graphics/vulkan/VKDeviceMemory.hx create mode 100644 src/lime/graphics/vulkan/VKFramebuffer.hx create mode 100644 src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx create mode 100644 src/lime/graphics/vulkan/VKImage.hx create mode 100644 src/lime/graphics/vulkan/VKImageView.hx create mode 100644 src/lime/graphics/vulkan/VKMemoryRequirements.hx create mode 100644 src/lime/graphics/vulkan/VKPipeline.hx create mode 100644 src/lime/graphics/vulkan/VKPipelineCache.hx create mode 100644 src/lime/graphics/vulkan/VKPipelineLayout.hx create mode 100644 src/lime/graphics/vulkan/VKRenderPass.hx create mode 100644 src/lime/graphics/vulkan/VKSampler.hx create mode 100644 src/lime/graphics/vulkan/VKShaderModule.hx create mode 100644 src/lime/graphics/vulkan/VKSwapchain.hx create mode 100644 src/lime/graphics/vulkan/VKVertexAttribute.hx create mode 100644 src/lime/graphics/vulkan/VKVertexBinding.hx create mode 100644 tests/vulkan-smoke/Assets/shaders/cube.frag.spv create mode 100644 tests/vulkan-smoke/Assets/shaders/cube.vert.spv create mode 100644 tests/vulkan-smoke/Assets/shaders/quad.frag.spv create mode 100644 tests/vulkan-smoke/Assets/shaders/quad.vert.spv diff --git a/docs/ImportAll.hx b/docs/ImportAll.hx index cd1be55208..a5032842a4 100644 --- a/docs/ImportAll.hx +++ b/docs/ImportAll.hx @@ -60,17 +60,39 @@ import lime.graphics.RenderContextAttributes; import lime.graphics.RenderContextType; import lime.graphics.VulkanRenderContext; import lime.graphics.vulkan.VK; +import lime.graphics.vulkan.VKAcquireResult; +import lime.graphics.vulkan.VKBuffer; import lime.graphics.vulkan.VKCommandBuffer; import lime.graphics.vulkan.VKCommandPool; +import lime.graphics.vulkan.VKDescriptorPool; +import lime.graphics.vulkan.VKDescriptorPoolSize; +import lime.graphics.vulkan.VKDescriptorSet; +import lime.graphics.vulkan.VKDescriptorSetLayout; +import lime.graphics.vulkan.VKDescriptorSetLayoutBinding; import lime.graphics.vulkan.VKDevice; +import lime.graphics.vulkan.VKDeviceMemory; import lime.graphics.vulkan.VKFence; -import lime.graphics.vulkan.VKRenderer; +import lime.graphics.vulkan.VKFramebuffer; +import lime.graphics.vulkan.VKGraphicsPipelineInfo; +import lime.graphics.vulkan.VKImage; +import lime.graphics.vulkan.VKImageView; import lime.graphics.vulkan.VKInstance; +import lime.graphics.vulkan.VKMemoryRequirements; import lime.graphics.vulkan.VKPhysicalDevice; +import lime.graphics.vulkan.VKPipeline; +import lime.graphics.vulkan.VKPipelineCache; +import lime.graphics.vulkan.VKPipelineLayout; import lime.graphics.vulkan.VKQueue; import lime.graphics.vulkan.VKQueueFamilyInfo; +import lime.graphics.vulkan.VKRenderPass; +import lime.graphics.vulkan.VKRenderer; +import lime.graphics.vulkan.VKSampler; import lime.graphics.vulkan.VKSemaphore; +import lime.graphics.vulkan.VKShaderModule; import lime.graphics.vulkan.VKSurface; +import lime.graphics.vulkan.VKSwapchain; +import lime.graphics.vulkan.VKVertexAttribute; +import lime.graphics.vulkan.VKVertexBinding; import lime.graphics.WebGL2RenderContext; import lime.graphics.WebGLRenderContext; import lime.math.ARGB; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 7bab73d4a4..dff828e2ab 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -58,6 +58,7 @@ #endif #include +#include #include #include #include @@ -398,10 +399,19 @@ namespace lime { } - if (!requestedExtensions.empty ()) { + uint32_t extensionCount = 0; + VkResult extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, 0); + if (extensionResult != VK_SUCCESS) { - uint32_t extensionCount = 0; - VkResult extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, 0); + lastVKError = "Could not enumerate Vulkan device extensions"; + return false; + + } + + std::vector availableExtensions (extensionCount); + if (extensionCount > 0) { + + extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, availableExtensions.data ()); if (extensionResult != VK_SUCCESS) { lastVKError = "Could not enumerate Vulkan device extensions"; @@ -409,45 +419,64 @@ namespace lime { } - std::vector availableExtensions (extensionCount); - if (extensionCount > 0) { + } + + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + bool portabilitySubsetSupported = false; + bool portabilitySubsetRequested = false; + #endif + + for (size_t i = 0; i < requestedExtensions.size (); ++i) { + + bool extensionSupported = false; + + for (size_t e = 0; e < availableExtensions.size (); ++e) { - extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, availableExtensions.data ()); - if (extensionResult != VK_SUCCESS) { + if (strcmp (availableExtensions[e].extensionName, requestedExtensions[i].c_str ()) == 0) { - lastVKError = "Could not enumerate Vulkan device extensions"; - return false; + extensionSupported = true; + break; } } - for (size_t i = 0; i < requestedExtensions.size (); ++i) { + if (!extensionSupported) { - bool extensionSupported = false; + lastVKError = std::string ("Vulkan physical device does not support ") + requestedExtensions[i]; + return false; - for (size_t e = 0; e < availableExtensions.size (); ++e) { + } - if (strcmp (availableExtensions[e].extensionName, requestedExtensions[i].c_str ()) == 0) { + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + if (strcmp (requestedExtensions[i].c_str (), VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) { - extensionSupported = true; - break; + portabilitySubsetRequested = true; - } + } + #endif - } + } - if (!extensionSupported) { + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + for (size_t i = 0; i < availableExtensions.size (); ++i) { - lastVKError = std::string ("Vulkan physical device does not support ") + requestedExtensions[i]; - return false; + if (strcmp (availableExtensions[i].extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) { - } + portabilitySubsetSupported = true; + break; } } + if (portabilitySubsetSupported && !portabilitySubsetRequested) { + + deviceExtensions.push_back (VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + + } + #endif + VkPhysicalDeviceFeatures deviceFeatures; memset (&deviceFeatures, 0, sizeof (deviceFeatures)); @@ -494,797 +523,907 @@ namespace lime { return true; } -#endif - void gc_application (value handle) { + struct ManagedVulkanSwapchain { - Application* application = (Application*)val_data (handle); - delete application; + VkSwapchainKHR handle; + VkFormat format; + VkColorSpaceKHR colorSpace; + VkExtent2D extent; + VkPresentModeKHR presentMode; + uint32_t imageCount; - } + }; - void hl_gc_application (HL_CFFIPointer* handle) { + static VkPresentModeKHR ChooseManagedVulkanPresentMode (const std::vector& presentModes, VkPresentModeKHR requestedPresentMode) { - Application* application = (Application*)handle->ptr; - delete application; + bool hasRequested = false; + bool hasFifo = false; + bool hasMailbox = false; + bool hasImmediate = false; - } + for (size_t i = 0; i < presentModes.size (); ++i) { + if (presentModes[i] == requestedPresentMode) hasRequested = true; + if (presentModes[i] == VK_PRESENT_MODE_FIFO_KHR) hasFifo = true; + if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) hasMailbox = true; + if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) hasImmediate = true; - void gc_file_watcher (value handle) { + } - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - delete watcher; - #endif + if (hasRequested) return requestedPresentMode; + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + return VK_PRESENT_MODE_FIFO_KHR; } - void hl_gc_file_watcher (HL_CFFIPointer* handle) { + static value CreateVulkanSwapchainValue (const ManagedVulkanSwapchain& swapchain) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - delete watcher; - #endif + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchain.handle)); + alloc_field (result, val_id ("format"), alloc_int ((int)swapchain.format)); + alloc_field (result, val_id ("colorSpace"), alloc_int ((int)swapchain.colorSpace)); + alloc_field (result, val_id ("width"), alloc_int ((int)swapchain.extent.width)); + alloc_field (result, val_id ("height"), alloc_int ((int)swapchain.extent.height)); + alloc_field (result, val_id ("imageCount"), alloc_int ((int)swapchain.imageCount)); + alloc_field (result, val_id ("presentMode"), alloc_int ((int)swapchain.presentMode)); + return result; } - void gc_font (value handle) { + static vdynamic* HLCreateVulkanSwapchainValue (const ManagedVulkanSwapchain& swapchain) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (handle); - delete font; - #endif + const int id_handle = hl_hash_utf8 ("handle"); + const int id_format = hl_hash_utf8 ("format"); + const int id_colorSpace = hl_hash_utf8 ("colorSpace"); + const int id_width = hl_hash_utf8 ("width"); + const int id_height = hl_hash_utf8 ("height"); + const int id_imageCount = hl_hash_utf8 ("imageCount"); + const int id_presentMode = hl_hash_utf8 ("presentMode"); + + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchain.handle)); + hl_dyn_seti (result, id_format, &hlt_i32, (int)swapchain.format); + hl_dyn_seti (result, id_colorSpace, &hlt_i32, (int)swapchain.colorSpace); + hl_dyn_seti (result, id_width, &hlt_i32, (int)swapchain.extent.width); + hl_dyn_seti (result, id_height, &hlt_i32, (int)swapchain.extent.height); + hl_dyn_seti (result, id_imageCount, &hlt_i32, (int)swapchain.imageCount); + hl_dyn_seti (result, id_presentMode, &hlt_i32, (int)swapchain.presentMode); + return result; } - void hl_gc_font (HL_CFFIPointer* handle) { + static value CreateVulkanAcquireValue (VkResult acquireResult, int imageIndex) { - #ifdef LIME_FREETYPE - Font* font = (Font*)handle->ptr; - delete font; - #endif + value result = alloc_empty_object (); + alloc_field (result, val_id ("result"), alloc_int ((int)acquireResult)); + alloc_field (result, val_id ("imageIndex"), alloc_int (imageIndex)); + return result; } - void gc_window (value handle) { + static vdynamic* HLCreateVulkanAcquireValue (VkResult acquireResult, int imageIndex) { - Window* window = (Window*)val_data (handle); - delete window; + const int id_result = hl_hash_utf8 ("result"); + const int id_imageIndex = hl_hash_utf8 ("imageIndex"); + + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_seti (result, id_result, &hlt_i32, (int)acquireResult); + hl_dyn_seti (result, id_imageIndex, &hlt_i32, imageIndex); + return result; } - void hl_gc_window (HL_CFFIPointer* handle) { + static value CreateVulkanMemoryRequirementsValue (const VkMemoryRequirements& requirements) { - Window* window = (Window*)handle->ptr; - delete window; + value result = alloc_empty_object (); + alloc_field (result, val_id ("size"), CreateVulkanHandleValue ((uint64_t)requirements.size)); + alloc_field (result, val_id ("alignment"), CreateVulkanHandleValue ((uint64_t)requirements.alignment)); + alloc_field (result, val_id ("memoryTypeBits"), alloc_int ((int)requirements.memoryTypeBits)); + return result; } - std::string wstring_utf8 (const std::wstring& val) { + static vdynamic* HLCreateVulkanMemoryRequirementsValue (const VkMemoryRequirements& requirements) { - std::string out; - unsigned int codepoint = 0; + const int id_size = hl_hash_utf8 ("size"); + const int id_alignment = hl_hash_utf8 ("alignment"); + const int id_memoryTypeBits = hl_hash_utf8 ("memoryTypeBits"); - for (const wchar_t chr : val) { + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_size, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)requirements.size)); + hl_dyn_setp (result, id_alignment, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)requirements.alignment)); + hl_dyn_seti (result, id_memoryTypeBits, &hlt_i32, (int)requirements.memoryTypeBits); + return result; - if (chr >= 0xd800 && chr <= 0xdbff) { + } - codepoint = ((chr - 0xd800) << 10) + 0x10000; - } else { + static value CreateVulkanMemoryValue (VkDeviceMemory memory, uint32_t memoryTypeIndex) { - if (chr >= 0xdc00 && chr <= 0xdfff) { + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)memory)); + alloc_field (result, val_id ("memoryTypeIndex"), alloc_int ((int)memoryTypeIndex)); + return result; - codepoint |= chr - 0xdc00; + } - } else { - codepoint = chr; + static vdynamic* HLCreateVulkanMemoryValue (VkDeviceMemory memory, uint32_t memoryTypeIndex) { - } + const int id_handle = hl_hash_utf8 ("handle"); + const int id_memoryTypeIndex = hl_hash_utf8 ("memoryTypeIndex"); - if (codepoint <= 0x7f) { + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)memory)); + hl_dyn_seti (result, id_memoryTypeIndex, &hlt_i32, (int)memoryTypeIndex); + return result; - out.append (1, static_cast (codepoint)); + } - } else if (codepoint <= 0x7ff) { - out.append (1, static_cast (0xc0 | ((codepoint >> 6) & 0x1f))); - out.append (1, static_cast (0x80 | (codepoint & 0x3f))); + static std::vector GetVulkanIntVector (value data) { - } else if (codepoint <= 0xffff) { + std::vector result; + if (val_is_null (data)) return result; - out.append (1, static_cast (0xe0 | ((codepoint >> 12) & 0x0f))); - out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); - out.append (1, static_cast (0x80 | (codepoint & 0x3f))); + int length = val_array_size (data); + result.reserve (length); + for (int i = 0; i < length; ++i) { - } else { + result.push_back (val_int (val_array_i (data, i))); - out.append (1, static_cast (0xf0 | ((codepoint >> 18) & 0x07))); - out.append (1, static_cast (0x80 | ((codepoint >> 12) & 0x3f))); - out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); - out.append (1, static_cast (0x80 | (codepoint & 0x3f))); + } - } + return result; - codepoint = 0; + } - } - } + static std::vector GetHLVulkanIntVector (hl_varray* data) { - return out; + std::vector result; + if (!data) return result; - } + result.reserve (data->size); + int* values = hl_aptr (data, int); + for (int i = 0; i < data->size; ++i) { + result.push_back (values[i]); - vbyte* hl_wstring_to_utf8_bytes (const std::wstring& val) { + } - const std::string utf8 (wstring_utf8 (val)); - vbyte* const bytes = hl_alloc_bytes (utf8.size () + 1); - std::memcpy(bytes, utf8.c_str (), utf8.size () + 1); - return bytes; + return result; } - std::wstring* hxstring_to_wstring (HxString val) { - - if (val.c_str ()) { + static std::vector GetVulkanDoubleVector (value data) { - #ifdef HX_WINDOWS - return new std::wstring (hxs_wchar (val, nullptr)); - #else - const std::string _val (hxs_utf8 (val, nullptr)); - return new std::wstring (_val.begin (), _val.end ()); - #endif + std::vector result; + if (val_is_null (data)) return result; - } else { + int length = val_array_size (data); + result.reserve (length); + for (int i = 0; i < length; ++i) { - return 0; + result.push_back (val_number (val_array_i (data, i))); } - } + return result; + } - std::wstring* hxstring_to_wstring (hl_vstring* val) { - if (val) { + static std::vector GetHLVulkanDoubleVector (hl_varray* data) { - std::string _val = std::string (hl_to_utf8 (val->bytes)); - #ifdef HX_WINDOWS - std::wstring_convert> converter; - return new std::wstring (converter.from_bytes (_val)); - #else - return new std::wstring (_val.begin (), _val.end ()); - #endif + std::vector result; + if (!data) return result; - } else { + result.reserve (data->size); + double* values = hl_aptr (data, double); + for (int i = 0; i < data->size; ++i) { - return 0; + result.push_back (values[i]); } - } - + return result; - value wstring_to_value (std::wstring* val) { + } - if (val) { - #ifdef HX_WINDOWS - return alloc_wstring (val->c_str ()); - #else - std::string _val = std::string (val->begin (), val->end ()); - return alloc_string (_val.c_str ()); - #endif + static bool FindManagedVulkanMemoryType (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, uint32_t typeFilter, + VkMemoryPropertyFlags properties, uint32_t* outMemoryTypeIndex) { - } else { + if (!targetWindow || !instance || !physicalDevice || !outMemoryTypeIndex) { - return 0; + lastVKError = "Missing Vulkan window, instance, physical device, or memory type output"; + return false; } - } + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; - value lime_application_create () { + } - Application* application = CreateApplication (); - return CFFIPointer (application, gc_application); + PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = + (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceMemoryProperties"); + if (!vkGetPhysicalDeviceMemoryProperties) { - } + lastVKError = "Missing Vulkan physical device memory properties function"; + return false; + } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_application_create) () { + VkPhysicalDeviceMemoryProperties memoryProperties; + memset (&memoryProperties, 0, sizeof (memoryProperties)); + vkGetPhysicalDeviceMemoryProperties (physicalDevice, &memoryProperties); - Application* application = CreateApplication (); - return HLCFFIPointer (application, (hl_finalizer)hl_gc_application); + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) { - } + if ((typeFilter & (1u << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { + *outMemoryTypeIndex = i; + lastVKError.clear (); + return true; - void lime_application_event_manager_register (value callback, value eventObject) { + } - ApplicationEvent::callback = new ValuePointer (callback); - ApplicationEvent::eventObject = new ValuePointer (eventObject); + } + + lastVKError = "Failed to find a compatible Vulkan memory type"; + return false; } - HL_PRIM void HL_NAME(hl_application_event_manager_register) (vclosure* callback, ApplicationEvent* eventObject) { + static bool CreateManagedVulkanSwapchain (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, + VkSurfaceKHR surface, uint32_t queueFamilyIndex, int requestedWidth, int requestedHeight, VkPresentModeKHR requestedPresentMode, + VkSwapchainKHR oldSwapchain, ManagedVulkanSwapchain* outSwapchain) { - ApplicationEvent::callback = new ValuePointer (callback); - ApplicationEvent::eventObject = new ValuePointer ((vobj*)eventObject); + if (!targetWindow || !instance || !physicalDevice || !device || !surface || !outSwapchain) { - } + lastVKError = "Missing Vulkan window, instance, device, surface, or output swapchain"; + return false; + } - int lime_application_exec (value application) { + outSwapchain->handle = VK_NULL_HANDLE; + outSwapchain->format = VK_FORMAT_UNDEFINED; + outSwapchain->colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + outSwapchain->extent.width = 0; + outSwapchain->extent.height = 0; + outSwapchain->presentMode = VK_PRESENT_MODE_FIFO_KHR; + outSwapchain->imageCount = 0; - Application* app = (Application*)val_data (application); - return app->Exec (); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { - } + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; + } - HL_PRIM int HL_NAME(hl_application_exec) (HL_CFFIPointer* application) { + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = + (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR = + (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR = + (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); - Application* app = (Application*)application->ptr; - return app->Exec (); + if (!vkGetPhysicalDeviceSurfaceCapabilitiesKHR || !vkGetPhysicalDeviceSurfaceFormatsKHR || !vkGetPhysicalDeviceSurfacePresentModesKHR) { - } + lastVKError = "Missing required Vulkan surface functions"; + return false; + } - void lime_application_init (value application) { + if (vkGetPhysicalDeviceSurfaceSupportKHR) { - Application* app = (Application*)val_data (application); - app->Init (); + VkBool32 supportsPresent = VK_FALSE; + VkResult supportResult = vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevice, queueFamilyIndex, surface, &supportsPresent); + if (supportResult != VK_SUCCESS || supportsPresent == VK_FALSE) { - } + lastVKError = "Vulkan queue family does not support presenting to this surface"; + return false; + } - HL_PRIM void HL_NAME(hl_application_init) (HL_CFFIPointer* application) { + } - Application* app = (Application*)application->ptr; - app->Init (); + VkSurfaceCapabilitiesKHR capabilities; + memset (&capabilities, 0, sizeof (capabilities)); + VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (physicalDevice, surface, &capabilities); + if (result != VK_SUCCESS) { - } + lastVKError = "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"; + return false; + } - int lime_application_quit (value application) { + uint32_t formatCount = 0; + result = vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, 0); + if (result != VK_SUCCESS || formatCount == 0) { - Application* app = (Application*)val_data (application); - return app->Quit (); + lastVKError = "Failed to query Vulkan surface formats"; + return false; - } + } + std::vector formats (formatCount); + result = vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, formats.data ()); + if (result != VK_SUCCESS) { - HL_PRIM int HL_NAME(hl_application_quit) (HL_CFFIPointer* application) { + lastVKError = "vkGetPhysicalDeviceSurfaceFormatsKHR failed"; + return false; - Application* app = (Application*)application->ptr; - return app->Quit (); + } - } + VkSurfaceFormatKHR surfaceFormat = formats[0]; + if (formats.size () == 1 && formats[0].format == VK_FORMAT_UNDEFINED) { + surfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM; + surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - void lime_application_set_frame_rate (value application, double frameRate) { + } else { - Application* app = (Application*)val_data (application); - app->SetFrameRate (frameRate); + for (size_t i = 0; i < formats.size (); ++i) { - } + if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + surfaceFormat = formats[i]; + break; - HL_PRIM void HL_NAME(hl_application_set_frame_rate) (HL_CFFIPointer* application, double frameRate) { + } - Application* app = (Application*)application->ptr; - app->SetFrameRate (frameRate); + } - } + } + uint32_t presentModeCount = 0; + result = vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, 0); + if (result != VK_SUCCESS) { - void lime_application_set_main_loop (value application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { + lastVKError = "Failed to query Vulkan present modes"; + return false; - Application* app = (Application*)val_data (application); - app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); + } - } + std::vector presentModes (presentModeCount > 0 ? presentModeCount : 1, VK_PRESENT_MODE_FIFO_KHR); + if (presentModeCount > 0) { + result = vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, presentModes.data ()); + if (result != VK_SUCCESS) { - HL_PRIM void HL_NAME(hl_application_set_main_loop) (HL_CFFIPointer* application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { + lastVKError = "vkGetPhysicalDeviceSurfacePresentModesKHR failed"; + return false; - Application* app = (Application*)application->ptr; - app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); + } - } + } + int drawableWidth = requestedWidth; + int drawableHeight = requestedHeight; + if (drawableWidth <= 0 || drawableHeight <= 0) { - void lime_application_set_vsync_mode (value application, int vsyncMode) { + drawableWidth = 0; + drawableHeight = 0; + targetWindow->GetVulkanDrawableSize (&drawableWidth, &drawableHeight); - Application* app = (Application*)val_data (application); - app->SetVSyncMode (vsyncMode); + } - } + if (drawableWidth <= 0 || drawableHeight <= 0) { + lastVKError = "Vulkan drawable size is zero"; + return false; - HL_PRIM void HL_NAME(hl_application_set_vsync_mode) (HL_CFFIPointer* application, int vsyncMode) { + } - Application* app = (Application*)application->ptr; - app->SetVSyncMode (vsyncMode); + VkExtent2D extent; + if (capabilities.currentExtent.width != UINT32_MAX) { - } + extent = capabilities.currentExtent; + } else { - bool lime_application_update (value application) { + extent.width = (uint32_t)(std::max) ((int)capabilities.minImageExtent.width, + (std::min) (drawableWidth, (int)capabilities.maxImageExtent.width)); + extent.height = (uint32_t)(std::max) ((int)capabilities.minImageExtent.height, + (std::min) (drawableHeight, (int)capabilities.maxImageExtent.height)); - Application* app = (Application*)val_data (application); - return app->Update (); + } - } + if ((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0) { + + lastVKError = "Vulkan surface images do not support color attachments"; + return false; + } - HL_PRIM bool HL_NAME(hl_application_update) (HL_CFFIPointer* application) { + VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + if (capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { - Application* app = (Application*)application->ptr; - return app->Update (); + imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - } + } + uint32_t imageCount = capabilities.minImageCount + 1; + if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) { - value lime_audio_load_bytes (value data, value buffer) { + imageCount = capabilities.maxImageCount; - Resource resource; - Bytes bytes; + } - AudioBuffer audioBuffer = AudioBuffer (buffer); + VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + const VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR + }; - bytes.Set (data); - resource = Resource (&bytes); + for (size_t i = 0; i < sizeof (compositeAlphaFlags) / sizeof (compositeAlphaFlags[0]); ++i) { - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, &audioBuffer)) { + if (capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) { - return audioBuffer.Value (buffer); + compositeAlpha = compositeAlphaFlags[i]; + break; + + } } - #endif + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSwapchainKHR"); + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkGetSwapchainImagesKHR"); + if (!vkCreateSwapchainKHR || !vkGetSwapchainImagesKHR) return false; - if (WAV::Decode (&resource, &audioBuffer)) { + VkSwapchainCreateInfoKHR createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = imageUsage; + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.preTransform = capabilities.currentTransform; + createInfo.compositeAlpha = compositeAlpha; + createInfo.presentMode = ChooseManagedVulkanPresentMode (presentModes, requestedPresentMode); + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = oldSwapchain; + + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + result = vkCreateSwapchainKHR (device, &createInfo, 0, &swapchain); + if (result != VK_SUCCESS) { - return audioBuffer.Value (buffer); + lastVKError = "vkCreateSwapchainKHR failed"; + return false; } - #ifdef LIME_OGG - if (OGG::Decode (&resource, &audioBuffer)) { + uint32_t swapchainImageCount = 0; + result = vkGetSwapchainImagesKHR (device, swapchain, &swapchainImageCount, 0); + if (result != VK_SUCCESS || swapchainImageCount == 0) { - return audioBuffer.Value (buffer); + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySwapchainKHR"); + if (vkDestroySwapchainKHR) vkDestroySwapchainKHR (device, swapchain, 0); + lastVKError = "Failed to query Vulkan swapchain images"; + return false; } - #endif - return alloc_null (); + outSwapchain->handle = swapchain; + outSwapchain->format = surfaceFormat.format; + outSwapchain->colorSpace = surfaceFormat.colorSpace; + outSwapchain->extent = extent; + outSwapchain->presentMode = createInfo.presentMode; + outSwapchain->imageCount = swapchainImageCount; + lastVKError.clear (); + return true; } +#endif - HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_bytes) (Bytes* data, AudioBuffer* buffer) { - - Resource resource = Resource (data); + void gc_application (value handle) { - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, buffer)) { + Application* application = (Application*)val_data (handle); + delete application; - return buffer; + } - } - #endif - if (WAV::Decode (&resource, buffer)) { + void hl_gc_application (HL_CFFIPointer* handle) { - return buffer; + Application* application = (Application*)handle->ptr; + delete application; - } + } - #ifdef LIME_OGG - if (OGG::Decode (&resource, buffer)) { - return buffer; + void gc_file_watcher (value handle) { - } + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + delete watcher; #endif - return 0; - } - value lime_audio_load_file (value data, value buffer) { - - Resource resource; + void hl_gc_file_watcher (HL_CFFIPointer* handle) { - AudioBuffer audioBuffer = AudioBuffer (buffer); + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + delete watcher; + #endif - resource = Resource (val_string (data)); + } - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, &audioBuffer)) { - return audioBuffer.Value (buffer); + void gc_font (value handle) { - } + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (handle); + delete font; #endif - if (WAV::Decode (&resource, &audioBuffer)) { - - return audioBuffer.Value (buffer); - - } + } - #ifdef LIME_OGG - if (OGG::Decode (&resource, &audioBuffer)) { - return audioBuffer.Value (buffer); + void hl_gc_font (HL_CFFIPointer* handle) { - } + #ifdef LIME_FREETYPE + Font* font = (Font*)handle->ptr; + delete font; #endif - return alloc_null (); - } - HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_file) (hl_vstring* data, AudioBuffer* buffer) { + void gc_window (value handle) { - Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); + Window* window = (Window*)val_data (handle); + delete window; - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, buffer)) { + } - return buffer; - } - #endif + void hl_gc_window (HL_CFFIPointer* handle) { - if (WAV::Decode (&resource, buffer)) { + Window* window = (Window*)handle->ptr; + delete window; - return buffer; + } - } - #ifdef LIME_OGG - if (OGG::Decode (&resource, buffer)) { + std::string wstring_utf8 (const std::wstring& val) { - return buffer; + std::string out; + unsigned int codepoint = 0; - } - #endif + for (const wchar_t chr : val) { - return 0; + if (chr >= 0xd800 && chr <= 0xdbff) { - } + codepoint = ((chr - 0xd800) << 10) + 0x10000; + } else { - value lime_audio_load (value data, value buffer) { + if (chr >= 0xdc00 && chr <= 0xdfff) { - if (val_is_string (data)) { + codepoint |= chr - 0xdc00; - return lime_audio_load_file (data, buffer); + } else { - } else { + codepoint = chr; - return lime_audio_load_bytes (data, buffer); + } - } + if (codepoint <= 0x7f) { - } + out.append (1, static_cast (codepoint)); + } else if (codepoint <= 0x7ff) { - value lime_bytes_from_data_pointer (double data, int length, value _bytes) { + out.append (1, static_cast (0xc0 | ((codepoint >> 6) & 0x1f))); + out.append (1, static_cast (0x80 | (codepoint & 0x3f))); - uintptr_t ptr = (uintptr_t)data; - Bytes bytes (_bytes); - bytes.Resize (length); + } else if (codepoint <= 0xffff) { - if (ptr) { + out.append (1, static_cast (0xe0 | ((codepoint >> 12) & 0x0f))); + out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); + out.append (1, static_cast (0x80 | (codepoint & 0x3f))); - memcpy (bytes.b, (const void*)ptr, length); + } else { - } + out.append (1, static_cast (0xf0 | ((codepoint >> 18) & 0x07))); + out.append (1, static_cast (0x80 | ((codepoint >> 12) & 0x3f))); + out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); + out.append (1, static_cast (0x80 | (codepoint & 0x3f))); - return bytes.Value (_bytes); + } - } + codepoint = 0; + } - HL_PRIM Bytes* HL_NAME(hl_bytes_from_data_pointer) (double data, int length, Bytes* bytes) { + } - uintptr_t ptr = (uintptr_t)data; - bytes->Resize (length); + return out; - if (ptr) { + } - memcpy (bytes->b, (const void*)ptr, length); - } + vbyte* hl_wstring_to_utf8_bytes (const std::wstring& val) { + const std::string utf8 (wstring_utf8 (val)); + vbyte* const bytes = hl_alloc_bytes (utf8.size () + 1); + std::memcpy(bytes, utf8.c_str (), utf8.size () + 1); return bytes; } - double lime_bytes_get_data_pointer (value bytes) { + std::wstring* hxstring_to_wstring (HxString val) { - Bytes data = Bytes (bytes); - return (uintptr_t)data.b; + if (val.c_str ()) { - } + #ifdef HX_WINDOWS + return new std::wstring (hxs_wchar (val, nullptr)); + #else + const std::string _val (hxs_utf8 (val, nullptr)); + return new std::wstring (_val.begin (), _val.end ()); + #endif + } else { - HL_PRIM double HL_NAME(hl_bytes_get_data_pointer) (Bytes* bytes) { + return 0; - return bytes ? (uintptr_t)bytes->b : 0; + } } - double lime_bytes_get_data_pointer_offset (value bytes, int offset) { - - if (val_is_null (bytes)) return 0; + std::wstring* hxstring_to_wstring (hl_vstring* val) { - Bytes data = Bytes (bytes); - return (uintptr_t)data.b + offset; + if (val) { - } + std::string _val = std::string (hl_to_utf8 (val->bytes)); + #ifdef HX_WINDOWS + std::wstring_convert> converter; + return new std::wstring (converter.from_bytes (_val)); + #else + return new std::wstring (_val.begin (), _val.end ()); + #endif + } else { - HL_PRIM double HL_NAME(hl_bytes_get_data_pointer_offset) (Bytes* bytes, int offset) { + return 0; - if (!bytes) return 0; - return (uintptr_t)bytes->b + offset; + } } - value lime_bytes_read_file (HxString path, value bytes) { + value wstring_to_value (std::wstring* val) { - Bytes data (bytes); - data.ReadFile (hxs_utf8 (path, nullptr)); - return data.Value (bytes); + if (val) { - } + #ifdef HX_WINDOWS + return alloc_wstring (val->c_str ()); + #else + std::string _val = std::string (val->begin (), val->end ()); + return alloc_string (_val.c_str ()); + #endif + } else { - HL_PRIM Bytes* HL_NAME(hl_bytes_read_file) (hl_vstring* path, Bytes* bytes) { + return 0; - if (!path) return 0; - bytes->ReadFile (hl_to_utf8 ((const uchar*)path->bytes)); - return bytes; + } } - double lime_cffi_get_native_pointer (value handle) { + value lime_application_create () { - return (uintptr_t)val_data (handle); + Application* application = CreateApplication (); + return CFFIPointer (application, gc_application); } - HL_PRIM double HL_NAME(hl_cffi_get_native_pointer) (HL_CFFIPointer* handle) { + HL_PRIM HL_CFFIPointer* HL_NAME(hl_application_create) () { - return (uintptr_t)handle->ptr; + Application* application = CreateApplication (); + return HLCFFIPointer (application, (hl_finalizer)hl_gc_application); } - void lime_cffi_finalizer (value abstract) { + void lime_application_event_manager_register (value callback, value eventObject) { - val_call0 ((value)val_data (abstract)); + ApplicationEvent::callback = new ValuePointer (callback); + ApplicationEvent::eventObject = new ValuePointer (eventObject); } - value lime_cffi_set_finalizer (value callback) { + HL_PRIM void HL_NAME(hl_application_event_manager_register) (vclosure* callback, ApplicationEvent* eventObject) { - value abstract = alloc_abstract (k_finalizer, callback); - val_gc (abstract, lime_cffi_finalizer); - return abstract; + ApplicationEvent::callback = new ValuePointer (callback); + ApplicationEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - void lime_clipboard_event_manager_register (value callback, value eventObject) { + int lime_application_exec (value application) { - ClipboardEvent::callback = new ValuePointer (callback); - ClipboardEvent::eventObject = new ValuePointer (eventObject); + Application* app = (Application*)val_data (application); + return app->Exec (); } - HL_PRIM void HL_NAME(hl_clipboard_event_manager_register) (vclosure* callback, ClipboardEvent* eventObject) { + HL_PRIM int HL_NAME(hl_application_exec) (HL_CFFIPointer* application) { - ClipboardEvent::callback = new ValuePointer (callback); - ClipboardEvent::eventObject = new ValuePointer ((vobj*)eventObject); + Application* app = (Application*)application->ptr; + return app->Exec (); } - value lime_clipboard_get_text () { - - if (Clipboard::HasText ()) { - - const char* text = Clipboard::GetText (); - value _text = alloc_string (text); - - // TODO: Should we free for all backends? (SDL requires it) - - free ((char*)text); - return _text; - - } else { - - return alloc_null (); + void lime_application_init (value application) { - } + Application* app = (Application*)val_data (application); + app->Init (); } - HL_PRIM vbyte* HL_NAME(hl_clipboard_get_text) () { + HL_PRIM void HL_NAME(hl_application_init) (HL_CFFIPointer* application) { - if (Clipboard::HasText ()) { + Application* app = (Application*)application->ptr; + app->Init (); - const char* text = Clipboard::GetText (); - return (vbyte*)text; + } - } else { - return 0; + int lime_application_quit (value application) { - } + Application* app = (Application*)val_data (application); + return app->Quit (); } - void lime_clipboard_set_text (HxString text) { + HL_PRIM int HL_NAME(hl_application_quit) (HL_CFFIPointer* application) { - Clipboard::SetText (hxs_utf8 (text, nullptr)); + Application* app = (Application*)application->ptr; + return app->Quit (); } - HL_PRIM void HL_NAME(hl_clipboard_set_text) (hl_vstring* text) { + void lime_application_set_frame_rate (value application, double frameRate) { - Clipboard::SetText (text ? (const char*)hl_to_utf8 ((const uchar*)text->bytes) : NULL); + Application* app = (Application*)val_data (application); + app->SetFrameRate (frameRate); } - double lime_data_pointer_offset (double pointer, int offset) { + HL_PRIM void HL_NAME(hl_application_set_frame_rate) (HL_CFFIPointer* application, double frameRate) { - return (uintptr_t)pointer + offset; + Application* app = (Application*)application->ptr; + app->SetFrameRate (frameRate); } - HL_PRIM double HL_NAME(hl_data_pointer_offset) (double pointer, int offset) { + void lime_application_set_main_loop (value application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { - return (uintptr_t)pointer + offset; + Application* app = (Application*)val_data (application); + app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); } - value lime_deflate_compress (value buffer, value bytes) { - - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - - Zlib::Compress (DEFLATE, &data, &result); + HL_PRIM void HL_NAME(hl_application_set_main_loop) (HL_CFFIPointer* application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { - return result.Value (bytes); - #else - return alloc_null(); - #endif + Application* app = (Application*)application->ptr; + app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); } - HL_PRIM Bytes* HL_NAME(hl_deflate_compress) (Bytes* buffer, Bytes* bytes) { + void lime_application_set_vsync_mode (value application, int vsyncMode) { - #ifdef LIME_ZLIB - Zlib::Compress (DEFLATE, buffer, bytes); - return bytes; - #else - return 0; - #endif + Application* app = (Application*)val_data (application); + app->SetVSyncMode (vsyncMode); } - value lime_deflate_decompress (value buffer, value bytes) { - - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - - Zlib::Decompress (DEFLATE, &data, &result); + HL_PRIM void HL_NAME(hl_application_set_vsync_mode) (HL_CFFIPointer* application, int vsyncMode) { - return result.Value (bytes); - #else - return alloc_null (); - #endif + Application* app = (Application*)application->ptr; + app->SetVSyncMode (vsyncMode); } - HL_PRIM Bytes* HL_NAME(hl_deflate_decompress) (Bytes* buffer, Bytes* bytes) { + bool lime_application_update (value application) { - #ifdef LIME_ZLIB - Zlib::Decompress (DEFLATE, buffer, bytes); - return bytes; - #else - return 0; - #endif + Application* app = (Application*)val_data (application); + return app->Update (); } - void lime_drop_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_application_update) (HL_CFFIPointer* application) { - DropEvent::callback = new ValuePointer (callback); - DropEvent::eventObject = new ValuePointer (eventObject); + Application* app = (Application*)application->ptr; + return app->Update (); } - HL_PRIM void HL_NAME(hl_drop_event_manager_register) (vclosure* callback, DropEvent* eventObject) { + value lime_audio_load_bytes (value data, value buffer) { - DropEvent::callback = new ValuePointer (callback); - DropEvent::eventObject = new ValuePointer ((vobj*)eventObject); + Resource resource; + Bytes bytes; - } + AudioBuffer audioBuffer = AudioBuffer (buffer); + bytes.Set (data); + resource = Resource (&bytes); - value lime_file_dialog_open_directory (HxString title, HxString filter, HxString defaultPath) { + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, &audioBuffer)) { - #ifdef LIME_TINYFILEDIALOGS + return audioBuffer.Value (buffer); - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + } + #endif - std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + if (WAV::Decode (&resource, &audioBuffer)) { - if (path) { + return audioBuffer.Value (buffer); - value _path = wstring_to_value (path); - delete path; - return _path; + } - } else { + #ifdef LIME_OGG + if (OGG::Decode (&resource, &audioBuffer)) { - return alloc_null (); + return audioBuffer.Value (buffer); } - #endif return alloc_null (); @@ -1292,448 +1431,334 @@ namespace lime { } - HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_directory) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_bytes) (Bytes* data, AudioBuffer* buffer) { - #ifdef LIME_TINYFILEDIALOGS + Resource resource = Resource (data); - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, buffer)) { - std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); + return buffer; - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + } + #endif - if (path) { + if (WAV::Decode (&resource, buffer)) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + return buffer; - } else { + } - return NULL; + #ifdef LIME_OGG + if (OGG::Decode (&resource, buffer)) { - } + return buffer; + } #endif - return NULL; + return 0; } - value lime_file_dialog_open_file (HxString title, HxString filter, HxString defaultPath) { + value lime_audio_load_file (value data, value buffer) { - #ifdef LIME_TINYFILEDIALOGS + Resource resource; - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + AudioBuffer audioBuffer = AudioBuffer (buffer); - std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); + resource = Resource (val_string (data)); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, &audioBuffer)) { - if (path) { + return audioBuffer.Value (buffer); - value _path = wstring_to_value (path); - delete path; - return _path; + } + #endif - } else { + if (WAV::Decode (&resource, &audioBuffer)) { - return alloc_null (); + return audioBuffer.Value (buffer); } - #endif + #ifdef LIME_OGG + if (OGG::Decode (&resource, &audioBuffer)) { - return alloc_null (); + return audioBuffer.Value (buffer); - } + } + #endif + return alloc_null (); - HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + } - #ifdef LIME_TINYFILEDIALOGS - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_file) (hl_vstring* data, AudioBuffer* buffer) { - std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); + Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, buffer)) { - if (path) { + return buffer; - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + } + #endif - } else { + if (WAV::Decode (&resource, buffer)) { - return NULL; + return buffer; } + #ifdef LIME_OGG + if (OGG::Decode (&resource, buffer)) { + + return buffer; + + } #endif - return NULL; + return 0; } - value lime_file_dialog_open_files (HxString title, HxString filter, HxString defaultPath) { - - #ifdef LIME_TINYFILEDIALOGS + value lime_audio_load (value data, value buffer) { - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + if (val_is_string (data)) { - std::vector files; + return lime_audio_load_file (data, buffer); - FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); - value result = alloc_array (files.size ()); + } else { - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + return lime_audio_load_bytes (data, buffer); - for (int i = 0; i < files.size (); i++) { + } - value _file = wstring_to_value (files[i]); - val_array_set_i (result, i, _file); - delete files[i]; + } - } - #else - value result = alloc_array (0); - #endif + value lime_bytes_from_data_pointer (double data, int length, value _bytes) { - return result; + uintptr_t ptr = (uintptr_t)data; + Bytes bytes (_bytes); + bytes.Resize (length); - } + if (ptr) { + memcpy (bytes.b, (const void*)ptr, length); - HL_PRIM hl_varray* HL_NAME(hl_file_dialog_open_files) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + } - #ifdef LIME_TINYFILEDIALOGS + return bytes.Value (_bytes); - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + } - std::vector files; - FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); - hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, files.size ()); - vbyte** resultData = hl_aptr (result, vbyte*); + HL_PRIM Bytes* HL_NAME(hl_bytes_from_data_pointer) (double data, int length, Bytes* bytes) { - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + uintptr_t ptr = (uintptr_t)data; + bytes->Resize (length); - for (int i = 0; i < files.size (); i++) { + if (ptr) { - *resultData++ = hl_wstring_to_utf8_bytes (*files[i]); - delete files[i]; + memcpy (bytes->b, (const void*)ptr, length); } - #else - hl_varray* result = hl_alloc_array (&hlt_bytes, 0); - #endif - - return result; + return bytes; } - value lime_file_dialog_save_file (HxString title, HxString filter, HxString defaultPath) { - - #ifdef LIME_TINYFILEDIALOGS + double lime_bytes_get_data_pointer (value bytes) { - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + Bytes data = Bytes (bytes); + return (uintptr_t)data.b; - std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); + } - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - if (path) { + HL_PRIM double HL_NAME(hl_bytes_get_data_pointer) (Bytes* bytes) { - value _path = wstring_to_value (path); - delete path; - return _path; + return bytes ? (uintptr_t)bytes->b : 0; - } else { + } - return alloc_null (); - } + double lime_bytes_get_data_pointer_offset (value bytes, int offset) { - #endif + if (val_is_null (bytes)) return 0; - return alloc_null (); + Bytes data = Bytes (bytes); + return (uintptr_t)data.b + offset; } - HL_PRIM vbyte* HL_NAME(hl_file_dialog_save_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { - - #ifdef LIME_TINYFILEDIALOGS - - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + HL_PRIM double HL_NAME(hl_bytes_get_data_pointer_offset) (Bytes* bytes, int offset) { - std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); + if (!bytes) return 0; + return (uintptr_t)bytes->b + offset; - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + } - if (path) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + value lime_bytes_read_file (HxString path, value bytes) { - } else { + Bytes data (bytes); + data.ReadFile (hxs_utf8 (path, nullptr)); + return data.Value (bytes); - return NULL; + } - } - #endif + HL_PRIM Bytes* HL_NAME(hl_bytes_read_file) (hl_vstring* path, Bytes* bytes) { - return NULL; + if (!path) return 0; + bytes->ReadFile (hl_to_utf8 ((const uchar*)path->bytes)); + return bytes; } - value lime_file_watcher_create (value callback) { + double lime_cffi_get_native_pointer (value handle) { - #ifdef LIME_EFSW - FileWatcher* watcher = new FileWatcher (callback); - return CFFIPointer (watcher, gc_file_watcher); - #else - return alloc_null (); - #endif + return (uintptr_t)val_data (handle); } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_file_watcher_create) (vclosure* callback) { + HL_PRIM double HL_NAME(hl_cffi_get_native_pointer) (HL_CFFIPointer* handle) { - // #ifdef LIME_EFSW - // FileWatcher* watcher = new FileWatcher (callback); - // return HLCFFIPointer (watcher, (hl_finalizer)hl_gc_file_watcher); - // #else - return 0; - // #endif + return (uintptr_t)handle->ptr; } - value lime_file_watcher_add_directory (value handle, value path, bool recursive) { + void lime_cffi_finalizer (value abstract) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - return alloc_int (watcher->AddDirectory (val_string (path), recursive)); - #else - return alloc_int (0); - #endif + val_call0 ((value)val_data (abstract)); } - HL_PRIM int HL_NAME(hl_file_watcher_add_directory) (HL_CFFIPointer* handle, hl_vstring* path, bool recursive) { + value lime_cffi_set_finalizer (value callback) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - return watcher->AddDirectory ((const char*)path, recursive); - #else - return 0; - #endif + value abstract = alloc_abstract (k_finalizer, callback); + val_gc (abstract, lime_cffi_finalizer); + return abstract; } - void lime_file_watcher_remove_directory (value handle, value watchID) { + void lime_clipboard_event_manager_register (value callback, value eventObject) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - watcher->RemoveDirectory (val_int (watchID)); - #endif + ClipboardEvent::callback = new ValuePointer (callback); + ClipboardEvent::eventObject = new ValuePointer (eventObject); } - HL_PRIM void HL_NAME(hl_file_watcher_remove_directory) (HL_CFFIPointer* handle, int watchID) { + HL_PRIM void HL_NAME(hl_clipboard_event_manager_register) (vclosure* callback, ClipboardEvent* eventObject) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - watcher->RemoveDirectory (watchID); - #endif + ClipboardEvent::callback = new ValuePointer (callback); + ClipboardEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - void lime_file_watcher_update (value handle) { + value lime_clipboard_get_text () { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - watcher->Update (); - #endif + if (Clipboard::HasText ()) { - } + const char* text = Clipboard::GetText (); + value _text = alloc_string (text); + // TODO: Should we free for all backends? (SDL requires it) - HL_PRIM void HL_NAME(hl_file_watcher_update) (HL_CFFIPointer* handle) { + free ((char*)text); + return _text; - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - watcher->Update (); - #endif + } else { - } + return alloc_null (); + } - int lime_font_get_ascender (value fontHandle) { + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetAscender (); - #else - return 0; - #endif - } + HL_PRIM vbyte* HL_NAME(hl_clipboard_get_text) () { + if (Clipboard::HasText ()) { - HL_PRIM int HL_NAME(hl_font_get_ascender) (HL_CFFIPointer* fontHandle) { - - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetAscender (); - #else - return 0; - #endif - - } + const char* text = Clipboard::GetText (); + return (vbyte*)text; + } else { - int lime_font_get_descender (value fontHandle) { + return 0; - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetDescender (); - #else - return 0; - #endif + } } - HL_PRIM int HL_NAME(hl_font_get_descender) (HL_CFFIPointer* fontHandle) { + void lime_clipboard_set_text (HxString text) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetDescender (); - #else - return 0; - #endif + Clipboard::SetText (hxs_utf8 (text, nullptr)); } - value lime_font_get_family_name (value fontHandle) { + HL_PRIM void HL_NAME(hl_clipboard_set_text) (hl_vstring* text) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - wchar_t *name = font->GetFamilyName (); - value result = alloc_wstring (name); - delete name; - return result; - #else - return alloc_null (); - #endif + Clipboard::SetText (text ? (const char*)hl_to_utf8 ((const uchar*)text->bytes) : NULL); } - HL_PRIM vbyte* HL_NAME(hl_font_get_family_name) (HL_CFFIPointer* fontHandle) { + double lime_data_pointer_offset (double pointer, int offset) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - wchar_t *name = font->GetFamilyName (); - if (!name) - return nullptr; - vbyte* const result = hl_wstring_to_utf8_bytes (name); - delete name; - return result; - #else - return 0; - #endif + return (uintptr_t)pointer + offset; } - int lime_font_get_glyph_index (value fontHandle, HxString character) { + HL_PRIM double HL_NAME(hl_data_pointer_offset) (double pointer, int offset) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetGlyphIndex (hxs_utf8 (character, nullptr)); - #else - return -1; - #endif + return (uintptr_t)pointer + offset; } - HL_PRIM int HL_NAME(hl_font_get_glyph_index) (HL_CFFIPointer* fontHandle, hl_vstring* character) { - - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetGlyphIndex (character ? (char*)hl_to_utf8 ((const uchar*)character->bytes) : NULL); - #else - return -1; - #endif - - } + value lime_deflate_compress (value buffer, value bytes) { + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); - value lime_font_get_glyph_indices (value fontHandle, HxString characters) { + Zlib::Compress (DEFLATE, &data, &result); - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->GetGlyphIndices (true, hxs_utf8 (characters, nullptr)); + return result.Value (bytes); #else - return alloc_null (); + return alloc_null(); #endif } - HL_PRIM hl_varray* HL_NAME(hl_font_get_glyph_indices) (HL_CFFIPointer* fontHandle, hl_vstring* characters) { + HL_PRIM Bytes* HL_NAME(hl_deflate_compress) (Bytes* buffer, Bytes* bytes) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (hl_varray*)font->GetGlyphIndices (false, characters ? (char*)hl_to_utf8 ((const uchar*)characters->bytes) : NULL); + #ifdef LIME_ZLIB + Zlib::Compress (DEFLATE, buffer, bytes); + return bytes; #else return 0; #endif @@ -1741,11 +1766,15 @@ namespace lime { } - value lime_font_get_glyph_metrics (value fontHandle, int index) { + value lime_deflate_decompress (value buffer, value bytes) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->GetGlyphMetrics (true, index); + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); + + Zlib::Decompress (DEFLATE, &data, &result); + + return result.Value (bytes); #else return alloc_null (); #endif @@ -1753,11 +1782,11 @@ namespace lime { } - HL_PRIM vdynamic* HL_NAME(hl_font_get_glyph_metrics) (HL_CFFIPointer* fontHandle, int index) { + HL_PRIM Bytes* HL_NAME(hl_deflate_decompress) (Bytes* buffer, Bytes* bytes) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (vdynamic*)font->GetGlyphMetrics (false, index); + #ifdef LIME_ZLIB + Zlib::Decompress (DEFLATE, buffer, bytes); + return bytes; #else return 0; #endif @@ -1765,252 +1794,248 @@ namespace lime { } - int lime_font_get_height (value fontHandle) { + void lime_drop_event_manager_register (value callback, value eventObject) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetHeight (); - #else - return 0; - #endif + DropEvent::callback = new ValuePointer (callback); + DropEvent::eventObject = new ValuePointer (eventObject); } - HL_PRIM int HL_NAME(hl_font_get_height) (HL_CFFIPointer* fontHandle) { + HL_PRIM void HL_NAME(hl_drop_event_manager_register) (vclosure* callback, DropEvent* eventObject) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetHeight (); - #else - return 0; - #endif + DropEvent::callback = new ValuePointer (callback); + DropEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - int lime_font_get_num_glyphs (value fontHandle) { + value lime_file_dialog_open_directory (HxString title, HxString filter, HxString defaultPath) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetNumGlyphs (); - #else - return 0; - #endif + #ifdef LIME_TINYFILEDIALOGS - } + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); - HL_PRIM int HL_NAME(hl_font_get_num_glyphs) (HL_CFFIPointer* fontHandle) { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetNumGlyphs (); - #else - return 0; - #endif + if (path) { - } + value _path = wstring_to_value (path); + delete path; + return _path; + } else { - int lime_font_get_underline_position (value fontHandle) { + return alloc_null (); + + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetUnderlinePosition (); - #else - return 0; #endif + return alloc_null (); + } - HL_PRIM int HL_NAME(hl_font_get_underline_position) (HL_CFFIPointer* fontHandle) { + HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_directory) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetUnderlinePosition (); - #else - return 0; - #endif + #ifdef LIME_TINYFILEDIALOGS - } + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); - int lime_font_get_underline_thickness (value fontHandle) { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetUnderlineThickness (); - #else - return 0; - #endif + if (path) { - } + vbyte* const result = hl_wstring_to_utf8_bytes (*path); + delete path; + return result; + } else { - HL_PRIM int HL_NAME(hl_font_get_underline_thickness) (HL_CFFIPointer* fontHandle) { + return NULL; + + } - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetUnderlineThickness (); - #else - return 0; #endif + return NULL; + } - int lime_font_get_strikethrough_position (value fontHandle) { + value lime_file_dialog_open_file (HxString title, HxString filter, HxString defaultPath) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetStrikethroughPosition (); - #else - return 0; - #endif + #ifdef LIME_TINYFILEDIALOGS - } + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); - HL_PRIM int HL_NAME(hl_font_get_strikethrough_position) (HL_CFFIPointer* fontHandle) { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetStrikethroughPosition (); - #else - return 0; - #endif + if (path) { - } + value _path = wstring_to_value (path); + delete path; + return _path; + } else { - int lime_font_get_strikethrough_thickness (value fontHandle) { + return alloc_null (); + + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetStrikethroughThickness (); - #else - return 0; #endif + return alloc_null (); + } - HL_PRIM int HL_NAME(hl_font_get_strikethrough_thickness) (HL_CFFIPointer* fontHandle) { + HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetStrikethroughThickness (); - #else - return 0; - #endif + #ifdef LIME_TINYFILEDIALOGS - } + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); - int lime_font_get_units_per_em (value fontHandle) { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetUnitsPerEM (); - #else - return 0; - #endif + if (path) { - } + vbyte* const result = hl_wstring_to_utf8_bytes (*path); + delete path; + return result; + } else { - HL_PRIM int HL_NAME(hl_font_get_units_per_em) (HL_CFFIPointer* fontHandle) { + return NULL; - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetUnitsPerEM (); - #else - return 0; - #endif + } - } + #endif + return NULL; - value lime_font_load_bytes (value data) { + } - #ifdef LIME_FREETYPE - Resource resource; - Bytes bytes; - bytes.Set (data); - resource = Resource (&bytes); + value lime_file_dialog_open_files (HxString title, HxString filter, HxString defaultPath) { - Font *font = new Font (&resource, 0); + #ifdef LIME_TINYFILEDIALOGS - if (font) { + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - if (font->face) { + std::vector files; - return CFFIPointer (font, gc_font); + FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); + value result = alloc_array (files.size ()); - } else { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - delete font; + for (int i = 0; i < files.size (); i++) { - } + value _file = wstring_to_value (files[i]); + val_array_set_i (result, i, _file); + delete files[i]; } + + #else + value result = alloc_array (0); #endif - return alloc_null (); + return result; } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_bytes) (Bytes* data) { - - #ifdef LIME_FREETYPE - Resource resource = Resource (data); + HL_PRIM hl_varray* HL_NAME(hl_file_dialog_open_files) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { - Font *font = new Font (&resource, 0); + #ifdef LIME_TINYFILEDIALOGS - if (font) { + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - if (font->face) { + std::vector files; - return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); + FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); + hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, files.size ()); + vbyte** resultData = hl_aptr (result, vbyte*); - } else { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - delete font; + for (int i = 0; i < files.size (); i++) { - } + *resultData++ = hl_wstring_to_utf8_bytes (*files[i]); + delete files[i]; } + + #else + hl_varray* result = hl_alloc_array (&hlt_bytes, 0); #endif - return 0; + return result; } - value lime_font_load_file (value data) { + value lime_file_dialog_save_file (HxString title, HxString filter, HxString defaultPath) { - #ifdef LIME_FREETYPE - Resource resource = Resource (val_string (data)); + #ifdef LIME_TINYFILEDIALOGS - Font *font = new Font (&resource, 0); + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - if (font) { + std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); - if (font->face) { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - return CFFIPointer (font, gc_font); + if (path) { - } else { + value _path = wstring_to_value (path); + delete path; + return _path; - delete font; + } else { - } + return alloc_null (); } + #endif return alloc_null (); @@ -2018,345 +2043,380 @@ namespace lime { } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_file) (hl_vstring* data) { + HL_PRIM vbyte* HL_NAME(hl_file_dialog_save_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { - #ifdef LIME_FREETYPE - Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); + #ifdef LIME_TINYFILEDIALOGS - Font *font = new Font (&resource, 0); + std::wstring* _title = hxstring_to_wstring (title); + std::wstring* _filter = hxstring_to_wstring (filter); + std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - if (font) { + std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); - if (font->face) { + if (_title) delete _title; + if (_filter) delete _filter; + if (_defaultPath) delete _defaultPath; - return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); + if (path) { - } else { + vbyte* const result = hl_wstring_to_utf8_bytes (*path); + delete path; + return result; - delete font; + } else { - } + return NULL; } + #endif - return 0; + return NULL; } - value lime_font_load (value data) { + value lime_file_watcher_create (value callback) { - if (val_is_string (data)) { + #ifdef LIME_EFSW + FileWatcher* watcher = new FileWatcher (callback); + return CFFIPointer (watcher, gc_file_watcher); + #else + return alloc_null (); + #endif - return lime_font_load_file (data); + } - } else { - return lime_font_load_bytes (data); + HL_PRIM HL_CFFIPointer* HL_NAME(hl_file_watcher_create) (vclosure* callback) { - } + // #ifdef LIME_EFSW + // FileWatcher* watcher = new FileWatcher (callback); + // return HLCFFIPointer (watcher, (hl_finalizer)hl_gc_file_watcher); + // #else + return 0; + // #endif } - value lime_font_outline_decompose (value fontHandle, int size) { + value lime_file_watcher_add_directory (value handle, value path, bool recursive) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->Decompose (true, size); + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + return alloc_int (watcher->AddDirectory (val_string (path), recursive)); #else - return alloc_null (); + return alloc_int (0); #endif } - value lime_font_outline_decompose_no_hint (value fontHandle, int size) { + HL_PRIM int HL_NAME(hl_file_watcher_add_directory) (HL_CFFIPointer* handle, hl_vstring* path, bool recursive) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->Decompose (true, size, false); + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + return watcher->AddDirectory ((const char*)path, recursive); #else - return alloc_null (); + return 0; #endif } - HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose) (HL_CFFIPointer* fontHandle, int size) { + void lime_file_watcher_remove_directory (value handle, value watchID) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (vdynamic*)font->Decompose (false, size); - #else - return 0; + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + watcher->RemoveDirectory (val_int (watchID)); #endif } - HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose_no_hint) (HL_CFFIPointer* fontHandle, int size) { + HL_PRIM void HL_NAME(hl_file_watcher_remove_directory) (HL_CFFIPointer* handle, int watchID) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (vdynamic*)font->Decompose (false, size, false); - #else - return 0; + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + watcher->RemoveDirectory (watchID); #endif } - value lime_font_render_glyph (value fontHandle, int index, value data) { + void lime_file_watcher_update (value handle) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - Bytes bytes (data); + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + watcher->Update (); + #endif - if (font->RenderGlyph (index, &bytes)) { + } - return bytes.Value (data); - } - #endif + HL_PRIM void HL_NAME(hl_file_watcher_update) (HL_CFFIPointer* handle) { - return alloc_null (); + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + watcher->Update (); + #endif } - value lime_font_render_glyph_with_flags (value fontHandle, int index, int loadFlags, value data) { + int lime_font_get_ascender (value fontHandle) { #ifdef LIME_FREETYPE Font *font = (Font*)val_data (fontHandle); - Bytes bytes (data); - - if (font->RenderGlyphWithFlags (index, loadFlags, &bytes)) { - - return bytes.Value (data); - - } + return font->GetAscender (); + #else + return 0; #endif - return alloc_null (); - } - HL_PRIM Bytes* HL_NAME(hl_font_render_glyph) (HL_CFFIPointer* fontHandle, int index, Bytes* data) { + HL_PRIM int HL_NAME(hl_font_get_ascender) (HL_CFFIPointer* fontHandle) { #ifdef LIME_FREETYPE Font *font = (Font*)fontHandle->ptr; + return font->GetAscender (); + #else + return 0; + #endif - if (font->RenderGlyph (index, data)) { + } - return data; - } - #endif + int lime_font_get_descender (value fontHandle) { - return NULL; + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetDescender (); + #else + return 0; + #endif } - HL_PRIM Bytes* HL_NAME(hl_font_render_glyph_with_flags) (HL_CFFIPointer* fontHandle, int index, int loadFlags, Bytes* data) { + HL_PRIM int HL_NAME(hl_font_get_descender) (HL_CFFIPointer* fontHandle) { #ifdef LIME_FREETYPE Font *font = (Font*)fontHandle->ptr; - - if (font->RenderGlyphWithFlags (index, loadFlags, data)) { - - return data; - - } + return font->GetDescender (); + #else + return 0; #endif - return NULL; - } - value lime_font_render_glyphs (value fontHandle, value indices, value data) { + value lime_font_get_family_name (value fontHandle) { #ifdef LIME_FREETYPE Font *font = (Font*)val_data (fontHandle); - Bytes bytes (data); - - if (font->RenderGlyphs (indices, &bytes)) { - - return bytes.Value (data); - - } - #endif - + wchar_t *name = font->GetFamilyName (); + value result = alloc_wstring (name); + delete name; + return result; + #else return alloc_null (); + #endif } - HL_PRIM Bytes* HL_NAME(hl_font_render_glyphs) (HL_CFFIPointer* fontHandle, hl_varray* indices, Bytes* data) { + HL_PRIM vbyte* HL_NAME(hl_font_get_family_name) (HL_CFFIPointer* fontHandle) { - // #ifdef LIME_FREETYPE - // Font *font = (Font*)fontHandle->ptr; - // return font->RenderGlyphs (indices, &bytes); - // #else - return NULL; - // #endif + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + wchar_t *name = font->GetFamilyName (); + if (!name) + return nullptr; + vbyte* const result = hl_wstring_to_utf8_bytes (name); + delete name; + return result; + #else + return 0; + #endif } - void lime_font_set_size (value fontHandle, int fontSize, int dpi) { + int lime_font_get_glyph_index (value fontHandle, HxString character) { #ifdef LIME_FREETYPE Font *font = (Font*)val_data (fontHandle); - font->SetSize (fontSize, dpi); + return font->GetGlyphIndex (hxs_utf8 (character, nullptr)); + #else + return -1; #endif } - HL_PRIM void HL_NAME(hl_font_set_size) (HL_CFFIPointer* fontHandle, int fontSize, int dpi) { + HL_PRIM int HL_NAME(hl_font_get_glyph_index) (HL_CFFIPointer* fontHandle, hl_vstring* character) { #ifdef LIME_FREETYPE Font *font = (Font*)fontHandle->ptr; - font->SetSize (fontSize, dpi); + return font->GetGlyphIndex (character ? (char*)hl_to_utf8 ((const uchar*)character->bytes) : NULL); + #else + return -1; #endif } - void lime_gamepad_add_mappings (value mappings) { - - int length = val_array_size (mappings); - - for (int i = 0; i < length; i++) { - - Gamepad::AddMapping (val_string (val_array_i (mappings, i))); + value lime_font_get_glyph_indices (value fontHandle, HxString characters) { - } + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->GetGlyphIndices (true, hxs_utf8 (characters, nullptr)); + #else + return alloc_null (); + #endif } - HL_PRIM void HL_NAME(hl_gamepad_add_mappings) (hl_varray* mappings) { - - int length = mappings->size; - hl_vstring** mappingsData = hl_aptr (mappings, hl_vstring*); - - for (int i = 0; i < length; i++) { - - Gamepad::AddMapping (hl_to_utf8 ((const uchar*)((*mappingsData++)->bytes))); + HL_PRIM hl_varray* HL_NAME(hl_font_get_glyph_indices) (HL_CFFIPointer* fontHandle, hl_vstring* characters) { - } + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (hl_varray*)font->GetGlyphIndices (false, characters ? (char*)hl_to_utf8 ((const uchar*)characters->bytes) : NULL); + #else + return 0; + #endif } - void lime_gamepad_event_manager_register (value callback, value eventObject) { + value lime_font_get_glyph_metrics (value fontHandle, int index) { - GamepadEvent::callback = new ValuePointer (callback); - GamepadEvent::eventObject = new ValuePointer (eventObject); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->GetGlyphMetrics (true, index); + #else + return alloc_null (); + #endif } - HL_PRIM void HL_NAME(hl_gamepad_event_manager_register) (vclosure* callback, GamepadEvent* eventObject) { + HL_PRIM vdynamic* HL_NAME(hl_font_get_glyph_metrics) (HL_CFFIPointer* fontHandle, int index) { - GamepadEvent::callback = new ValuePointer (callback); - GamepadEvent::eventObject = new ValuePointer ((vobj*)eventObject); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (vdynamic*)font->GetGlyphMetrics (false, index); + #else + return 0; + #endif } - value lime_gamepad_get_device_guid (int id) { - - const char* guid = Gamepad::GetDeviceGUID (id); - - if (guid) { - - value result = alloc_string (guid); - delete guid; - return result; - - } else { - - return alloc_null (); + int lime_font_get_height (value fontHandle) { - } + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetHeight (); + #else + return 0; + #endif } - HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_guid) (int id) { - - const char* guid = Gamepad::GetDeviceGUID (id); + HL_PRIM int HL_NAME(hl_font_get_height) (HL_CFFIPointer* fontHandle) { - if (guid) { + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetHeight (); + #else + return 0; + #endif - return (vbyte*)guid; + } - } else { - return 0; + int lime_font_get_num_glyphs (value fontHandle) { - } + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetNumGlyphs (); + #else + return 0; + #endif } - value lime_gamepad_get_device_name (int id) { + HL_PRIM int HL_NAME(hl_font_get_num_glyphs) (HL_CFFIPointer* fontHandle) { - const char* name = Gamepad::GetDeviceName (id); - return name ? alloc_string (name) : alloc_null (); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetNumGlyphs (); + #else + return 0; + #endif } - HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_name) (int id) { + int lime_font_get_underline_position (value fontHandle) { - return (vbyte*)Gamepad::GetDeviceName (id); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetUnderlinePosition (); + #else + return 0; + #endif } - void lime_gamepad_rumble (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { + HL_PRIM int HL_NAME(hl_font_get_underline_position) (HL_CFFIPointer* fontHandle) { - Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetUnderlinePosition (); + #else + return 0; + #endif } - HL_PRIM void HL_NAME(hl_gamepad_rumble) (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { + int lime_font_get_underline_thickness (value fontHandle) { - Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetUnderlineThickness (); + #else + return 0; + #endif } - value lime_gzip_compress (value buffer, value bytes) { - - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - - Zlib::Compress (GZIP, &data, &result); + HL_PRIM int HL_NAME(hl_font_get_underline_thickness) (HL_CFFIPointer* fontHandle) { - return result.Value (bytes); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetUnderlineThickness (); #else - return alloc_null (); + return 0; #endif } - HL_PRIM Bytes* HL_NAME(hl_gzip_compress) (Bytes* buffer, Bytes* bytes) { + int lime_font_get_strikethrough_position (value fontHandle) { - #ifdef LIME_ZLIB - Zlib::Compress (GZIP, buffer, bytes); - return bytes; + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetStrikethroughPosition (); #else return 0; #endif @@ -2364,27 +2424,23 @@ namespace lime { } - value lime_gzip_decompress (value buffer, value bytes) { - - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - - Zlib::Decompress (GZIP, &data, &result); + HL_PRIM int HL_NAME(hl_font_get_strikethrough_position) (HL_CFFIPointer* fontHandle) { - return result.Value (bytes); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetStrikethroughPosition (); #else - return alloc_null (); + return 0; #endif } - HL_PRIM Bytes* HL_NAME(hl_gzip_decompress) (Bytes* buffer, Bytes* bytes) { + int lime_font_get_strikethrough_thickness (value fontHandle) { - #ifdef LIME_ZLIB - Zlib::Decompress (GZIP, buffer, bytes); - return bytes; + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetStrikethroughThickness (); #else return 0; #endif @@ -2392,119 +2448,118 @@ namespace lime { } - void lime_haptic_vibrate (int period, int duration) { + HL_PRIM int HL_NAME(hl_font_get_strikethrough_thickness) (HL_CFFIPointer* fontHandle) { - #ifdef IPHONE - Haptic::Vibrate (period, duration); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetStrikethroughThickness (); + #else + return 0; #endif } - HL_PRIM void HL_NAME(hl_haptic_vibrate) (int period, int duration) { + int lime_font_get_units_per_em (value fontHandle) { - #ifdef IPHONE - Haptic::Vibrate (period, duration); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetUnitsPerEM (); + #else + return 0; #endif } - value lime_image_encode (value buffer, int type, int quality, value bytes) { + HL_PRIM int HL_NAME(hl_font_get_units_per_em) (HL_CFFIPointer* fontHandle) { - ImageBuffer imageBuffer = ImageBuffer (buffer); - Bytes data = Bytes (bytes); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetUnitsPerEM (); + #else + return 0; + #endif - switch (type) { + } - case 0: - #ifdef LIME_PNG - if (PNG::Encode (&imageBuffer, &data)) { + value lime_font_load_bytes (value data) { - return data.Value (bytes); + #ifdef LIME_FREETYPE + Resource resource; + Bytes bytes; - } - #endif - break; + bytes.Set (data); + resource = Resource (&bytes); - case 1: + Font *font = new Font (&resource, 0); - #ifdef LIME_JPEG - if (JPEG::Encode (&imageBuffer, &data, quality)) { + if (font) { - return data.Value (bytes); + if (font->face) { - } - #endif - break; + return CFFIPointer (font, gc_font); - default: break; + } else { + + delete font; + + } } + #endif return alloc_null (); } - HL_PRIM Bytes* HL_NAME(hl_image_encode) (ImageBuffer* buffer, int type, int quality, Bytes* bytes) { - - switch (type) { - - case 0: + HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_bytes) (Bytes* data) { - #ifdef LIME_PNG - if (PNG::Encode (buffer, bytes)) { + #ifdef LIME_FREETYPE + Resource resource = Resource (data); - return bytes; + Font *font = new Font (&resource, 0); - } - #endif - break; + if (font) { - case 1: + if (font->face) { - #ifdef LIME_JPEG - if (JPEG::Encode (buffer, bytes, quality)) { + return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); - return bytes; + } else { - } - #endif - break; + delete font; - default: break; + } } + #endif return 0; } - value lime_image_load_bytes (value data, value buffer) { + value lime_font_load_file (value data) { - Resource resource; - Bytes bytes; + #ifdef LIME_FREETYPE + Resource resource = Resource (val_string (data)); - ImageBuffer imageBuffer = ImageBuffer (buffer); + Font *font = new Font (&resource, 0); - bytes.Set (data); - resource = Resource (&bytes); + if (font) { - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer)) { + if (font->face) { - return imageBuffer.Value (buffer); + return CFFIPointer (font, gc_font); - } - #endif + } else { - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer)) { + delete font; - return imageBuffer.Value (buffer); + } } #endif @@ -2514,22 +2569,24 @@ namespace lime { } - HL_PRIM ImageBuffer* HL_NAME(hl_image_load_bytes) (Bytes* data, ImageBuffer* buffer) { + HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_file) (hl_vstring* data) { - Resource resource = Resource (data); + #ifdef LIME_FREETYPE + Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer)) { + Font *font = new Font (&resource, 0); - return buffer; + if (font) { - } - #endif + if (font->face) { - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer)) { + return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); - return buffer; + } else { + + delete font; + + } } #endif @@ -2539,347 +2596,346 @@ namespace lime { } - value lime_image_load_file (value data, value buffer) { + value lime_font_load (value data) { - Resource resource = Resource (val_string (data)); - ImageBuffer imageBuffer = ImageBuffer (buffer); + if (val_is_string (data)) { - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer)) { + return lime_font_load_file (data); - return imageBuffer.Value (buffer); + } else { + + return lime_font_load_bytes (data); } - #endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer)) { + } - return imageBuffer.Value (buffer); - } - #endif + value lime_font_outline_decompose (value fontHandle, int size) { + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->Decompose (true, size); + #else return alloc_null (); + #endif } - HL_PRIM ImageBuffer* HL_NAME(hl_image_load_file) (hl_vstring* data, ImageBuffer* buffer) { + value lime_font_outline_decompose_no_hint (value fontHandle, int size) { - Resource resource = Resource (data); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->Decompose (true, size, false); + #else + return alloc_null (); + #endif - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer)) { + } - return buffer; - } + HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose) (HL_CFFIPointer* fontHandle, int size) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (vdynamic*)font->Decompose (false, size); + #else + return 0; #endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer)) { + } - return buffer; - } - #endif + HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose_no_hint) (HL_CFFIPointer* fontHandle, int size) { + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (vdynamic*)font->Decompose (false, size, false); + #else return 0; + #endif } - value lime_image_load (value data, value buffer) { - - if (val_is_string (data)) { + value lime_font_render_glyph (value fontHandle, int index, value data) { - return lime_image_load_file (data, buffer); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + Bytes bytes (data); - } else { + if (font->RenderGlyph (index, &bytes)) { - return lime_image_load_bytes (data, buffer); + return bytes.Value (data); } + #endif + + return alloc_null (); } - void lime_image_data_util_color_transform (value image, value rect, value colorMatrix) { + value lime_font_render_glyph_with_flags (value fontHandle, int index, int loadFlags, value data) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); - ImageDataUtil::ColorTransform (&_image, &_rect, &_colorMatrix); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + Bytes bytes (data); - } + if (font->RenderGlyphWithFlags (index, loadFlags, &bytes)) { + return bytes.Value (data); - HL_PRIM void HL_NAME(hl_image_data_util_color_transform) (Image* image, Rectangle* rect, ArrayBufferView* colorMatrix) { + } + #endif - ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); - ImageDataUtil::ColorTransform (image, rect, &_colorMatrix); + return alloc_null (); } - void lime_image_data_util_copy_channel (value image, value sourceImage, value sourceRect, value destPoint, int srcChannel, int destChannel) { + HL_PRIM Bytes* HL_NAME(hl_font_render_glyph) (HL_CFFIPointer* fontHandle, int index, Bytes* data) { - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - ImageDataUtil::CopyChannel (&_image, &_sourceImage, &_sourceRect, &_destPoint, srcChannel, destChannel); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; - } + if (font->RenderGlyph (index, data)) { + return data; - HL_PRIM void HL_NAME(hl_image_data_util_copy_channel) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) { + } + #endif - ImageDataUtil::CopyChannel (image, sourceImage, sourceRect, destPoint, srcChannel, destChannel); + return NULL; } - void lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value alphaImage, value alphaPoint, bool mergeAlpha) { + HL_PRIM Bytes* HL_NAME(hl_font_render_glyph_with_flags) (HL_CFFIPointer* fontHandle, int index, int loadFlags, Bytes* data) { - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; - if (val_is_null (alphaImage)) { + if (font->RenderGlyphWithFlags (index, loadFlags, data)) { - ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, 0, 0, mergeAlpha); - - } else { - - Image _alphaImage = Image (alphaImage); - Vector2 _alphaPoint = Vector2 (alphaPoint); - - ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, &_alphaImage, &_alphaPoint, mergeAlpha); + return data; } + #endif - } + return NULL; + } - HL_PRIM void HL_NAME(hl_image_data_util_copy_pixels) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha) { - if (!alphaImage) { + value lime_font_render_glyphs (value fontHandle, value indices, value data) { - ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, NULL, NULL, mergeAlpha); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + Bytes bytes (data); - } else { + if (font->RenderGlyphs (indices, &bytes)) { - if (!alphaPoint) { + return bytes.Value (data); - Vector2 _alphaPoint = Vector2 (0, 0); + } + #endif - ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, &_alphaPoint, mergeAlpha); + return alloc_null (); - } else { + } - ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); - } + HL_PRIM Bytes* HL_NAME(hl_font_render_glyphs) (HL_CFFIPointer* fontHandle, hl_varray* indices, Bytes* data) { - } + // #ifdef LIME_FREETYPE + // Font *font = (Font*)fontHandle->ptr; + // return font->RenderGlyphs (indices, &bytes); + // #else + return NULL; + // #endif } - void lime_image_data_util_fill_rect (value image, value rect, int rg, int ba) { + void lime_font_set_size (value fontHandle, int fontSize, int dpi) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - int32_t color = (rg << 16) | ba; - ImageDataUtil::FillRect (&_image, &_rect, color); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + font->SetSize (fontSize, dpi); + #endif } - HL_PRIM void HL_NAME(hl_image_data_util_fill_rect) (Image* image, Rectangle* rect, int rg, int ba) { + HL_PRIM void HL_NAME(hl_font_set_size) (HL_CFFIPointer* fontHandle, int fontSize, int dpi) { - int32_t color = (rg << 16) | ba; - ImageDataUtil::FillRect (image, rect, color); + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + font->SetSize (fontSize, dpi); + #endif } - void lime_image_data_util_flood_fill (value image, int x, int y, int rg, int ba) { - - Image _image = Image (image); - int32_t color = (rg << 16) | ba; - ImageDataUtil::FloodFill (&_image, x, y, color); + void lime_gamepad_add_mappings (value mappings) { - } + int length = val_array_size (mappings); + for (int i = 0; i < length; i++) { - HL_PRIM void HL_NAME(hl_image_data_util_flood_fill) (Image* image, int x, int y, int rg, int ba) { + Gamepad::AddMapping (val_string (val_array_i (mappings, i))); - int32_t color = (rg << 16) | ba; - ImageDataUtil::FloodFill (image, x, y, color); + } } - void lime_image_data_util_get_pixels (value image, value rect, int format, value bytes) { - - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - PixelFormat _format = (PixelFormat)format; - Bytes pixels = Bytes (bytes); - ImageDataUtil::GetPixels (&_image, &_rect, _format, &pixels); + HL_PRIM void HL_NAME(hl_gamepad_add_mappings) (hl_varray* mappings) { - } + int length = mappings->size; + hl_vstring** mappingsData = hl_aptr (mappings, hl_vstring*); + for (int i = 0; i < length; i++) { - HL_PRIM void HL_NAME(hl_image_data_util_get_pixels) (Image* image, Rectangle* rect, PixelFormat format, Bytes* bytes) { + Gamepad::AddMapping (hl_to_utf8 ((const uchar*)((*mappingsData++)->bytes))); - ImageDataUtil::GetPixels (image, rect, format, bytes); + } } - void lime_image_data_util_merge (value image, value sourceImage, value sourceRect, value destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { + void lime_gamepad_event_manager_register (value callback, value eventObject) { - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - ImageDataUtil::Merge (&_image, &_sourceImage, &_sourceRect, &_destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); + GamepadEvent::callback = new ValuePointer (callback); + GamepadEvent::eventObject = new ValuePointer (eventObject); } - HL_PRIM void HL_NAME(hl_image_data_util_merge) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { + HL_PRIM void HL_NAME(hl_gamepad_event_manager_register) (vclosure* callback, GamepadEvent* eventObject) { - ImageDataUtil::Merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); + GamepadEvent::callback = new ValuePointer (callback); + GamepadEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - void lime_image_data_util_multiply_alpha (value image) { + value lime_gamepad_get_device_guid (int id) { - Image _image = Image (image); - ImageDataUtil::MultiplyAlpha (&_image); + const char* guid = Gamepad::GetDeviceGUID (id); - } + if (guid) { + value result = alloc_string (guid); + delete guid; + return result; - HL_PRIM void HL_NAME(hl_image_data_util_multiply_alpha) (Image* image) { + } else { - ImageDataUtil::MultiplyAlpha (image); + return alloc_null (); + + } } - void lime_image_data_util_resize (value image, value buffer, int width, int height) { + HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_guid) (int id) { - Image _image = Image (image); - ImageBuffer _buffer = ImageBuffer (buffer); - ImageDataUtil::Resize (&_image, &_buffer, width, height); + const char* guid = Gamepad::GetDeviceGUID (id); - } + if (guid) { + return (vbyte*)guid; - HL_PRIM void HL_NAME(hl_image_data_util_resize) (Image* image, ImageBuffer* buffer, int width, int height) { + } else { - ImageDataUtil::Resize (image, buffer, width, height); + return 0; + + } } - void lime_image_data_util_set_format (value image, int format) { + value lime_gamepad_get_device_name (int id) { - Image _image = Image (image); - PixelFormat _format = (PixelFormat)format; - ImageDataUtil::SetFormat (&_image, _format); + const char* name = Gamepad::GetDeviceName (id); + return name ? alloc_string (name) : alloc_null (); } - HL_PRIM void HL_NAME(hl_image_data_util_set_format) (Image* image, PixelFormat format) { + HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_name) (int id) { - ImageDataUtil::SetFormat (image, format); + return (vbyte*)Gamepad::GetDeviceName (id); } - void lime_image_data_util_set_pixels (value image, value rect, value bytes, int offset, int format, int endian) { + void lime_gamepad_rumble (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - Bytes _bytes (bytes); - PixelFormat _format = (PixelFormat)format; - Endian _endian = (Endian)endian; - ImageDataUtil::SetPixels (&_image, &_rect, &_bytes, offset, _format, _endian); + Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); } - HL_PRIM void HL_NAME(hl_image_data_util_set_pixels) (Image* image, Rectangle* rect, Bytes* bytes, int offset, PixelFormat format, Endian endian) { + HL_PRIM void HL_NAME(hl_gamepad_rumble) (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { - ImageDataUtil::SetPixels (image, rect, bytes, offset, format, endian); + Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); } - int lime_image_data_util_threshold (value image, value sourceImage, value sourceRect, value destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { - - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - int32_t threshold = (thresholdRG << 16) | thresholdBA; - int32_t color = (colorRG << 16) | colorBA; - int32_t mask = (maskRG << 16) | maskBA; - return ImageDataUtil::Threshold (&_image, &_sourceImage, &_sourceRect, &_destPoint, operation, threshold, color, mask, copySource); - - } + value lime_gzip_compress (value buffer, value bytes) { + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); - HL_PRIM int HL_NAME(hl_image_data_util_threshold) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { + Zlib::Compress (GZIP, &data, &result); - int32_t threshold = (thresholdRG << 16) | thresholdBA; - int32_t color = (colorRG << 16) | colorBA; - int32_t mask = (maskRG << 16) | maskBA; - return ImageDataUtil::Threshold (image, sourceImage, sourceRect, destPoint, operation, threshold, color, mask, copySource); + return result.Value (bytes); + #else + return alloc_null (); + #endif } - void lime_image_data_util_unmultiply_alpha (value image) { + HL_PRIM Bytes* HL_NAME(hl_gzip_compress) (Bytes* buffer, Bytes* bytes) { - Image _image = Image (image); - ImageDataUtil::UnmultiplyAlpha (&_image); + #ifdef LIME_ZLIB + Zlib::Compress (GZIP, buffer, bytes); + return bytes; + #else + return 0; + #endif } - HL_PRIM void HL_NAME(hl_image_data_util_unmultiply_alpha) (Image* image) { - - ImageDataUtil::UnmultiplyAlpha (image); - - } + value lime_gzip_decompress (value buffer, value bytes) { + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); - double lime_jni_getenv () { + Zlib::Decompress (GZIP, &data, &result); - #ifdef ANDROID - return (uintptr_t)JNI::GetEnv (); + return result.Value (bytes); #else - return 0; + return alloc_null (); #endif } - HL_PRIM double HL_NAME(hl_jni_getenv) () { + HL_PRIM Bytes* HL_NAME(hl_gzip_decompress) (Bytes* buffer, Bytes* bytes) { - #ifdef ANDROID - return (uintptr_t)JNI::GetEnv (); + #ifdef LIME_ZLIB + Zlib::Decompress (GZIP, buffer, bytes); + return bytes; #else return 0; #endif @@ -2887,103 +2943,117 @@ namespace lime { } - void lime_joystick_event_manager_register (value callback, value eventObject) { + void lime_haptic_vibrate (int period, int duration) { - JoystickEvent::callback = new ValuePointer (callback); - JoystickEvent::eventObject = new ValuePointer (eventObject); + #ifdef IPHONE + Haptic::Vibrate (period, duration); + #endif } - HL_PRIM void HL_NAME(hl_joystick_event_manager_register) (vclosure* callback, JoystickEvent* eventObject) { + HL_PRIM void HL_NAME(hl_haptic_vibrate) (int period, int duration) { - JoystickEvent::callback = new ValuePointer (callback); - JoystickEvent::eventObject = new ValuePointer ((vobj*)eventObject); + #ifdef IPHONE + Haptic::Vibrate (period, duration); + #endif } - value lime_joystick_get_device_guid (int id) { - - const char* guid = Joystick::GetDeviceGUID (id); - return guid ? alloc_string (guid) : alloc_null (); + value lime_image_encode (value buffer, int type, int quality, value bytes) { - } + ImageBuffer imageBuffer = ImageBuffer (buffer); + Bytes data = Bytes (bytes); + switch (type) { - HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_guid) (int id) { + case 0: - return (vbyte*)Joystick::GetDeviceGUID (id); + #ifdef LIME_PNG + if (PNG::Encode (&imageBuffer, &data)) { - } + return data.Value (bytes); + } + #endif + break; - value lime_joystick_get_device_name (int id) { + case 1: - const char* name = Joystick::GetDeviceName (id); - return name ? alloc_string (name) : alloc_null (); + #ifdef LIME_JPEG + if (JPEG::Encode (&imageBuffer, &data, quality)) { - } + return data.Value (bytes); + } + #endif + break; - HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_name) (int id) { - - return (vbyte*)Joystick::GetDeviceName (id); - - } - + default: break; - int lime_joystick_get_num_axes (int id) { + } - return Joystick::GetNumAxes (id); + return alloc_null (); } - HL_PRIM int HL_NAME(hl_joystick_get_num_axes) (int id) { - - return Joystick::GetNumAxes (id); + HL_PRIM Bytes* HL_NAME(hl_image_encode) (ImageBuffer* buffer, int type, int quality, Bytes* bytes) { - } + switch (type) { + case 0: - int lime_joystick_get_num_buttons (int id) { + #ifdef LIME_PNG + if (PNG::Encode (buffer, bytes)) { - return Joystick::GetNumButtons (id); + return bytes; - } + } + #endif + break; + case 1: - HL_PRIM int HL_NAME(hl_joystick_get_num_buttons) (int id) { + #ifdef LIME_JPEG + if (JPEG::Encode (buffer, bytes, quality)) { - return Joystick::GetNumButtons (id); + return bytes; - } + } + #endif + break; + default: break; - int lime_joystick_get_num_hats (int id) { + } - return Joystick::GetNumHats (id); + return 0; } - HL_PRIM int HL_NAME(hl_joystick_get_num_hats) (int id) { + value lime_image_load_bytes (value data, value buffer) { - return Joystick::GetNumHats (id); + Resource resource; + Bytes bytes; - } + ImageBuffer imageBuffer = ImageBuffer (buffer); + bytes.Set (data); + resource = Resource (&bytes); - value lime_jpeg_decode_bytes (value data, bool decodeData, value buffer) { + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer)) { - ImageBuffer imageBuffer (buffer); + return imageBuffer.Value (buffer); - Bytes bytes (data); - Resource resource = Resource (&bytes); + } + #endif #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + if (JPEG::Decode (&resource, &imageBuffer)) { return imageBuffer.Value (buffer); @@ -2995,12 +3065,20 @@ namespace lime { } - HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { + HL_PRIM ImageBuffer* HL_NAME(hl_image_load_bytes) (Bytes* data, ImageBuffer* buffer) { Resource resource = Resource (data); + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer, decodeData)) { + if (JPEG::Decode (&resource, buffer)) { return buffer; @@ -3012,13 +3090,21 @@ namespace lime { } - value lime_jpeg_decode_file (HxString path, bool decodeData, value buffer) { + value lime_image_load_file (value data, value buffer) { - ImageBuffer imageBuffer (buffer); - Resource resource = Resource (hxs_utf8 (path, nullptr)); + Resource resource = Resource (val_string (data)); + ImageBuffer imageBuffer = ImageBuffer (buffer); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer)) { + + return imageBuffer.Value (buffer); + + } + #endif #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + if (JPEG::Decode (&resource, &imageBuffer)) { return imageBuffer.Value (buffer); @@ -3030,12 +3116,20 @@ namespace lime { } - HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { + HL_PRIM ImageBuffer* HL_NAME(hl_image_load_file) (hl_vstring* data, ImageBuffer* buffer) { - Resource resource = Resource (path); + Resource resource = Resource (data); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer, decodeData)) { + if (JPEG::Decode (&resource, buffer)) { return buffer; @@ -3047,639 +3141,598 @@ namespace lime { } - int lime_key_code_from_scan_code (int scanCode) { + value lime_image_load (value data, value buffer) { - return KeyCode::FromScanCode (scanCode); + if (val_is_string (data)) { - } + return lime_image_load_file (data, buffer); + } else { - HL_PRIM int HL_NAME(hl_key_code_from_scan_code) (int scanCode) { + return lime_image_load_bytes (data, buffer); - return KeyCode::FromScanCode (scanCode); + } } - int lime_key_code_to_scan_code (int keyCode) { + void lime_image_data_util_color_transform (value image, value rect, value colorMatrix) { - return KeyCode::ToScanCode (keyCode); + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); + ImageDataUtil::ColorTransform (&_image, &_rect, &_colorMatrix); } - HL_PRIM int HL_NAME(hl_key_code_to_scan_code) (int keyCode) { + HL_PRIM void HL_NAME(hl_image_data_util_color_transform) (Image* image, Rectangle* rect, ArrayBufferView* colorMatrix) { - return KeyCode::ToScanCode (keyCode); + ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); + ImageDataUtil::ColorTransform (image, rect, &_colorMatrix); } - void lime_key_event_manager_register (value callback, value eventObject) { + void lime_image_data_util_copy_channel (value image, value sourceImage, value sourceRect, value destPoint, int srcChannel, int destChannel) { - KeyEvent::callback = new ValuePointer (callback); - KeyEvent::eventObject = new ValuePointer (eventObject); + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + ImageDataUtil::CopyChannel (&_image, &_sourceImage, &_sourceRect, &_destPoint, srcChannel, destChannel); } - HL_PRIM void HL_NAME(hl_key_event_manager_register) (vclosure* callback, KeyEvent* eventObject) { + HL_PRIM void HL_NAME(hl_image_data_util_copy_channel) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) { - KeyEvent::callback = new ValuePointer (callback); - KeyEvent::eventObject = new ValuePointer ((vobj*)eventObject); + ImageDataUtil::CopyChannel (image, sourceImage, sourceRect, destPoint, srcChannel, destChannel); } - value lime_locale_get_system_locale () { + void lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value alphaImage, value alphaPoint, bool mergeAlpha) { - std::string* locale = Locale::GetSystemLocale (); + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); - if (!locale) { + if (val_is_null (alphaImage)) { - return alloc_null (); + ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, 0, 0, mergeAlpha); } else { - value result = alloc_string (locale->c_str ()); - delete locale; - return result; + Image _alphaImage = Image (alphaImage); + Vector2 _alphaPoint = Vector2 (alphaPoint); + + ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, &_alphaImage, &_alphaPoint, mergeAlpha); } } - HL_PRIM vbyte* HL_NAME(hl_locale_get_system_locale) () { - - std::string* locale = Locale::GetSystemLocale (); + HL_PRIM void HL_NAME(hl_image_data_util_copy_pixels) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha) { - if (!locale) { + if (!alphaImage) { - return 0; + ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, NULL, NULL, mergeAlpha); } else { - int size = locale->size (); - char* _locale = (char*)malloc (size + 1); - strncpy (_locale, locale->c_str (), size); - _locale[size] = '\0'; - delete locale; - - return (vbyte*)_locale; - - } + if (!alphaPoint) { - } + Vector2 _alphaPoint = Vector2 (0, 0); + ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, &_alphaPoint, mergeAlpha); - value lime_lzma_compress (value buffer, value bytes) { + } else { - #ifdef LIME_LZMA - Bytes data (buffer); - Bytes result (bytes); + ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); - LZMA::Compress (&data, &result); + } - return result.Value (bytes); - #else - return alloc_null (); - #endif + } } - HL_PRIM Bytes* HL_NAME(hl_lzma_compress) (Bytes* buffer, Bytes* bytes) { + void lime_image_data_util_fill_rect (value image, value rect, int rg, int ba) { - #ifdef LIME_LZMA - LZMA::Compress (buffer, bytes); - return bytes; - #else - return 0; - #endif + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + int32_t color = (rg << 16) | ba; + ImageDataUtil::FillRect (&_image, &_rect, color); } - value lime_lzma_decompress (value buffer, value bytes) { - - #ifdef LIME_LZMA - Bytes data (buffer); - Bytes result (bytes); - - LZMA::Decompress (&data, &result); + HL_PRIM void HL_NAME(hl_image_data_util_fill_rect) (Image* image, Rectangle* rect, int rg, int ba) { - return result.Value (bytes); - #else - return alloc_null (); - #endif + int32_t color = (rg << 16) | ba; + ImageDataUtil::FillRect (image, rect, color); } - HL_PRIM Bytes* HL_NAME(hl_lzma_decompress) (Bytes* buffer, Bytes* bytes) { + void lime_image_data_util_flood_fill (value image, int x, int y, int rg, int ba) { - #ifdef LIME_LZMA - LZMA::Decompress (buffer, bytes); - return bytes; - #else - return 0; - #endif + Image _image = Image (image); + int32_t color = (rg << 16) | ba; + ImageDataUtil::FloodFill (&_image, x, y, color); } - void lime_mouse_event_manager_register (value callback, value eventObject) { + HL_PRIM void HL_NAME(hl_image_data_util_flood_fill) (Image* image, int x, int y, int rg, int ba) { - MouseEvent::callback = new ValuePointer (callback); - MouseEvent::eventObject = new ValuePointer (eventObject); + int32_t color = (rg << 16) | ba; + ImageDataUtil::FloodFill (image, x, y, color); } - HL_PRIM void HL_NAME(hl_mouse_event_manager_register) (vclosure* callback, MouseEvent* eventObject) { + void lime_image_data_util_get_pixels (value image, value rect, int format, value bytes) { - MouseEvent::callback = new ValuePointer (callback); - MouseEvent::eventObject = new ValuePointer ((vobj*)eventObject); + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + PixelFormat _format = (PixelFormat)format; + Bytes pixels = Bytes (bytes); + ImageDataUtil::GetPixels (&_image, &_rect, _format, &pixels); } - void lime_neko_execute (HxString module) { + HL_PRIM void HL_NAME(hl_image_data_util_get_pixels) (Image* image, Rectangle* rect, PixelFormat format, Bytes* bytes) { - #ifdef LIME_NEKO - NekoVM::Execute (module.c_str ()); - #endif + ImageDataUtil::GetPixels (image, rect, format, bytes); } - void lime_orientation_event_manager_register (value callback, value eventObject) { + void lime_image_data_util_merge (value image, value sourceImage, value sourceRect, value destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { - OrientationEvent::callback = new ValuePointer (callback); - OrientationEvent::eventObject = new ValuePointer (eventObject); - System::EnableDeviceOrientationChange(true); + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + ImageDataUtil::Merge (&_image, &_sourceImage, &_sourceRect, &_destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); } - HL_PRIM void HL_NAME(hl_orientation_event_manager_register) (vclosure* callback, OrientationEvent* eventObject) { + HL_PRIM void HL_NAME(hl_image_data_util_merge) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { - OrientationEvent::callback = new ValuePointer (callback); - OrientationEvent::eventObject = new ValuePointer ((vobj*)eventObject); + ImageDataUtil::Merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); } - value lime_png_decode_bytes (value data, bool decodeData, value buffer) { + void lime_image_data_util_multiply_alpha (value image) { - ImageBuffer imageBuffer (buffer); - Bytes bytes (data); - Resource resource = Resource (&bytes); + Image _image = Image (image); + ImageDataUtil::MultiplyAlpha (&_image); - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + } - return imageBuffer.Value (buffer); - } - #endif + HL_PRIM void HL_NAME(hl_image_data_util_multiply_alpha) (Image* image) { - return alloc_null (); + ImageDataUtil::MultiplyAlpha (image); } - HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { + void lime_image_data_util_resize (value image, value buffer, int width, int height) { - Resource resource = Resource (data); + Image _image = Image (image); + ImageBuffer _buffer = ImageBuffer (buffer); + ImageDataUtil::Resize (&_image, &_buffer, width, height); - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer, decodeData)) { + } - return buffer; - } - #endif + HL_PRIM void HL_NAME(hl_image_data_util_resize) (Image* image, ImageBuffer* buffer, int width, int height) { - return 0; + ImageDataUtil::Resize (image, buffer, width, height); } - value lime_png_decode_file (HxString path, bool decodeData, value buffer) { + void lime_image_data_util_set_format (value image, int format) { - ImageBuffer imageBuffer (buffer); - Resource resource = Resource (hxs_utf8 (path, nullptr)); + Image _image = Image (image); + PixelFormat _format = (PixelFormat)format; + ImageDataUtil::SetFormat (&_image, _format); - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + } - return imageBuffer.Value (buffer); - } - #endif + HL_PRIM void HL_NAME(hl_image_data_util_set_format) (Image* image, PixelFormat format) { - return alloc_null (); + ImageDataUtil::SetFormat (image, format); } - HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { + void lime_image_data_util_set_pixels (value image, value rect, value bytes, int offset, int format, int endian) { - Resource resource = Resource (path); + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + Bytes _bytes (bytes); + PixelFormat _format = (PixelFormat)format; + Endian _endian = (Endian)endian; + ImageDataUtil::SetPixels (&_image, &_rect, &_bytes, offset, _format, _endian); - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer, decodeData)) { + } - return buffer; - } - #endif + HL_PRIM void HL_NAME(hl_image_data_util_set_pixels) (Image* image, Rectangle* rect, Bytes* bytes, int offset, PixelFormat format, Endian endian) { - return 0; + ImageDataUtil::SetPixels (image, rect, bytes, offset, format, endian); } - void lime_render_event_manager_register (value callback, value eventObject) { + int lime_image_data_util_threshold (value image, value sourceImage, value sourceRect, value destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { - RenderEvent::callback = new ValuePointer (callback); - RenderEvent::eventObject = new ValuePointer (eventObject); + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + int32_t threshold = (thresholdRG << 16) | thresholdBA; + int32_t color = (colorRG << 16) | colorBA; + int32_t mask = (maskRG << 16) | maskBA; + return ImageDataUtil::Threshold (&_image, &_sourceImage, &_sourceRect, &_destPoint, operation, threshold, color, mask, copySource); } - HL_PRIM void HL_NAME(hl_render_event_manager_register) (vclosure* callback, RenderEvent* eventObject) { + HL_PRIM int HL_NAME(hl_image_data_util_threshold) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { - RenderEvent::callback = new ValuePointer (callback); - RenderEvent::eventObject = new ValuePointer ((vobj*)eventObject); + int32_t threshold = (thresholdRG << 16) | thresholdBA; + int32_t color = (colorRG << 16) | colorBA; + int32_t mask = (maskRG << 16) | maskBA; + return ImageDataUtil::Threshold (image, sourceImage, sourceRect, destPoint, operation, threshold, color, mask, copySource); } - void lime_sensor_event_manager_register (value callback, value eventObject) { + void lime_image_data_util_unmultiply_alpha (value image) { - SensorEvent::callback = new ValuePointer (callback); - SensorEvent::eventObject = new ValuePointer (eventObject); + Image _image = Image (image); + ImageDataUtil::UnmultiplyAlpha (&_image); } - HL_PRIM void HL_NAME(hl_sensor_event_manager_register) (vclosure* callback, SensorEvent* eventObject) { + HL_PRIM void HL_NAME(hl_image_data_util_unmultiply_alpha) (Image* image) { - SensorEvent::callback = new ValuePointer (callback); - SensorEvent::eventObject = new ValuePointer ((vobj*)eventObject); + ImageDataUtil::UnmultiplyAlpha (image); } - bool lime_system_get_allow_screen_timeout () { + double lime_jni_getenv () { - return System::GetAllowScreenTimeout (); + #ifdef ANDROID + return (uintptr_t)JNI::GetEnv (); + #else + return 0; + #endif } - HL_PRIM bool HL_NAME(hl_system_get_allow_screen_timeout) () { + HL_PRIM double HL_NAME(hl_jni_getenv) () { - return System::GetAllowScreenTimeout (); + #ifdef ANDROID + return (uintptr_t)JNI::GetEnv (); + #else + return 0; + #endif } - value lime_system_get_device_model () { - - std::wstring* model = System::GetDeviceModel (); + void lime_joystick_event_manager_register (value callback, value eventObject) { - if (model) { + JoystickEvent::callback = new ValuePointer (callback); + JoystickEvent::eventObject = new ValuePointer (eventObject); - value result = alloc_wstring (model->c_str ()); - delete model; - return result; + } - } else { - return alloc_null (); + HL_PRIM void HL_NAME(hl_joystick_event_manager_register) (vclosure* callback, JoystickEvent* eventObject) { - } + JoystickEvent::callback = new ValuePointer (callback); + JoystickEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - HL_PRIM vbyte* HL_NAME(hl_system_get_device_model) () { + value lime_joystick_get_device_guid (int id) { - #ifndef EMSCRIPTEN + const char* guid = Joystick::GetDeviceGUID (id); + return guid ? alloc_string (guid) : alloc_null (); - std::wstring* model = System::GetDeviceModel (); + } - if (model) { - vbyte* const result = hl_wstring_to_utf8_bytes (*model); - delete model; - return result; + HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_guid) (int id) { - } + return (vbyte*)Joystick::GetDeviceGUID (id); - #endif + } - return 0; - } + value lime_joystick_get_device_name (int id) { + const char* name = Joystick::GetDeviceName (id); + return name ? alloc_string (name) : alloc_null (); - value lime_system_get_device_vendor () { + } - std::wstring* vendor = System::GetDeviceVendor (); - if (vendor) { + HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_name) (int id) { - value result = alloc_wstring (vendor->c_str ()); - delete vendor; - return result; + return (vbyte*)Joystick::GetDeviceName (id); - } else { + } - return alloc_null (); - } + int lime_joystick_get_num_axes (int id) { + + return Joystick::GetNumAxes (id); } - HL_PRIM vbyte* HL_NAME(hl_system_get_device_vendor) () { + HL_PRIM int HL_NAME(hl_joystick_get_num_axes) (int id) { - #ifndef EMSCRIPTEN + return Joystick::GetNumAxes (id); - std::wstring* vendor = System::GetDeviceVendor (); + } - if (vendor) { - vbyte* const result = hl_wstring_to_utf8_bytes (*vendor); - delete vendor; - return result; + int lime_joystick_get_num_buttons (int id) { - } + return Joystick::GetNumButtons (id); - #endif + } - return 0; - } + HL_PRIM int HL_NAME(hl_joystick_get_num_buttons) (int id) { + return Joystick::GetNumButtons (id); - value lime_system_get_directory (int type, HxString company, HxString title) { + } - std::wstring* path = System::GetDirectory ((SystemDirectory)type, hxs_utf8 (company, nullptr), hxs_utf8 (title, nullptr)); - if (path) { + int lime_joystick_get_num_hats (int id) { - value result = alloc_wstring (path->c_str ()); - delete path; - return result; + return Joystick::GetNumHats (id); - } else { + } - return alloc_null (); - } + HL_PRIM int HL_NAME(hl_joystick_get_num_hats) (int id) { + + return Joystick::GetNumHats (id); } - HL_PRIM vbyte* HL_NAME(hl_system_get_directory) (int type, hl_vstring* company, hl_vstring* title) { + value lime_jpeg_decode_bytes (value data, bool decodeData, value buffer) { - #ifndef EMSCRIPTEN + ImageBuffer imageBuffer (buffer); - std::wstring* path = System::GetDirectory ((SystemDirectory)type, company ? (char*)hl_to_utf8 ((const uchar*)company->bytes) : NULL, title ? (char*)hl_to_utf8 ((const uchar*)title->bytes) : NULL); + Bytes bytes (data); + Resource resource = Resource (&bytes); - if (path) { + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + return imageBuffer.Value (buffer); } - #endif - return 0; + return alloc_null (); } - value lime_system_get_display (int id) { + HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { - return (value)System::GetDisplay (true, id); + Resource resource = Resource (data); - } + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, buffer, decodeData)) { + return buffer; - HL_PRIM vdynamic* HL_NAME(hl_system_get_display) (int id) { + } + #endif - return (vdynamic*)System::GetDisplay (false, id); + return 0; } - bool lime_system_get_ios_tablet () { + value lime_jpeg_decode_file (HxString path, bool decodeData, value buffer) { - #ifdef IPHONE - return System::GetIOSTablet (); - #else - return false; - #endif + ImageBuffer imageBuffer (buffer); + Resource resource = Resource (hxs_utf8 (path, nullptr)); - } + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + return imageBuffer.Value (buffer); - HL_PRIM bool HL_NAME(hl_system_get_ios_tablet) () { - - #ifdef IPHONE - return System::GetIOSTablet (); - #else - return false; + } #endif + return alloc_null (); + } - int lime_system_get_num_displays () { + HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { - return System::GetNumDisplays (); + Resource resource = Resource (path); - } + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, buffer, decodeData)) { + return buffer; - HL_PRIM int HL_NAME(hl_system_get_num_displays) () { + } + #endif - return System::GetNumDisplays (); + return 0; } - int lime_system_get_device_orientation () { + int lime_key_code_from_scan_code (int scanCode) { - return System::GetDeviceOrientation(); + return KeyCode::FromScanCode (scanCode); } - HL_PRIM int HL_NAME(hl_system_get_device_orientation) () { + HL_PRIM int HL_NAME(hl_key_code_from_scan_code) (int scanCode) { - return System::GetDeviceOrientation(); + return KeyCode::FromScanCode (scanCode); } - value lime_system_get_platform_label () { - - std::wstring* label = System::GetPlatformLabel (); + int lime_key_code_to_scan_code (int keyCode) { - if (label) { + return KeyCode::ToScanCode (keyCode); - value result = alloc_wstring (label->c_str ()); - delete label; - return result; + } - } else { - return alloc_null (); + HL_PRIM int HL_NAME(hl_key_code_to_scan_code) (int keyCode) { - } + return KeyCode::ToScanCode (keyCode); } - HL_PRIM vbyte* HL_NAME(hl_system_get_platform_label) () { - - #ifndef EMSCRIPTEN - - std::wstring* label = System::GetPlatformLabel (); + void lime_key_event_manager_register (value callback, value eventObject) { - if (label) { + KeyEvent::callback = new ValuePointer (callback); + KeyEvent::eventObject = new ValuePointer (eventObject); - vbyte* const result = hl_wstring_to_utf8_bytes (*label); - delete label; - return result; + } - } - #endif + HL_PRIM void HL_NAME(hl_key_event_manager_register) (vclosure* callback, KeyEvent* eventObject) { - return 0; + KeyEvent::callback = new ValuePointer (callback); + KeyEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - value lime_system_get_platform_name () { + value lime_locale_get_system_locale () { - std::wstring* name = System::GetPlatformName (); + std::string* locale = Locale::GetSystemLocale (); - if (name) { + if (!locale) { - value result = alloc_wstring (name->c_str ()); - delete name; - return result; + return alloc_null (); } else { - return 0; - - } - - } - - - HL_PRIM vbyte* HL_NAME(hl_system_get_platform_name) () { - - #ifndef EMSCRIPTEN - - std::wstring* name = System::GetPlatformName (); - - if (name) { - - vbyte* const result = hl_wstring_to_utf8_bytes (*name); - delete name; + value result = alloc_string (locale->c_str ()); + delete locale; return result; } - #endif - - return 0; - } - value lime_system_get_platform_version () { + HL_PRIM vbyte* HL_NAME(hl_locale_get_system_locale) () { - std::wstring* version = System::GetPlatformVersion (); + std::string* locale = Locale::GetSystemLocale (); - if (version) { + if (!locale) { - value result = alloc_wstring (version->c_str ()); - delete version; - return result; + return 0; } else { - return alloc_null (); + int size = locale->size (); + char* _locale = (char*)malloc (size + 1); + strncpy (_locale, locale->c_str (), size); + _locale[size] = '\0'; + delete locale; + + return (vbyte*)_locale; } } - HL_PRIM vbyte* HL_NAME(hl_system_get_platform_version) () { - - #ifndef EMSCRIPTEN - - std::wstring* version = System::GetPlatformVersion (); + value lime_lzma_compress (value buffer, value bytes) { - if (version) { + #ifdef LIME_LZMA + Bytes data (buffer); + Bytes result (bytes); - vbyte* const result = hl_wstring_to_utf8_bytes (*version); - delete version; - return result; - } + LZMA::Compress (&data, &result); + return result.Value (bytes); + #else + return alloc_null (); #endif - return 0; - } - double lime_system_get_timer () { + HL_PRIM Bytes* HL_NAME(hl_lzma_compress) (Bytes* buffer, Bytes* bytes) { - return System::GetTimer (); + #ifdef LIME_LZMA + LZMA::Compress (buffer, bytes); + return bytes; + #else + return 0; + #endif } - HL_PRIM double HL_NAME(hl_system_get_timer) () { - - return System::GetTimer (); - - } + value lime_lzma_decompress (value buffer, value bytes) { + #ifdef LIME_LZMA + Bytes data (buffer); + Bytes result (bytes); - int lime_system_get_windows_console_mode (int handleType) { + LZMA::Decompress (&data, &result); - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::GetWindowsConsoleMode (handleType); + return result.Value (bytes); #else - return 0; + return alloc_null (); #endif } - HL_PRIM int HL_NAME(hl_system_get_windows_console_mode) (int handleType) { + HL_PRIM Bytes* HL_NAME(hl_lzma_decompress) (Bytes* buffer, Bytes* bytes) { - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::GetWindowsConsoleMode (handleType); + #ifdef LIME_LZMA + LZMA::Decompress (buffer, bytes); + return bytes; #else return 0; #endif @@ -3687,1010 +3740,6002 @@ namespace lime { } - void lime_system_open_file (HxString path) { + void lime_mouse_event_manager_register (value callback, value eventObject) { - #ifdef IPHONE - System::OpenFile (path.c_str ()); - #endif + MouseEvent::callback = new ValuePointer (callback); + MouseEvent::eventObject = new ValuePointer (eventObject); } - HL_PRIM void HL_NAME(hl_system_open_file) (vbyte* path) { + HL_PRIM void HL_NAME(hl_mouse_event_manager_register) (vclosure* callback, MouseEvent* eventObject) { - #ifdef IPHONE - System::OpenFile ((char*)path); - #endif + MouseEvent::callback = new ValuePointer (callback); + MouseEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - void lime_system_open_url (HxString url, HxString target) { + void lime_neko_execute (HxString module) { - #ifdef IPHONE - System::OpenURL (url.c_str (), target.c_str ()); + #ifdef LIME_NEKO + NekoVM::Execute (module.c_str ()); #endif } - HL_PRIM void HL_NAME(hl_system_open_url) (vbyte* url, vbyte* target) { + void lime_orientation_event_manager_register (value callback, value eventObject) { - #ifdef IPHONE - System::OpenURL ((char*)url, (char*)target); - #endif + OrientationEvent::callback = new ValuePointer (callback); + OrientationEvent::eventObject = new ValuePointer (eventObject); + System::EnableDeviceOrientationChange(true); } - bool lime_system_set_allow_screen_timeout (bool allow) { + HL_PRIM void HL_NAME(hl_orientation_event_manager_register) (vclosure* callback, OrientationEvent* eventObject) { - return System::SetAllowScreenTimeout (allow); + OrientationEvent::callback = new ValuePointer (callback); + OrientationEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - HL_PRIM bool HL_NAME(hl_system_set_allow_screen_timeout) (bool allow) { - - return System::SetAllowScreenTimeout (allow); + value lime_png_decode_bytes (value data, bool decodeData, value buffer) { - } + ImageBuffer imageBuffer (buffer); + Bytes bytes (data); + Resource resource = Resource (&bytes); + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer, decodeData)) { - bool lime_system_set_windows_console_mode (int handleType, int mode) { + return imageBuffer.Value (buffer); - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::SetWindowsConsoleMode (handleType, mode); - #else - return false; + } #endif + return alloc_null (); + } - HL_PRIM bool HL_NAME(hl_system_set_windows_console_mode) (int handleType, int mode) { + HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::SetWindowsConsoleMode (handleType, mode); - #else - return false; - #endif + Resource resource = Resource (data); - } + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer, decodeData)) { + return buffer; - void lime_text_event_manager_register (value callback, value eventObject) { + } + #endif - TextEvent::callback = new ValuePointer (callback); - TextEvent::eventObject = new ValuePointer (eventObject); + return 0; } - HL_PRIM void HL_NAME(hl_text_event_manager_register) (vclosure* callback, TextEvent* eventObject) { + value lime_png_decode_file (HxString path, bool decodeData, value buffer) { - TextEvent::callback = new ValuePointer (callback); - TextEvent::eventObject = new ValuePointer ((vobj*)eventObject); + ImageBuffer imageBuffer (buffer); + Resource resource = Resource (hxs_utf8 (path, nullptr)); - } + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + return imageBuffer.Value (buffer); - void lime_touch_event_manager_register (value callback, value eventObject) { + } + #endif - TouchEvent::callback = new ValuePointer (callback); - TouchEvent::eventObject = new ValuePointer (eventObject); + return alloc_null (); } - HL_PRIM void HL_NAME(hl_touch_event_manager_register) (vclosure* callback, TouchEvent* eventObject) { + HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { - TouchEvent::callback = new ValuePointer (callback); - TouchEvent::eventObject = new ValuePointer ((vobj*)eventObject); + Resource resource = Resource (path); - } + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer, decodeData)) { + return buffer; - void lime_window_alert (value window, HxString message, HxString title) { + } + #endif - Window* targetWindow = (Window*)val_data (window); - targetWindow->Alert (hxs_utf8 (message, nullptr), hxs_utf8 (title, nullptr)); + return 0; } - HL_PRIM void HL_NAME(hl_window_alert) (HL_CFFIPointer* window, hl_vstring* message, hl_vstring* title) { + void lime_render_event_manager_register (value callback, value eventObject) { - Window* targetWindow = (Window*)window->ptr; - const char *cmessage = message ? hl_to_utf8(message->bytes) : nullptr; - const char *ctitle = title ? hl_to_utf8(title->bytes) : nullptr; - targetWindow->Alert (cmessage, ctitle); + RenderEvent::callback = new ValuePointer (callback); + RenderEvent::eventObject = new ValuePointer (eventObject); } - void lime_window_close (value window) { + HL_PRIM void HL_NAME(hl_render_event_manager_register) (vclosure* callback, RenderEvent* eventObject) { - Window* targetWindow = (Window*)val_data (window); - targetWindow->Close (); + RenderEvent::callback = new ValuePointer (callback); + RenderEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - HL_PRIM void HL_NAME(hl_window_close) (HL_CFFIPointer* window) { + void lime_sensor_event_manager_register (value callback, value eventObject) { - Window* targetWindow = (Window*)window->ptr; - targetWindow->Close (); + SensorEvent::callback = new ValuePointer (callback); + SensorEvent::eventObject = new ValuePointer (eventObject); } - void lime_window_context_flip (value window) { + HL_PRIM void HL_NAME(hl_sensor_event_manager_register) (vclosure* callback, SensorEvent* eventObject) { - ((Window*)val_data (window))->ContextFlip (); + SensorEvent::callback = new ValuePointer (callback); + SensorEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - HL_PRIM void HL_NAME(hl_window_context_flip) (HL_CFFIPointer* window) { + bool lime_system_get_allow_screen_timeout () { - ((Window*)window->ptr)->ContextFlip (); + return System::GetAllowScreenTimeout (); } - value lime_window_context_lock (value window) { + HL_PRIM bool HL_NAME(hl_system_get_allow_screen_timeout) () { - return (value)((Window*)val_data (window))->ContextLock (true); + return System::GetAllowScreenTimeout (); } - HL_PRIM vdynamic* HL_NAME(hl_window_context_lock) (HL_CFFIPointer* window) { + value lime_system_get_device_model () { - return (vdynamic*)((Window*)window->ptr)->ContextLock (false); + std::wstring* model = System::GetDeviceModel (); - } + if (model) { + value result = alloc_wstring (model->c_str ()); + delete model; + return result; - void lime_window_context_make_current (value window) { + } else { - ((Window*)val_data (window))->ContextMakeCurrent (); + return alloc_null (); + + } } - HL_PRIM void HL_NAME(hl_window_context_make_current) (HL_CFFIPointer* window) { + HL_PRIM vbyte* HL_NAME(hl_system_get_device_model) () { - ((Window*)window->ptr)->ContextMakeCurrent (); + #ifndef EMSCRIPTEN - } + std::wstring* model = System::GetDeviceModel (); + if (model) { - void lime_window_context_unlock (value window) { + vbyte* const result = hl_wstring_to_utf8_bytes (*model); + delete model; + return result; - ((Window*)val_data (window))->ContextUnlock (); + } + + #endif + + return 0; } - HL_PRIM void HL_NAME(hl_window_context_unlock) (HL_CFFIPointer* window) { + value lime_system_get_device_vendor () { - ((Window*)window->ptr)->ContextUnlock (); + std::wstring* vendor = System::GetDeviceVendor (); - } + if (vendor) { + value result = alloc_wstring (vendor->c_str ()); + delete vendor; + return result; - value lime_window_create (value application, int width, int height, int flags, HxString title) { + } else { - Window* window = CreateWindow ((Application*)val_data (application), width, height, flags, hxs_utf8 (title, nullptr)); - return CFFIPointer (window, gc_window); + return alloc_null (); + + } } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_window_create) (HL_CFFIPointer* application, int width, int height, int flags, hl_vstring* title) { + HL_PRIM vbyte* HL_NAME(hl_system_get_device_vendor) () { - Window* window = CreateWindow ((Application*)application->ptr, width, height, flags, (const char*)hl_to_utf8 ((const uchar*)title->bytes)); - return HLCFFIPointer (window, (hl_finalizer)hl_gc_window); + #ifndef EMSCRIPTEN - } + std::wstring* vendor = System::GetDeviceVendor (); + if (vendor) { - void lime_window_event_manager_register (value callback, value eventObject) { + vbyte* const result = hl_wstring_to_utf8_bytes (*vendor); + delete vendor; + return result; - WindowEvent::callback = new ValuePointer (callback); - WindowEvent::eventObject = new ValuePointer (eventObject); + } + + #endif + + return 0; } - HL_PRIM void HL_NAME(hl_window_event_manager_register) (vclosure* callback, WindowEvent* eventObject) { + value lime_system_get_directory (int type, HxString company, HxString title) { - WindowEvent::callback = new ValuePointer (callback); - WindowEvent::eventObject = new ValuePointer ((vobj*)eventObject); + std::wstring* path = System::GetDirectory ((SystemDirectory)type, hxs_utf8 (company, nullptr), hxs_utf8 (title, nullptr)); - } + if (path) { + value result = alloc_wstring (path->c_str ()); + delete path; + return result; - void lime_window_focus (value window) { + } else { - Window* targetWindow = (Window*)val_data (window); - targetWindow->Focus (); + return alloc_null (); + + } } - HL_PRIM void HL_NAME(hl_window_focus) (HL_CFFIPointer* window) { + HL_PRIM vbyte* HL_NAME(hl_system_get_directory) (int type, hl_vstring* company, hl_vstring* title) { - Window* targetWindow = (Window*)window->ptr; - targetWindow->Focus (); + #ifndef EMSCRIPTEN - } + std::wstring* path = System::GetDirectory ((SystemDirectory)type, company ? (char*)hl_to_utf8 ((const uchar*)company->bytes) : NULL, title ? (char*)hl_to_utf8 ((const uchar*)title->bytes) : NULL); + if (path) { - double lime_window_get_context (value window) { + vbyte* const result = hl_wstring_to_utf8_bytes (*path); + delete path; + return result; - Window* targetWindow = (Window*)val_data (window); - return (uintptr_t)targetWindow->GetContext (); + } + + #endif + + return 0; } - HL_PRIM double HL_NAME(hl_window_get_context) (HL_CFFIPointer* window) { + value lime_system_get_display (int id) { - Window* targetWindow = (Window*)window->ptr; - return (uintptr_t)targetWindow->GetContext (); + return (value)System::GetDisplay (true, id); } - value lime_window_get_context_type (value window) { + HL_PRIM vdynamic* HL_NAME(hl_system_get_display) (int id) { - Window* targetWindow = (Window*)val_data (window); - const char* type = targetWindow->GetContextType (); - return type ? alloc_string (type) : alloc_null (); + return (vdynamic*)System::GetDisplay (false, id); } - HL_PRIM vbyte* HL_NAME(hl_window_get_context_type) (HL_CFFIPointer* window) { + bool lime_system_get_ios_tablet () { - Window* targetWindow = (Window*)window->ptr; - return (vbyte*)targetWindow->GetContextType (); + #ifdef IPHONE + return System::GetIOSTablet (); + #else + return false; + #endif } - value lime_window_get_vulkan_instance_extensions (value window) { + HL_PRIM bool HL_NAME(hl_system_get_ios_tablet) () { - Window* targetWindow = (Window*)val_data (window); - unsigned int count = 0; + #ifdef IPHONE + return System::GetIOSTablet (); + #else + return false; + #endif - if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + } - return alloc_array (0); - } + int lime_system_get_num_displays () { - std::vector names (count); - if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + return System::GetNumDisplays (); - return alloc_array (0); + } - } - value result = alloc_array (count); + HL_PRIM int HL_NAME(hl_system_get_num_displays) () { - for (unsigned int i = 0; i < count; ++i) { + return System::GetNumDisplays (); - val_array_set_i (result, i, alloc_string (names[i])); + } - } - return result; + int lime_system_get_device_orientation () { + + return System::GetDeviceOrientation(); } - HL_PRIM hl_varray* HL_NAME(hl_window_get_vulkan_instance_extensions) (HL_CFFIPointer* window) { + HL_PRIM int HL_NAME(hl_system_get_device_orientation) () { - Window* targetWindow = (Window*)window->ptr; - unsigned int count = 0; + return System::GetDeviceOrientation(); - if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + } - return hl_alloc_array (&hlt_bytes, 0); - } + value lime_system_get_platform_label () { - std::vector names (count); - if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + std::wstring* label = System::GetPlatformLabel (); - return hl_alloc_array (&hlt_bytes, 0); + if (label) { + + value result = alloc_wstring (label->c_str ()); + delete label; + return result; + + } else { + + return alloc_null (); } - hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, count); - vbyte** resultData = hl_aptr (result, vbyte*); + } - for (unsigned int i = 0; i < count; ++i) { - *resultData++ = hl_copy_bytes ((const vbyte*)names[i], (int)std::strlen (names[i]) + 1); + HL_PRIM vbyte* HL_NAME(hl_system_get_platform_label) () { - } + #ifndef EMSCRIPTEN - return result; + std::wstring* label = System::GetPlatformLabel (); - } + if (label) { + vbyte* const result = hl_wstring_to_utf8_bytes (*label); + delete label; + return result; - value lime_window_get_vulkan_drawable_size (value window) { + } - Window* targetWindow = (Window*)val_data (window); - int width = 0; - int height = 0; - targetWindow->GetVulkanDrawableSize (&width, &height); + #endif - value result = alloc_empty_object (); - alloc_field (result, val_id ("width"), alloc_int (width)); - alloc_field (result, val_id ("height"), alloc_int (height)); - return result; + return 0; } - HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_drawable_size) (HL_CFFIPointer* window) { + value lime_system_get_platform_name () { - Window* targetWindow = (Window*)window->ptr; - int width = 0; - int height = 0; - targetWindow->GetVulkanDrawableSize (&width, &height); + std::wstring* name = System::GetPlatformName (); - const int id_width = hl_hash_utf8 ("width"); - const int id_height = hl_hash_utf8 ("height"); - vdynamic* result = (vdynamic*)hl_alloc_dynobj(); - hl_dyn_seti (result, id_width, &hlt_i32, width); - hl_dyn_seti (result, id_height, &hlt_i32, height); - return result; + if (name) { - } + value result = alloc_wstring (name->c_str ()); + delete name; + return result; + } else { - value lime_window_get_vulkan_instance_proc_addr (value window) { + return 0; - Window* targetWindow = (Window*)val_data (window); - return CreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + } } - HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_instance_proc_addr) (HL_CFFIPointer* window) { + HL_PRIM vbyte* HL_NAME(hl_system_get_platform_name) () { - Window* targetWindow = (Window*)window->ptr; - return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + #ifndef EMSCRIPTEN + + std::wstring* name = System::GetPlatformName (); + + if (name) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*name); + delete name; + return result; + + } + + #endif + + return 0; } - value lime_window_create_vulkan_surface (value window, int instanceHigh, int instanceLow) { + value lime_system_get_platform_version () { - Window* targetWindow = (Window*)val_data (window); - uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + std::wstring* version = System::GetPlatformVersion (); - if (!surface) { + if (version) { + + value result = alloc_wstring (version->c_str ()); + delete version; + return result; + + } else { return alloc_null (); } - return CreateVulkanHandleValue (surface); - } - HL_PRIM vdynamic* HL_NAME(hl_window_create_vulkan_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + HL_PRIM vbyte* HL_NAME(hl_system_get_platform_version) () { - Window* targetWindow = (Window*)window->ptr; - uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + #ifndef EMSCRIPTEN - if (!surface) { + std::wstring* version = System::GetPlatformVersion (); - return 0; + if (version) { + vbyte* const result = hl_wstring_to_utf8_bytes (*version); + delete version; + return result; } - return HLCreateVulkanHandleValue (surface); + #endif + + return 0; } - value lime_vk_create_instance (value window, HxString applicationName) { + double lime_system_get_timer () { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = VK_NULL_HANDLE; + return System::GetTimer (); - if (!CreateManagedVulkanInstance (targetWindow, applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0, &instance)) { + } - return alloc_null (); - } + HL_PRIM double HL_NAME(hl_system_get_timer) () { - return CreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); -#else - lastVKError = "Lime was built without lime-vulkan support"; - return alloc_null (); -#endif + return System::GetTimer (); } - HL_PRIM vdynamic* HL_NAME(hl_vk_create_instance) (HL_CFFIPointer* window, hl_vstring* applicationName) { + int lime_system_get_windows_console_mode (int handleType) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = VK_NULL_HANDLE; - const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::GetWindowsConsoleMode (handleType); + #else + return 0; + #endif - if (!CreateManagedVulkanInstance (targetWindow, applicationNameUTF8, &instance)) { + } - return 0; - } + HL_PRIM int HL_NAME(hl_system_get_windows_console_mode) (int handleType) { - return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); -#else - lastVKError = "Lime was built without lime-vulkan support"; + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::GetWindowsConsoleMode (handleType); + #else return 0; -#endif + #endif } - void lime_vk_destroy_instance (value window, int instanceHigh, int instanceLow) { + void lime_system_open_file (HxString path) { -#ifdef LIME_VULKAN - if (instanceHigh == 0 && instanceLow == 0) return; - Window* targetWindow = (Window*)val_data (window); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr) return; + #ifdef IPHONE + System::OpenFile (path.c_str ()); + #endif - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); - if (vkDestroyInstance) { + } - vkDestroyInstance (instance, 0); - } -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + HL_PRIM void HL_NAME(hl_system_open_file) (vbyte* path) { + + #ifdef IPHONE + System::OpenFile ((char*)path); + #endif } - HL_PRIM void HL_NAME(hl_vk_destroy_instance) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + void lime_system_open_url (HxString url, HxString target) { -#ifdef LIME_VULKAN - if (instanceHigh == 0 && instanceLow == 0) return; - Window* targetWindow = (Window*)window->ptr; - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr) return; + #ifdef IPHONE + System::OpenURL (url.c_str (), target.c_str ()); + #endif - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); - if (vkDestroyInstance) { + } - vkDestroyInstance (instance, 0); - } -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + HL_PRIM void HL_NAME(hl_system_open_url) (vbyte* url, vbyte* target) { + + #ifdef IPHONE + System::OpenURL ((char*)url, (char*)target); + #endif } - void lime_vk_destroy_surface (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + bool lime_system_set_allow_screen_timeout (bool allow) { -#ifdef LIME_VULKAN - if (instanceHigh == 0 && instanceLow == 0) return; - Window* targetWindow = (Window*)val_data (window); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr) return; + return System::SetAllowScreenTimeout (allow); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); - if (!surface) return; + } - PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); - if (vkDestroySurfaceKHR) { - vkDestroySurfaceKHR (instance, surface, 0); + HL_PRIM bool HL_NAME(hl_system_set_allow_screen_timeout) (bool allow) { - } -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + return System::SetAllowScreenTimeout (allow); } - HL_PRIM void HL_NAME(hl_vk_destroy_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + bool lime_system_set_windows_console_mode (int handleType, int mode) { -#ifdef LIME_VULKAN - if (instanceHigh == 0 && instanceLow == 0) return; - Window* targetWindow = (Window*)window->ptr; - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr) return; + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::SetWindowsConsoleMode (handleType, mode); + #else + return false; + #endif - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); - if (!surface) return; + } - PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); - if (vkDestroySurfaceKHR) { - vkDestroySurfaceKHR (instance, surface, 0); + HL_PRIM bool HL_NAME(hl_system_set_windows_console_mode) (int handleType, int mode) { - } -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::SetWindowsConsoleMode (handleType, mode); + #else + return false; + #endif } - value lime_vk_get_physical_devices (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + void lime_text_event_manager_register (value callback, value eventObject) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + TextEvent::callback = new ValuePointer (callback); + TextEvent::eventObject = new ValuePointer (eventObject); - if (!targetWindow || !instance) { + } - lastVKError = "Missing Vulkan window or instance"; - return alloc_null (); - } + HL_PRIM void HL_NAME(hl_text_event_manager_register) (vclosure* callback, TextEvent* eventObject) { - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); - if (!vkGetInstanceProcAddr) { + TextEvent::callback = new ValuePointer (callback); + TextEvent::eventObject = new ValuePointer ((vobj*)eventObject); - lastVKError = "SDL did not expose vkGetInstanceProcAddr"; - return alloc_null (); + } - } - PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, - "vkEnumeratePhysicalDevices"); - PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, - "vkGetPhysicalDeviceProperties"); - PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = - (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); - PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = - (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + void lime_touch_event_manager_register (value callback, value eventObject) { - if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + TouchEvent::callback = new ValuePointer (callback); + TouchEvent::eventObject = new ValuePointer (eventObject); - lastVKError = "Missing required Vulkan instance functions"; - return alloc_null (); + } - } - VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); - uint32_t deviceCount = 0; - VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + HL_PRIM void HL_NAME(hl_touch_event_manager_register) (vclosure* callback, TouchEvent* eventObject) { - if (result != VK_SUCCESS) { + TouchEvent::callback = new ValuePointer (callback); + TouchEvent::eventObject = new ValuePointer ((vobj*)eventObject); - lastVKError = "vkEnumeratePhysicalDevices failed"; - return alloc_null (); + } - } - value devices = alloc_array (deviceCount); + void lime_window_alert (value window, HxString message, HxString title) { + + Window* targetWindow = (Window*)val_data (window); + targetWindow->Alert (hxs_utf8 (message, nullptr), hxs_utf8 (title, nullptr)); + + } + + + HL_PRIM void HL_NAME(hl_window_alert) (HL_CFFIPointer* window, hl_vstring* message, hl_vstring* title) { + + Window* targetWindow = (Window*)window->ptr; + const char *cmessage = message ? hl_to_utf8(message->bytes) : nullptr; + const char *ctitle = title ? hl_to_utf8(title->bytes) : nullptr; + targetWindow->Alert (cmessage, ctitle); + + } + + + void lime_window_close (value window) { + + Window* targetWindow = (Window*)val_data (window); + targetWindow->Close (); + + } + + + HL_PRIM void HL_NAME(hl_window_close) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + targetWindow->Close (); + + } + + + void lime_window_context_flip (value window) { + + ((Window*)val_data (window))->ContextFlip (); + + } + + + HL_PRIM void HL_NAME(hl_window_context_flip) (HL_CFFIPointer* window) { + + ((Window*)window->ptr)->ContextFlip (); + + } + + + value lime_window_context_lock (value window) { + + return (value)((Window*)val_data (window))->ContextLock (true); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_context_lock) (HL_CFFIPointer* window) { + + return (vdynamic*)((Window*)window->ptr)->ContextLock (false); + + } + + + void lime_window_context_make_current (value window) { + + ((Window*)val_data (window))->ContextMakeCurrent (); + + } + + + HL_PRIM void HL_NAME(hl_window_context_make_current) (HL_CFFIPointer* window) { + + ((Window*)window->ptr)->ContextMakeCurrent (); + + } + + + void lime_window_context_unlock (value window) { + + ((Window*)val_data (window))->ContextUnlock (); + + } + + + HL_PRIM void HL_NAME(hl_window_context_unlock) (HL_CFFIPointer* window) { + + ((Window*)window->ptr)->ContextUnlock (); + + } + + + value lime_window_create (value application, int width, int height, int flags, HxString title) { + + Window* window = CreateWindow ((Application*)val_data (application), width, height, flags, hxs_utf8 (title, nullptr)); + return CFFIPointer (window, gc_window); + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_window_create) (HL_CFFIPointer* application, int width, int height, int flags, hl_vstring* title) { + + Window* window = CreateWindow ((Application*)application->ptr, width, height, flags, (const char*)hl_to_utf8 ((const uchar*)title->bytes)); + return HLCFFIPointer (window, (hl_finalizer)hl_gc_window); + + } + + + void lime_window_event_manager_register (value callback, value eventObject) { + + WindowEvent::callback = new ValuePointer (callback); + WindowEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_window_event_manager_register) (vclosure* callback, WindowEvent* eventObject) { + + WindowEvent::callback = new ValuePointer (callback); + WindowEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + void lime_window_focus (value window) { + + Window* targetWindow = (Window*)val_data (window); + targetWindow->Focus (); + + } + + + HL_PRIM void HL_NAME(hl_window_focus) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + targetWindow->Focus (); + + } + + + double lime_window_get_context (value window) { + + Window* targetWindow = (Window*)val_data (window); + return (uintptr_t)targetWindow->GetContext (); + + } + + + HL_PRIM double HL_NAME(hl_window_get_context) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return (uintptr_t)targetWindow->GetContext (); + + } + + + value lime_window_get_context_type (value window) { + + Window* targetWindow = (Window*)val_data (window); + const char* type = targetWindow->GetContextType (); + return type ? alloc_string (type) : alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_window_get_context_type) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return (vbyte*)targetWindow->GetContextType (); + + } + + + value lime_window_get_vulkan_instance_extensions (value window) { + + Window* targetWindow = (Window*)val_data (window); + unsigned int count = 0; + + if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + + return alloc_array (0); + + } + + std::vector names (count); + if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + + return alloc_array (0); + + } + + value result = alloc_array (count); + + for (unsigned int i = 0; i < count; ++i) { + + val_array_set_i (result, i, alloc_string (names[i])); + + } + + return result; + + } + + + HL_PRIM hl_varray* HL_NAME(hl_window_get_vulkan_instance_extensions) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + unsigned int count = 0; + + if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + + return hl_alloc_array (&hlt_bytes, 0); + + } + + std::vector names (count); + if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + + return hl_alloc_array (&hlt_bytes, 0); + + } + + hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, count); + vbyte** resultData = hl_aptr (result, vbyte*); + + for (unsigned int i = 0; i < count; ++i) { + + *resultData++ = hl_copy_bytes ((const vbyte*)names[i], (int)std::strlen (names[i]) + 1); + + } + + return result; + + } + + + value lime_window_get_vulkan_drawable_size (value window) { + + Window* targetWindow = (Window*)val_data (window); + int width = 0; + int height = 0; + targetWindow->GetVulkanDrawableSize (&width, &height); + + value result = alloc_empty_object (); + alloc_field (result, val_id ("width"), alloc_int (width)); + alloc_field (result, val_id ("height"), alloc_int (height)); + return result; + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_drawable_size) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + int width = 0; + int height = 0; + targetWindow->GetVulkanDrawableSize (&width, &height); + + const int id_width = hl_hash_utf8 ("width"); + const int id_height = hl_hash_utf8 ("height"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj(); + hl_dyn_seti (result, id_width, &hlt_i32, width); + hl_dyn_seti (result, id_height, &hlt_i32, height); + return result; + + } + + + value lime_window_get_vulkan_instance_proc_addr (value window) { + + Window* targetWindow = (Window*)val_data (window); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_instance_proc_addr) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + + } + + + value lime_window_create_vulkan_surface (value window, int instanceHigh, int instanceLow) { + + Window* targetWindow = (Window*)val_data (window); + uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + + if (!surface) { + + return alloc_null (); + + } + + return CreateVulkanHandleValue (surface); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_create_vulkan_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + + Window* targetWindow = (Window*)window->ptr; + uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + + if (!surface) { + + return 0; + + } + + return HLCreateVulkanHandleValue (surface); + + } + + + value lime_vk_create_instance (value window, HxString applicationName) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = VK_NULL_HANDLE; + + if (!CreateManagedVulkanInstance (targetWindow, applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0, &instance)) { + + return alloc_null (); + + } + + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_instance) (HL_CFFIPointer* window, hl_vstring* applicationName) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = VK_NULL_HANDLE; + const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + + if (!CreateManagedVulkanInstance (targetWindow, applicationNameUTF8, &instance)) { + + return 0; + + } + + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_instance (value window, int instanceHigh, int instanceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); + if (vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_instance) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); + if (vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + void lime_vk_destroy_surface (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + if (!surface) return; + + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); + if (vkDestroySurfaceKHR) { + + vkDestroySurfaceKHR (instance, surface, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + if (!surface) return; + + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); + if (vkDestroySurfaceKHR) { + + vkDestroySurfaceKHR (instance, surface, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_physical_devices (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + + if (!targetWindow || !instance) { + + lastVKError = "Missing Vulkan window or instance"; + return alloc_null (); + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return alloc_null (); + + } + + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, + "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, + "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan instance functions"; + return alloc_null (); + + } + + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices failed"; + return alloc_null (); + + } + + value devices = alloc_array (deviceCount); + if (deviceCount == 0) { + + lastVKError.clear (); + return devices; + + } + + std::vector physicalDevices (deviceCount); + result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + return alloc_null (); + + } + + const int id_handle = val_id ("handle"); + const int id_name = val_id ("name"); + const int id_apiVersion = val_id ("apiVersion"); + const int id_driverVersion = val_id ("driverVersion"); + const int id_vendorID = val_id ("vendorID"); + const int id_deviceID = val_id ("deviceID"); + const int id_deviceType = val_id ("deviceType"); + const int id_queueFamilies = val_id ("queueFamilies"); + + const int id_index = val_id ("index"); + const int id_flags = val_id ("flags"); + const int id_queueCount = val_id ("queueCount"); + const int id_timestampValidBits = val_id ("timestampValidBits"); + const int id_supportsGraphics = val_id ("supportsGraphics"); + const int id_supportsCompute = val_id ("supportsCompute"); + const int id_supportsTransfer = val_id ("supportsTransfer"); + const int id_supportsPresent = val_id ("supportsPresent"); + + for (uint32_t i = 0; i < deviceCount; ++i) { + + VkPhysicalDeviceProperties properties; + memset (&properties, 0, sizeof (properties)); + vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); + std::vector queueFamilies (queueFamilyCount); + if (queueFamilyCount > 0) { + + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + + } + + value queueFamilyArray = alloc_array (queueFamilyCount); + + for (uint32_t q = 0; q < queueFamilyCount; ++q) { + + VkBool32 supportsPresent = VK_FALSE; + if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + + vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + + } + + value queueFamilyObject = alloc_empty_object (); + alloc_field (queueFamilyObject, id_index, alloc_int (q)); + alloc_field (queueFamilyObject, id_flags, alloc_int (queueFamilies[q].queueFlags)); + alloc_field (queueFamilyObject, id_queueCount, alloc_int (queueFamilies[q].queueCount)); + alloc_field (queueFamilyObject, id_timestampValidBits, alloc_int (queueFamilies[q].timestampValidBits)); + alloc_field (queueFamilyObject, id_supportsGraphics, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsCompute, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsTransfer, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsPresent, alloc_bool (supportsPresent != VK_FALSE)); + val_array_set_i (queueFamilyArray, q, queueFamilyObject); + + } + + value deviceObject = alloc_empty_object (); + alloc_field (deviceObject, id_handle, CreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); + alloc_field (deviceObject, id_name, alloc_string (properties.deviceName)); + alloc_field (deviceObject, id_apiVersion, alloc_int (properties.apiVersion)); + alloc_field (deviceObject, id_driverVersion, alloc_int (properties.driverVersion)); + alloc_field (deviceObject, id_vendorID, alloc_int (properties.vendorID)); + alloc_field (deviceObject, id_deviceID, alloc_int (properties.deviceID)); + alloc_field (deviceObject, id_deviceType, alloc_int (properties.deviceType)); + alloc_field (deviceObject, id_queueFamilies, queueFamilyArray); + val_array_set_i (devices, i, deviceObject); + + } + + lastVKError.clear (); + return devices; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_array (0); +#endif + + } + + + HL_PRIM hl_varray* HL_NAME(hl_vk_get_physical_devices) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + + if (!targetWindow || !instance) { + + lastVKError = "Missing Vulkan window or instance"; + return 0; + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return 0; + + } + + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, + "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, + "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan instance functions"; + return 0; + + } + + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices failed"; + return 0; + + } + + hl_varray* devices = (hl_varray*)hl_alloc_array (&hlt_dynobj, deviceCount); if (deviceCount == 0) { lastVKError.clear (); - return devices; + return devices; + + } + + std::vector physicalDevices (deviceCount); + result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + return 0; + + } + + vdynamic** deviceData = hl_aptr (devices, vdynamic*); + + const int id_handle = hl_hash_utf8 ("handle"); + const int id_name = hl_hash_utf8 ("name"); + const int id_apiVersion = hl_hash_utf8 ("apiVersion"); + const int id_driverVersion = hl_hash_utf8 ("driverVersion"); + const int id_vendorID = hl_hash_utf8 ("vendorID"); + const int id_deviceID = hl_hash_utf8 ("deviceID"); + const int id_deviceType = hl_hash_utf8 ("deviceType"); + const int id_queueFamilies = hl_hash_utf8 ("queueFamilies"); + + const int id_index = hl_hash_utf8 ("index"); + const int id_flags = hl_hash_utf8 ("flags"); + const int id_queueCount = hl_hash_utf8 ("queueCount"); + const int id_timestampValidBits = hl_hash_utf8 ("timestampValidBits"); + const int id_supportsGraphics = hl_hash_utf8 ("supportsGraphics"); + const int id_supportsCompute = hl_hash_utf8 ("supportsCompute"); + const int id_supportsTransfer = hl_hash_utf8 ("supportsTransfer"); + const int id_supportsPresent = hl_hash_utf8 ("supportsPresent"); + + for (uint32_t i = 0; i < deviceCount; ++i) { + + VkPhysicalDeviceProperties properties; + memset (&properties, 0, sizeof (properties)); + vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); + std::vector queueFamilies (queueFamilyCount); + if (queueFamilyCount > 0) { + + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + + } + + hl_varray* queueFamilyArray = (hl_varray*)hl_alloc_array (&hlt_dynobj, queueFamilyCount); + vdynamic** queueFamilyData = hl_aptr (queueFamilyArray, vdynamic*); + + for (uint32_t q = 0; q < queueFamilyCount; ++q) { + + VkBool32 supportsPresent = VK_FALSE; + if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + + vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + + } + + vdynamic* queueFamilyObject = (vdynamic*)hl_alloc_dynobj (); + *queueFamilyData++ = queueFamilyObject; + hl_dyn_seti (queueFamilyObject, id_index, &hlt_i32, q); + hl_dyn_seti (queueFamilyObject, id_flags, &hlt_i32, queueFamilies[q].queueFlags); + hl_dyn_seti (queueFamilyObject, id_queueCount, &hlt_i32, queueFamilies[q].queueCount); + hl_dyn_seti (queueFamilyObject, id_timestampValidBits, &hlt_i32, queueFamilies[q].timestampValidBits); + hl_dyn_seti (queueFamilyObject, id_supportsGraphics, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsCompute, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsTransfer, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsPresent, &hlt_bool, supportsPresent != VK_FALSE); + + } + + vdynamic* deviceObject = (vdynamic*)hl_alloc_dynobj (); + *deviceData++ = deviceObject; + hl_dyn_setp (deviceObject, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); + hl_dyn_setp (deviceObject, id_name, &hlt_bytes, hl_copy_bytes ((const vbyte*)properties.deviceName, (int)std::strlen (properties.deviceName) + 1)); + hl_dyn_seti (deviceObject, id_apiVersion, &hlt_i32, properties.apiVersion); + hl_dyn_seti (deviceObject, id_driverVersion, &hlt_i32, properties.driverVersion); + hl_dyn_seti (deviceObject, id_vendorID, &hlt_i32, properties.vendorID); + hl_dyn_seti (deviceObject, id_deviceID, &hlt_i32, properties.deviceID); + hl_dyn_seti (deviceObject, id_deviceType, &hlt_i32, properties.deviceType); + hl_dyn_setp (deviceObject, id_queueFamilies, &hlt_array, queueFamilyArray); + + } + + lastVKError.clear (); + return devices; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return (hl_varray*)hl_alloc_array (&hlt_dynobj, 0); +#endif + + } + + + value lime_vk_create_device (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int queueFamilyIndex, + value extensions) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + std::vector deviceExtensions = GetVulkanDeviceExtensions (extensions); + VkDevice device = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + + return alloc_null (); + + } + + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); + alloc_field (result, val_id ("queue"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); + alloc_field (result, val_id ("queueFamilyIndex"), alloc_int (queueFamilyIndex)); + return result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int queueFamilyIndex, hl_varray* extensions) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + std::vector deviceExtensions = GetHLVulkanDeviceExtensions (extensions); + VkDevice device = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + + return 0; + + } + + const int id_handle = hl_hash_utf8 ("handle"); + const int id_queue = hl_hash_utf8 ("queue"); + const int id_queueFamilyIndex = hl_hash_utf8 ("queueFamilyIndex"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); + hl_dyn_setp (result, id_queue, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); + hl_dyn_seti (result, id_queueFamilyIndex, &hlt_i32, queueFamilyIndex); + return result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_device (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + if (deviceHigh == 0 && deviceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) return; + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); + if (vkDestroyDevice) { + + vkDestroyDevice (device, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + if (deviceHigh == 0 && deviceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) return; + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); + if (vkDestroyDevice) { + + vkDestroyDevice (device, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_device_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); + if (!vkDeviceWaitIdle) { + + lastVKError = "Missing Vulkan device wait idle function"; + return false; + + } + + VkResult result = vkDeviceWaitIdle (device); + if (result != VK_SUCCESS) { + + lastVKError = "vkDeviceWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_device_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); + if (!vkDeviceWaitIdle) { + + lastVKError = "Missing Vulkan device wait idle function"; + return false; + + } + + VkResult result = vkDeviceWaitIdle (device); + if (result != VK_SUCCESS) { + + lastVKError = "vkDeviceWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_queue_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device || !queue) { + + lastVKError = "Missing Vulkan window, instance, device, or queue"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); + if (!vkQueueWaitIdle) { + + lastVKError = "Missing Vulkan queue wait idle function"; + return false; + + } + + VkResult result = vkQueueWaitIdle (queue); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_queue_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device || !queue) { + + lastVKError = "Missing Vulkan window, instance, device, or queue"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); + if (!vkQueueWaitIdle) { + + lastVKError = "Missing Vulkan queue wait idle function"; + return false; + + } + + VkResult result = vkQueueWaitIdle (queue); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueFamilyIndex, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateCommandPool"); + if (!vkCreateCommandPool) return alloc_null (); + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = flags; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool commandPool = VK_NULL_HANDLE; + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateCommandPool failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueFamilyIndex, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateCommandPool"); + if (!vkCreateCommandPool) return 0; + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = flags; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool commandPool = VK_NULL_HANDLE; + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateCommandPool failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow) { + +#ifdef LIME_VULKAN + if (commandPoolHigh == 0 && commandPoolLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyCommandPool"); + if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow) { + +#ifdef LIME_VULKAN + if (commandPoolHigh == 0 && commandPoolLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyCommandPool"); + if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_reset_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandPool"); + if (!vkResetCommandPool) return false; + + VkResult result = vkResetCommandPool (device, commandPool, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandPool"); + if (!vkResetCommandPool) return false; + + VkResult result = vkResetCommandPool (device, commandPool, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_allocate_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int level) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAllocateCommandBuffers"); + if (!vkAllocateCommandBuffers) return alloc_null (); + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = (VkCommandBufferLevel)level; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateCommandBuffers failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandPoolHigh, int commandPoolLow, int level) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAllocateCommandBuffers"); + if (!vkAllocateCommandBuffers) return 0; + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = (VkCommandBufferLevel)level; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateCommandBuffers failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_free_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + if (commandBufferHigh == 0 && commandBufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkFreeCommandBuffers"); + if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_free_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + if (commandBufferHigh == 0 && commandBufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkFreeCommandBuffers"); + if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_begin_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBeginCommandBuffer"); + if (!vkBeginCommandBuffer) return false; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = flags; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + lastVKError = "vkBeginCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_begin_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBeginCommandBuffer"); + if (!vkBeginCommandBuffer) return false; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = flags; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + lastVKError = "vkBeginCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_end_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkEndCommandBuffer"); + if (!vkEndCommandBuffer) return false; + + VkResult result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkEndCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_end_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkEndCommandBuffer"); + if (!vkEndCommandBuffer) return false; + + VkResult result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkEndCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_reset_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandBuffer"); + if (!vkResetCommandBuffer) return false; + + VkResult result = vkResetCommandBuffer (commandBuffer, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandBuffer"); + if (!vkResetCommandBuffer) return false; + + VkResult result = vkResetCommandBuffer (commandBuffer, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSemaphore"); + if (!vkCreateSemaphore) return alloc_null (); + + VkSemaphoreCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkSemaphore semaphore = VK_NULL_HANDLE; + VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSemaphore failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSemaphore"); + if (!vkCreateSemaphore) return 0; + + VkSemaphoreCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkSemaphore semaphore = VK_NULL_HANDLE; + VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSemaphore failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int semaphoreHigh, + int semaphoreLow) { + +#ifdef LIME_VULKAN + if (semaphoreHigh == 0 && semaphoreLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySemaphore"); + if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int semaphoreHigh, int semaphoreLow) { + +#ifdef LIME_VULKAN + if (semaphoreHigh == 0 && semaphoreLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySemaphore"); + if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); + if (!vkCreateFence) return alloc_null (); + + VkFenceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + createInfo.flags = flags; + + VkFence fence = VK_NULL_HANDLE; + VkResult result = vkCreateFence (device, &createInfo, 0, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFence failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); + if (!vkCreateFence) return 0; + + VkFenceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + createInfo.flags = flags; + + VkFence fence = VK_NULL_HANDLE; + VkResult result = vkCreateFence (device, &createInfo, 0, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFence failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + if (fenceHigh == 0 && fenceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); + if (vkDestroyFence) vkDestroyFence (device, fence, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow) { + +#ifdef LIME_VULKAN + if (fenceHigh == 0 && fenceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); + if (vkDestroyFence) vkDestroyFence (device, fence, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_wait_for_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow, + int timeoutHigh, int timeoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); + if (!vkWaitForFences) return false; + + VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); + if (result != VK_SUCCESS) { + + lastVKError = "vkWaitForFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_wait_for_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow, int timeoutHigh, int timeoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); + if (!vkWaitForFences) return false; + + VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); + if (result != VK_SUCCESS) { + + lastVKError = "vkWaitForFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_reset_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); + if (!vkResetFences) return false; + + VkResult result = vkResetFences (device, 1, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); + if (!vkResetFences) return false; + + VkResult result = vkResetFences (device, 1, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_queue_submit (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow, + int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueSubmit failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_queue_submit) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueSubmit failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_allocate_memory (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int deviceHigh, + int deviceLow, int sizeHigh, int sizeLow, int memoryTypeBits, int properties) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + uint64_t size = CombineVulkanHandle (sizeHigh, sizeLow); + uint32_t memoryTypeIndex = 0; + if (!FindManagedVulkanMemoryType (targetWindow, instance, physicalDevice, (uint32_t)memoryTypeBits, (VkMemoryPropertyFlags)properties, + &memoryTypeIndex)) { + + return alloc_null (); + + } + + PFN_vkAllocateMemory vkAllocateMemory = (PFN_vkAllocateMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateMemory"); + if (!vkAllocateMemory) return alloc_null (); + + VkMemoryAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = (VkDeviceSize)size; + allocateInfo.memoryTypeIndex = memoryTypeIndex; + + VkDeviceMemory memory = VK_NULL_HANDLE; + VkResult result = vkAllocateMemory (device, &allocateInfo, 0, &memory); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateMemory failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanMemoryValue (memory, memoryTypeIndex); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int deviceHigh, int deviceLow, int sizeHigh, int sizeLow, int memoryTypeBits, int properties) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + uint64_t size = CombineVulkanHandle (sizeHigh, sizeLow); + uint32_t memoryTypeIndex = 0; + if (!FindManagedVulkanMemoryType (targetWindow, instance, physicalDevice, (uint32_t)memoryTypeBits, (VkMemoryPropertyFlags)properties, + &memoryTypeIndex)) { + + return 0; + + } + + PFN_vkAllocateMemory vkAllocateMemory = (PFN_vkAllocateMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateMemory"); + if (!vkAllocateMemory) return 0; + + VkMemoryAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = (VkDeviceSize)size; + allocateInfo.memoryTypeIndex = memoryTypeIndex; + + VkDeviceMemory memory = VK_NULL_HANDLE; + VkResult result = vkAllocateMemory (device, &allocateInfo, 0, &memory); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateMemory failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanMemoryValue (memory, memoryTypeIndex); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_free_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + if (memoryHigh == 0 && memoryLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFreeMemory vkFreeMemory = (PFN_vkFreeMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFreeMemory"); + if (vkFreeMemory) { + + vkFreeMemory (device, memory, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_free_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + if (memoryHigh == 0 && memoryLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFreeMemory vkFreeMemory = (PFN_vkFreeMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFreeMemory"); + if (vkFreeMemory) { + + vkFreeMemory (device, memory, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_upload_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, value bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + Bytes data (bytes); + if (!memory || !data.b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.length) { + + lastVKError = "Invalid Vulkan memory upload range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (mappedData, data.b + byteOffset, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_upload_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !bytes || !bytes->b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid Vulkan memory upload range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (mappedData, bytes->b + byteOffset, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int sizeHigh, int sizeLow, int usage) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateBuffer vkCreateBuffer = (PFN_vkCreateBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateBuffer"); + if (!vkCreateBuffer) return alloc_null (); + + VkBufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.size = (VkDeviceSize)CombineVulkanHandle (sizeHigh, sizeLow); + createInfo.usage = (VkBufferUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkBuffer buffer = VK_NULL_HANDLE; + VkResult result = vkCreateBuffer (device, &createInfo, 0, &buffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateBuffer failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)buffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int sizeHigh, int sizeLow, int usage) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateBuffer vkCreateBuffer = (PFN_vkCreateBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateBuffer"); + if (!vkCreateBuffer) return 0; + + VkBufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.size = (VkDeviceSize)CombineVulkanHandle (sizeHigh, sizeLow); + createInfo.usage = (VkBufferUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkBuffer buffer = VK_NULL_HANDLE; + VkResult result = vkCreateBuffer (device, &createInfo, 0, &buffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateBuffer failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)buffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int bufferHigh, int bufferLow) { + +#ifdef LIME_VULKAN + if (bufferHigh == 0 && bufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkDestroyBuffer vkDestroyBuffer = (PFN_vkDestroyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyBuffer"); + if (vkDestroyBuffer) { + + vkDestroyBuffer (device, buffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int bufferHigh, int bufferLow) { + +#ifdef LIME_VULKAN + if (bufferHigh == 0 && bufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkDestroyBuffer vkDestroyBuffer = (PFN_vkDestroyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyBuffer"); + if (vkDestroyBuffer) { + + vkDestroyBuffer (device, buffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_buffer_memory_requirements (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int bufferHigh, + int bufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements = + (PFN_vkGetBufferMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetBufferMemoryRequirements"); + if (!vkGetBufferMemoryRequirements || !buffer) return alloc_null (); + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetBufferMemoryRequirements (device, buffer, &requirements); + lastVKError.clear (); + return CreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_get_buffer_memory_requirements) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, + int deviceHigh, int deviceLow, int bufferHigh, int bufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements = + (PFN_vkGetBufferMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetBufferMemoryRequirements"); + if (!vkGetBufferMemoryRequirements || !buffer) return 0; + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetBufferMemoryRequirements (device, buffer, &requirements); + lastVKError.clear (); + return HLCreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + bool lime_vk_bind_buffer_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int bufferHigh, int bufferLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindBufferMemory vkBindBufferMemory = (PFN_vkBindBufferMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindBufferMemory"); + if (!vkBindBufferMemory || !buffer || !memory) return false; + + VkResult result = vkBindBufferMemory (device, buffer, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindBufferMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_bind_buffer_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int bufferHigh, int bufferLow, int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindBufferMemory vkBindBufferMemory = (PFN_vkBindBufferMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindBufferMemory"); + if (!vkBindBufferMemory || !buffer || !memory) return false; + + VkResult result = vkBindBufferMemory (device, buffer, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindBufferMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int width, int height, int depth, + int mipLevels, int arrayLayers, int format, int imageType, int tiling, int usage, int samples) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateImage vkCreateImage = (PFN_vkCreateImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImage"); + if (!vkCreateImage) return alloc_null (); + + VkImageCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + createInfo.imageType = (VkImageType)imageType; + createInfo.format = (VkFormat)format; + createInfo.extent.width = (uint32_t)width; + createInfo.extent.height = (uint32_t)height; + createInfo.extent.depth = (uint32_t)depth; + createInfo.mipLevels = (uint32_t)mipLevels; + createInfo.arrayLayers = (uint32_t)arrayLayers; + createInfo.samples = (VkSampleCountFlagBits)samples; + createInfo.tiling = (VkImageTiling)tiling; + createInfo.usage = (VkImageUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if ((VkImageViewType)imageType == VK_IMAGE_VIEW_TYPE_CUBE || arrayLayers == 6) { + + createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + } + + VkImage image = VK_NULL_HANDLE; + VkResult result = vkCreateImage (device, &createInfo, 0, &image); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImage failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)image); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int width, int height, int depth, int mipLevels, int arrayLayers, int format, int imageType, int tiling, int usage, int samples) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateImage vkCreateImage = (PFN_vkCreateImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImage"); + if (!vkCreateImage) return 0; + + VkImageCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + createInfo.imageType = (VkImageType)imageType; + createInfo.format = (VkFormat)format; + createInfo.extent.width = (uint32_t)width; + createInfo.extent.height = (uint32_t)height; + createInfo.extent.depth = (uint32_t)depth; + createInfo.mipLevels = (uint32_t)mipLevels; + createInfo.arrayLayers = (uint32_t)arrayLayers; + createInfo.samples = (VkSampleCountFlagBits)samples; + createInfo.tiling = (VkImageTiling)tiling; + createInfo.usage = (VkImageUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if ((VkImageViewType)imageType == VK_IMAGE_VIEW_TYPE_CUBE || arrayLayers == 6) { + + createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + } + + VkImage image = VK_NULL_HANDLE; + VkResult result = vkCreateImage (device, &createInfo, 0, &image); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImage failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)image); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow) { + +#ifdef LIME_VULKAN + if (imageHigh == 0 && imageLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkDestroyImage vkDestroyImage = (PFN_vkDestroyImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyImage"); + if (vkDestroyImage) { + + vkDestroyImage (device, image, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageHigh, int imageLow) { + +#ifdef LIME_VULKAN + if (imageHigh == 0 && imageLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkDestroyImage vkDestroyImage = (PFN_vkDestroyImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyImage"); + if (vkDestroyImage) { + + vkDestroyImage (device, image, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_image_memory_requirements (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, + int imageLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = + (PFN_vkGetImageMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetImageMemoryRequirements"); + if (!vkGetImageMemoryRequirements || !image) return alloc_null (); + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetImageMemoryRequirements (device, image, &requirements); + lastVKError.clear (); + return CreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_get_image_memory_requirements) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int imageHigh, int imageLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = + (PFN_vkGetImageMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetImageMemoryRequirements"); + if (!vkGetImageMemoryRequirements || !image) return 0; + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetImageMemoryRequirements (device, image, &requirements); + lastVKError.clear (); + return HLCreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + bool lime_vk_bind_image_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindImageMemory vkBindImageMemory = (PFN_vkBindImageMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindImageMemory"); + if (!vkBindImageMemory || !image || !memory) return false; + + VkResult result = vkBindImageMemory (device, image, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindImageMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_bind_image_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageHigh, int imageLow, int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindImageMemory vkBindImageMemory = (PFN_vkBindImageMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindImageMemory"); + if (!vkBindImageMemory || !image || !memory) return false; + + VkResult result = vkBindImageMemory (device, image, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindImageMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_swapchain (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int deviceHigh, + int deviceLow, int surfaceHigh, int surfaceLow, int queueFamilyIndex, int width, int height, int presentMode, int oldSwapchainHigh, + int oldSwapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + VkSwapchainKHR oldSwapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (oldSwapchainHigh, oldSwapchainLow); + ManagedVulkanSwapchain swapchain; + + if (!CreateManagedVulkanSwapchain (targetWindow, instance, physicalDevice, device, surface, (uint32_t)queueFamilyIndex, width, height, + (VkPresentModeKHR)presentMode, oldSwapchain, &swapchain)) { + + return alloc_null (); + + } + + return CreateVulkanSwapchainValue (swapchain); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_swapchain) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int deviceHigh, int deviceLow, int surfaceHigh, int surfaceLow, int queueFamilyIndex, int width, int height, + int presentMode, int oldSwapchainHigh, int oldSwapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + VkSwapchainKHR oldSwapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (oldSwapchainHigh, oldSwapchainLow); + ManagedVulkanSwapchain swapchain; + + if (!CreateManagedVulkanSwapchain (targetWindow, instance, physicalDevice, device, surface, (uint32_t)queueFamilyIndex, width, height, + (VkPresentModeKHR)presentMode, oldSwapchain, &swapchain)) { + + return 0; + + } + + return HLCreateVulkanSwapchainValue (swapchain); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_swapchain (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int swapchainHigh, int swapchainLow) { + +#ifdef LIME_VULKAN + if (swapchainHigh == 0 && swapchainLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySwapchainKHR"); + if (vkDestroySwapchainKHR) { + + vkDestroySwapchainKHR (device, swapchain, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_swapchain) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int swapchainHigh, int swapchainLow) { + +#ifdef LIME_VULKAN + if (swapchainHigh == 0 && swapchainLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySwapchainKHR"); + if (vkDestroySwapchainKHR) { + + vkDestroySwapchainKHR (device, swapchain, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_swapchain_images (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int swapchainHigh, + int swapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkGetSwapchainImagesKHR"); + if (!vkGetSwapchainImagesKHR || !swapchain) return alloc_null (); + + uint32_t imageCount = 0; + VkResult result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, 0); + if (result != VK_SUCCESS) { + + lastVKError = "Failed to query Vulkan swapchain image count"; + return alloc_null (); + + } + + value images = alloc_array (imageCount); + if (imageCount == 0) { + + lastVKError.clear (); + return images; + + } + + std::vector swapchainImages (imageCount); + result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, swapchainImages.data ()); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetSwapchainImagesKHR failed"; + return alloc_null (); + + } + + for (uint32_t i = 0; i < imageCount; ++i) { + + val_array_set_i (images, i, CreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchainImages[i])); + + } + + lastVKError.clear (); + return images; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_array (0); +#endif + + } + + + HL_PRIM hl_varray* HL_NAME(hl_vk_get_swapchain_images) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int swapchainHigh, int swapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkGetSwapchainImagesKHR"); + if (!vkGetSwapchainImagesKHR || !swapchain) return 0; + + uint32_t imageCount = 0; + VkResult result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, 0); + if (result != VK_SUCCESS) { + + lastVKError = "Failed to query Vulkan swapchain image count"; + return 0; + + } + + hl_varray* images = (hl_varray*)hl_alloc_array (&hlt_dynobj, imageCount); + if (imageCount == 0) { + + lastVKError.clear (); + return images; + + } + + std::vector swapchainImages (imageCount); + result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, swapchainImages.data ()); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetSwapchainImagesKHR failed"; + return 0; + + } + + vdynamic** imageData = hl_aptr (images, vdynamic*); + for (uint32_t i = 0; i < imageCount; ++i) { + + *imageData++ = HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchainImages[i]); + + } + + lastVKError.clear (); + return images; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return (hl_varray*)hl_alloc_array (&hlt_dynobj, 0); +#endif + + } + + + value lime_vk_acquire_next_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int swapchainHigh, + int swapchainLow, int timeoutHigh, int timeoutLow, int semaphoreHigh, int semaphoreLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + if (!semaphore && !fence) { + + lastVKError = "Vulkan image acquisition requires a semaphore or fence"; + return CreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + } + + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAcquireNextImageKHR"); + if (!vkAcquireNextImageKHR || !swapchain) return CreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + uint32_t imageIndex = 0; + VkResult result = vkAcquireNextImageKHR (device, swapchain, timeout, semaphore, fence, &imageIndex); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + return CreateVulkanAcquireValue (result, (int)imageIndex); + + } + + lastVKError = "vkAcquireNextImageKHR failed"; + return CreateVulkanAcquireValue (result, -1); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_acquire_next_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int swapchainHigh, int swapchainLow, int timeoutHigh, int timeoutLow, int semaphoreHigh, int semaphoreLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + if (!semaphore && !fence) { + + lastVKError = "Vulkan image acquisition requires a semaphore or fence"; + return HLCreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + } + + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAcquireNextImageKHR"); + if (!vkAcquireNextImageKHR || !swapchain) return HLCreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + uint32_t imageIndex = 0; + VkResult result = vkAcquireNextImageKHR (device, swapchain, timeout, semaphore, fence, &imageIndex); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + return HLCreateVulkanAcquireValue (result, (int)imageIndex); + + } + + lastVKError = "vkAcquireNextImageKHR failed"; + return HLCreateVulkanAcquireValue (result, -1); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + int lime_vk_queue_present (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow, + int swapchainHigh, int swapchainLow, int imageIndex, int waitSemaphoreHigh, int waitSemaphoreLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (waitSemaphoreHigh, waitSemaphoreLow); + PFN_vkQueuePresentKHR vkQueuePresentKHR = (PFN_vkQueuePresentKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkQueuePresentKHR"); + if (!vkQueuePresentKHR || !queue || !swapchain) return VK_ERROR_INITIALIZATION_FAILED; + + VkPresentInfoKHR presentInfo; + memset (&presentInfo, 0, sizeof (presentInfo)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + presentInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + uint32_t swapchainImageIndex = (uint32_t)imageIndex; + presentInfo.pImageIndices = &swapchainImageIndex; + + VkResult result = vkQueuePresentKHR (queue, &presentInfo); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + + } else { + + lastVKError = "vkQueuePresentKHR failed"; + + } + + return (int)result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return -3; +#endif + + } + + + HL_PRIM int HL_NAME(hl_vk_queue_present) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int swapchainHigh, int swapchainLow, int imageIndex, int waitSemaphoreHigh, int waitSemaphoreLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (waitSemaphoreHigh, waitSemaphoreLow); + PFN_vkQueuePresentKHR vkQueuePresentKHR = (PFN_vkQueuePresentKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkQueuePresentKHR"); + if (!vkQueuePresentKHR || !queue || !swapchain) return VK_ERROR_INITIALIZATION_FAILED; + + VkPresentInfoKHR presentInfo; + memset (&presentInfo, 0, sizeof (presentInfo)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + presentInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + uint32_t swapchainImageIndex = (uint32_t)imageIndex; + presentInfo.pImageIndices = &swapchainImageIndex; + + VkResult result = vkQueuePresentKHR (queue, &presentInfo); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + + } else { + + lastVKError = "vkQueuePresentKHR failed"; + + } + + return (int)result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return -3; +#endif + + } + + + value lime_vk_create_image_view (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow, + int format, int aspectMask, int viewType) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return alloc_null (); + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return alloc_null (); + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_image_view) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageHigh, int imageLow, int format, int aspectMask, int viewType) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return 0; + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return 0; + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_image_view (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageViewHigh, + int imageViewLow) { + +#ifdef LIME_VULKAN + if (imageViewHigh == 0 && imageViewLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImageView imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + PFN_vkDestroyImageView vkDestroyImageView = (PFN_vkDestroyImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyImageView"); + if (vkDestroyImageView) { + + vkDestroyImageView (device, imageView, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_image_view) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageViewHigh, int imageViewLow) { + +#ifdef LIME_VULKAN + if (imageViewHigh == 0 && imageViewLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImageView imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + PFN_vkDestroyImageView vkDestroyImageView = (PFN_vkDestroyImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyImageView"); + if (vkDestroyImageView) { + + vkDestroyImageView (device, imageView, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_image_view_ex (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow, + int format, int aspectMask, int viewType, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return alloc_null (); + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return alloc_null (); + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = (uint32_t)baseMipLevel; + createInfo.subresourceRange.levelCount = (uint32_t)levelCount; + createInfo.subresourceRange.baseArrayLayer = (uint32_t)baseArrayLayer; + createInfo.subresourceRange.layerCount = (uint32_t)layerCount; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_image_view_ex) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int imageHigh, int imageLow, int format, int aspectMask, int viewType, int baseMipLevel, int levelCount, + int baseArrayLayer, int layerCount) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return 0; + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return 0; + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = (uint32_t)baseMipLevel; + createInfo.subresourceRange.levelCount = (uint32_t)levelCount; + createInfo.subresourceRange.baseArrayLayer = (uint32_t)baseArrayLayer; + createInfo.subresourceRange.layerCount = (uint32_t)layerCount; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + value lime_vk_create_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int colorFormat, + int depthStencilFormat, int samples, int colorLoadOp, int colorStoreOp, int colorInitialLayout, int colorFinalLayout, int depthLoadOp, + int depthStoreOp, int depthFinalLayout) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateRenderPass vkCreateRenderPass = (PFN_vkCreateRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateRenderPass"); + if (!vkCreateRenderPass) return alloc_null (); + + std::vector attachments; + VkAttachmentDescription colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.format = (VkFormat)colorFormat; + colorAttachment.samples = (VkSampleCountFlagBits)samples; + colorAttachment.loadOp = (VkAttachmentLoadOp)colorLoadOp; + colorAttachment.storeOp = (VkAttachmentStoreOp)colorStoreOp; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = (VkImageLayout)colorInitialLayout; + colorAttachment.finalLayout = (VkImageLayout)colorFinalLayout; + attachments.push_back (colorAttachment); + + VkAttachmentReference colorReference; + memset (&colorReference, 0, sizeof (colorReference)); + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference; + memset (&depthReference, 0, sizeof (depthReference)); + bool hasDepth = depthStencilFormat != VK_FORMAT_UNDEFINED; + if (hasDepth) { + + VkAttachmentDescription depthAttachment; + memset (&depthAttachment, 0, sizeof (depthAttachment)); + depthAttachment.format = (VkFormat)depthStencilFormat; + depthAttachment.samples = (VkSampleCountFlagBits)samples; + depthAttachment.loadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.storeOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.stencilLoadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.stencilStoreOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthAttachment.finalLayout = (VkImageLayout)depthFinalLayout; + attachments.push_back (depthAttachment); + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + } + + VkSubpassDescription subpass; + memset (&subpass, 0, sizeof (subpass)); + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pDepthStencilAttachment = hasDepth ? &depthReference : 0; + + VkSubpassDependency dependency; + memset (&dependency, 0, sizeof (dependency)); + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + createInfo.attachmentCount = (uint32_t)attachments.size (); + createInfo.pAttachments = attachments.data (); + createInfo.subpassCount = 1; + createInfo.pSubpasses = &subpass; + createInfo.dependencyCount = 1; + createInfo.pDependencies = &dependency; + + VkRenderPass renderPass = VK_NULL_HANDLE; + VkResult result = vkCreateRenderPass (device, &createInfo, 0, &renderPass); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateRenderPass failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)renderPass); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int colorFormat, int depthStencilFormat, int samples, int colorLoadOp, int colorStoreOp, int colorInitialLayout, + int colorFinalLayout, int depthLoadOp, int depthStoreOp, int depthFinalLayout) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateRenderPass vkCreateRenderPass = (PFN_vkCreateRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateRenderPass"); + if (!vkCreateRenderPass) return 0; + + std::vector attachments; + VkAttachmentDescription colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.format = (VkFormat)colorFormat; + colorAttachment.samples = (VkSampleCountFlagBits)samples; + colorAttachment.loadOp = (VkAttachmentLoadOp)colorLoadOp; + colorAttachment.storeOp = (VkAttachmentStoreOp)colorStoreOp; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = (VkImageLayout)colorInitialLayout; + colorAttachment.finalLayout = (VkImageLayout)colorFinalLayout; + attachments.push_back (colorAttachment); + + VkAttachmentReference colorReference; + memset (&colorReference, 0, sizeof (colorReference)); + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference; + memset (&depthReference, 0, sizeof (depthReference)); + bool hasDepth = depthStencilFormat != VK_FORMAT_UNDEFINED; + if (hasDepth) { + + VkAttachmentDescription depthAttachment; + memset (&depthAttachment, 0, sizeof (depthAttachment)); + depthAttachment.format = (VkFormat)depthStencilFormat; + depthAttachment.samples = (VkSampleCountFlagBits)samples; + depthAttachment.loadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.storeOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.stencilLoadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.stencilStoreOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthAttachment.finalLayout = (VkImageLayout)depthFinalLayout; + attachments.push_back (depthAttachment); + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + } + + VkSubpassDescription subpass; + memset (&subpass, 0, sizeof (subpass)); + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pDepthStencilAttachment = hasDepth ? &depthReference : 0; + + VkSubpassDependency dependency; + memset (&dependency, 0, sizeof (dependency)); + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + createInfo.attachmentCount = (uint32_t)attachments.size (); + createInfo.pAttachments = attachments.data (); + createInfo.subpassCount = 1; + createInfo.pSubpasses = &subpass; + createInfo.dependencyCount = 1; + createInfo.pDependencies = &dependency; + + VkRenderPass renderPass = VK_NULL_HANDLE; + VkResult result = vkCreateRenderPass (device, &createInfo, 0, &renderPass); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateRenderPass failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)renderPass); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + value lime_vk_get_last_error () { + + return alloc_string (lastVKError.c_str ()); + + } + + + void lime_vk_destroy_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow) { + +#ifdef LIME_VULKAN + if (renderPassHigh == 0 && renderPassLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + PFN_vkDestroyRenderPass vkDestroyRenderPass = (PFN_vkDestroyRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyRenderPass"); + if (vkDestroyRenderPass) { + + vkDestroyRenderPass (device, renderPass, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow) { + +#ifdef LIME_VULKAN + if (renderPassHigh == 0 && renderPassLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + PFN_vkDestroyRenderPass vkDestroyRenderPass = (PFN_vkDestroyRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyRenderPass"); + if (vkDestroyRenderPass) { + + vkDestroyRenderPass (device, renderPass, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_framebuffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow, value attachments, int width, int height, int layers) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + std::vector packed = GetVulkanIntVector (attachments); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) { + + lastVKError = "Invalid Vulkan framebuffer attachment list"; + return alloc_null (); + + } + + std::vector imageViews; + imageViews.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { + + imageViews.push_back ((VkImageView)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); + + } + + PFN_vkCreateFramebuffer vkCreateFramebuffer = (PFN_vkCreateFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateFramebuffer"); + if (!vkCreateFramebuffer || !renderPass) return alloc_null (); + + VkFramebufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = (uint32_t)imageViews.size (); + createInfo.pAttachments = imageViews.data (); + createInfo.width = (uint32_t)width; + createInfo.height = (uint32_t)height; + createInfo.layers = (uint32_t)layers; + + VkFramebuffer framebuffer = VK_NULL_HANDLE; + VkResult result = vkCreateFramebuffer (device, &createInfo, 0, &framebuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFramebuffer failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)framebuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_framebuffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow, hl_varray* attachments, int width, int height, int layers) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + std::vector packed = GetHLVulkanIntVector (attachments); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) { + + lastVKError = "Invalid Vulkan framebuffer attachment list"; + return 0; + + } + + std::vector imageViews; + imageViews.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { + + imageViews.push_back ((VkImageView)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); + + } + + PFN_vkCreateFramebuffer vkCreateFramebuffer = (PFN_vkCreateFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateFramebuffer"); + if (!vkCreateFramebuffer || !renderPass) return 0; + + VkFramebufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = (uint32_t)imageViews.size (); + createInfo.pAttachments = imageViews.data (); + createInfo.width = (uint32_t)width; + createInfo.height = (uint32_t)height; + createInfo.layers = (uint32_t)layers; + + VkFramebuffer framebuffer = VK_NULL_HANDLE; + VkResult result = vkCreateFramebuffer (device, &createInfo, 0, &framebuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFramebuffer failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)framebuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_framebuffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int framebufferHigh, + int framebufferLow) { + +#ifdef LIME_VULKAN + if (framebufferHigh == 0 && framebufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFramebuffer framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + PFN_vkDestroyFramebuffer vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyFramebuffer"); + if (vkDestroyFramebuffer) { + + vkDestroyFramebuffer (device, framebuffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_framebuffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int framebufferHigh, int framebufferLow) { + +#ifdef LIME_VULKAN + if (framebufferHigh == 0 && framebufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFramebuffer framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + PFN_vkDestroyFramebuffer vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyFramebuffer"); + if (vkDestroyFramebuffer) { + + vkDestroyFramebuffer (device, framebuffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_shader_module (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bytes, int byteOffset, + int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + Bytes data (bytes); + if (!data.b || byteOffset < 0 || byteLength <= 0 || byteOffset + byteLength > data.length || (byteLength % 4) != 0) { + + lastVKError = "Invalid Vulkan shader module bytes"; + return alloc_null (); + + } + + PFN_vkCreateShaderModule vkCreateShaderModule = (PFN_vkCreateShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateShaderModule"); + if (!vkCreateShaderModule) return alloc_null (); + + VkShaderModuleCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = (size_t)byteLength; + createInfo.pCode = (const uint32_t*)(data.b + byteOffset); + + VkShaderModule shaderModule = VK_NULL_HANDLE; + VkResult result = vkCreateShaderModule (device, &createInfo, 0, &shaderModule); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateShaderModule failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)shaderModule); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_shader_module) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + if (!bytes || !bytes->b || byteOffset < 0 || byteLength <= 0 || byteOffset + byteLength > bytes->length || (byteLength % 4) != 0) { + + lastVKError = "Invalid Vulkan shader module bytes"; + return 0; + + } + + PFN_vkCreateShaderModule vkCreateShaderModule = (PFN_vkCreateShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateShaderModule"); + if (!vkCreateShaderModule) return 0; + + VkShaderModuleCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = (size_t)byteLength; + createInfo.pCode = (const uint32_t*)(bytes->b + byteOffset); + + VkShaderModule shaderModule = VK_NULL_HANDLE; + VkResult result = vkCreateShaderModule (device, &createInfo, 0, &shaderModule); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateShaderModule failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)shaderModule); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_shader_module (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int shaderModuleHigh, + int shaderModuleLow) { + +#ifdef LIME_VULKAN + if (shaderModuleHigh == 0 && shaderModuleLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkShaderModule shaderModule = (VkShaderModule)(uintptr_t)CombineVulkanHandle (shaderModuleHigh, shaderModuleLow); + PFN_vkDestroyShaderModule vkDestroyShaderModule = (PFN_vkDestroyShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyShaderModule"); + if (vkDestroyShaderModule) { + + vkDestroyShaderModule (device, shaderModule, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_shader_module) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int shaderModuleHigh, int shaderModuleLow) { + +#ifdef LIME_VULKAN + if (shaderModuleHigh == 0 && shaderModuleLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkShaderModule shaderModule = (VkShaderModule)(uintptr_t)CombineVulkanHandle (shaderModuleHigh, shaderModuleLow); + PFN_vkDestroyShaderModule vkDestroyShaderModule = (PFN_vkDestroyShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyShaderModule"); + if (vkDestroyShaderModule) { + + vkDestroyShaderModule (device, shaderModule, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_sampler (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int filter, int addressMode, + int mipmapMode, bool anisotropyEnable, double maxAnisotropy, int compareOp, double minLod, double maxLod) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSampler vkCreateSampler = (PFN_vkCreateSampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateSampler"); + if (!vkCreateSampler) return alloc_null (); + + VkSamplerCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + createInfo.magFilter = (VkFilter)filter; + createInfo.minFilter = (VkFilter)filter; + createInfo.mipmapMode = (VkSamplerMipmapMode)mipmapMode; + createInfo.addressModeU = (VkSamplerAddressMode)addressMode; + createInfo.addressModeV = (VkSamplerAddressMode)addressMode; + createInfo.addressModeW = (VkSamplerAddressMode)addressMode; + createInfo.anisotropyEnable = anisotropyEnable ? VK_TRUE : VK_FALSE; + createInfo.maxAnisotropy = (float)maxAnisotropy; + createInfo.compareEnable = compareOp >= 0 ? VK_TRUE : VK_FALSE; + createInfo.compareOp = compareOp >= 0 ? (VkCompareOp)compareOp : VK_COMPARE_OP_ALWAYS; + createInfo.minLod = (float)minLod; + createInfo.maxLod = (float)maxLod; + createInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + + VkSampler sampler = VK_NULL_HANDLE; + VkResult result = vkCreateSampler (device, &createInfo, 0, &sampler); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSampler failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)sampler); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_sampler) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int filter, int addressMode, int mipmapMode, bool anisotropyEnable, double maxAnisotropy, int compareOp, double minLod, double maxLod) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSampler vkCreateSampler = (PFN_vkCreateSampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateSampler"); + if (!vkCreateSampler) return 0; + + VkSamplerCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + createInfo.magFilter = (VkFilter)filter; + createInfo.minFilter = (VkFilter)filter; + createInfo.mipmapMode = (VkSamplerMipmapMode)mipmapMode; + createInfo.addressModeU = (VkSamplerAddressMode)addressMode; + createInfo.addressModeV = (VkSamplerAddressMode)addressMode; + createInfo.addressModeW = (VkSamplerAddressMode)addressMode; + createInfo.anisotropyEnable = anisotropyEnable ? VK_TRUE : VK_FALSE; + createInfo.maxAnisotropy = (float)maxAnisotropy; + createInfo.compareEnable = compareOp >= 0 ? VK_TRUE : VK_FALSE; + createInfo.compareOp = compareOp >= 0 ? (VkCompareOp)compareOp : VK_COMPARE_OP_ALWAYS; + createInfo.minLod = (float)minLod; + createInfo.maxLod = (float)maxLod; + createInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + + VkSampler sampler = VK_NULL_HANDLE; + VkResult result = vkCreateSampler (device, &createInfo, 0, &sampler); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSampler failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)sampler); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_sampler (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int samplerHigh, int samplerLow) { + +#ifdef LIME_VULKAN + if (samplerHigh == 0 && samplerLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSampler sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + PFN_vkDestroySampler vkDestroySampler = (PFN_vkDestroySampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroySampler"); + if (vkDestroySampler) { + + vkDestroySampler (device, sampler, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_sampler) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int samplerHigh, int samplerLow) { + +#ifdef LIME_VULKAN + if (samplerHigh == 0 && samplerLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSampler sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + PFN_vkDestroySampler vkDestroySampler = (PFN_vkDestroySampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroySampler"); + if (vkDestroySampler) { + + vkDestroySampler (device, sampler, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_descriptor_set_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bindings) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetVulkanIntVector (bindings); + if (packed.size () < 2 || packed.size () < (size_t)(2 + packed[1] * 4)) return alloc_null (); + + std::vector nativeBindings; + nativeBindings.reserve ((size_t)packed[1]); + for (int i = 0; i < packed[1]; ++i) { + + int base = 2 + i * 4; + VkDescriptorSetLayoutBinding binding; + memset (&binding, 0, sizeof (binding)); + binding.binding = (uint32_t)packed[base]; + binding.descriptorType = (VkDescriptorType)packed[base + 1]; + binding.descriptorCount = (uint32_t)packed[base + 2]; + binding.stageFlags = (VkShaderStageFlags)packed[base + 3]; + nativeBindings.push_back (binding); + + } + + PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = + (PFN_vkCreateDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorSetLayout"); + if (!vkCreateDescriptorSetLayout) return alloc_null (); + + VkDescriptorSetLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + createInfo.flags = (VkDescriptorSetLayoutCreateFlags)packed[0]; + createInfo.bindingCount = (uint32_t)nativeBindings.size (); + createInfo.pBindings = nativeBindings.empty () ? 0 : nativeBindings.data (); + + VkDescriptorSetLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorSetLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateDescriptorSetLayout failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_descriptor_set_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* bindings) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetHLVulkanIntVector (bindings); + if (packed.size () < 2 || packed.size () < (size_t)(2 + packed[1] * 4)) return 0; + + std::vector nativeBindings; + nativeBindings.reserve ((size_t)packed[1]); + for (int i = 0; i < packed[1]; ++i) { + + int base = 2 + i * 4; + VkDescriptorSetLayoutBinding binding; + memset (&binding, 0, sizeof (binding)); + binding.binding = (uint32_t)packed[base]; + binding.descriptorType = (VkDescriptorType)packed[base + 1]; + binding.descriptorCount = (uint32_t)packed[base + 2]; + binding.stageFlags = (VkShaderStageFlags)packed[base + 3]; + nativeBindings.push_back (binding); + + } + + PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = + (PFN_vkCreateDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorSetLayout"); + if (!vkCreateDescriptorSetLayout) return 0; + + VkDescriptorSetLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + createInfo.flags = (VkDescriptorSetLayoutCreateFlags)packed[0]; + createInfo.bindingCount = (uint32_t)nativeBindings.size (); + createInfo.pBindings = nativeBindings.empty () ? 0 : nativeBindings.data (); + + VkDescriptorSetLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorSetLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateDescriptorSetLayout failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_descriptor_set_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int layoutHigh, + int layoutLow) { + +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = + (PFN_vkDestroyDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorSetLayout"); + if (vkDestroyDescriptorSetLayout) { + + vkDestroyDescriptorSetLayout (device, layout, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_descriptor_set_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int layoutHigh, int layoutLow) { + +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = + (PFN_vkDestroyDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorSetLayout"); + if (vkDestroyDescriptorSetLayout) { + + vkDestroyDescriptorSetLayout (device, layout, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_descriptor_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value poolSizes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetVulkanIntVector (poolSizes); + if (packed.size () < 3 || packed.size () < (size_t)(3 + packed[2] * 2)) return alloc_null (); + + std::vector nativeSizes; + nativeSizes.reserve ((size_t)packed[2]); + for (int i = 0; i < packed[2]; ++i) { + + int base = 3 + i * 2; + VkDescriptorPoolSize size; + size.type = (VkDescriptorType)packed[base]; + size.descriptorCount = (uint32_t)packed[base + 1]; + nativeSizes.push_back (size); + + } + + PFN_vkCreateDescriptorPool vkCreateDescriptorPool = + (PFN_vkCreateDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorPool"); + if (!vkCreateDescriptorPool) return alloc_null (); + + VkDescriptorPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + createInfo.flags = (VkDescriptorPoolCreateFlags)packed[0]; + createInfo.maxSets = (uint32_t)packed[1]; + createInfo.poolSizeCount = (uint32_t)nativeSizes.size (); + createInfo.pPoolSizes = nativeSizes.empty () ? 0 : nativeSizes.data (); + + VkDescriptorPool pool = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorPool (device, &createInfo, 0, &pool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateDescriptorPool failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)pool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_descriptor_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* poolSizes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetHLVulkanIntVector (poolSizes); + if (packed.size () < 3 || packed.size () < (size_t)(3 + packed[2] * 2)) return 0; + + std::vector nativeSizes; + nativeSizes.reserve ((size_t)packed[2]); + for (int i = 0; i < packed[2]; ++i) { + + int base = 3 + i * 2; + VkDescriptorPoolSize size; + size.type = (VkDescriptorType)packed[base]; + size.descriptorCount = (uint32_t)packed[base + 1]; + nativeSizes.push_back (size); + + } + + PFN_vkCreateDescriptorPool vkCreateDescriptorPool = + (PFN_vkCreateDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorPool"); + if (!vkCreateDescriptorPool) return 0; + + VkDescriptorPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + createInfo.flags = (VkDescriptorPoolCreateFlags)packed[0]; + createInfo.maxSets = (uint32_t)packed[1]; + createInfo.poolSizeCount = (uint32_t)nativeSizes.size (); + createInfo.pPoolSizes = nativeSizes.empty () ? 0 : nativeSizes.data (); + + VkDescriptorPool pool = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorPool (device, &createInfo, 0, &pool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateDescriptorPool failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)pool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + HL_PRIM vbyte* HL_NAME(hl_vk_get_last_error) () { + + return hl_copy_bytes ((const vbyte*)lastVKError.c_str (), (int)lastVKError.size () + 1); + + } + + + void lime_vk_destroy_descriptor_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, int poolLow) { + +#ifdef LIME_VULKAN + if (poolHigh == 0 && poolLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = + (PFN_vkDestroyDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorPool"); + if (vkDestroyDescriptorPool) { + + vkDestroyDescriptorPool (device, pool, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_descriptor_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int poolHigh, int poolLow) { + +#ifdef LIME_VULKAN + if (poolHigh == 0 && poolLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = + (PFN_vkDestroyDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorPool"); + if (vkDestroyDescriptorPool) { + + vkDestroyDescriptorPool (device, pool, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_allocate_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, + int poolLow, int layoutHigh, int layoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = + (PFN_vkAllocateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateDescriptorSets"); + if (!vkAllocateDescriptorSets || !pool || !layout) return alloc_null (); + + VkDescriptorSetAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocateInfo.descriptorPool = pool; + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &layout; + + VkDescriptorSet descriptorSet = VK_NULL_HANDLE; + VkResult result = vkAllocateDescriptorSets (device, &allocateInfo, &descriptorSet); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateDescriptorSets failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)descriptorSet); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_descriptor_set) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int poolHigh, int poolLow, int layoutHigh, int layoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = + (PFN_vkAllocateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateDescriptorSets"); + if (!vkAllocateDescriptorSets || !pool || !layout) return 0; + + VkDescriptorSetAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocateInfo.descriptorPool = pool; + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &layout; + + VkDescriptorSet descriptorSet = VK_NULL_HANDLE; + VkResult result = vkAllocateDescriptorSets (device, &allocateInfo, &descriptorSet); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateDescriptorSets failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)descriptorSet); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + bool lime_vk_update_descriptor_set_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int setHigh, + int setLow, int binding, int descriptorType, int imageViewHigh, int imageViewLow, int samplerHigh, int samplerLow, int imageLayout) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorImageInfo imageInfo; + memset (&imageInfo, 0, sizeof (imageInfo)); + imageInfo.sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + imageInfo.imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + imageInfo.imageLayout = (VkImageLayout)imageLayout; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pImageInfo = &imageInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_set_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int setHigh, int setLow, int binding, int descriptorType, int imageViewHigh, int imageViewLow, int samplerHigh, + int samplerLow, int imageLayout) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorImageInfo imageInfo; + memset (&imageInfo, 0, sizeof (imageInfo)); + imageInfo.sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + imageInfo.imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + imageInfo.imageLayout = (VkImageLayout)imageLayout; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pImageInfo = &imageInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + +#ifdef LIME_VULKAN + value lime_vulkan_renderer_create (value window, HxString applicationName) { + + Window* targetWindow = (Window*)val_data (window); + VulkanRenderer* renderer = new VulkanRenderer (targetWindow); + + if (!renderer->Create (applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0)) { + + lastVulkanRendererError = renderer->GetLastError (); + delete renderer; + return alloc_null (); + + } + + lastVulkanRendererError.clear (); + return CFFIPointer (renderer); + + } + + + bool lime_vk_update_descriptor_set_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int setHigh, + int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorBufferInfo bufferInfo; + memset (&bufferInfo, 0, sizeof (bufferInfo)); + bufferInfo.buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + bufferInfo.offset = (VkDeviceSize)(uint32_t)offset; + bufferInfo.range = range > 0 ? (VkDeviceSize)(uint32_t)range : VK_WHOLE_SIZE; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pBufferInfo = &bufferInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_set_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int setHigh, int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorBufferInfo bufferInfo; + memset (&bufferInfo, 0, sizeof (bufferInfo)); + bufferInfo.buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + bufferInfo.offset = (VkDeviceSize)(uint32_t)offset; + bufferInfo.range = range > 0 ? (VkDeviceSize)(uint32_t)range : VK_WHOLE_SIZE; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pBufferInfo = &bufferInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value setLayouts, + int pushConstantStages, int pushConstantSize) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetVulkanIntVector (setLayouts); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) return alloc_null (); + + std::vector layouts; + layouts.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { + + layouts.push_back ((VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); + + } + + VkPushConstantRange pushRange; + memset (&pushRange, 0, sizeof (pushRange)); + pushRange.stageFlags = (VkShaderStageFlags)pushConstantStages; + pushRange.offset = 0; + pushRange.size = (uint32_t)pushConstantSize; + + PFN_vkCreatePipelineLayout vkCreatePipelineLayout = + (PFN_vkCreatePipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineLayout"); + if (!vkCreatePipelineLayout) return alloc_null (); + + VkPipelineLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + createInfo.setLayoutCount = (uint32_t)layouts.size (); + createInfo.pSetLayouts = layouts.empty () ? 0 : layouts.data (); + createInfo.pushConstantRangeCount = pushConstantSize > 0 ? 1 : 0; + createInfo.pPushConstantRanges = pushConstantSize > 0 ? &pushRange : 0; + + VkPipelineLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreatePipelineLayout failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* setLayouts, int pushConstantStages, int pushConstantSize) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetHLVulkanIntVector (setLayouts); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) return 0; + + std::vector layouts; + layouts.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { + + layouts.push_back ((VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); + + } + + VkPushConstantRange pushRange; + memset (&pushRange, 0, sizeof (pushRange)); + pushRange.stageFlags = (VkShaderStageFlags)pushConstantStages; + pushRange.offset = 0; + pushRange.size = (uint32_t)pushConstantSize; + + PFN_vkCreatePipelineLayout vkCreatePipelineLayout = + (PFN_vkCreatePipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineLayout"); + if (!vkCreatePipelineLayout) return 0; + + VkPipelineLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + createInfo.setLayoutCount = (uint32_t)layouts.size (); + createInfo.pSetLayouts = layouts.empty () ? 0 : layouts.data (); + createInfo.pushConstantRangeCount = pushConstantSize > 0 ? 1 : 0; + createInfo.pPushConstantRanges = pushConstantSize > 0 ? &pushRange : 0; + + VkPipelineLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreatePipelineLayout failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_vulkan_renderer_create) (HL_CFFIPointer* window, hl_vstring* applicationName) { + + Window* targetWindow = (Window*)window->ptr; + VulkanRenderer* renderer = new VulkanRenderer (targetWindow); + const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + + if (!renderer->Create (applicationNameUTF8)) { + + lastVulkanRendererError = renderer->GetLastError (); + delete renderer; + return 0; + + } + + lastVulkanRendererError.clear (); + return HLCFFIPointer (renderer); + + } + + + void lime_vk_destroy_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int layoutHigh, + int layoutLow) { + +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = + (PFN_vkDestroyPipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineLayout"); + if (vkDestroyPipelineLayout) { + + vkDestroyPipelineLayout (device, layout, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - std::vector physicalDevices (deviceCount); - result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int layoutHigh, int layoutLow) { + +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = + (PFN_vkDestroyPipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineLayout"); + if (vkDestroyPipelineLayout) { + + vkDestroyPipelineLayout (device, layout, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreatePipelineCache vkCreatePipelineCache = + (PFN_vkCreatePipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineCache"); + if (!vkCreatePipelineCache) return alloc_null (); + + VkPipelineCacheCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + + VkPipelineCache cache = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineCache (device, &createInfo, 0, &cache); if (result != VK_SUCCESS) { - lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + lastVKError = "vkCreatePipelineCache failed"; return alloc_null (); } - const int id_handle = val_id ("handle"); - const int id_name = val_id ("name"); - const int id_apiVersion = val_id ("apiVersion"); - const int id_driverVersion = val_id ("driverVersion"); - const int id_vendorID = val_id ("vendorID"); - const int id_deviceID = val_id ("deviceID"); - const int id_deviceType = val_id ("deviceType"); - const int id_queueFamilies = val_id ("queueFamilies"); + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)cache); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif - const int id_index = val_id ("index"); - const int id_flags = val_id ("flags"); - const int id_queueCount = val_id ("queueCount"); - const int id_timestampValidBits = val_id ("timestampValidBits"); - const int id_supportsGraphics = val_id ("supportsGraphics"); - const int id_supportsCompute = val_id ("supportsCompute"); - const int id_supportsTransfer = val_id ("supportsTransfer"); - const int id_supportsPresent = val_id ("supportsPresent"); + } - for (uint32_t i = 0; i < deviceCount; ++i) { - VkPhysicalDeviceProperties properties; - memset (&properties, 0, sizeof (properties)); - vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow) { - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); - std::vector queueFamilies (queueFamilyCount); - if (queueFamilyCount > 0) { +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreatePipelineCache vkCreatePipelineCache = + (PFN_vkCreatePipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineCache"); + if (!vkCreatePipelineCache) return 0; - vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + VkPipelineCacheCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - } + VkPipelineCache cache = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineCache (device, &createInfo, 0, &cache); + if (result != VK_SUCCESS) { - value queueFamilyArray = alloc_array (queueFamilyCount); + lastVKError = "vkCreatePipelineCache failed"; + return 0; - for (uint32_t q = 0; q < queueFamilyCount; ++q) { + } - VkBool32 supportsPresent = VK_FALSE; - if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)cache); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif - vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + } - } - value queueFamilyObject = alloc_empty_object (); - alloc_field (queueFamilyObject, id_index, alloc_int (q)); - alloc_field (queueFamilyObject, id_flags, alloc_int (queueFamilies[q].queueFlags)); - alloc_field (queueFamilyObject, id_queueCount, alloc_int (queueFamilies[q].queueCount)); - alloc_field (queueFamilyObject, id_timestampValidBits, alloc_int (queueFamilies[q].timestampValidBits)); - alloc_field (queueFamilyObject, id_supportsGraphics, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)); - alloc_field (queueFamilyObject, id_supportsCompute, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)); - alloc_field (queueFamilyObject, id_supportsTransfer, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)); - alloc_field (queueFamilyObject, id_supportsPresent, alloc_bool (supportsPresent != VK_FALSE)); - val_array_set_i (queueFamilyArray, q, queueFamilyObject); + void lime_vk_destroy_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow) { - } +#ifdef LIME_VULKAN + if (cacheHigh == 0 && cacheLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkDestroyPipelineCache vkDestroyPipelineCache = + (PFN_vkDestroyPipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineCache"); + if (vkDestroyPipelineCache) { - value deviceObject = alloc_empty_object (); - alloc_field (deviceObject, id_handle, CreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); - alloc_field (deviceObject, id_name, alloc_string (properties.deviceName)); - alloc_field (deviceObject, id_apiVersion, alloc_int (properties.apiVersion)); - alloc_field (deviceObject, id_driverVersion, alloc_int (properties.driverVersion)); - alloc_field (deviceObject, id_vendorID, alloc_int (properties.vendorID)); - alloc_field (deviceObject, id_deviceID, alloc_int (properties.deviceID)); - alloc_field (deviceObject, id_deviceType, alloc_int (properties.deviceType)); - alloc_field (deviceObject, id_queueFamilies, queueFamilyArray); - val_array_set_i (devices, i, deviceObject); + vkDestroyPipelineCache (device, cache, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int cacheHigh, int cacheLow) { + +#ifdef LIME_VULKAN + if (cacheHigh == 0 && cacheLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkDestroyPipelineCache vkDestroyPipelineCache = + (PFN_vkDestroyPipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineCache"); + if (vkDestroyPipelineCache) { + + vkDestroyPipelineCache (device, cache, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + void lime_vulkan_renderer_destroy (value handle) { + + if (val_is_null (handle)) return; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + delete renderer; + + } + + +#ifdef LIME_VULKAN + static VkPipeline CreateManagedVulkanGraphicsPipeline (Window* targetWindow, VkInstance instance, VkDevice device, VkRenderPass renderPass, + VkPipelineLayout layout, VkShaderModule vertexShader, VkShaderModule fragmentShader, const std::vector& state) { + + if (state.size () < 19 || !renderPass || !layout || !vertexShader || !fragmentShader) { + + lastVKError = "Invalid Vulkan graphics pipeline state"; + return VK_NULL_HANDLE; + + } + + int cursor = 0; + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (state[cursor], state[cursor + 1]); + cursor += 2; + int topology = state[cursor++]; + bool primitiveRestart = state[cursor++] != 0; + int polygonMode = state[cursor++]; + int cullMode = state[cursor++]; + int frontFace = state[cursor++]; + bool depthTest = state[cursor++] != 0; + bool depthWrite = state[cursor++] != 0; + int depthCompareOp = state[cursor++]; + bool blend = state[cursor++] != 0; + int srcColorBlendFactor = state[cursor++]; + int dstColorBlendFactor = state[cursor++]; + int colorBlendOp = state[cursor++]; + int srcAlphaBlendFactor = state[cursor++]; + int dstAlphaBlendFactor = state[cursor++]; + int alphaBlendOp = state[cursor++]; + int dynamicStateFlags = state[cursor++]; + int bindingCount = state[cursor++]; + + if ((int)state.size () < cursor + bindingCount * 3 + 1) { + + lastVKError = "Invalid Vulkan vertex binding state"; + return VK_NULL_HANDLE; + + } + + std::vector bindings; + bindings.reserve ((size_t)bindingCount); + for (int i = 0; i < bindingCount; ++i) { + + VkVertexInputBindingDescription binding; + binding.binding = (uint32_t)state[cursor++]; + binding.stride = (uint32_t)state[cursor++]; + binding.inputRate = (VkVertexInputRate)state[cursor++]; + bindings.push_back (binding); + + } + + int attributeCount = state[cursor++]; + if ((int)state.size () < cursor + attributeCount * 4) { + + lastVKError = "Invalid Vulkan vertex attribute state"; + return VK_NULL_HANDLE; + + } + + std::vector attributes; + attributes.reserve ((size_t)attributeCount); + for (int i = 0; i < attributeCount; ++i) { + + VkVertexInputAttributeDescription attribute; + attribute.location = (uint32_t)state[cursor++]; + attribute.binding = (uint32_t)state[cursor++]; + attribute.format = (VkFormat)state[cursor++]; + attribute.offset = (uint32_t)state[cursor++]; + attributes.push_back (attribute); + + } + + PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines = + (PFN_vkCreateGraphicsPipelines)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateGraphicsPipelines"); + if (!vkCreateGraphicsPipelines) return VK_NULL_HANDLE; + + VkPipelineShaderStageCreateInfo stages[2]; + memset (stages, 0, sizeof (stages)); + stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stages[0].module = vertexShader; + stages[0].pName = "main"; + stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stages[1].module = fragmentShader; + stages[1].pName = "main"; + + VkPipelineVertexInputStateCreateInfo vertexInput; + memset (&vertexInput, 0, sizeof (vertexInput)); + vertexInput.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInput.vertexBindingDescriptionCount = (uint32_t)bindings.size (); + vertexInput.pVertexBindingDescriptions = bindings.empty () ? 0 : bindings.data (); + vertexInput.vertexAttributeDescriptionCount = (uint32_t)attributes.size (); + vertexInput.pVertexAttributeDescriptions = attributes.empty () ? 0 : attributes.data (); + + VkPipelineInputAssemblyStateCreateInfo inputAssembly; + memset (&inputAssembly, 0, sizeof (inputAssembly)); + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = (VkPrimitiveTopology)topology; + inputAssembly.primitiveRestartEnable = primitiveRestart ? VK_TRUE : VK_FALSE; + + VkViewport viewport; + memset (&viewport, 0, sizeof (viewport)); + viewport.width = 1.0f; + viewport.height = 1.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + memset (&scissor, 0, sizeof (scissor)); + scissor.extent.width = 1; + scissor.extent.height = 1; + + VkPipelineViewportStateCreateInfo viewportState; + memset (&viewportState, 0, sizeof (viewportState)); + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterization; + memset (&rasterization, 0, sizeof (rasterization)); + rasterization.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization.polygonMode = (VkPolygonMode)polygonMode; + rasterization.cullMode = (VkCullModeFlags)cullMode; + rasterization.frontFace = (VkFrontFace)frontFace; + rasterization.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo multisample; + memset (&multisample, 0, sizeof (multisample)); + multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineDepthStencilStateCreateInfo depthStencil; + memset (&depthStencil, 0, sizeof (depthStencil)); + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthTestEnable = depthTest ? VK_TRUE : VK_FALSE; + depthStencil.depthWriteEnable = depthWrite ? VK_TRUE : VK_FALSE; + depthStencil.depthCompareOp = (VkCompareOp)depthCompareOp; + + VkPipelineColorBlendAttachmentState colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorAttachment.blendEnable = blend ? VK_TRUE : VK_FALSE; + colorAttachment.srcColorBlendFactor = (VkBlendFactor)srcColorBlendFactor; + colorAttachment.dstColorBlendFactor = (VkBlendFactor)dstColorBlendFactor; + colorAttachment.colorBlendOp = (VkBlendOp)colorBlendOp; + colorAttachment.srcAlphaBlendFactor = (VkBlendFactor)srcAlphaBlendFactor; + colorAttachment.dstAlphaBlendFactor = (VkBlendFactor)dstAlphaBlendFactor; + colorAttachment.alphaBlendOp = (VkBlendOp)alphaBlendOp; + + VkPipelineColorBlendStateCreateInfo colorBlend; + memset (&colorBlend, 0, sizeof (colorBlend)); + colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlend.attachmentCount = 1; + colorBlend.pAttachments = &colorAttachment; + + std::vector dynamicStates; + if (dynamicStateFlags & 0x1) dynamicStates.push_back (VK_DYNAMIC_STATE_VIEWPORT); + if (dynamicStateFlags & 0x2) dynamicStates.push_back (VK_DYNAMIC_STATE_SCISSOR); + VkPipelineDynamicStateCreateInfo dynamicState; + memset (&dynamicState, 0, sizeof (dynamicState)); + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size (); + dynamicState.pDynamicStates = dynamicStates.empty () ? 0 : dynamicStates.data (); + + VkGraphicsPipelineCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + createInfo.stageCount = 2; + createInfo.pStages = stages; + createInfo.pVertexInputState = &vertexInput; + createInfo.pInputAssemblyState = &inputAssembly; + createInfo.pViewportState = &viewportState; + createInfo.pRasterizationState = &rasterization; + createInfo.pMultisampleState = &multisample; + createInfo.pDepthStencilState = &depthStencil; + createInfo.pColorBlendState = &colorBlend; + createInfo.pDynamicState = dynamicStates.empty () ? 0 : &dynamicState; + createInfo.layout = layout; + createInfo.renderPass = renderPass; + createInfo.subpass = 0; + + VkPipeline pipeline = VK_NULL_HANDLE; + VkResult result = vkCreateGraphicsPipelines (device, cache, 1, &createInfo, 0, &pipeline); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateGraphicsPipelines failed"; + return VK_NULL_HANDLE; } lastVKError.clear (); - return devices; + return pipeline; + + } + +#endif + + + value lime_vk_create_graphics_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, int fragmentShaderHigh, int fragmentShaderLow, + value state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = CreateManagedVulkanGraphicsPipeline (targetWindow, instance, device, + (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow), + (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (vertexShaderHigh, vertexShaderLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (fragmentShaderHigh, fragmentShaderLow), + GetVulkanIntVector (state)); + return pipeline ? CreateVulkanHandleValue ((uint64_t)(uintptr_t)pipeline) : alloc_null (); #else lastVKError = "Lime was built without lime-vulkan support"; - return alloc_array (0); + return alloc_null (); #endif } - HL_PRIM hl_varray* HL_NAME(hl_vk_get_physical_devices) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_graphics_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, + int fragmentShaderHigh, int fragmentShaderLow, hl_varray* state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = CreateManagedVulkanGraphicsPipeline (targetWindow, instance, device, + (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow), + (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (vertexShaderHigh, vertexShaderLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (fragmentShaderHigh, fragmentShaderLow), + GetHLVulkanIntVector (state)); + return pipeline ? HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)pipeline) : 0; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif - if (!targetWindow || !instance) { - - lastVKError = "Missing Vulkan window or instance"; - return 0; - - } - - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); - if (!vkGetInstanceProcAddr) { - - lastVKError = "SDL did not expose vkGetInstanceProcAddr"; - return 0; + } - } - PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, - "vkEnumeratePhysicalDevices"); - PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, - "vkGetPhysicalDeviceProperties"); - PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = - (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); - PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = - (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + void lime_vk_destroy_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int pipelineHigh, int pipelineLow) { - if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { +#ifdef LIME_VULKAN + if (pipelineHigh == 0 && pipelineLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + PFN_vkDestroyPipeline vkDestroyPipeline = (PFN_vkDestroyPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyPipeline"); + if (vkDestroyPipeline) { - lastVKError = "Missing required Vulkan instance functions"; - return 0; + vkDestroyPipeline (device, pipeline, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); - uint32_t deviceCount = 0; - VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); - - if (result != VK_SUCCESS) { + } - lastVKError = "vkEnumeratePhysicalDevices failed"; - return 0; - } + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int pipelineHigh, int pipelineLow) { - hl_varray* devices = (hl_varray*)hl_alloc_array (&hlt_dynobj, deviceCount); - if (deviceCount == 0) { +#ifdef LIME_VULKAN + if (pipelineHigh == 0 && pipelineLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + PFN_vkDestroyPipeline vkDestroyPipeline = (PFN_vkDestroyPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyPipeline"); + if (vkDestroyPipeline) { + vkDestroyPipeline (device, pipeline, 0); lastVKError.clear (); - return devices; } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - std::vector physicalDevices (deviceCount); - result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + } - if (result != VK_SUCCESS) { + HL_PRIM void HL_NAME(hl_vulkan_renderer_destroy) (HL_CFFIPointer* handle) { - lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; - return 0; + if (!handle || !handle->ptr) return; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + handle->ptr = 0; + delete renderer; - } + } - vdynamic** deviceData = hl_aptr (devices, vdynamic*); - const int id_handle = hl_hash_utf8 ("handle"); - const int id_name = hl_hash_utf8 ("name"); - const int id_apiVersion = hl_hash_utf8 ("apiVersion"); - const int id_driverVersion = hl_hash_utf8 ("driverVersion"); - const int id_vendorID = hl_hash_utf8 ("vendorID"); - const int id_deviceID = hl_hash_utf8 ("deviceID"); - const int id_deviceType = hl_hash_utf8 ("deviceType"); - const int id_queueFamilies = hl_hash_utf8 ("queueFamilies"); + bool lime_vk_queue_submit_synced (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, value state) { - const int id_index = hl_hash_utf8 ("index"); - const int id_flags = hl_hash_utf8 ("flags"); - const int id_queueCount = hl_hash_utf8 ("queueCount"); - const int id_timestampValidBits = hl_hash_utf8 ("timestampValidBits"); - const int id_supportsGraphics = hl_hash_utf8 ("supportsGraphics"); - const int id_supportsCompute = hl_hash_utf8 ("supportsCompute"); - const int id_supportsTransfer = hl_hash_utf8 ("supportsTransfer"); - const int id_supportsPresent = hl_hash_utf8 ("supportsPresent"); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (packed.size () < 7) return false; - for (uint32_t i = 0; i < deviceCount; ++i) { + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[0], packed[1]); + VkPipelineStageFlags waitStage = (VkPipelineStageFlags)packed[2]; + VkSemaphore signalSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[3], packed[4]); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (packed[5], packed[6]); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit || !queue || !commandBuffer) return false; - VkPhysicalDeviceProperties properties; - memset (&properties, 0, sizeof (properties)); - vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + submitInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + submitInfo.pWaitDstStageMask = waitSemaphore ? &waitStage : 0; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.signalSemaphoreCount = signalSemaphore ? 1 : 0; + submitInfo.pSignalSemaphores = signalSemaphore ? &signalSemaphore : 0; - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); - std::vector queueFamilies (queueFamilyCount); - if (queueFamilyCount > 0) { + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { - vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + lastVKError = "vkQueueSubmit failed"; + return false; - } + } - hl_varray* queueFamilyArray = (hl_varray*)hl_alloc_array (&hlt_dynobj, queueFamilyCount); - vdynamic** queueFamilyData = hl_aptr (queueFamilyArray, vdynamic*); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - for (uint32_t q = 0; q < queueFamilyCount; ++q) { + } - VkBool32 supportsPresent = VK_FALSE; - if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { - vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + HL_PRIM bool HL_NAME(hl_vk_queue_submit_synced) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueHigh, int queueLow, int commandBufferHigh, int commandBufferLow, hl_varray* state) { - } +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (packed.size () < 7) return false; - vdynamic* queueFamilyObject = (vdynamic*)hl_alloc_dynobj (); - *queueFamilyData++ = queueFamilyObject; - hl_dyn_seti (queueFamilyObject, id_index, &hlt_i32, q); - hl_dyn_seti (queueFamilyObject, id_flags, &hlt_i32, queueFamilies[q].queueFlags); - hl_dyn_seti (queueFamilyObject, id_queueCount, &hlt_i32, queueFamilies[q].queueCount); - hl_dyn_seti (queueFamilyObject, id_timestampValidBits, &hlt_i32, queueFamilies[q].timestampValidBits); - hl_dyn_seti (queueFamilyObject, id_supportsGraphics, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0); - hl_dyn_seti (queueFamilyObject, id_supportsCompute, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0); - hl_dyn_seti (queueFamilyObject, id_supportsTransfer, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0); - hl_dyn_seti (queueFamilyObject, id_supportsPresent, &hlt_bool, supportsPresent != VK_FALSE); + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[0], packed[1]); + VkPipelineStageFlags waitStage = (VkPipelineStageFlags)packed[2]; + VkSemaphore signalSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[3], packed[4]); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (packed[5], packed[6]); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit || !queue || !commandBuffer) return false; - } + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + submitInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + submitInfo.pWaitDstStageMask = waitSemaphore ? &waitStage : 0; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.signalSemaphoreCount = signalSemaphore ? 1 : 0; + submitInfo.pSignalSemaphores = signalSemaphore ? &signalSemaphore : 0; - vdynamic* deviceObject = (vdynamic*)hl_alloc_dynobj (); - *deviceData++ = deviceObject; - hl_dyn_setp (deviceObject, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); - hl_dyn_setp (deviceObject, id_name, &hlt_bytes, hl_copy_bytes ((const vbyte*)properties.deviceName, (int)std::strlen (properties.deviceName) + 1)); - hl_dyn_seti (deviceObject, id_apiVersion, &hlt_i32, properties.apiVersion); - hl_dyn_seti (deviceObject, id_driverVersion, &hlt_i32, properties.driverVersion); - hl_dyn_seti (deviceObject, id_vendorID, &hlt_i32, properties.vendorID); - hl_dyn_seti (deviceObject, id_deviceID, &hlt_i32, properties.deviceID); - hl_dyn_seti (deviceObject, id_deviceType, &hlt_i32, properties.deviceType); - hl_dyn_setp (deviceObject, id_queueFamilies, &hlt_array, queueFamilyArray); + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueSubmit failed"; + return false; } lastVKError.clear (); - return devices; + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return (hl_varray*)hl_alloc_array (&hlt_dynobj, 0); + return false; #endif } - value lime_vk_create_device (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int queueFamilyIndex, - value extensions) { + bool lime_vk_cmd_begin_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, value state, value clear) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); - std::vector deviceExtensions = GetVulkanDeviceExtensions (extensions); - VkDevice device = VK_NULL_HANDLE; - VkQueue queue = VK_NULL_HANDLE; - - if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { - - return alloc_null (); - - } - - value result = alloc_empty_object (); - alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); - alloc_field (result, val_id ("queue"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); - alloc_field (result, val_id ("queueFamilyIndex"), alloc_int (queueFamilyIndex)); - return result; + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBeginRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdBeginRenderPass || !commandBuffer || packed.size () < 5 || clearValues.size () < 5) return false; + uint32_t clearValueCount = packed.size () > 5 ? (uint32_t)packed[5] : 2; + if (clearValueCount < 1) clearValueCount = 1; + if (clearValueCount > 2) clearValueCount = 2; + + VkClearValue clears[2]; + memset (clears, 0, sizeof (clears)); + clears[0].color.float32[0] = (float)clearValues[0]; + clears[0].color.float32[1] = (float)clearValues[1]; + clears[0].color.float32[2] = (float)clearValues[2]; + clears[0].color.float32[3] = (float)clearValues[3]; + clears[1].depthStencil.depth = (float)clearValues[4]; + clears[1].depthStencil.stencil = (uint32_t)packed[4]; + + VkRenderPassBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + beginInfo.renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + beginInfo.framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + beginInfo.renderArea.offset.x = packed[0]; + beginInfo.renderArea.offset.y = packed[1]; + beginInfo.renderArea.extent.width = (uint32_t)packed[2]; + beginInfo.renderArea.extent.height = (uint32_t)packed[3]; + beginInfo.clearValueCount = clearValueCount; + beginInfo.pClearValues = clears; + + vkCmdBeginRenderPass (commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return alloc_null (); + return false; #endif } - HL_PRIM vdynamic* HL_NAME(hl_vk_create_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, - int physicalDeviceLow, int queueFamilyIndex, hl_varray* extensions) { + HL_PRIM bool HL_NAME(hl_vk_cmd_begin_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, + hl_varray* state, hl_varray* clear) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); - std::vector deviceExtensions = GetHLVulkanDeviceExtensions (extensions); - VkDevice device = VK_NULL_HANDLE; - VkQueue queue = VK_NULL_HANDLE; + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBeginRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdBeginRenderPass || !commandBuffer || packed.size () < 5 || clearValues.size () < 5) return false; + uint32_t clearValueCount = packed.size () > 5 ? (uint32_t)packed[5] : 2; + if (clearValueCount < 1) clearValueCount = 1; + if (clearValueCount > 2) clearValueCount = 2; + + VkClearValue clears[2]; + memset (clears, 0, sizeof (clears)); + clears[0].color.float32[0] = (float)clearValues[0]; + clears[0].color.float32[1] = (float)clearValues[1]; + clears[0].color.float32[2] = (float)clearValues[2]; + clears[0].color.float32[3] = (float)clearValues[3]; + clears[1].depthStencil.depth = (float)clearValues[4]; + clears[1].depthStencil.stencil = (uint32_t)packed[4]; + + VkRenderPassBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + beginInfo.renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + beginInfo.framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + beginInfo.renderArea.offset.x = packed[0]; + beginInfo.renderArea.offset.y = packed[1]; + beginInfo.renderArea.extent.width = (uint32_t)packed[2]; + beginInfo.renderArea.extent.height = (uint32_t)packed[3]; + beginInfo.clearValueCount = clearValueCount; + beginInfo.pClearValues = clears; + + vkCmdBeginRenderPass (commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + } - return 0; - } + bool lime_vk_cmd_end_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { - const int id_handle = hl_hash_utf8 ("handle"); - const int id_queue = hl_hash_utf8 ("queue"); - const int id_queueFamilyIndex = hl_hash_utf8 ("queueFamilyIndex"); - vdynamic* result = (vdynamic*)hl_alloc_dynobj (); - hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); - hl_dyn_setp (result, id_queue, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); - hl_dyn_seti (result, id_queueFamilyIndex, &hlt_i32, queueFamilyIndex); - return result; +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdEndRenderPass vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdEndRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdEndRenderPass || !commandBuffer) return false; + vkCmdEndRenderPass (commandBuffer); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return 0; + return false; #endif } - void lime_vk_destroy_device (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_end_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow) { #ifdef LIME_VULKAN - if (deviceHigh == 0 && deviceLow == 0) return; - Window* targetWindow = (Window*)val_data (window); + Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr) return; + PFN_vkCmdEndRenderPass vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdEndRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdEndRenderPass || !commandBuffer) return false; + vkCmdEndRenderPass (commandBuffer); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); - if (!vkGetDeviceProcAddr) return; + } - PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); - if (vkDestroyDevice) { - vkDestroyDevice (device, 0); + bool lime_vk_cmd_bind_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { - } +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindPipeline vkCmdBindPipeline = (PFN_vkCmdBindPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBindPipeline"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + if (!vkCmdBindPipeline || !commandBuffer || !pipeline) return false; + vkCmdBindPipeline (commandBuffer, (VkPipelineBindPoint)bindPoint, pipeline); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; + return false; #endif } - HL_PRIM void HL_NAME(hl_vk_destroy_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { #ifdef LIME_VULKAN - if (deviceHigh == 0 && deviceLow == 0) return; Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr) return; - - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); - if (!vkGetDeviceProcAddr) return; - - PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); - if (vkDestroyDevice) { - - vkDestroyDevice (device, 0); - - } + PFN_vkCmdBindPipeline vkCmdBindPipeline = (PFN_vkCmdBindPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBindPipeline"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + if (!vkCmdBindPipeline || !commandBuffer || !pipeline) return false; + vkCmdBindPipeline (commandBuffer, (VkPipelineBindPoint)bindPoint, pipeline); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; + return false; #endif } - bool lime_vk_device_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + bool lime_vk_cmd_bind_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, int firstSet) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr || !instance || !device) { - - lastVKError = "Missing Vulkan window, instance, or device"; - return false; - - } - - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); - if (!vkGetDeviceProcAddr) { - - lastVKError = "Missing Vulkan device proc address function"; - return false; - - } - - PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); - if (!vkDeviceWaitIdle) { - - lastVKError = "Missing Vulkan device wait idle function"; - return false; - - } - - VkResult result = vkDeviceWaitIdle (device); - if (result != VK_SUCCESS) { - - lastVKError = "vkDeviceWaitIdle failed"; - return false; - - } - - lastVKError.clear (); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 0, 0); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -4700,45 +9745,75 @@ namespace lime { } - HL_PRIM bool HL_NAME(hl_vk_device_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, + int firstSet) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr || !instance || !device) { - - lastVKError = "Missing Vulkan window, instance, or device"; - return false; + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 0, 0); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - } + } - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); - if (!vkGetDeviceProcAddr) { + value lime_vulkan_renderer_get_info (value handle) { - lastVKError = "Missing Vulkan device proc address function"; - return false; + if (val_is_null (handle)) return alloc_string (""); + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + return alloc_string (renderer->GetInfo ().c_str ()); - } + } - PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); - if (!vkDeviceWaitIdle) { - lastVKError = "Missing Vulkan device wait idle function"; - return false; + bool lime_vk_cmd_bind_vertex_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { - } +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = + (PFN_vkCmdBindVertexBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindVertexBuffers"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + if (!vkCmdBindVertexBuffers || !commandBuffer || !buffer) return false; + vkCmdBindVertexBuffers (commandBuffer, (uint32_t)binding, 1, &buffer, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - VkResult result = vkDeviceWaitIdle (device); - if (result != VK_SUCCESS) { + } - lastVKError = "vkDeviceWaitIdle failed"; - return false; - } + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_vertex_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { - lastVKError.clear (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = + (PFN_vkCmdBindVertexBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindVertexBuffers"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + if (!vkCmdBindVertexBuffers || !commandBuffer || !buffer) return false; + vkCmdBindVertexBuffers (commandBuffer, (uint32_t)binding, 1, &buffer, &offset); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -4748,46 +9823,19 @@ namespace lime { } - bool lime_vk_queue_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow) { + bool lime_vk_cmd_bind_index_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr || !instance || !device || !queue) { - - lastVKError = "Missing Vulkan window, instance, device, or queue"; - return false; - - } - - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); - if (!vkGetDeviceProcAddr) { - - lastVKError = "Missing Vulkan device proc address function"; - return false; - - } - - PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); - if (!vkQueueWaitIdle) { - - lastVKError = "Missing Vulkan queue wait idle function"; - return false; - - } - - VkResult result = vkQueueWaitIdle (queue); - if (result != VK_SUCCESS) { - - lastVKError = "vkQueueWaitIdle failed"; - return false; - - } - - lastVKError.clear (); + PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = + (PFN_vkCmdBindIndexBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindIndexBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdBindIndexBuffer || !commandBuffer || !buffer) return false; + vkCmdBindIndexBuffer (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (VkIndexType)indexType); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -4797,47 +9845,47 @@ namespace lime { } - HL_PRIM bool HL_NAME(hl_vk_queue_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, - int queueLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_index_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; - if (!vkGetInstanceProcAddr || !instance || !device || !queue) { - - lastVKError = "Missing Vulkan window, instance, device, or queue"; - return false; - - } - - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); - if (!vkGetDeviceProcAddr) { - - lastVKError = "Missing Vulkan device proc address function"; - return false; - - } - - PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); - if (!vkQueueWaitIdle) { - - lastVKError = "Missing Vulkan queue wait idle function"; - return false; - - } + PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = + (PFN_vkCmdBindIndexBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindIndexBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdBindIndexBuffer || !commandBuffer || !buffer) return false; + vkCmdBindIndexBuffer (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (VkIndexType)indexType); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - VkResult result = vkQueueWaitIdle (queue); - if (result != VK_SUCCESS) { + } - lastVKError = "vkQueueWaitIdle failed"; - return false; - } + bool lime_vk_cmd_set_viewport (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - lastVKError.clear (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdSetViewport vkCmdSetViewport = (PFN_vkCmdSetViewport)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdSetViewport"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetViewport || !commandBuffer) return false; + VkViewport viewport; + viewport.x = (float)x; + viewport.y = (float)y; + viewport.width = (float)width; + viewport.height = (float)height; + viewport.minDepth = (float)minDepth; + viewport.maxDepth = (float)maxDepth; + vkCmdSetViewport (commandBuffer, 0, 1, &viewport); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -4847,136 +9895,144 @@ namespace lime { } - value lime_vk_create_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueFamilyIndex, int flags) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_viewport) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { #ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); + Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkCreateCommandPool"); - if (!vkCreateCommandPool) return alloc_null (); + PFN_vkCmdSetViewport vkCmdSetViewport = (PFN_vkCmdSetViewport)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdSetViewport"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetViewport || !commandBuffer) return false; + VkViewport viewport; + viewport.x = (float)x; + viewport.y = (float)y; + viewport.width = (float)width; + viewport.height = (float)height; + viewport.minDepth = (float)minDepth; + viewport.maxDepth = (float)maxDepth; + vkCmdSetViewport (commandBuffer, 0, 1, &viewport); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - VkCommandPoolCreateInfo createInfo; - memset (&createInfo, 0, sizeof (createInfo)); - createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - createInfo.flags = flags; - createInfo.queueFamilyIndex = queueFamilyIndex; + } - VkCommandPool commandPool = VK_NULL_HANDLE; - VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); - if (result != VK_SUCCESS) { + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_info) (HL_CFFIPointer* handle) { - lastVKError = "vkCreateCommandPool failed"; - return alloc_null (); + if (!handle || !handle->ptr) return 0; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + return hl_copy_bytes ((const vbyte*)renderer->GetInfo ().c_str (), (int)renderer->GetInfo ().size () + 1); - } + } - lastVKError.clear (); - return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); + + bool lime_vk_cmd_set_scissor (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int x, int y, int width, int height) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdSetScissor vkCmdSetScissor = (PFN_vkCmdSetScissor)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdSetScissor"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetScissor || !commandBuffer) return false; + VkRect2D scissor; + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = (uint32_t)width; + scissor.extent.height = (uint32_t)height; + vkCmdSetScissor (commandBuffer, 0, 1, &scissor); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return alloc_null (); + return false; #endif } - HL_PRIM vdynamic* HL_NAME(hl_vk_create_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int queueFamilyIndex, int flags) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_scissor) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int x, int y, int width, int height) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkCreateCommandPool"); - if (!vkCreateCommandPool) return 0; - - VkCommandPoolCreateInfo createInfo; - memset (&createInfo, 0, sizeof (createInfo)); - createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - createInfo.flags = flags; - createInfo.queueFamilyIndex = queueFamilyIndex; - - VkCommandPool commandPool = VK_NULL_HANDLE; - VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); - if (result != VK_SUCCESS) { - - lastVKError = "vkCreateCommandPool failed"; - return 0; - - } - - lastVKError.clear (); - return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); + PFN_vkCmdSetScissor vkCmdSetScissor = (PFN_vkCmdSetScissor)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdSetScissor"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetScissor || !commandBuffer) return false; + VkRect2D scissor; + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = (uint32_t)width; + scissor.extent.height = (uint32_t)height; + vkCmdSetScissor (commandBuffer, 0, 1, &scissor); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return 0; + return false; #endif } - void lime_vk_destroy_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, - int commandPoolLow) { + bool lime_vk_cmd_draw (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { #ifdef LIME_VULKAN - if (commandPoolHigh == 0 && commandPoolLow == 0) return; Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); - PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkDestroyCommandPool"); - if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); + PFN_vkCmdDraw vkCmdDraw = (PFN_vkCmdDraw)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDraw"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDraw || !commandBuffer) return false; + vkCmdDraw (commandBuffer, (uint32_t)vertexCount, (uint32_t)instanceCount, (uint32_t)firstVertex, (uint32_t)firstInstance); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; + return false; #endif } - HL_PRIM void HL_NAME(hl_vk_destroy_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandPoolHigh, int commandPoolLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { #ifdef LIME_VULKAN - if (commandPoolHigh == 0 && commandPoolLow == 0) return; Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); - PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkDestroyCommandPool"); - if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); + PFN_vkCmdDraw vkCmdDraw = (PFN_vkCmdDraw)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDraw"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDraw || !commandBuffer) return false; + vkCmdDraw (commandBuffer, (uint32_t)vertexCount, (uint32_t)instanceCount, (uint32_t)firstVertex, (uint32_t)firstInstance); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; + return false; #endif } - bool lime_vk_reset_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, - int commandPoolLow, int flags) { + bool lime_vk_cmd_draw_indexed (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); - PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkResetCommandPool"); - if (!vkResetCommandPool) return false; - - VkResult result = vkResetCommandPool (device, commandPool, flags); - if (result != VK_SUCCESS) { - - lastVKError = "vkResetCommandPool failed"; - return false; - - } - - lastVKError.clear (); + PFN_vkCmdDrawIndexed vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndexed"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDrawIndexed || !commandBuffer) return false; + vkCmdDrawIndexed (commandBuffer, (uint32_t)indexCount, (uint32_t)instanceCount, (uint32_t)firstIndex, vertexOffset, (uint32_t)firstInstance); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -4986,27 +10042,18 @@ namespace lime { } - HL_PRIM bool HL_NAME(hl_vk_reset_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandPoolHigh, int commandPoolLow, int flags) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); - PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkResetCommandPool"); - if (!vkResetCommandPool) return false; - - VkResult result = vkResetCommandPool (device, commandPool, flags); - if (result != VK_SUCCESS) { - - lastVKError = "vkResetCommandPool failed"; - return false; - - } - - lastVKError.clear (); + PFN_vkCmdDrawIndexed vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndexed"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDrawIndexed || !commandBuffer) return false; + vkCmdDrawIndexed (commandBuffer, (uint32_t)indexCount, (uint32_t)instanceCount, (uint32_t)firstIndex, vertexOffset, (uint32_t)firstInstance); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -5015,149 +10062,203 @@ namespace lime { } + value lime_vulkan_renderer_get_last_error () { + + return alloc_string (lastVulkanRendererError.c_str ()); + + } + - value lime_vk_allocate_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, - int commandPoolLow, int level) { + bool lime_vk_cmd_copy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); - PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkAllocateCommandBuffers"); - if (!vkAllocateCommandBuffers) return alloc_null (); - - VkCommandBufferAllocateInfo allocateInfo; - memset (&allocateInfo, 0, sizeof (allocateInfo)); - allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocateInfo.commandPool = commandPool; - allocateInfo.level = (VkCommandBufferLevel)level; - allocateInfo.commandBufferCount = 1; - - VkCommandBuffer commandBuffer = VK_NULL_HANDLE; - VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); - if (result != VK_SUCCESS) { - - lastVKError = "vkAllocateCommandBuffers failed"; - return alloc_null (); - - } - - lastVKError.clear (); - return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); + PFN_vkCmdCopyBuffer vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdCopyBuffer || !commandBuffer || packed.size () < 6) return false; + + VkBufferCopy region; + region.size = (VkDeviceSize)CombineVulkanHandle (packed[0], packed[1]); + region.srcOffset = (VkDeviceSize)CombineVulkanHandle (packed[2], packed[3]); + region.dstOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + vkCmdCopyBuffer (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), + (VkBuffer)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), 1, ®ion); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return alloc_null (); + return false; #endif } - HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, - int deviceLow, int commandPoolHigh, int commandPoolLow, int level) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); - PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkAllocateCommandBuffers"); - if (!vkAllocateCommandBuffers) return 0; - - VkCommandBufferAllocateInfo allocateInfo; - memset (&allocateInfo, 0, sizeof (allocateInfo)); - allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocateInfo.commandPool = commandPool; - allocateInfo.level = (VkCommandBufferLevel)level; - allocateInfo.commandBufferCount = 1; - - VkCommandBuffer commandBuffer = VK_NULL_HANDLE; - VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); - if (result != VK_SUCCESS) { - - lastVKError = "vkAllocateCommandBuffers failed"; - return 0; - - } - - lastVKError.clear (); - return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); + PFN_vkCmdCopyBuffer vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdCopyBuffer || !commandBuffer || packed.size () < 6) return false; + + VkBufferCopy region; + region.size = (VkDeviceSize)CombineVulkanHandle (packed[0], packed[1]); + region.srcOffset = (VkDeviceSize)CombineVulkanHandle (packed[2], packed[3]); + region.dstOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + vkCmdCopyBuffer (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), + (VkBuffer)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), 1, ®ion); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; - return 0; + return false; #endif } - void lime_vk_free_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, - int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + bool lime_vk_cmd_copy_buffer_to_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, int height, int layout) { #ifdef LIME_VULKAN - if (commandBufferHigh == 0 && commandBufferLow == 0) return; Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = + (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkFreeCommandBuffers"); - if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); + if (!vkCmdCopyBufferToImage || !commandBuffer) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = (uint32_t)width; + region.imageExtent.height = (uint32_t)height; + region.imageExtent.depth = 1; + vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), + (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, 1, ®ion); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; + return false; #endif } - HL_PRIM void HL_NAME(hl_vk_free_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandPoolHigh, int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, + int height, int layout) { #ifdef LIME_VULKAN - if (commandBufferHigh == 0 && commandBufferLow == 0) return; Window* targetWindow = (Window*)window->ptr; VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = + (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkFreeCommandBuffers"); - if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); + if (!vkCmdCopyBufferToImage || !commandBuffer) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = (uint32_t)width; + region.imageExtent.height = (uint32_t)height; + region.imageExtent.depth = 1; + vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), + (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, 1, ®ion); + return true; #else lastVKError = "Lime was built without lime-vulkan support"; + return false; #endif } + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { + + return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); + + } - bool lime_vk_begin_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, - int commandBufferLow, int flags) { + + bool lime_vk_cmd_pipeline_barrier_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = + (PFN_vkCmdPipelineBarrier)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPipelineBarrier"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkBeginCommandBuffer"); - if (!vkBeginCommandBuffer) return false; - - VkCommandBufferBeginInfo beginInfo; - memset (&beginInfo, 0, sizeof (beginInfo)); - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = flags; + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdPipelineBarrier || !commandBuffer || packed.size () < 11) return false; + + VkImageMemoryBarrier barrier; + memset (&barrier, 0, sizeof (barrier)); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = (VkImageLayout)packed[0]; + barrier.newLayout = (VkImageLayout)packed[1]; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + barrier.srcAccessMask = (VkAccessFlags)packed[4]; + barrier.dstAccessMask = (VkAccessFlags)packed[5]; + barrier.subresourceRange.aspectMask = (VkImageAspectFlags)packed[6]; + barrier.subresourceRange.baseMipLevel = (uint32_t)packed[7]; + barrier.subresourceRange.levelCount = (uint32_t)packed[8]; + barrier.subresourceRange.baseArrayLayer = (uint32_t)packed[9]; + barrier.subresourceRange.layerCount = (uint32_t)packed[10]; + + vkCmdPipelineBarrier (commandBuffer, (VkPipelineStageFlags)packed[2], (VkPipelineStageFlags)packed[3], 0, 0, 0, 0, 0, 1, &barrier); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); - if (result != VK_SUCCESS) { + } - lastVKError = "vkBeginCommandBuffer failed"; - return false; - } + HL_PRIM bool HL_NAME(hl_vk_cmd_pipeline_barrier_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state) { - lastVKError.clear (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = + (PFN_vkCmdPipelineBarrier)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPipelineBarrier"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdPipelineBarrier || !commandBuffer || packed.size () < 11) return false; + + VkImageMemoryBarrier barrier; + memset (&barrier, 0, sizeof (barrier)); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = (VkImageLayout)packed[0]; + barrier.newLayout = (VkImageLayout)packed[1]; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + barrier.srcAccessMask = (VkAccessFlags)packed[4]; + barrier.dstAccessMask = (VkAccessFlags)packed[5]; + barrier.subresourceRange.aspectMask = (VkImageAspectFlags)packed[6]; + barrier.subresourceRange.baseMipLevel = (uint32_t)packed[7]; + barrier.subresourceRange.levelCount = (uint32_t)packed[8]; + barrier.subresourceRange.baseArrayLayer = (uint32_t)packed[9]; + barrier.subresourceRange.layerCount = (uint32_t)packed[10]; + + vkCmdPipelineBarrier (commandBuffer, (VkPipelineStageFlags)packed[2], (VkPipelineStageFlags)packed[3], 0, 0, 0, 0, 0, 1, &barrier); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -5167,32 +10268,63 @@ namespace lime { } - HL_PRIM bool HL_NAME(hl_vk_begin_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandBufferHigh, int commandBufferLow, int flags) { + bool lime_vk_cmd_clear_color_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, value clear) { #ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; + Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearColorImage vkCmdClearColorImage = + (PFN_vkCmdClearColorImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearColorImage"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkBeginCommandBuffer"); - if (!vkBeginCommandBuffer) return false; - - VkCommandBufferBeginInfo beginInfo; - memset (&beginInfo, 0, sizeof (beginInfo)); - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = flags; + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdClearColorImage || !commandBuffer || clearValues.size () < 4) return false; + + VkClearColorValue color; + color.float32[0] = (float)clearValues[0]; + color.float32[1] = (float)clearValues[1]; + color.float32[2] = (float)clearValues[2]; + color.float32[3] = (float)clearValues[3]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)aspectMask; + range.levelCount = 1; + range.layerCount = 1; + vkCmdClearColorImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, &color, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); - if (result != VK_SUCCESS) { + } - lastVKError = "vkBeginCommandBuffer failed"; - return false; - } + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_color_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, hl_varray* clear) { - lastVKError.clear (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearColorImage vkCmdClearColorImage = + (PFN_vkCmdClearColorImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearColorImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdClearColorImage || !commandBuffer || clearValues.size () < 4) return false; + + VkClearColorValue color; + color.float32[0] = (float)clearValues[0]; + color.float32[1] = (float)clearValues[1]; + color.float32[2] = (float)clearValues[2]; + color.float32[3] = (float)clearValues[3]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)aspectMask; + range.levelCount = 1; + range.layerCount = 1; + vkCmdClearColorImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, &color, 1, &range); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -5202,27 +10334,67 @@ namespace lime { } - bool lime_vk_end_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, - int commandBufferLow) { + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBlitImage vkCmdBlitImage = (PFN_vkCmdBlitImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBlitImage"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkEndCommandBuffer"); - if (!vkEndCommandBuffer) return false; + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdBlitImage || !commandBuffer || packed.size () < 5) return false; + + VkImageBlit blit; + memset (&blit, 0, sizeof (blit)); + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.layerCount = 1; + blit.srcOffsets[1].x = packed[0]; + blit.srcOffsets[1].y = packed[1]; + blit.srcOffsets[1].z = 1; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.layerCount = 1; + blit.dstOffsets[1].x = packed[0]; + blit.dstOffsets[1].y = packed[1]; + blit.dstOffsets[1].z = 1; + vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)packed[2], + (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)packed[3], 1, &blit, (VkFilter)packed[4]); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - VkResult result = vkEndCommandBuffer (commandBuffer); - if (result != VK_SUCCESS) { + } - lastVKError = "vkEndCommandBuffer failed"; - return false; - } + HL_PRIM bool HL_NAME(hl_vk_cmd_blit_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { - lastVKError.clear (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBlitImage vkCmdBlitImage = (PFN_vkCmdBlitImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBlitImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdBlitImage || !commandBuffer || packed.size () < 5) return false; + + VkImageBlit blit; + memset (&blit, 0, sizeof (blit)); + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.layerCount = 1; + blit.srcOffsets[1].x = packed[0]; + blit.srcOffsets[1].y = packed[1]; + blit.srcOffsets[1].z = 1; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.layerCount = 1; + blit.dstOffsets[1].x = packed[0]; + blit.dstOffsets[1].y = packed[1]; + blit.dstOffsets[1].z = 1; + vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)packed[2], + (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)packed[3], 1, &blit, (VkFilter)packed[4]); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -5231,687 +10403,497 @@ namespace lime { } + bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { + + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + Bytes data (bytes); + bool result = renderer->SetOverlay (data.b, width, height, x, y); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_set_overlay) (HL_CFFIPointer* handle, Bytes* bytes, int width, int height, int x, int y) { + + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->SetOverlay (bytes ? bytes->b : 0, width, height, x, y); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + bool lime_vulkan_renderer_clear_overlay (value handle) { + + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->ClearOverlay (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + + + HL_PRIM bool HL_NAME(hl_vulkan_renderer_clear_overlay) (HL_CFFIPointer* handle) { + + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->ClearOverlay (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } + - HL_PRIM bool HL_NAME(hl_vk_end_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandBufferHigh, int commandBufferLow) { + bool lime_vulkan_renderer_render (value handle, double red, double green, double blue, double alpha) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkEndCommandBuffer"); - if (!vkEndCommandBuffer) return false; + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->Render (red, green, blue, alpha); + lastVulkanRendererError = renderer->GetLastError (); + return result; - VkResult result = vkEndCommandBuffer (commandBuffer); - if (result != VK_SUCCESS) { + } - lastVKError = "vkEndCommandBuffer failed"; - return false; - } + HL_PRIM bool HL_NAME(hl_vulkan_renderer_render) (HL_CFFIPointer* handle, double red, double green, double blue, double alpha) { - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->Render (red, green, blue, alpha); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - bool lime_vk_reset_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, - int commandBufferLow, int flags) { + bool lime_vulkan_renderer_resize (value handle) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkResetCommandBuffer"); - if (!vkResetCommandBuffer) return false; + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->Resize (); + lastVulkanRendererError = renderer->GetLastError (); + return result; - VkResult result = vkResetCommandBuffer (commandBuffer, flags); - if (result != VK_SUCCESS) { + } - lastVKError = "vkResetCommandBuffer failed"; - return false; - } + HL_PRIM bool HL_NAME(hl_vulkan_renderer_resize) (HL_CFFIPointer* handle) { - lastVKError.clear (); - return true; + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->Resize (); + lastVulkanRendererError = renderer->GetLastError (); + return result; + + } #else + static inline bool LimeVulkanUnavailableBool () { + lastVKError = "Lime was built without lime-vulkan support"; return false; -#endif } - HL_PRIM bool HL_NAME(hl_vk_reset_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandBufferHigh, int commandBufferLow, int flags) { + static inline value LimeVulkanUnavailableValue () { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkResetCommandBuffer"); - if (!vkResetCommandBuffer) return false; + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); - VkResult result = vkResetCommandBuffer (commandBuffer, flags); - if (result != VK_SUCCESS) { + } - lastVKError = "vkResetCommandBuffer failed"; - return false; - } + static inline vdynamic* HLLimeVulkanUnavailableValue () { - lastVKError.clear (); - return true; -#else lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + return 0; } - value lime_vk_create_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { - -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkCreateSemaphore"); - if (!vkCreateSemaphore) return alloc_null (); + static inline void LimeVulkanUnavailableVoid () { - VkSemaphoreCreateInfo createInfo; - memset (&createInfo, 0, sizeof (createInfo)); - createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + lastVKError = "Lime was built without lime-vulkan support"; - VkSemaphore semaphore = VK_NULL_HANDLE; - VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); - if (result != VK_SUCCESS) { + } - lastVKError = "vkCreateSemaphore failed"; - return alloc_null (); - } + bool lime_vk_update_descriptor_set_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int setHigh, + int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { - lastVKError.clear (); - return CreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); -#else - lastVKError = "Lime was built without lime-vulkan support"; - return alloc_null (); -#endif + return LimeVulkanUnavailableBool (); } - HL_PRIM vdynamic* HL_NAME(hl_vk_create_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { - -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkCreateSemaphore"); - if (!vkCreateSemaphore) return 0; + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_set_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int setHigh, int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { - VkSemaphoreCreateInfo createInfo; - memset (&createInfo, 0, sizeof (createInfo)); - createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + return LimeVulkanUnavailableBool (); - VkSemaphore semaphore = VK_NULL_HANDLE; - VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); - if (result != VK_SUCCESS) { + } - lastVKError = "vkCreateSemaphore failed"; - return 0; - } + value lime_vk_create_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value setLayouts, + int pushConstantStages, int pushConstantSize) { - lastVKError.clear (); - return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); -#else - lastVKError = "Lime was built without lime-vulkan support"; - return 0; -#endif + return LimeVulkanUnavailableValue (); } - void lime_vk_destroy_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int semaphoreHigh, - int semaphoreLow) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* setLayouts, int pushConstantStages, int pushConstantSize) { -#ifdef LIME_VULKAN - if (semaphoreHigh == 0 && semaphoreLow == 0) return; - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); - PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkDestroySemaphore"); - if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + return HLLimeVulkanUnavailableValue (); } - HL_PRIM void HL_NAME(hl_vk_destroy_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int semaphoreHigh, int semaphoreLow) { + void lime_vk_destroy_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int layoutHigh, + int layoutLow) { -#ifdef LIME_VULKAN - if (semaphoreHigh == 0 && semaphoreLow == 0) return; - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); - PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, - "vkDestroySemaphore"); - if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + LimeVulkanUnavailableVoid (); } - value lime_vk_create_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int flags) { - -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); - if (!vkCreateFence) return alloc_null (); + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int layoutHigh, int layoutLow) { - VkFenceCreateInfo createInfo; - memset (&createInfo, 0, sizeof (createInfo)); - createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - createInfo.flags = flags; + LimeVulkanUnavailableVoid (); - VkFence fence = VK_NULL_HANDLE; - VkResult result = vkCreateFence (device, &createInfo, 0, &fence); - if (result != VK_SUCCESS) { + } - lastVKError = "vkCreateFence failed"; - return alloc_null (); - } + value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { - lastVKError.clear (); - return CreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); -#else - lastVKError = "Lime was built without lime-vulkan support"; - return alloc_null (); -#endif + return LimeVulkanUnavailableValue (); } - HL_PRIM vdynamic* HL_NAME(hl_vk_create_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int flags) { - -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); - if (!vkCreateFence) return 0; + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow) { - VkFenceCreateInfo createInfo; - memset (&createInfo, 0, sizeof (createInfo)); - createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - createInfo.flags = flags; + return HLLimeVulkanUnavailableValue (); - VkFence fence = VK_NULL_HANDLE; - VkResult result = vkCreateFence (device, &createInfo, 0, &fence); - if (result != VK_SUCCESS) { + } - lastVKError = "vkCreateFence failed"; - return 0; - } + void lime_vk_destroy_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow) { - lastVKError.clear (); - return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); -#else - lastVKError = "Lime was built without lime-vulkan support"; - return 0; -#endif + LimeVulkanUnavailableVoid (); } - void lime_vk_destroy_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int cacheHigh, int cacheLow) { -#ifdef LIME_VULKAN - if (fenceHigh == 0 && fenceLow == 0) return; - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); - if (vkDestroyFence) vkDestroyFence (device, fence, 0); -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + LimeVulkanUnavailableVoid (); } - HL_PRIM void HL_NAME(hl_vk_destroy_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, - int fenceLow) { + value lime_vk_create_graphics_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, int fragmentShaderHigh, int fragmentShaderLow, + value state) { -#ifdef LIME_VULKAN - if (fenceHigh == 0 && fenceLow == 0) return; - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); - if (vkDestroyFence) vkDestroyFence (device, fence, 0); -#else - lastVKError = "Lime was built without lime-vulkan support"; -#endif + return LimeVulkanUnavailableValue (); } - bool lime_vk_wait_for_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow, - int timeoutHigh, int timeoutLow) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_graphics_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, + int fragmentShaderHigh, int fragmentShaderLow, hl_varray* state) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); - PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); - if (!vkWaitForFences) return false; + return HLLimeVulkanUnavailableValue (); - VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); - if (result != VK_SUCCESS) { + } - lastVKError = "vkWaitForFences failed"; - return false; - } + void lime_vk_destroy_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int pipelineHigh, + int pipelineLow) { - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + LimeVulkanUnavailableVoid (); } - HL_PRIM bool HL_NAME(hl_vk_wait_for_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, - int fenceLow, int timeoutHigh, int timeoutLow) { + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int pipelineHigh, int pipelineLow) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); - PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); - if (!vkWaitForFences) return false; + LimeVulkanUnavailableVoid (); - VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); - if (result != VK_SUCCESS) { + } - lastVKError = "vkWaitForFences failed"; - return false; - } + bool lime_vk_queue_submit_synced (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, value state) { - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + return LimeVulkanUnavailableBool (); } - bool lime_vk_reset_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + HL_PRIM bool HL_NAME(hl_vk_queue_submit_synced) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueHigh, int queueLow, int commandBufferHigh, int commandBufferLow, hl_varray* state) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); - if (!vkResetFences) return false; + return LimeVulkanUnavailableBool (); - VkResult result = vkResetFences (device, 1, &fence); - if (result != VK_SUCCESS) { + } - lastVKError = "vkResetFences failed"; - return false; - } + bool lime_vk_cmd_begin_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, value state, value clear) { - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_vk_reset_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, - int fenceLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_begin_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, + hl_varray* state, hl_varray* clear) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); - if (!vkResetFences) return false; + return LimeVulkanUnavailableBool (); - VkResult result = vkResetFences (device, 1, &fence); - if (result != VK_SUCCESS) { + } - lastVKError = "vkResetFences failed"; - return false; - } + bool lime_vk_cmd_end_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + return LimeVulkanUnavailableBool (); } - bool lime_vk_queue_submit (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow, - int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_end_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); - if (!vkQueueSubmit) return false; + return LimeVulkanUnavailableBool (); - VkSubmitInfo submitInfo; - memset (&submitInfo, 0, sizeof (submitInfo)); - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; + } - VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); - if (result != VK_SUCCESS) { - lastVKError = "vkQueueSubmit failed"; - return false; + bool lime_vk_cmd_bind_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { - } + return LimeVulkanUnavailableBool (); + + } - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { + + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_vk_queue_submit) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, - int queueLow, int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + bool lime_vk_cmd_bind_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, int firstSet) { -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); - PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); - if (!vkQueueSubmit) return false; + return LimeVulkanUnavailableBool (); - VkSubmitInfo submitInfo; - memset (&submitInfo, 0, sizeof (submitInfo)); - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; + } - VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); - if (result != VK_SUCCESS) { - lastVKError = "vkQueueSubmit failed"; - return false; + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, + int firstSet) { - } + return LimeVulkanUnavailableBool (); + + } - lastVKError.clear (); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif + + bool lime_vk_cmd_bind_vertex_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { + + return LimeVulkanUnavailableBool (); } - value lime_vk_get_last_error () { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_vertex_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { - return alloc_string (lastVKError.c_str ()); + return LimeVulkanUnavailableBool (); } - HL_PRIM vbyte* HL_NAME(hl_vk_get_last_error) () { + bool lime_vk_cmd_bind_index_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { - return hl_copy_bytes ((const vbyte*)lastVKError.c_str (), (int)lastVKError.size () + 1); + return LimeVulkanUnavailableBool (); } -#ifdef LIME_VULKAN - value lime_vulkan_renderer_create (value window, HxString applicationName) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_index_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { - Window* targetWindow = (Window*)val_data (window); - VulkanRenderer* renderer = new VulkanRenderer (targetWindow); + return LimeVulkanUnavailableBool (); - if (!renderer->Create (applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0)) { + } - lastVulkanRendererError = renderer->GetLastError (); - delete renderer; - return alloc_null (); - } + bool lime_vk_cmd_set_viewport (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - lastVulkanRendererError.clear (); - return CFFIPointer (renderer); + return LimeVulkanUnavailableBool (); } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_vulkan_renderer_create) (HL_CFFIPointer* window, hl_vstring* applicationName) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_viewport) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - Window* targetWindow = (Window*)window->ptr; - VulkanRenderer* renderer = new VulkanRenderer (targetWindow); - const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + return LimeVulkanUnavailableBool (); - if (!renderer->Create (applicationNameUTF8)) { + } - lastVulkanRendererError = renderer->GetLastError (); - delete renderer; - return 0; - } + bool lime_vk_cmd_set_scissor (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int x, int y, int width, int height) { - lastVulkanRendererError.clear (); - return HLCFFIPointer (renderer); + return LimeVulkanUnavailableBool (); } - void lime_vulkan_renderer_destroy (value handle) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_scissor) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int x, int y, int width, int height) { - if (val_is_null (handle)) return; - VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); - delete renderer; + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_vulkan_renderer_destroy) (HL_CFFIPointer* handle) { + bool lime_vk_cmd_draw (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - if (!handle || !handle->ptr) return; - VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; - handle->ptr = 0; - delete renderer; + return LimeVulkanUnavailableBool (); } - value lime_vulkan_renderer_get_info (value handle) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - if (val_is_null (handle)) return alloc_string (""); - VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); - return alloc_string (renderer->GetInfo ().c_str ()); + return LimeVulkanUnavailableBool (); } - HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_info) (HL_CFFIPointer* handle) { + bool lime_vk_cmd_draw_indexed (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { - if (!handle || !handle->ptr) return 0; - VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; - return hl_copy_bytes ((const vbyte*)renderer->GetInfo ().c_str (), (int)renderer->GetInfo ().size () + 1); + return LimeVulkanUnavailableBool (); } - value lime_vulkan_renderer_get_last_error () { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { - return alloc_string (lastVulkanRendererError.c_str ()); + return LimeVulkanUnavailableBool (); } - HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { + bool lime_vk_cmd_copy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { - return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); + return LimeVulkanUnavailableBool (); } - bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { - if (val_is_null (handle)) return false; - VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); - Bytes data (bytes); - bool result = renderer->SetOverlay (data.b, width, height, x, y); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_vulkan_renderer_set_overlay) (HL_CFFIPointer* handle, Bytes* bytes, int width, int height, int x, int y) { + bool lime_vk_cmd_copy_buffer_to_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, int height, int layout) { - if (!handle || !handle->ptr) return false; - VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; - bool result = renderer->SetOverlay (bytes ? bytes->b : 0, width, height, x, y); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - bool lime_vulkan_renderer_clear_overlay (value handle) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, + int height, int layout) { - if (val_is_null (handle)) return false; - VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); - bool result = renderer->ClearOverlay (); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_vulkan_renderer_clear_overlay) (HL_CFFIPointer* handle) { + bool lime_vk_cmd_pipeline_barrier_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state) { - if (!handle || !handle->ptr) return false; - VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; - bool result = renderer->ClearOverlay (); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - bool lime_vulkan_renderer_render (value handle, double red, double green, double blue, double alpha) { + HL_PRIM bool HL_NAME(hl_vk_cmd_pipeline_barrier_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state) { - if (val_is_null (handle)) return false; - VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); - bool result = renderer->Render (red, green, blue, alpha); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_vulkan_renderer_render) (HL_CFFIPointer* handle, double red, double green, double blue, double alpha) { + bool lime_vk_cmd_clear_color_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, value clear) { - if (!handle || !handle->ptr) return false; - VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; - bool result = renderer->Render (red, green, blue, alpha); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - bool lime_vulkan_renderer_resize (value handle) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_color_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, hl_varray* clear) { - if (val_is_null (handle)) return false; - VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); - bool result = renderer->Resize (); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_vulkan_renderer_resize) (HL_CFFIPointer* handle) { + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { - if (!handle || !handle->ptr) return false; - VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; - bool result = renderer->Resize (); - lastVulkanRendererError = renderer->GetLastError (); - return result; + return LimeVulkanUnavailableBool (); } -#else + + + HL_PRIM bool HL_NAME(hl_vk_cmd_blit_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { + + return LimeVulkanUnavailableBool (); + + } + + value lime_vulkan_renderer_create (value window, HxString applicationName) { lastVulkanRendererError = "Lime was built without lime-vulkan support"; @@ -6825,6 +11807,62 @@ namespace lime { DEFINE_PRIME9 (lime_vk_wait_for_fence); DEFINE_PRIME7 (lime_vk_reset_fence); DEFINE_PRIME11 (lime_vk_queue_submit); + DEFINE_PRIME11 (lime_vk_allocate_memory); + DEFINE_PRIME7v (lime_vk_free_memory); + DEFINE_PRIME12 (lime_vk_upload_memory); + DEFINE_PRIME8 (lime_vk_create_buffer); + DEFINE_PRIME7v (lime_vk_destroy_buffer); + DEFINE_PRIME7 (lime_vk_get_buffer_memory_requirements); + DEFINE_PRIME11 (lime_vk_bind_buffer_memory); + DEFINE_PRIME15 (lime_vk_create_image); + DEFINE_PRIME7v (lime_vk_destroy_image); + DEFINE_PRIME7 (lime_vk_get_image_memory_requirements); + DEFINE_PRIME11 (lime_vk_bind_image_memory); + DEFINE_PRIME15 (lime_vk_create_swapchain); + DEFINE_PRIME7v (lime_vk_destroy_swapchain); + DEFINE_PRIME7 (lime_vk_get_swapchain_images); + DEFINE_PRIME13 (lime_vk_acquire_next_image); + DEFINE_PRIME12 (lime_vk_queue_present); + DEFINE_PRIME10 (lime_vk_create_image_view); + DEFINE_PRIME7v (lime_vk_destroy_image_view); + DEFINE_PRIME14 (lime_vk_create_image_view_ex); + DEFINE_PRIME15 (lime_vk_create_render_pass); + DEFINE_PRIME7v (lime_vk_destroy_render_pass); + DEFINE_PRIME11 (lime_vk_create_framebuffer); + DEFINE_PRIME7v (lime_vk_destroy_framebuffer); + DEFINE_PRIME8 (lime_vk_create_shader_module); + DEFINE_PRIME7v (lime_vk_destroy_shader_module); + DEFINE_PRIME13 (lime_vk_create_sampler); + DEFINE_PRIME7v (lime_vk_destroy_sampler); + DEFINE_PRIME6 (lime_vk_create_descriptor_set_layout); + DEFINE_PRIME7v (lime_vk_destroy_descriptor_set_layout); + DEFINE_PRIME6 (lime_vk_create_descriptor_pool); + DEFINE_PRIME7v (lime_vk_destroy_descriptor_pool); + DEFINE_PRIME9 (lime_vk_allocate_descriptor_set); + DEFINE_PRIME14 (lime_vk_update_descriptor_set_image); + DEFINE_PRIME13 (lime_vk_update_descriptor_set_buffer); + DEFINE_PRIME8 (lime_vk_create_pipeline_layout); + DEFINE_PRIME7v (lime_vk_destroy_pipeline_layout); + DEFINE_PRIME5 (lime_vk_create_pipeline_cache); + DEFINE_PRIME7v (lime_vk_destroy_pipeline_cache); + DEFINE_PRIME14 (lime_vk_create_graphics_pipeline); + DEFINE_PRIME7v (lime_vk_destroy_pipeline); + DEFINE_PRIME10 (lime_vk_queue_submit_synced); + DEFINE_PRIME13 (lime_vk_cmd_begin_render_pass); + DEFINE_PRIME7 (lime_vk_cmd_end_render_pass); + DEFINE_PRIME10 (lime_vk_cmd_bind_pipeline); + DEFINE_PRIME13 (lime_vk_cmd_bind_descriptor_set); + DEFINE_PRIME12 (lime_vk_cmd_bind_vertex_buffer); + DEFINE_PRIME12 (lime_vk_cmd_bind_index_buffer); + DEFINE_PRIME13 (lime_vk_cmd_set_viewport); + DEFINE_PRIME11 (lime_vk_cmd_set_scissor); + DEFINE_PRIME11 (lime_vk_cmd_draw); + DEFINE_PRIME12 (lime_vk_cmd_draw_indexed); + DEFINE_PRIME12 (lime_vk_cmd_copy_buffer); + DEFINE_PRIME14 (lime_vk_cmd_copy_buffer_to_image); + DEFINE_PRIME10 (lime_vk_cmd_pipeline_barrier_image); + DEFINE_PRIME12 (lime_vk_cmd_clear_color_image); + DEFINE_PRIME12 (lime_vk_cmd_blit_image); DEFINE_PRIME0 (lime_vk_get_last_error); DEFINE_PRIME2 (lime_vulkan_renderer_create); DEFINE_PRIME1v (lime_vulkan_renderer_destroy); @@ -7060,6 +12098,13 @@ namespace lime { DEFINE_HL_PRIM (_BOOL, hl_vk_wait_for_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_BOOL, hl_vk_reset_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_BOOL, hl_vk_queue_submit, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_swapchain, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_swapchain, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_ARR, hl_vk_get_swapchain_images, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_acquire_next_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_I32, hl_vk_queue_present, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_image_view, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_image_view, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_BYTES, hl_vk_get_last_error, _NO_ARG); DEFINE_HL_PRIM (_TCFFIPOINTER, hl_vulkan_renderer_create, _TCFFIPOINTER _STRING); DEFINE_HL_PRIM (_VOID, hl_vulkan_renderer_destroy, _TCFFIPOINTER); diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index a33d5fa464..f36431e453 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -414,6 +414,182 @@ class NativeCFFI @:cffi private static function lime_vk_queue_submit(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, fenceLow:Int):Bool; + + @:cffi private static function lime_vk_allocate_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, + physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, memoryTypeBits:Int, properties:Int):Dynamic; + + @:cffi private static function lime_vk_free_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int):Void; + + @:cffi private static function lime_vk_upload_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + + @:cffi private static function lime_vk_create_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bufferHigh:Int, bufferLow:Int):Void; + + @:cffi private static function lime_vk_get_buffer_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, bufferHigh:Int, bufferLow:Int):Dynamic; + + @:cffi private static function lime_vk_bind_buffer_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; + + @:cffi private static function lime_vk_create_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + width:Int, height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, imageType:Int, tiling:Int, usage:Int, samples:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int):Void; + + @:cffi private static function lime_vk_get_image_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, imageHigh:Int, imageLow:Int):Dynamic; + + @:cffi private static function lime_vk_bind_image_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; + + @:cffi private static function lime_vk_create_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, + physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, queueFamilyIndex:Int, width:Int, height:Int, + presentMode:Int, oldSwapchainHigh:Int, oldSwapchainLow:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + swapchainHigh:Int, swapchainLow:Int):Void; + + @:cffi private static function lime_vk_get_swapchain_images(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + swapchainHigh:Int, swapchainLow:Int):Dynamic; + + @:cffi private static function lime_vk_acquire_next_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + swapchainHigh:Int, swapchainLow:Int, timeoutHigh:Int, timeoutLow:Int, semaphoreHigh:Int, semaphoreLow:Int, fenceHigh:Int, fenceLow:Int):Dynamic; + + @:cffi private static function lime_vk_queue_present(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, + queueLow:Int, swapchainHigh:Int, swapchainLow:Int, imageIndex:Int, waitSemaphoreHigh:Int, waitSemaphoreLow:Int):Int; + + @:cffi private static function lime_vk_create_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageViewHigh:Int, imageViewLow:Int):Void; + + @:cffi private static function lime_vk_create_image_view_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int, baseMipLevel:Int, levelCount:Int, baseArrayLayer:Int, + layerCount:Int):Dynamic; + + @:cffi private static function lime_vk_create_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + colorFormat:Int, depthStencilFormat:Int, samples:Int, colorLoadOp:Int, colorStoreOp:Int, colorInitialLayout:Int, colorFinalLayout:Int, + depthLoadOp:Int, depthStoreOp:Int, depthFinalLayout:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + renderPassHigh:Int, renderPassLow:Int):Void; + + @:cffi private static function lime_vk_create_framebuffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + renderPassHigh:Int, renderPassLow:Int, attachments:Array, width:Int, height:Int, layers:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_framebuffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + framebufferHigh:Int, framebufferLow:Int):Void; + + @:cffi private static function lime_vk_create_shader_module(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bytes:Dynamic, byteOffset:Int, byteLength:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_shader_module(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + shaderModuleHigh:Int, shaderModuleLow:Int):Void; + + @:cffi private static function lime_vk_create_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + filter:Int, addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, maxAnisotropy:Float, compareOp:Int, minLod:Float, maxLod:Float):Dynamic; + + @:cffi private static function lime_vk_destroy_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + samplerHigh:Int, samplerLow:Int):Void; + + @:cffi private static function lime_vk_create_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, bindings:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void; + + @:cffi private static function lime_vk_create_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, poolSizes:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, poolHigh:Int, poolLow:Int):Void; + + @:cffi private static function lime_vk_allocate_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic; + + @:cffi private static function lime_vk_update_descriptor_set_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, imageViewHigh:Int, imageViewLow:Int, samplerHigh:Int, + samplerLow:Int, imageLayout:Int):Bool; + + @:cffi private static function lime_vk_update_descriptor_set_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool; + + @:cffi private static function lime_vk_create_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, setLayouts:Array, pushConstantStages:Int, pushConstantSize:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void; + + @:cffi private static function lime_vk_create_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void; + + @:cffi private static function lime_vk_create_graphics_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, + fragmentShaderHigh:Int, fragmentShaderLow:Int, state:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + pipelineHigh:Int, pipelineLow:Int):Void; + + @:cffi private static function lime_vk_queue_submit_synced(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_begin_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, renderPassLow:Int, framebufferHigh:Int, framebufferLow:Int, + state:Array, clear:Array):Bool; + + @:cffi private static function lime_vk_cmd_end_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, bindPoint:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, + firstSet:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_vertex_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_index_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, indexType:Int):Bool; + + @:cffi private static function lime_vk_cmd_set_viewport(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, x:Float, y:Float, width:Float, height:Float, minDepth:Float, maxDepth:Float):Bool; + + @:cffi private static function lime_vk_cmd_set_scissor(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, height:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, firstInstance:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw_indexed(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, firstIndex:Int, vertexOffset:Int, firstInstance:Int):Bool; + + @:cffi private static function lime_vk_cmd_copy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_copy_buffer_to_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, width:Int, + height:Int, layout:Int):Bool; + + @:cffi private static function lime_vk_cmd_pipeline_barrier_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_clear_color_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, layout:Int, aspectMask:Int, clear:Array):Bool; + + @:cffi private static function lime_vk_cmd_blit_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; #end @:cffi private static function lime_vk_get_last_error():Dynamic; @@ -789,6 +965,118 @@ class NativeCFFI "lime_vk_reset_fence", "oiiiiiib", false)); private static var lime_vk_queue_submit = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_queue_submit", "oiiiiiiiiiib", false)); + private static var lime_vk_allocate_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime( + "lime", "lime_vk_allocate_memory", "oiiiiiiiiiio", false)); + private static var lime_vk_free_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_free_memory", "oiiiiiiv", false)); + private static var lime_vk_upload_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_upload_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_create_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_buffer", "oiiiiiiio", false)); + private static var lime_vk_destroy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_buffer", "oiiiiiiv", false)); + private static var lime_vk_get_buffer_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_buffer_memory_requirements", "oiiiiiio", false)); + private static var lime_vk_bind_buffer_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_bind_buffer_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_create_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( + cpp.Prime._loadPrime("lime", "lime_vk_create_image", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_destroy_image = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_image", "oiiiiiiv", false)); + private static var lime_vk_get_image_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_image_memory_requirements", "oiiiiiio", false)); + private static var lime_vk_bind_image_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_bind_image_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_create_swapchain = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_swapchain", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_destroy_swapchain = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_swapchain", "oiiiiiiv", false)); + private static var lime_vk_get_swapchain_images = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_swapchain_images", "oiiiiiio", false)); + private static var lime_vk_acquire_next_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_acquire_next_image", "oiiiiiiiiiiiio", false)); + private static var lime_vk_queue_present = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int>(cpp.Prime._loadPrime("lime", + "lime_vk_queue_present", "oiiiiiiiiiiii", false)); + private static var lime_vk_create_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_image_view", "oiiiiiiiiio", false)); + private static var lime_vk_destroy_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_image_view", "oiiiiiiv", false)); + private static var lime_vk_create_image_view_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( + cpp.Prime._loadPrime("lime", "lime_vk_create_image_view_ex", "oiiiiiiiiiiiiio", false)); + private static var lime_vk_create_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( + cpp.Prime._loadPrime("lime", "lime_vk_create_render_pass", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_destroy_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_render_pass", "oiiiiiiv", false)); + private static var lime_vk_create_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Int->cpp.Object>( + cpp.Prime._loadPrime("lime", "lime_vk_create_framebuffer", "oiiiiiioiiio", false)); + private static var lime_vk_destroy_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_framebuffer", "oiiiiiiv", false)); + private static var lime_vk_create_shader_module = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_shader_module", "oiiiioiio", false)); + private static var lime_vk_destroy_shader_module = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_shader_module", "oiiiiiiv", false)); + private static var lime_vk_create_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool->Float->Int->Float->Float->cpp.Object>( + cpp.Prime._loadPrime("lime", "lime_vk_create_sampler", "oiiiiiiibdiddo", false)); + private static var lime_vk_destroy_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_sampler", "oiiiiiiv", false)); + private static var lime_vk_create_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_descriptor_set_layout", "oiiiioo", false)); + private static var lime_vk_destroy_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_descriptor_set_layout", "oiiiiiiv", false)); + private static var lime_vk_create_descriptor_pool = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_descriptor_pool", "oiiiioo", false)); + private static var lime_vk_destroy_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_descriptor_pool", "oiiiiiiv", false)); + private static var lime_vk_allocate_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_allocate_descriptor_set", "oiiiiiiiio", false)); + private static var lime_vk_update_descriptor_set_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_image", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_update_descriptor_set_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_buffer", "oiiiiiiiiiiiib", false)); + private static var lime_vk_create_pipeline_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_pipeline_layout", "oiiiioiio", false)); + private static var lime_vk_destroy_pipeline_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_pipeline_layout", "oiiiiiiv", false)); + private static var lime_vk_create_pipeline_cache = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_pipeline_cache", "oiiiio", false)); + private static var lime_vk_destroy_pipeline_cache = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_pipeline_cache", "oiiiiiiv", false)); + private static var lime_vk_create_graphics_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_graphics_pipeline", "oiiiiiiiiiiiioo", false)); + private static var lime_vk_destroy_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_pipeline", "oiiiiiiv", false)); + private static var lime_vk_queue_submit_synced = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_queue_submit_synced", "oiiiiiiiiob", false)); + private static var lime_vk_cmd_begin_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_begin_render_pass", "oiiiiiiiiiioob", false)); + private static var lime_vk_cmd_end_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_end_render_pass", "oiiiiiib", false)); + private static var lime_vk_cmd_bind_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_bind_pipeline", "oiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_vertex_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_vertex_buffer", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_index_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_index_buffer", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_set_viewport = new cpp.CallableInt->Int->Int->Int->Int->Int->Float->Float->Float->Float->Float->Float->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_set_viewport", "oiiiiiiddddddb", false)); + private static var lime_vk_cmd_set_scissor = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_set_scissor", "oiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_draw", "oiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indexed = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_draw_indexed", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_copy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_copy_buffer_to_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_pipeline_barrier_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_pipeline_barrier_image", "oiiiiiiiiob", false)); + private static var lime_vk_cmd_clear_color_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_color_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_blit_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_blit_image", "oiiiiiiiiiiob", false)); #end private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_last_error", "o", false)); @@ -1031,6 +1319,62 @@ class NativeCFFI private static var lime_vk_wait_for_fence = CFFI.load("lime", "lime_vk_wait_for_fence", -1); private static var lime_vk_reset_fence = CFFI.load("lime", "lime_vk_reset_fence", -1); private static var lime_vk_queue_submit = CFFI.load("lime", "lime_vk_queue_submit", -1); + private static var lime_vk_allocate_memory = CFFI.load("lime", "lime_vk_allocate_memory", -1); + private static var lime_vk_free_memory = CFFI.load("lime", "lime_vk_free_memory", -1); + private static var lime_vk_upload_memory = CFFI.load("lime", "lime_vk_upload_memory", -1); + private static var lime_vk_create_buffer = CFFI.load("lime", "lime_vk_create_buffer", -1); + private static var lime_vk_destroy_buffer = CFFI.load("lime", "lime_vk_destroy_buffer", -1); + private static var lime_vk_get_buffer_memory_requirements = CFFI.load("lime", "lime_vk_get_buffer_memory_requirements", -1); + private static var lime_vk_bind_buffer_memory = CFFI.load("lime", "lime_vk_bind_buffer_memory", -1); + private static var lime_vk_create_image = CFFI.load("lime", "lime_vk_create_image", -1); + private static var lime_vk_destroy_image = CFFI.load("lime", "lime_vk_destroy_image", -1); + private static var lime_vk_get_image_memory_requirements = CFFI.load("lime", "lime_vk_get_image_memory_requirements", -1); + private static var lime_vk_bind_image_memory = CFFI.load("lime", "lime_vk_bind_image_memory", -1); + private static var lime_vk_create_swapchain = CFFI.load("lime", "lime_vk_create_swapchain", -1); + private static var lime_vk_destroy_swapchain = CFFI.load("lime", "lime_vk_destroy_swapchain", -1); + private static var lime_vk_get_swapchain_images = CFFI.load("lime", "lime_vk_get_swapchain_images", -1); + private static var lime_vk_acquire_next_image = CFFI.load("lime", "lime_vk_acquire_next_image", -1); + private static var lime_vk_queue_present = CFFI.load("lime", "lime_vk_queue_present", -1); + private static var lime_vk_create_image_view = CFFI.load("lime", "lime_vk_create_image_view", -1); + private static var lime_vk_destroy_image_view = CFFI.load("lime", "lime_vk_destroy_image_view", -1); + private static var lime_vk_create_image_view_ex = CFFI.load("lime", "lime_vk_create_image_view_ex", -1); + private static var lime_vk_create_render_pass = CFFI.load("lime", "lime_vk_create_render_pass", -1); + private static var lime_vk_destroy_render_pass = CFFI.load("lime", "lime_vk_destroy_render_pass", -1); + private static var lime_vk_create_framebuffer = CFFI.load("lime", "lime_vk_create_framebuffer", -1); + private static var lime_vk_destroy_framebuffer = CFFI.load("lime", "lime_vk_destroy_framebuffer", -1); + private static var lime_vk_create_shader_module = CFFI.load("lime", "lime_vk_create_shader_module", -1); + private static var lime_vk_destroy_shader_module = CFFI.load("lime", "lime_vk_destroy_shader_module", -1); + private static var lime_vk_create_sampler = CFFI.load("lime", "lime_vk_create_sampler", -1); + private static var lime_vk_destroy_sampler = CFFI.load("lime", "lime_vk_destroy_sampler", -1); + private static var lime_vk_create_descriptor_set_layout = CFFI.load("lime", "lime_vk_create_descriptor_set_layout", -1); + private static var lime_vk_destroy_descriptor_set_layout = CFFI.load("lime", "lime_vk_destroy_descriptor_set_layout", -1); + private static var lime_vk_create_descriptor_pool = CFFI.load("lime", "lime_vk_create_descriptor_pool", -1); + private static var lime_vk_destroy_descriptor_pool = CFFI.load("lime", "lime_vk_destroy_descriptor_pool", -1); + private static var lime_vk_allocate_descriptor_set = CFFI.load("lime", "lime_vk_allocate_descriptor_set", -1); + private static var lime_vk_update_descriptor_set_image = CFFI.load("lime", "lime_vk_update_descriptor_set_image", -1); + private static var lime_vk_update_descriptor_set_buffer = CFFI.load("lime", "lime_vk_update_descriptor_set_buffer", -1); + private static var lime_vk_create_pipeline_layout = CFFI.load("lime", "lime_vk_create_pipeline_layout", -1); + private static var lime_vk_destroy_pipeline_layout = CFFI.load("lime", "lime_vk_destroy_pipeline_layout", -1); + private static var lime_vk_create_pipeline_cache = CFFI.load("lime", "lime_vk_create_pipeline_cache", -1); + private static var lime_vk_destroy_pipeline_cache = CFFI.load("lime", "lime_vk_destroy_pipeline_cache", -1); + private static var lime_vk_create_graphics_pipeline = CFFI.load("lime", "lime_vk_create_graphics_pipeline", -1); + private static var lime_vk_destroy_pipeline = CFFI.load("lime", "lime_vk_destroy_pipeline", -1); + private static var lime_vk_queue_submit_synced = CFFI.load("lime", "lime_vk_queue_submit_synced", -1); + private static var lime_vk_cmd_begin_render_pass = CFFI.load("lime", "lime_vk_cmd_begin_render_pass", -1); + private static var lime_vk_cmd_end_render_pass = CFFI.load("lime", "lime_vk_cmd_end_render_pass", -1); + private static var lime_vk_cmd_bind_pipeline = CFFI.load("lime", "lime_vk_cmd_bind_pipeline", -1); + private static var lime_vk_cmd_bind_descriptor_set = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set", -1); + private static var lime_vk_cmd_bind_vertex_buffer = CFFI.load("lime", "lime_vk_cmd_bind_vertex_buffer", -1); + private static var lime_vk_cmd_bind_index_buffer = CFFI.load("lime", "lime_vk_cmd_bind_index_buffer", -1); + private static var lime_vk_cmd_set_viewport = CFFI.load("lime", "lime_vk_cmd_set_viewport", -1); + private static var lime_vk_cmd_set_scissor = CFFI.load("lime", "lime_vk_cmd_set_scissor", -1); + private static var lime_vk_cmd_draw = CFFI.load("lime", "lime_vk_cmd_draw", -1); + private static var lime_vk_cmd_draw_indexed = CFFI.load("lime", "lime_vk_cmd_draw_indexed", -1); + private static var lime_vk_cmd_copy_buffer = CFFI.load("lime", "lime_vk_cmd_copy_buffer", -1); + private static var lime_vk_cmd_copy_buffer_to_image = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image", -1); + private static var lime_vk_cmd_pipeline_barrier_image = CFFI.load("lime", "lime_vk_cmd_pipeline_barrier_image", -1); + private static var lime_vk_cmd_clear_color_image = CFFI.load("lime", "lime_vk_cmd_clear_color_image", -1); + private static var lime_vk_cmd_blit_image = CFFI.load("lime", "lime_vk_cmd_blit_image", -1); #end private static var lime_vk_get_last_error = CFFI.load("lime", "lime_vk_get_last_error", 0); private static var lime_vulkan_renderer_create = CFFI.load("lime", "lime_vulkan_renderer_create", 2); @@ -1804,6 +2148,332 @@ class NativeCFFI { return false; } + + @:hlNative("lime", "hl_vk_allocate_memory") private static function lime_vk_allocate_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, + memoryTypeBits:Int, properties:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_free_memory") private static function lime_vk_free_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} + + @:hlNative("lime", "hl_vk_upload_memory") private static function lime_vk_upload_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, + byteOffset:Int, byteLength:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_buffer") private static function lime_vk_create_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_buffer") private static function lime_vk_destroy_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_buffer_memory_requirements") private static function lime_vk_get_buffer_memory_requirements(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_bind_buffer_memory") private static function lime_vk_bind_buffer_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, + offsetLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_image") private static function lime_vk_create_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, width:Int, height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, + imageType:Int, tiling:Int, usage:Int, samples:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_image") private static function lime_vk_destroy_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_image_memory_requirements") private static function lime_vk_get_image_memory_requirements(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_bind_image_memory") private static function lime_vk_bind_image_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, + offsetLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_swapchain") private static function lime_vk_create_swapchain(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, + queueFamilyIndex:Int, width:Int, height:Int, presentMode:Int, oldSwapchainHigh:Int, oldSwapchainLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_swapchain") private static function lime_vk_destroy_swapchain(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_swapchain_images") private static function lime_vk_get_swapchain_images(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):hl.NativeArray + { + return null; + } + + @:hlNative("lime", "hl_vk_acquire_next_image") private static function lime_vk_acquire_next_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int, timeoutHigh:Int, timeoutLow:Int, semaphoreHigh:Int, + semaphoreLow:Int, fenceHigh:Int, fenceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_queue_present") private static function lime_vk_queue_present(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, swapchainHigh:Int, swapchainLow:Int, imageIndex:Int, waitSemaphoreHigh:Int, + waitSemaphoreLow:Int):Int + { + return -3; + } + + @:hlNative("lime", "hl_vk_create_image_view") private static function lime_vk_create_image_view(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_image_view") private static function lime_vk_destroy_image_view(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageViewHigh:Int, imageViewLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_image_view_ex") private static function lime_vk_create_image_view_ex(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, + viewType:Int, baseMipLevel:Int, levelCount:Int, baseArrayLayer:Int, layerCount:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_create_render_pass") private static function lime_vk_create_render_pass(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, colorFormat:Int, depthStencilFormat:Int, samples:Int, colorLoadOp:Int, + colorStoreOp:Int, colorInitialLayout:Int, colorFinalLayout:Int, depthLoadOp:Int, depthStoreOp:Int, depthFinalLayout:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_render_pass") private static function lime_vk_destroy_render_pass(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_framebuffer") private static function lime_vk_create_framebuffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, attachments:hl.NativeArray, + width:Int, height:Int, layers:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_framebuffer") private static function lime_vk_destroy_framebuffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, framebufferHigh:Int, framebufferLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_shader_module") private static function lime_vk_create_shader_module(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_shader_module") private static function lime_vk_destroy_shader_module(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, shaderModuleHigh:Int, shaderModuleLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_sampler") private static function lime_vk_create_sampler(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, filter:Int, addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, + maxAnisotropy:Float, compareOp:Int, minLod:Float, maxLod:Float):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_sampler") private static function lime_vk_destroy_sampler(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, samplerHigh:Int, samplerLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_descriptor_set_layout") private static function lime_vk_create_descriptor_set_layout(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bindings:hl.NativeArray):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_descriptor_set_layout") private static function lime_vk_destroy_descriptor_set_layout(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_descriptor_pool") private static function lime_vk_create_descriptor_pool(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolSizes:hl.NativeArray):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_descriptor_pool") private static function lime_vk_destroy_descriptor_pool(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int):Void {} + + @:hlNative("lime", "hl_vk_allocate_descriptor_set") private static function lime_vk_allocate_descriptor_set(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_update_descriptor_set_image") private static function lime_vk_update_descriptor_set_image(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, + imageViewHigh:Int, imageViewLow:Int, samplerHigh:Int, samplerLow:Int, imageLayout:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_update_descriptor_set_buffer") private static function lime_vk_update_descriptor_set_buffer(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, + bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_pipeline_layout") private static function lime_vk_create_pipeline_layout(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setLayouts:hl.NativeArray, pushConstantStages:Int, + pushConstantSize:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_pipeline_layout") private static function lime_vk_destroy_pipeline_layout(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_pipeline_cache") private static function lime_vk_create_pipeline_cache(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_pipeline_cache") private static function lime_vk_destroy_pipeline_cache(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_graphics_pipeline") private static function lime_vk_create_graphics_pipeline(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, + layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, fragmentShaderHigh:Int, fragmentShaderLow:Int, + state:hl.NativeArray):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_pipeline") private static function lime_vk_destroy_pipeline(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, pipelineHigh:Int, pipelineLow:Int):Void {} + + @:hlNative("lime", "hl_vk_queue_submit_synced") private static function lime_vk_queue_submit_synced(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, + commandBufferLow:Int, state:hl.NativeArray):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_begin_render_pass") private static function lime_vk_cmd_begin_render_pass(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, + renderPassLow:Int, framebufferHigh:Int, framebufferLow:Int, state:hl.NativeArray, clear:hl.NativeArray):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_end_render_pass") private static function lime_vk_cmd_end_render_pass(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_bind_pipeline") private static function lime_vk_cmd_bind_pipeline(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, + bindPoint:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set") private static function lime_vk_cmd_bind_descriptor_set(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, + layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, firstSet:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_bind_vertex_buffer") private static function lime_vk_cmd_bind_vertex_buffer(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, + bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_bind_index_buffer") private static function lime_vk_cmd_bind_index_buffer(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, + bufferLow:Int, offsetHigh:Int, offsetLow:Int, indexType:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_set_viewport") private static function lime_vk_cmd_set_viewport(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Float, y:Float, width:Float, + height:Float, minDepth:Float, maxDepth:Float):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_set_scissor") private static function lime_vk_cmd_set_scissor(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, + height:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_draw") private static function lime_vk_cmd_draw(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, + firstInstance:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_draw_indexed") private static function lime_vk_cmd_draw_indexed(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, + firstIndex:Int, vertexOffset:Int, firstInstance:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_copy_buffer") private static function lime_vk_cmd_copy_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, + destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_copy_buffer_to_image") private static function lime_vk_cmd_copy_buffer_to_image(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, + bufferLow:Int, imageHigh:Int, imageLow:Int, width:Int, height:Int, layout:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_pipeline_barrier_image") private static function lime_vk_cmd_pipeline_barrier_image(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, + imageLow:Int, state:hl.NativeArray):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_clear_color_image") private static function lime_vk_cmd_clear_color_image(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, + imageLow:Int, layout:Int, aspectMask:Int, clear:hl.NativeArray):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_blit_image") private static function lime_vk_cmd_blit_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, + destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool + { + return false; + } #end @:hlNative("lime", "hl_vk_get_last_error") private static function lime_vk_get_last_error():hl.Bytes diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx index 24cc8b32e3..149ef3e60f 100644 --- a/src/lime/graphics/vulkan/VK.hx +++ b/src/lime/graphics/vulkan/VK.hx @@ -27,6 +27,9 @@ class VK public static inline var EVENT_SET = 3; public static inline var EVENT_RESET = 4; public static inline var INCOMPLETE = 5; + public static inline var SUBOPTIMAL_KHR = 1000001003; + public static inline var ERROR_INITIALIZATION_FAILED = -3; + public static inline var ERROR_OUT_OF_DATE_KHR = -1000001004; public static inline var KHR_SWAPCHAIN_EXTENSION_NAME = "VK_KHR_swapchain"; @@ -56,6 +59,245 @@ class VK public static inline var FENCE_CREATE_SIGNALED_BIT = 0x00000001; + public static inline var FORMAT_UNDEFINED = 0; + public static inline var FORMAT_R8_UNORM = 9; + public static inline var FORMAT_R8G8_UNORM = 16; + public static inline var FORMAT_R8G8B8A8_UNORM = 37; + public static inline var FORMAT_R8G8B8A8_SRGB = 43; + public static inline var FORMAT_B8G8R8A8_UNORM = 44; + public static inline var FORMAT_B8G8R8A8_SRGB = 50; + public static inline var FORMAT_R16G16B16A16_SFLOAT = 97; + public static inline var FORMAT_R32_SFLOAT = 100; + public static inline var FORMAT_R32G32_SFLOAT = 103; + public static inline var FORMAT_R32G32B32_SFLOAT = 106; + public static inline var FORMAT_R32G32B32A32_SFLOAT = 109; + public static inline var FORMAT_D16_UNORM = 124; + public static inline var FORMAT_X8_D24_UNORM_PACK32 = 125; + public static inline var FORMAT_D32_SFLOAT = 126; + public static inline var FORMAT_S8_UINT = 127; + public static inline var FORMAT_D24_UNORM_S8_UINT = 129; + public static inline var FORMAT_D32_SFLOAT_S8_UINT = 130; + + public static inline var COLOR_SPACE_SRGB_NONLINEAR_KHR = 0; + + public static inline var PRESENT_MODE_IMMEDIATE_KHR = 0; + public static inline var PRESENT_MODE_MAILBOX_KHR = 1; + public static inline var PRESENT_MODE_FIFO_KHR = 2; + public static inline var PRESENT_MODE_FIFO_RELAXED_KHR = 3; + + public static inline var BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001; + public static inline var BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002; + public static inline var BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004; + public static inline var BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008; + public static inline var BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010; + public static inline var BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020; + public static inline var BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040; + public static inline var BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080; + public static inline var BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100; + + public static inline var MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001; + public static inline var MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002; + public static inline var MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004; + public static inline var MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008; + public static inline var MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010; + + public static inline var IMAGE_TYPE_1D = 0; + public static inline var IMAGE_TYPE_2D = 1; + public static inline var IMAGE_TYPE_3D = 2; + + public static inline var IMAGE_TILING_OPTIMAL = 0; + public static inline var IMAGE_TILING_LINEAR = 1; + + public static inline var IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001; + public static inline var IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002; + public static inline var IMAGE_USAGE_SAMPLED_BIT = 0x00000004; + public static inline var IMAGE_USAGE_STORAGE_BIT = 0x00000008; + public static inline var IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010; + public static inline var IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020; + public static inline var IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040; + public static inline var IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080; + + public static inline var IMAGE_ASPECT_COLOR_BIT = 0x00000001; + public static inline var IMAGE_ASPECT_DEPTH_BIT = 0x00000002; + public static inline var IMAGE_ASPECT_STENCIL_BIT = 0x00000004; + public static inline var IMAGE_ASPECT_METADATA_BIT = 0x00000008; + + public static inline var IMAGE_LAYOUT_UNDEFINED = 0; + public static inline var IMAGE_LAYOUT_GENERAL = 1; + public static inline var IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2; + public static inline var IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3; + public static inline var IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4; + public static inline var IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5; + public static inline var IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6; + public static inline var IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7; + public static inline var IMAGE_LAYOUT_PREINITIALIZED = 8; + public static inline var IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002; + + public static inline var IMAGE_VIEW_TYPE_1D = 0; + public static inline var IMAGE_VIEW_TYPE_2D = 1; + public static inline var IMAGE_VIEW_TYPE_3D = 2; + public static inline var IMAGE_VIEW_TYPE_CUBE = 3; + public static inline var IMAGE_VIEW_TYPE_1D_ARRAY = 4; + public static inline var IMAGE_VIEW_TYPE_2D_ARRAY = 5; + public static inline var IMAGE_VIEW_TYPE_CUBE_ARRAY = 6; + + public static inline var PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001; + public static inline var PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002; + public static inline var PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004; + public static inline var PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008; + public static inline var PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080; + public static inline var PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100; + public static inline var PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200; + public static inline var PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400; + public static inline var PIPELINE_STAGE_TRANSFER_BIT = 0x00001000; + public static inline var PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000; + public static inline var PIPELINE_STAGE_HOST_BIT = 0x00004000; + public static inline var PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000; + public static inline var PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000; + + public static inline var ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001; + public static inline var ACCESS_INDEX_READ_BIT = 0x00000002; + public static inline var ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004; + public static inline var ACCESS_UNIFORM_READ_BIT = 0x00000008; + public static inline var ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010; + public static inline var ACCESS_SHADER_READ_BIT = 0x00000020; + public static inline var ACCESS_SHADER_WRITE_BIT = 0x00000040; + public static inline var ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080; + public static inline var ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100; + public static inline var ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200; + public static inline var ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400; + public static inline var ACCESS_TRANSFER_READ_BIT = 0x00000800; + public static inline var ACCESS_TRANSFER_WRITE_BIT = 0x00001000; + public static inline var ACCESS_HOST_READ_BIT = 0x00002000; + public static inline var ACCESS_HOST_WRITE_BIT = 0x00004000; + public static inline var ACCESS_MEMORY_READ_BIT = 0x00008000; + public static inline var ACCESS_MEMORY_WRITE_BIT = 0x00010000; + + public static inline var SHADER_STAGE_VERTEX_BIT = 0x00000001; + public static inline var SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002; + public static inline var SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004; + public static inline var SHADER_STAGE_GEOMETRY_BIT = 0x00000008; + public static inline var SHADER_STAGE_FRAGMENT_BIT = 0x00000010; + public static inline var SHADER_STAGE_COMPUTE_BIT = 0x00000020; + public static inline var SHADER_STAGE_ALL_GRAPHICS = 0x0000001F; + public static inline var SHADER_STAGE_ALL = 0x7FFFFFFF; + + public static inline var DESCRIPTOR_TYPE_SAMPLER = 0; + public static inline var DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1; + public static inline var DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2; + public static inline var DESCRIPTOR_TYPE_STORAGE_IMAGE = 3; + public static inline var DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4; + public static inline var DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5; + public static inline var DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6; + public static inline var DESCRIPTOR_TYPE_STORAGE_BUFFER = 7; + public static inline var DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8; + public static inline var DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9; + public static inline var DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10; + + public static inline var PRIMITIVE_TOPOLOGY_POINT_LIST = 0; + public static inline var PRIMITIVE_TOPOLOGY_LINE_LIST = 1; + public static inline var PRIMITIVE_TOPOLOGY_LINE_STRIP = 2; + public static inline var PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3; + public static inline var PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4; + public static inline var PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5; + + public static inline var POLYGON_MODE_FILL = 0; + public static inline var POLYGON_MODE_LINE = 1; + public static inline var POLYGON_MODE_POINT = 2; + + public static inline var CULL_MODE_NONE = 0; + public static inline var CULL_MODE_FRONT_BIT = 0x00000001; + public static inline var CULL_MODE_BACK_BIT = 0x00000002; + public static inline var CULL_MODE_FRONT_AND_BACK = 0x00000003; + + public static inline var FRONT_FACE_COUNTER_CLOCKWISE = 0; + public static inline var FRONT_FACE_CLOCKWISE = 1; + + public static inline var COMPARE_OP_NEVER = 0; + public static inline var COMPARE_OP_LESS = 1; + public static inline var COMPARE_OP_EQUAL = 2; + public static inline var COMPARE_OP_LESS_OR_EQUAL = 3; + public static inline var COMPARE_OP_GREATER = 4; + public static inline var COMPARE_OP_NOT_EQUAL = 5; + public static inline var COMPARE_OP_GREATER_OR_EQUAL = 6; + public static inline var COMPARE_OP_ALWAYS = 7; + + public static inline var STENCIL_OP_KEEP = 0; + public static inline var STENCIL_OP_ZERO = 1; + public static inline var STENCIL_OP_REPLACE = 2; + public static inline var STENCIL_OP_INCREMENT_AND_CLAMP = 3; + public static inline var STENCIL_OP_DECREMENT_AND_CLAMP = 4; + public static inline var STENCIL_OP_INVERT = 5; + public static inline var STENCIL_OP_INCREMENT_AND_WRAP = 6; + public static inline var STENCIL_OP_DECREMENT_AND_WRAP = 7; + + public static inline var BLEND_FACTOR_ZERO = 0; + public static inline var BLEND_FACTOR_ONE = 1; + public static inline var BLEND_FACTOR_SRC_COLOR = 2; + public static inline var BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3; + public static inline var BLEND_FACTOR_DST_COLOR = 4; + public static inline var BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5; + public static inline var BLEND_FACTOR_SRC_ALPHA = 6; + public static inline var BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7; + public static inline var BLEND_FACTOR_DST_ALPHA = 8; + public static inline var BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9; + public static inline var BLEND_FACTOR_CONSTANT_COLOR = 10; + public static inline var BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11; + public static inline var BLEND_FACTOR_CONSTANT_ALPHA = 12; + public static inline var BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13; + public static inline var BLEND_FACTOR_SRC_ALPHA_SATURATE = 14; + + public static inline var BLEND_OP_ADD = 0; + public static inline var BLEND_OP_SUBTRACT = 1; + public static inline var BLEND_OP_REVERSE_SUBTRACT = 2; + public static inline var BLEND_OP_MIN = 3; + public static inline var BLEND_OP_MAX = 4; + + public static inline var DYNAMIC_STATE_VIEWPORT = 0; + public static inline var DYNAMIC_STATE_SCISSOR = 1; + public static inline var DYNAMIC_STATE_LINE_WIDTH = 2; + public static inline var DYNAMIC_STATE_DEPTH_BIAS = 3; + public static inline var DYNAMIC_STATE_BLEND_CONSTANTS = 4; + public static inline var DYNAMIC_STATE_DEPTH_BOUNDS = 5; + public static inline var DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6; + public static inline var DYNAMIC_STATE_STENCIL_WRITE_MASK = 7; + public static inline var DYNAMIC_STATE_STENCIL_REFERENCE = 8; + public static inline var DYNAMIC_STATE_VIEWPORT_BIT = 0x00000001; + public static inline var DYNAMIC_STATE_SCISSOR_BIT = 0x00000002; + + public static inline var SAMPLE_COUNT_1_BIT = 0x00000001; + public static inline var SAMPLE_COUNT_2_BIT = 0x00000002; + public static inline var SAMPLE_COUNT_4_BIT = 0x00000004; + public static inline var SAMPLE_COUNT_8_BIT = 0x00000008; + public static inline var SAMPLE_COUNT_16_BIT = 0x00000010; + public static inline var SAMPLE_COUNT_32_BIT = 0x00000020; + public static inline var SAMPLE_COUNT_64_BIT = 0x00000040; + + public static inline var INDEX_TYPE_UINT16 = 0; + public static inline var INDEX_TYPE_UINT32 = 1; + public static inline var INDEX_TYPE_UINT8_KHR = 1000265000; + + public static inline var ATTACHMENT_LOAD_OP_LOAD = 0; + public static inline var ATTACHMENT_LOAD_OP_CLEAR = 1; + public static inline var ATTACHMENT_LOAD_OP_DONT_CARE = 2; + public static inline var ATTACHMENT_STORE_OP_STORE = 0; + public static inline var ATTACHMENT_STORE_OP_DONT_CARE = 1; + + public static inline var FILTER_NEAREST = 0; + public static inline var FILTER_LINEAR = 1; + public static inline var SAMPLER_MIPMAP_MODE_NEAREST = 0; + public static inline var SAMPLER_MIPMAP_MODE_LINEAR = 1; + public static inline var SAMPLER_ADDRESS_MODE_REPEAT = 0; + public static inline var SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1; + public static inline var SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2; + public static inline var SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3; + + public static inline var PIPELINE_BIND_POINT_GRAPHICS = 0; + public static inline var SUBPASS_CONTENTS_INLINE = 0; + public static inline var SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1; + public static inline var VERTEX_INPUT_RATE_VERTEX = 0; + public static inline var VERTEX_INPUT_RATE_INSTANCE = 1; + /** Creates a managed `VkInstance` for the current Lime Vulkan window. **/ @@ -135,14 +377,30 @@ class VK } @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKBuffer) @:allow(lime.graphics.vulkan.VKCommandBuffer) @:allow(lime.graphics.vulkan.VKCommandPool) + @:allow(lime.graphics.vulkan.VKDescriptorPool) + @:allow(lime.graphics.vulkan.VKDescriptorSet) + @:allow(lime.graphics.vulkan.VKDescriptorSetLayout) @:allow(lime.graphics.vulkan.VKDevice) + @:allow(lime.graphics.vulkan.VKDeviceMemory) @:allow(lime.graphics.vulkan.VKFence) + @:allow(lime.graphics.vulkan.VKFramebuffer) + @:allow(lime.graphics.vulkan.VKImage) + @:allow(lime.graphics.vulkan.VKImageView) @:allow(lime.graphics.vulkan.VKInstance) + @:allow(lime.graphics.vulkan.VKMemoryRequirements) @:allow(lime.graphics.vulkan.VKPhysicalDevice) + @:allow(lime.graphics.vulkan.VKPipeline) + @:allow(lime.graphics.vulkan.VKPipelineCache) + @:allow(lime.graphics.vulkan.VKPipelineLayout) @:allow(lime.graphics.vulkan.VKQueue) + @:allow(lime.graphics.vulkan.VKRenderPass) + @:allow(lime.graphics.vulkan.VKSampler) @:allow(lime.graphics.vulkan.VKSemaphore) + @:allow(lime.graphics.vulkan.VKShaderModule) + @:allow(lime.graphics.vulkan.VKSwapchain) private static function __makeHandle(value:Dynamic):Int64 { if (value == null) @@ -154,13 +412,29 @@ class VK } @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKBuffer) @:allow(lime.graphics.vulkan.VKCommandBuffer) @:allow(lime.graphics.vulkan.VKCommandPool) + @:allow(lime.graphics.vulkan.VKDescriptorPool) + @:allow(lime.graphics.vulkan.VKDescriptorSet) + @:allow(lime.graphics.vulkan.VKDescriptorSetLayout) @:allow(lime.graphics.vulkan.VKDevice) + @:allow(lime.graphics.vulkan.VKDeviceMemory) @:allow(lime.graphics.vulkan.VKFence) + @:allow(lime.graphics.vulkan.VKFramebuffer) + @:allow(lime.graphics.vulkan.VKImage) + @:allow(lime.graphics.vulkan.VKImageView) @:allow(lime.graphics.vulkan.VKInstance) + @:allow(lime.graphics.vulkan.VKMemoryRequirements) @:allow(lime.graphics.vulkan.VKQueue) + @:allow(lime.graphics.vulkan.VKPipeline) + @:allow(lime.graphics.vulkan.VKPipelineCache) + @:allow(lime.graphics.vulkan.VKPipelineLayout) + @:allow(lime.graphics.vulkan.VKRenderPass) + @:allow(lime.graphics.vulkan.VKSampler) @:allow(lime.graphics.vulkan.VKSemaphore) + @:allow(lime.graphics.vulkan.VKShaderModule) + @:allow(lime.graphics.vulkan.VKSwapchain) private static inline function __isZero(handle:Int64):Bool { return handle.high == 0 && handle.low == 0; diff --git a/src/lime/graphics/vulkan/VKAcquireResult.hx b/src/lime/graphics/vulkan/VKAcquireResult.hx new file mode 100644 index 0000000000..60b269426d --- /dev/null +++ b/src/lime/graphics/vulkan/VKAcquireResult.hx @@ -0,0 +1,22 @@ +package lime.graphics.vulkan; + +/** + Result metadata from `vkAcquireNextImageKHR`. +**/ +class VKAcquireResult +{ + public var imageIndex(default, null):Int; + public var result(default, null):Int; + + @:allow(lime.graphics.vulkan.VKSwapchain) + private function new(result:Int, imageIndex:Int) + { + this.result = result; + this.imageIndex = imageIndex; + } + + public inline function isSuccess():Bool + { + return result == VK.SUCCESS || result == VK.SUBOPTIMAL_KHR; + } +} diff --git a/src/lime/graphics/vulkan/VKBuffer.hx b/src/lime/graphics/vulkan/VKBuffer.hx new file mode 100644 index 0000000000..d173be9ab9 --- /dev/null +++ b/src/lime/graphics/vulkan/VKBuffer.hx @@ -0,0 +1,123 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan buffer usable for vertex, index, uniform, staging, or storage data. +**/ +class VKBuffer +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var memory(default, null):VKDeviceMemory; + public var size(default, null):Int64; + public var usage(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, size:Int64, usage:Int) + { + this.device = device; + this.handle = handle; + this.size = size; + this.usage = usage; + } + + public function allocateMemory(properties:Int):VKDeviceMemory + { + if (device == null) + { + return null; + } + + var allocated = device.allocateMemory(getMemoryRequirements(), properties); + if (allocated != null && bindMemory(allocated)) + { + memory = allocated; + return allocated; + } + + if (allocated != null) + { + allocated.dispose(); + } + return null; + } + + public function bindMemory(memory:VKDeviceMemory, offset:Int64 = null):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && memory != null && memory.isValid()) + { + var result = NativeCFFI.lime_vk_bind_buffer_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, memory.handle.high, memory.handle.low, + offset.high, offset.low); + if (result) + { + this.memory = memory; + } + return result; + } + #end + + return false; + } + + public function dispose(destroyMemory:Bool = false):Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + + if (destroyMemory && memory != null) + { + memory.dispose(); + memory = null; + } + } + + public inline function get():Int64 + { + return handle; + } + + public function getMemoryRequirements():VKMemoryRequirements + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_get_buffer_memory_requirements(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + return VKMemoryRequirements.fromDynamic(data); + } + #end + + return null; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function upload(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + return memory != null && memory.upload(bytes, memoryOffset, byteOffset, byteLength); + } +} diff --git a/src/lime/graphics/vulkan/VKCommandBuffer.hx b/src/lime/graphics/vulkan/VKCommandBuffer.hx index 685ecfe448..b3fe89118b 100644 --- a/src/lime/graphics/vulkan/VKCommandBuffer.hx +++ b/src/lime/graphics/vulkan/VKCommandBuffer.hx @@ -47,6 +47,185 @@ class VKCommandBuffer } } + public function beginRenderPass(renderPass:VKRenderPass, framebuffer:VKFramebuffer, width:Int, height:Int, + clearRed:Float = 0, clearGreen:Float = 0, clearBlue:Float = 0, clearAlpha:Float = 1, + clearDepth:Float = 1, clearStencil:Int = 0, x:Int = 0, y:Int = 0):Bool + { + var clearValueCount = renderPass != null && renderPass.depthStencilFormat != VK.FORMAT_UNDEFINED ? 2 : 1; + var state = [x, y, width, height, clearStencil, clearValueCount]; + var clear = [clearRed, clearGreen, clearBlue, clearAlpha, clearDepth]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && renderPass != null && renderPass.isValid() && framebuffer != null + && framebuffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_begin_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, renderPass.handle.high, + renderPass.handle.low, framebuffer.handle.high, framebuffer.handle.low, state, clear); + } + #end + + return false; + } + + public function bindDescriptorSet(layout:VKPipelineLayout, descriptorSet:VKDescriptorSet, firstSet:Int = 0, + bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout != null && layout.isValid() && descriptorSet != null && descriptorSet.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, + descriptorSet.handle.high, descriptorSet.handle.low, bindPoint, firstSet); + } + #end + + return false; + } + + public function bindIndexBuffer(buffer:VKBuffer, offset:Int64 = null, indexType:Int = VK.INDEX_TYPE_UINT16):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_index_buffer(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + offset.high, offset.low, indexType); + } + #end + + return false; + } + + public function bindPipeline(pipeline:VKPipeline, bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && pipeline != null && pipeline.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_pipeline(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, pipeline.handle.high, pipeline.handle.low, + bindPoint); + } + #end + + return false; + } + + public function bindVertexBuffer(buffer:VKBuffer, binding:Int = 0, offset:Int64 = null):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_vertex_buffer(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + binding, offset.high, offset.low); + } + #end + + return false; + } + + public function blitImage(source:VKImage, destination:VKImage, width:Int, height:Int, sourceLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + destinationLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, filter:Int = VK.FILTER_LINEAR):Bool + { + var state = [width, height, sourceLayout, destinationLayout, filter]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && source != null && source.isValid() && destination != null && destination.isValid()) + { + return NativeCFFI.lime_vk_cmd_blit_image(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, source.handle.high, source.handle.low, destination.handle.high, + destination.handle.low, state); + } + #end + + return false; + } + + public function clearColorImage(image:VKImage, layout:Int, red:Float, green:Float, blue:Float, alpha:Float, + aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_clear_color_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, + layout, aspectMask, [red, green, blue, alpha]); + } + #end + + return false; + } + + public function copyBuffer(source:VKBuffer, destination:VKBuffer, size:Int64, sourceOffset:Int64 = null, destinationOffset:Int64 = null):Bool + { + if (sourceOffset == null) sourceOffset = Int64.ofInt(0); + if (destinationOffset == null) destinationOffset = Int64.ofInt(0); + var state = [size.high, size.low, sourceOffset.high, sourceOffset.low, destinationOffset.high, destinationOffset.low]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && source != null && source.isValid() && destination != null && destination.isValid()) + { + return NativeCFFI.lime_vk_cmd_copy_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, source.handle.high, source.handle.low, destination.handle.high, + destination.handle.low, state); + } + #end + + return false; + } + + public function copyBufferToImage(buffer:VKBuffer, image:VKImage, width:Int, height:Int, + layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_copy_buffer_to_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + image.handle.high, image.handle.low, width, height, layout); + } + #end + + return false; + } + + public function draw(vertexCount:Int, instanceCount:Int = 1, firstVertex:Int = 0, firstInstance:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, vertexCount, instanceCount, firstVertex, firstInstance); + } + #end + + return false; + } + + public function drawIndexed(indexCount:Int, instanceCount:Int = 1, firstIndex:Int = 0, vertexOffset:Int = 0, firstInstance:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw_indexed(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); + } + #end + + return false; + } + public function end():Bool { #if (!macro && lime_cffi && lime_vulkan) @@ -60,6 +239,19 @@ class VKCommandBuffer return false; } + public function endRenderPass():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_end_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + return false; + } + public inline function get():Int64 { return handle; @@ -83,6 +275,49 @@ class VKCommandBuffer return false; } + public function pipelineBarrierImage(image:VKImage, oldLayout:Int, newLayout:Int, srcStageMask:Int, dstStageMask:Int, srcAccessMask:Int, + dstAccessMask:Int, aspectMask:Int, baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):Bool + { + var state = [oldLayout, newLayout, srcStageMask, dstStageMask, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount, + baseArrayLayer, layerCount]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_pipeline_barrier_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, state); + } + #end + + return false; + } + + public function setScissor(x:Int, y:Int, width:Int, height:Int):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_set_scissor(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, x, y, width, height); + } + #end + + return false; + } + + public function setViewport(x:Float, y:Float, width:Float, height:Float, minDepth:Float = 0, maxDepth:Float = 1):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_set_viewport(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, x, y, width, height, minDepth, maxDepth); + } + #end + + return false; + } + @:allow(lime.graphics.vulkan.VKCommandPool) private function __invalidate():Void { diff --git a/src/lime/graphics/vulkan/VKDescriptorPool.hx b/src/lime/graphics/vulkan/VKDescriptorPool.hx new file mode 100644 index 0000000000..3ec009bca9 --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorPool.hx @@ -0,0 +1,62 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKDescriptorPool +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function allocate(layout:VKDescriptorSetLayout):VKDescriptorSet + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout != null && layout.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_allocate_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low); + var descriptorSetHandle = VK.__makeHandle(data); + if (!VK.__isZero(descriptorSetHandle)) + { + return new VKDescriptorSet(this, layout, descriptorSetHandle); + } + } + #end + + return null; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_descriptor_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorPoolSize.hx b/src/lime/graphics/vulkan/VKDescriptorPoolSize.hx new file mode 100644 index 0000000000..6b83cab5ef --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorPoolSize.hx @@ -0,0 +1,13 @@ +package lime.graphics.vulkan; + +class VKDescriptorPoolSize +{ + public var descriptorCount:Int; + public var descriptorType:Int; + + public function new(descriptorType:Int, descriptorCount:Int) + { + this.descriptorType = descriptorType; + this.descriptorCount = descriptorCount; + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorSet.hx b/src/lime/graphics/vulkan/VKDescriptorSet.hx new file mode 100644 index 0000000000..26c7d806c6 --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorSet.hx @@ -0,0 +1,73 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKDescriptorSet +{ + public var device(get, never):VKDevice; + public var handle(default, null):Int64; + public var layout(default, null):VKDescriptorSetLayout; + public var pool(default, null):VKDescriptorPool; + + @:allow(lime.graphics.vulkan.VKDescriptorPool) + private function new(pool:VKDescriptorPool, layout:VKDescriptorSetLayout, handle:Int64) + { + this.pool = pool; + this.layout = layout; + this.handle = handle; + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function updateBuffer(binding:Int, buffer:VKBuffer, range:Int, offset:Int = 0, + descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + var device = get_device(); + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_update_descriptor_set_buffer(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, + buffer.handle.high, buffer.handle.low, offset, range); + } + #end + + return false; + } + + public function updateImage(binding:Int, imageView:VKImageView, sampler:VKSampler = null, + layout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + var device = get_device(); + if (isValid() && device != null && device.isValid() && imageView != null && imageView.isValid()) + { + var samplerHandle = (sampler != null && sampler.isValid()) ? sampler.handle : Int64.ofInt(0); + return NativeCFFI.lime_vk_update_descriptor_set_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, + imageView.handle.high, imageView.handle.low, samplerHandle.high, samplerHandle.low, layout); + } + #end + + return false; + } + + private inline function get_device():VKDevice + { + return pool != null ? pool.device : null; + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx b/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx new file mode 100644 index 0000000000..d14fb572ba --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx @@ -0,0 +1,44 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKDescriptorSetLayout +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_descriptor_set_layout(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx b/src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx new file mode 100644 index 0000000000..b3ab2368ae --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx @@ -0,0 +1,17 @@ +package lime.graphics.vulkan; + +class VKDescriptorSetLayoutBinding +{ + public var binding:Int; + public var descriptorCount:Int; + public var descriptorType:Int; + public var stageFlags:Int; + + public function new(binding:Int, descriptorType:Int, stageFlags:Int, descriptorCount:Int = 1) + { + this.binding = binding; + this.descriptorType = descriptorType; + this.stageFlags = stageFlags; + this.descriptorCount = descriptorCount; + } +} diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx index dbcdd331aa..1107c728ea 100644 --- a/src/lime/graphics/vulkan/VKDevice.hx +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -1,6 +1,7 @@ package lime.graphics.vulkan; import haxe.Int64; +import haxe.io.Bytes; #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; @@ -73,6 +74,335 @@ class VKDevice return null; } + public function allocateMemory(requirements:VKMemoryRequirements, properties:Int):VKDeviceMemory + { + if (requirements == null) + { + return null; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_allocate_memory(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + physicalDevice.handle.high, physicalDevice.handle.low, handle.high, handle.low, requirements.size.high, requirements.size.low, + requirements.memoryTypeBits, properties); + var memoryHandle = VK.__makeHandle(data != null ? data.handle : null); + if (!VK.__isZero(memoryHandle)) + { + return new VKDeviceMemory(this, memoryHandle, requirements.size, data.memoryTypeIndex, properties); + } + } + #end + + return null; + } + + public function createBuffer(size:Int64, usage:Int):VKBuffer + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_buffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, size.high, size.low, usage); + var bufferHandle = VK.__makeHandle(data); + if (!VK.__isZero(bufferHandle)) + { + return new VKBuffer(this, bufferHandle, size, usage); + } + } + #end + + return null; + } + + public function createBufferWithMemory(size:Int64, usage:Int, properties:Int, bytes:Bytes = null):VKBuffer + { + var buffer = createBuffer(size, usage); + if (buffer == null) + { + return null; + } + + var memory = buffer.allocateMemory(properties); + if (memory == null) + { + buffer.dispose(); + return null; + } + + if (bytes != null && !buffer.upload(bytes)) + { + buffer.dispose(true); + return null; + } + + return buffer; + } + + public inline function createIndexBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_INDEX_BUFFER_BIT, properties, bytes); + } + + public inline function createStagingBuffer(size:Int64, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_TRANSFER_SRC_BIT, + VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, bytes); + } + + public inline function createStorageBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_STORAGE_BUFFER_BIT, properties, bytes); + } + + public inline function createUniformBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_UNIFORM_BUFFER_BIT, properties, bytes); + } + + public inline function createVertexBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_VERTEX_BUFFER_BIT, properties, bytes); + } + + public function createDescriptorPool(maxSets:Int, poolSizes:Array, flags:Int = 0):VKDescriptorPool + { + var packed = [flags, maxSets, poolSizes != null ? poolSizes.length : 0]; + if (poolSizes != null) + { + for (poolSize in poolSizes) + { + packed.push(poolSize.descriptorType); + packed.push(poolSize.descriptorCount); + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_descriptor_pool(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, packed); + var descriptorPoolHandle = VK.__makeHandle(data); + if (!VK.__isZero(descriptorPoolHandle)) + { + return new VKDescriptorPool(this, descriptorPoolHandle); + } + } + #end + + return null; + } + + public function createDescriptorSetLayout(bindings:Array, flags:Int = 0):VKDescriptorSetLayout + { + var packed = [flags, bindings != null ? bindings.length : 0]; + if (bindings != null) + { + for (binding in bindings) + { + packed.push(binding.binding); + packed.push(binding.descriptorType); + packed.push(binding.descriptorCount); + packed.push(binding.stageFlags); + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_descriptor_set_layout(instance.context.__windowHandle, instance.handle.high, + instance.handle.low, handle.high, handle.low, packed); + var descriptorSetLayoutHandle = VK.__makeHandle(data); + if (!VK.__isZero(descriptorSetLayoutHandle)) + { + return new VKDescriptorSetLayout(this, descriptorSetLayoutHandle); + } + } + #end + + return null; + } + + public function createFramebuffer(renderPass:VKRenderPass, attachments:Array, width:Int, height:Int, layers:Int = 1):VKFramebuffer + { + if (renderPass == null || !renderPass.isValid() || attachments == null || attachments.length == 0) + { + return null; + } + + var packed = [attachments.length]; + for (attachment in attachments) + { + if (attachment == null || !attachment.isValid()) + { + return null; + } + packed.push(attachment.handle.high); + packed.push(attachment.handle.low); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_framebuffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, packed, width, height, layers); + var framebufferHandle = VK.__makeHandle(data); + if (!VK.__isZero(framebufferHandle)) + { + return new VKFramebuffer(this, renderPass, framebufferHandle, width, height); + } + } + #end + + return null; + } + + public function createGraphicsPipeline(renderPass:VKRenderPass, layout:VKPipelineLayout, vertexShader:VKShaderModule, + fragmentShader:VKShaderModule, info:VKGraphicsPipelineInfo, cache:VKPipelineCache = null):VKPipeline + { + if (renderPass == null || layout == null || vertexShader == null || fragmentShader == null) + { + return null; + } + if (info == null) + { + info = new VKGraphicsPipelineInfo(); + } + + var cacheHandle = cache != null && cache.isValid() ? cache.handle : Int64.ofInt(0); + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && renderPass.isValid() && layout.isValid() && vertexShader.isValid() && fragmentShader.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_graphics_pipeline(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, layout.handle.high, layout.handle.low, + vertexShader.handle.high, vertexShader.handle.low, fragmentShader.handle.high, fragmentShader.handle.low, info.pack(cacheHandle)); + var pipelineHandle = VK.__makeHandle(data); + if (!VK.__isZero(pipelineHandle)) + { + return new VKPipeline(this, layout, pipelineHandle); + } + } + #end + + return null; + } + + public function createImage(width:Int, height:Int, format:Int, usage:Int, depth:Int = 1, mipLevels:Int = 1, arrayLayers:Int = 1, + imageType:Int = VK.IMAGE_TYPE_2D, tiling:Int = VK.IMAGE_TILING_OPTIMAL, samples:Int = VK.SAMPLE_COUNT_1_BIT):VKImage + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_image(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, width, height, depth, mipLevels, arrayLayers, format, imageType, tiling, usage, samples); + var imageHandle = VK.__makeHandle(data); + if (!VK.__isZero(imageHandle)) + { + return VKImage.createOwned(this, imageHandle, width, height, format); + } + } + #end + + return null; + } + + public function createPipelineCache():VKPipelineCache + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_pipeline_cache(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low); + var pipelineCacheHandle = VK.__makeHandle(data); + if (!VK.__isZero(pipelineCacheHandle)) + { + return new VKPipelineCache(this, pipelineCacheHandle); + } + } + #end + + return null; + } + + public function createPipelineLayout(descriptorSetLayouts:Array = null, pushConstantStages:Int = 0, + pushConstantSize:Int = 0):VKPipelineLayout + { + var packed = [descriptorSetLayouts != null ? descriptorSetLayouts.length : 0]; + if (descriptorSetLayouts != null) + { + for (layout in descriptorSetLayouts) + { + if (layout == null || !layout.isValid()) + { + return null; + } + packed.push(layout.handle.high); + packed.push(layout.handle.low); + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_pipeline_layout(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, packed, pushConstantStages, pushConstantSize); + var pipelineLayoutHandle = VK.__makeHandle(data); + if (!VK.__isZero(pipelineLayoutHandle)) + { + return new VKPipelineLayout(this, pipelineLayoutHandle); + } + } + #end + + return null; + } + + public function createRenderPass(colorFormat:Int, depthStencilFormat:Int = VK.FORMAT_UNDEFINED, + samples:Int = VK.SAMPLE_COUNT_1_BIT, colorLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, + colorStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, colorInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, + colorFinalLayout:Int = VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE, + depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL):VKRenderPass + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_render_pass(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, colorFormat, depthStencilFormat, samples, colorLoadOp, colorStoreOp, colorInitialLayout, colorFinalLayout, + depthLoadOp, depthStoreOp, depthFinalLayout); + var renderPassHandle = VK.__makeHandle(data); + if (!VK.__isZero(renderPassHandle)) + { + return new VKRenderPass(this, renderPassHandle, colorFormat, depthStencilFormat, samples); + } + } + #end + + return null; + } + + public function createSampler(filter:Int = VK.FILTER_LINEAR, addressMode:Int = VK.SAMPLER_ADDRESS_MODE_REPEAT, + mipmapMode:Int = VK.SAMPLER_MIPMAP_MODE_LINEAR, anisotropyEnable:Bool = false, maxAnisotropy:Float = 1, + compareOp:Int = -1, minLod:Float = 0, maxLod:Float = 0):VKSampler + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_sampler(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, filter, addressMode, mipmapMode, anisotropyEnable, maxAnisotropy, compareOp, minLod, maxLod); + var samplerHandle = VK.__makeHandle(data); + if (!VK.__isZero(samplerHandle)) + { + return new VKSampler(this, samplerHandle); + } + } + #end + + return null; + } + public function createSemaphore():VKSemaphore { #if (!macro && lime_cffi && lime_vulkan) @@ -91,6 +421,58 @@ class VKDevice return null; } + public function createShaderModule(bytes:Bytes, byteOffset:Int = 0, byteLength:Int = -1):VKShaderModule + { + if (bytes == null) + { + return null; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_shader_module(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, bytes, byteOffset, byteLength); + var shaderModuleHandle = VK.__makeHandle(data); + if (!VK.__isZero(shaderModuleHandle)) + { + return new VKShaderModule(this, shaderModuleHandle); + } + } + #end + + return null; + } + + /** + Creates a swapchain for a window surface. Pass an existing swapchain as + `oldSwapchain` when recreating resources after a resize. + **/ + public function createSwapchain(surface:VKSurface, width:Int = 0, height:Int = 0, presentMode:Int = VK.PRESENT_MODE_FIFO_KHR, + oldSwapchain:VKSwapchain = null):VKSwapchain + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && surface != null && surface.isValid() && queueFamily != null) + { + var oldSwapchainHandle = (oldSwapchain != null && oldSwapchain.isValid()) ? oldSwapchain.handle : Int64.ofInt(0); + var data:Dynamic = NativeCFFI.lime_vk_create_swapchain(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + physicalDevice.handle.high, physicalDevice.handle.low, handle.high, handle.low, surface.high, surface.low, queueFamily.index, width, + height, presentMode, oldSwapchainHandle.high, oldSwapchainHandle.low); + var swapchainHandle = VK.__makeHandle(data != null ? data.handle : null); + if (!VK.__isZero(swapchainHandle)) + { + return new VKSwapchain(this, surface, data); + } + } + #end + + return null; + } + /** Destroys the logical device. All resources created from the device should be destroyed before calling this method. diff --git a/src/lime/graphics/vulkan/VKDeviceMemory.hx b/src/lime/graphics/vulkan/VKDeviceMemory.hx new file mode 100644 index 0000000000..5a739ec646 --- /dev/null +++ b/src/lime/graphics/vulkan/VKDeviceMemory.hx @@ -0,0 +1,85 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + Device memory allocated from a `VKDevice`. +**/ +class VKDeviceMemory +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var memoryTypeIndex(default, null):Int; + public var properties(default, null):Int; + public var size(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, size:Int64, memoryTypeIndex:Int, properties:Int) + { + this.device = device; + this.handle = handle; + this.size = size; + this.memoryTypeIndex = memoryTypeIndex; + this.properties = properties; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_free_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + /** + Copies bytes into host-visible memory. This maps and unmaps internally, + which is convenient for staging/uniform data and avoids exposing unsafe + raw pointers at the Lime boundary. + **/ + public function upload(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + if (memoryOffset == null) + { + memoryOffset = Int64.ofInt(0); + } + if (bytes == null) + { + return false; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_upload_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, memoryOffset.high, memoryOffset.low, bytes, byteOffset, byteLength); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKFramebuffer.hx b/src/lime/graphics/vulkan/VKFramebuffer.hx new file mode 100644 index 0000000000..be12eaf8b9 --- /dev/null +++ b/src/lime/graphics/vulkan/VKFramebuffer.hx @@ -0,0 +1,50 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKFramebuffer +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var height(default, null):Int; + public var renderPass(default, null):VKRenderPass; + public var width(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, renderPass:VKRenderPass, handle:Int64, width:Int, height:Int) + { + this.device = device; + this.renderPass = renderPass; + this.handle = handle; + this.width = width; + this.height = height; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_framebuffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx new file mode 100644 index 0000000000..c0733351b5 --- /dev/null +++ b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx @@ -0,0 +1,77 @@ +package lime.graphics.vulkan; + +class VKGraphicsPipelineInfo +{ + public var alphaBlendOp:Int = VK.BLEND_OP_ADD; + public var colorBlendOp:Int = VK.BLEND_OP_ADD; + public var cullMode:Int = VK.CULL_MODE_BACK_BIT; + public var depthCompareOp:Int = VK.COMPARE_OP_LESS; + public var depthTest:Bool = false; + public var depthWrite:Bool = false; + public var dstAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + public var dstColorBlendFactor:Int = VK.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + public var dynamicStateFlags:Int = VK.DYNAMIC_STATE_VIEWPORT_BIT | VK.DYNAMIC_STATE_SCISSOR_BIT; + public var frontFace:Int = VK.FRONT_FACE_COUNTER_CLOCKWISE; + public var polygonMode:Int = VK.POLYGON_MODE_FILL; + public var primitiveRestart:Bool = false; + public var srcAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE; + public var srcColorBlendFactor:Int = VK.BLEND_FACTOR_SRC_ALPHA; + public var topology:Int = VK.PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + public var vertexAttributes:Array; + public var vertexBindings:Array; + public var blend:Bool = false; + + public function new() + { + vertexAttributes = []; + vertexBindings = []; + } + + @:allow(lime.graphics.vulkan.VKDevice) + private function pack(cacheHandle:haxe.Int64 = null):Array + { + if (cacheHandle == null) + { + cacheHandle = haxe.Int64.ofInt(0); + } + var result = [ + cacheHandle.high, + cacheHandle.low, + topology, + primitiveRestart ? 1 : 0, + polygonMode, + cullMode, + frontFace, + depthTest ? 1 : 0, + depthWrite ? 1 : 0, + depthCompareOp, + blend ? 1 : 0, + srcColorBlendFactor, + dstColorBlendFactor, + colorBlendOp, + srcAlphaBlendFactor, + dstAlphaBlendFactor, + alphaBlendOp, + dynamicStateFlags, + vertexBindings.length + ]; + + for (binding in vertexBindings) + { + result.push(binding.binding); + result.push(binding.stride); + result.push(binding.inputRate); + } + + result.push(vertexAttributes.length); + for (attribute in vertexAttributes) + { + result.push(attribute.location); + result.push(attribute.binding); + result.push(attribute.format); + result.push(attribute.offset); + } + + return result; + } +} diff --git a/src/lime/graphics/vulkan/VKImage.hx b/src/lime/graphics/vulkan/VKImage.hx new file mode 100644 index 0000000000..491f40350a --- /dev/null +++ b/src/lime/graphics/vulkan/VKImage.hx @@ -0,0 +1,165 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan image handle. Swapchain images are owned by their `VKSwapchain`. +**/ +class VKImage +{ + public var device(default, null):VKDevice; + public var format(default, null):Int; + public var handle(default, null):Int64; + public var height(default, null):Int; + public var index(default, null):Int; + public var memory(default, null):VKDeviceMemory; + public var ownsHandle(default, null):Bool; + public var swapchain(default, null):VKSwapchain; + public var width(default, null):Int; + + @:allow(lime.graphics.vulkan.VKSwapchain) + private function new(swapchain:VKSwapchain, handle:Int64, index:Int) + { + this.swapchain = swapchain; + this.device = swapchain != null ? swapchain.device : null; + this.handle = handle; + this.index = index; + this.format = swapchain != null ? swapchain.format : VK.FORMAT_UNDEFINED; + this.width = swapchain != null ? swapchain.width : 0; + this.height = swapchain != null ? swapchain.height : 0; + this.ownsHandle = false; + } + + @:allow(lime.graphics.vulkan.VKDevice) + private static function createOwned(device:VKDevice, handle:Int64, width:Int, height:Int, format:Int):VKImage + { + var image = new VKImage(null, handle, -1); + image.swapchain = null; + image.device = device; + image.handle = handle; + image.index = -1; + image.format = format; + image.width = width; + image.height = height; + image.ownsHandle = true; + return image; + } + + public function allocateMemory(properties:Int):VKDeviceMemory + { + if (device == null) + { + return null; + } + + var allocated = device.allocateMemory(getMemoryRequirements(), properties); + if (allocated != null && bindMemory(allocated)) + { + memory = allocated; + return allocated; + } + + if (allocated != null) + { + allocated.dispose(); + } + return null; + } + + public function bindMemory(memory:VKDeviceMemory, offset:Int64 = null):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && memory != null && memory.isValid()) + { + var result = NativeCFFI.lime_vk_bind_image_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, memory.handle.high, memory.handle.low, + offset.high, offset.low); + if (result) + { + this.memory = memory; + } + return result; + } + #end + + return false; + } + + public function createView(format:Int = 0, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT, viewType:Int = VK.IMAGE_VIEW_TYPE_2D, + baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):VKImageView + { + if (format == 0) + { + format = this.format; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_image_view_ex(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, format, aspectMask, viewType, + baseMipLevel, levelCount, baseArrayLayer, layerCount); + var imageViewHandle = VK.__makeHandle(data); + if (!VK.__isZero(imageViewHandle)) + { + return new VKImageView(this, imageViewHandle, format, aspectMask, viewType); + } + } + #end + + return null; + } + + public function dispose(destroyMemory:Bool = false):Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (ownsHandle && isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_image(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + + if (destroyMemory && memory != null) + { + memory.dispose(); + memory = null; + } + } + + public inline function get():Int64 + { + return handle; + } + + public function getMemoryRequirements():VKMemoryRequirements + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_get_image_memory_requirements(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + return VKMemoryRequirements.fromDynamic(data); + } + #end + + return null; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKImageView.hx b/src/lime/graphics/vulkan/VKImageView.hx new file mode 100644 index 0000000000..5cf888f93a --- /dev/null +++ b/src/lime/graphics/vulkan/VKImageView.hx @@ -0,0 +1,55 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan image view created for a `VKImage`. +**/ +class VKImageView +{ + public var aspectMask(default, null):Int; + public var device(default, null):VKDevice; + public var format(default, null):Int; + public var handle(default, null):Int64; + public var image(default, null):VKImage; + public var viewType(default, null):Int; + + @:allow(lime.graphics.vulkan.VKImage) + private function new(image:VKImage, handle:Int64, format:Int, aspectMask:Int, viewType:Int) + { + this.image = image; + this.device = image.device; + this.handle = handle; + this.format = format; + this.aspectMask = aspectMask; + this.viewType = viewType; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_image_view(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKMemoryRequirements.hx b/src/lime/graphics/vulkan/VKMemoryRequirements.hx new file mode 100644 index 0000000000..5be95984ff --- /dev/null +++ b/src/lime/graphics/vulkan/VKMemoryRequirements.hx @@ -0,0 +1,32 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +/** + Memory requirements returned by Vulkan for buffers and images. +**/ +class VKMemoryRequirements +{ + public var alignment(default, null):Int64; + public var memoryTypeBits(default, null):Int; + public var size(default, null):Int64; + + public function new(size:Int64, alignment:Int64, memoryTypeBits:Int) + { + this.size = size; + this.alignment = alignment; + this.memoryTypeBits = memoryTypeBits; + } + + @:allow(lime.graphics.vulkan.VKBuffer) + @:allow(lime.graphics.vulkan.VKImage) + private static function fromDynamic(data:Dynamic):VKMemoryRequirements + { + if (data == null) + { + return null; + } + + return new VKMemoryRequirements(VK.__makeHandle(data.size), VK.__makeHandle(data.alignment), data.memoryTypeBits); + } +} diff --git a/src/lime/graphics/vulkan/VKPipeline.hx b/src/lime/graphics/vulkan/VKPipeline.hx new file mode 100644 index 0000000000..20b377ec44 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPipeline.hx @@ -0,0 +1,46 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKPipeline +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var layout(default, null):VKPipelineLayout; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, layout:VKPipelineLayout, handle:Int64) + { + this.device = device; + this.layout = layout; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_pipeline(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKPipelineCache.hx b/src/lime/graphics/vulkan/VKPipelineCache.hx new file mode 100644 index 0000000000..69ea68dbe5 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPipelineCache.hx @@ -0,0 +1,44 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKPipelineCache +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_pipeline_cache(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKPipelineLayout.hx b/src/lime/graphics/vulkan/VKPipelineLayout.hx new file mode 100644 index 0000000000..83c3b77ed2 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPipelineLayout.hx @@ -0,0 +1,44 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKPipelineLayout +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_pipeline_layout(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKQueue.hx b/src/lime/graphics/vulkan/VKQueue.hx index 9f6e62cb09..a372e78d26 100644 --- a/src/lime/graphics/vulkan/VKQueue.hx +++ b/src/lime/graphics/vulkan/VKQueue.hx @@ -37,6 +37,24 @@ class VKQueue return !VK.__isZero(handle); } + /** + Presents an acquired swapchain image on this queue. + **/ + public function present(swapchain:VKSwapchain, imageIndex:Int, waitSemaphore:VKSemaphore = null):Int + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && swapchain != null && swapchain.isValid()) + { + var waitSemaphoreHandle = (waitSemaphore != null && waitSemaphore.isValid()) ? waitSemaphore.handle : Int64.ofInt(0); + return NativeCFFI.lime_vk_queue_present(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, swapchain.handle.high, swapchain.handle.low, imageIndex, + waitSemaphoreHandle.high, waitSemaphoreHandle.low); + } + #end + + return VK.ERROR_INITIALIZATION_FAILED; + } + /** Submits one command buffer to this queue. A fence may be provided to track completion from the CPU. @@ -57,6 +75,30 @@ class VKQueue return false; } + /** + Submits one command buffer with optional acquire/render/present sync. + This preserves the simple `submit(commandBuffer, fence)` path while + exposing the explicit wait/signal pieces renderers need per frame. + **/ + public function submitSynced(commandBuffer:VKCommandBuffer, waitSemaphore:VKSemaphore = null, signalSemaphore:VKSemaphore = null, + fence:VKFence = null, waitStageMask:Int = VK.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && commandBuffer != null && commandBuffer.isValid()) + { + var waitHandle = waitSemaphore != null && waitSemaphore.isValid() ? waitSemaphore.handle : Int64.ofInt(0); + var signalHandle = signalSemaphore != null && signalSemaphore.isValid() ? signalSemaphore.handle : Int64.ofInt(0); + var fenceHandle = fence != null && fence.isValid() ? fence.handle : Int64.ofInt(0); + var state = [waitHandle.high, waitHandle.low, waitStageMask, signalHandle.high, signalHandle.low, fenceHandle.high, fenceHandle.low]; + + return NativeCFFI.lime_vk_queue_submit_synced(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low, state); + } + #end + + return false; + } + /** Blocks until this queue has completed all submitted work. **/ diff --git a/src/lime/graphics/vulkan/VKRenderPass.hx b/src/lime/graphics/vulkan/VKRenderPass.hx new file mode 100644 index 0000000000..bcbf0ec83f --- /dev/null +++ b/src/lime/graphics/vulkan/VKRenderPass.hx @@ -0,0 +1,50 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKRenderPass +{ + public var colorFormat(default, null):Int; + public var depthStencilFormat(default, null):Int; + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var samples(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, colorFormat:Int, depthStencilFormat:Int, samples:Int) + { + this.device = device; + this.handle = handle; + this.colorFormat = colorFormat; + this.depthStencilFormat = depthStencilFormat; + this.samples = samples; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKSampler.hx b/src/lime/graphics/vulkan/VKSampler.hx new file mode 100644 index 0000000000..69504203a1 --- /dev/null +++ b/src/lime/graphics/vulkan/VKSampler.hx @@ -0,0 +1,44 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKSampler +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_sampler(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKShaderModule.hx b/src/lime/graphics/vulkan/VKShaderModule.hx new file mode 100644 index 0000000000..4204a32c3a --- /dev/null +++ b/src/lime/graphics/vulkan/VKShaderModule.hx @@ -0,0 +1,44 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKShaderModule +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_shader_module(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKSwapchain.hx b/src/lime/graphics/vulkan/VKSwapchain.hx new file mode 100644 index 0000000000..389c36e58e --- /dev/null +++ b/src/lime/graphics/vulkan/VKSwapchain.hx @@ -0,0 +1,140 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan swapchain created for a Lime window surface. +**/ +class VKSwapchain +{ + public var colorSpace(default, null):Int; + public var device(default, null):VKDevice; + public var format(default, null):Int; + public var handle(default, null):Int64; + public var height(default, null):Int; + public var imageCount(default, null):Int; + public var images(default, null):Array; + public var presentMode(default, null):Int; + public var surface(default, null):VKSurface; + public var width(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, surface:VKSurface, data:Dynamic) + { + this.device = device; + this.surface = surface; + handle = VK.__makeHandle(data.handle); + format = data.format; + colorSpace = data.colorSpace; + width = data.width; + height = data.height; + imageCount = data.imageCount; + presentMode = data.presentMode; + images = []; + refreshImages(); + } + + /** + Acquires the next presentable image from the swapchain. + **/ + public function acquireNextImage(semaphore:VKSemaphore = null, fence:VKFence = null, timeout:Int64 = null):VKAcquireResult + { + if (timeout == null) + { + timeout = Int64.make(-1, -1); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var semaphoreHandle = (semaphore != null && semaphore.isValid()) ? semaphore.handle : Int64.ofInt(0); + var fenceHandle = (fence != null && fence.isValid()) ? fence.handle : Int64.ofInt(0); + var data:Dynamic = NativeCFFI.lime_vk_acquire_next_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, timeout.high, timeout.low, + semaphoreHandle.high, semaphoreHandle.low, fenceHandle.high, fenceHandle.low); + + if (data != null) + { + return new VKAcquireResult(data.result, data.imageIndex); + } + } + #end + + return new VKAcquireResult(VK.ERROR_INITIALIZATION_FAILED, -1); + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_swapchain(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + images = []; + imageCount = 0; + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function refreshImages():Array + { + images = []; + imageCount = 0; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_get_swapchain_images(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + + if (data != null) + { + var length:Int = untyped data.length; + for (i in 0...length) + { + images.push(new VKImage(this, VK.__makeHandle(untyped data[i]), i)); + } + imageCount = images.length; + } + } + #end + + return images; + } + + /** + Creates a replacement swapchain using this swapchain as the old handle. + Dispose the old swapchain after any in-flight work has finished. + **/ + public function recreate(width:Int = 0, height:Int = 0, presentMode:Int = -1):VKSwapchain + { + if (presentMode < 0) + { + presentMode = this.presentMode; + } + + if (device == null) + { + return null; + } + + return device.createSwapchain(surface, width, height, presentMode, this); + } +} diff --git a/src/lime/graphics/vulkan/VKVertexAttribute.hx b/src/lime/graphics/vulkan/VKVertexAttribute.hx new file mode 100644 index 0000000000..4a1641c077 --- /dev/null +++ b/src/lime/graphics/vulkan/VKVertexAttribute.hx @@ -0,0 +1,17 @@ +package lime.graphics.vulkan; + +class VKVertexAttribute +{ + public var binding:Int; + public var format:Int; + public var location:Int; + public var offset:Int; + + public function new(location:Int, binding:Int, format:Int, offset:Int) + { + this.location = location; + this.binding = binding; + this.format = format; + this.offset = offset; + } +} diff --git a/src/lime/graphics/vulkan/VKVertexBinding.hx b/src/lime/graphics/vulkan/VKVertexBinding.hx new file mode 100644 index 0000000000..071a35139e --- /dev/null +++ b/src/lime/graphics/vulkan/VKVertexBinding.hx @@ -0,0 +1,15 @@ +package lime.graphics.vulkan; + +class VKVertexBinding +{ + public var binding:Int; + public var inputRate:Int; + public var stride:Int; + + public function new(binding:Int, stride:Int, inputRate:Int = VK.VERTEX_INPUT_RATE_VERTEX) + { + this.binding = binding; + this.stride = stride; + this.inputRate = inputRate; + } +} diff --git a/tests/vulkan-smoke/Assets/shaders/cube.frag.spv b/tests/vulkan-smoke/Assets/shaders/cube.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..f55655e156556acbcf490d5b0fd224e3a9b8886a GIT binary patch literal 668 zcmYk2PfG$}5XRrsHOul(mKH&1-K9fC5Owk3#alt=Ko3E+u({F~=!^BKx&-}xZ!7I9 ztY932d*`S5LHnQ;fuxuwA_<`*q7$ZN&1pzgdj=S#pe%;k7b@M)|lEWut}O` z^T?~kS*xORin3ZKHt@{VIgQzWJ|g!9>uQ$y?rv_q$JXvWiWh_!_lfIZLu^35_nCXs zkpBkWuOxm`P>UfLKoxed6{4JP4li^k+ZL&*Qv^?_>(K zICp&6Fe#F3AatUPXND3_2E|$OJ0{Ni=p|n_O@19F!y+17#3LUY;JZoFkuT7E%+3k) zo0mR`iafc9hhPndalbh^@1u!ZkiM?Ofw6xyn%2g_$L){!uA61~rOSn%=n*zv@^#zI z(k!<;!CmC+Bh|Ky^L^~`nEhsaO=CO;2gI?j$GC&Re@`Cn#2pD?XHFm?-rMaGeT?bh zm^leGh@(bNHQ-}g!tr*?nxzdl&58{#RU1yQ*@JxEPu1=?n|=%Gif(BJ_Ts*zTSGdO zEGwTmvDtS~|C7?8gwt{M6W!^zA^WK`@nB8e;K$d%hlGlolJ;C4IGgtaMxU87&eo+5 z_N;`nA{*|g%Un%m!66v6pG&g~7`3tC6%79icPE}5m!+AR-uPFf$0Xq7W5YWbvk<#3 zG3L)V;#<0r%RJO;OB3V!?dXmloO;-NH!$*FN>khWvG*KCJoWjGKK_mK(GNd1-<2Al z^zP^jFC23I3*k+E*FU>2O5g)NzbFzOmL%ZV?7b#o=Tqgd%Z9_GM%bpq=Au-V8hPW+C&y6>LfT2f50E}tK67)PBX-5 zQdHmDw{BHUQaN4=VI|b~?S;i@hYCyx^-zs@G`<}VKl10{>Dh^jMo6MiO_RD+vhnux z^6tYr(I$3@7FyqE!Y#o$gl`H{*m6w@V_i1OZ?e~H$`vLJTjbf@uG#>`Zd|Ot(Q+uYdV0@d3&@59;*WEJSkpiQUO#|0Y>K=TzS!>m{#V?2dB2?-cjt zd}4R@{hTkVkGpuB`3EK?U%@&Z>3geQ`Iq@Bo@#un z&U`s-iZe&fSrg}5&b#;VSkE|nJ8zn8308iG7;}8D@S4Kr=qmC2X&S6A2hU)QmH&8; z-B(WkQ>^nPzc|foz2{)-JDc%ySaapAC-y$6-U4syCBN8v$t@GVgw0Xq%{_j}TmL3_ z8EZeeZC>6Y&7e0T_a|>0B7q@r6`SPA` z>^;4KVvoNt8TJ#bw|j = []; + private var imageAvailable:VKSemaphore; + private var imageViews:Array = []; + private var instance:VKInstance; + private var offscreenDescriptorSet:VKDescriptorSet; + private var offscreenDescriptorSetLayout:VKDescriptorSetLayout; + private var offscreenFramebuffer:VKFramebuffer; + private var offscreenImage:VKImage; + private var offscreenPipeline:VKPipeline; + private var offscreenPipelineLayout:VKPipelineLayout; + private var offscreenRenderPass:VKRenderPass; + private var offscreenSampler:VKSampler; + private var offscreenView:VKImageView; + private var physicalDevice:VKPhysicalDevice; + private var preloadComplete:Bool; + private var quadFragmentShader:VKShaderModule; + private var quadIndexBuffer:VKBuffer; + private var quadVertexBuffer:VKBuffer; + private var quadVertexShader:VKShaderModule; + private var queueFamily:VKQueueFamilyInfo; + private var renderFinished:VKSemaphore; + private var renderPass:VKRenderPass; + private var sourceTextureImage:VKImage; + private var sourceTextureSampler:VKSampler; + private var sourceTextureView:VKImageView; + private var surface:VKSurface; + private var swapchain:VKSwapchain; + private var uniformBuffer:VKBuffer; + private var windowCreated:Bool; public function new() { @@ -36,13 +111,25 @@ class Main extends Application return; } - var context = window.context.vulkan; - validateBootstrap(context); + windowCreated = true; + tryCreateRenderer(); + } + + override public function onPreloadComplete():Void + { + super.onPreloadComplete(); + + preloadComplete = true; + tryCreateRenderer(); + } + + override public function onWindowResize(width:Int, height:Int):Void + { + super.onWindowResize(width, height); - renderer = context.createRenderer("LimeVulkanSmoke"); - if (renderer == null || !renderer.isValid) + if (!finished && device != null && device.isValid() && width > 0 && height > 0) { - fail("Failed to create Vulkan renderer: " + VKRenderer.getLastError()); + recreateSwapchain(width, height); } } @@ -50,14 +137,13 @@ class Main extends Application { super.render(context); - if (finished || renderer == null) + if (finished || device == null) { return; } - if (!renderer.render(0.125, 0.25, 0.5, 1.0)) + if (!drawFrame()) { - fail("Failed to render Vulkan frame: " + renderer.lastError); return; } @@ -65,7 +151,7 @@ class Main extends Application Timer.delay(complete, 50); } - private function validateBootstrap(context:VulkanRenderContext):Void + private function createRenderer(context:VulkanRenderContext):Void { var extensions = context.getInstanceExtensions(); if (extensions == null || extensions.length == 0) @@ -81,180 +167,751 @@ class Main extends Application return; } - var instance = VK.createInstance(context, "LimeVulkanSmoke"); + instance = VK.createInstance(context, "LimeVulkanSmoke"); if (instance == null || !instance.isValid()) { fail("Failed to create Vulkan instance: " + VK.getLastError()); return; } - var surface = instance.createSurface(); + surface = instance.createSurface(); if (surface == null || !surface.isValid()) { - instance.dispose(); fail("Failed to create Vulkan surface"); return; } - var devices = instance.enumeratePhysicalDevices(surface); - if (devices.length == 0) + physicalDevice = instance.pickPhysicalDevice(surface); + if (physicalDevice == null || !physicalDevice.hasQueueFamily(true, true)) { - surface.dispose(); - instance.dispose(); - fail("No Vulkan physical devices were enumerated"); + fail("No present-capable graphics queue family was found"); return; } - var device = instance.pickPhysicalDevice(surface); - if (device == null || !device.hasQueueFamily(true, true)) + queueFamily = physicalDevice.getQueueFamily(true, true); + device = physicalDevice.createDevice(queueFamily); + if (device == null || !device.isValid() || device.graphicsQueue == null || !device.graphicsQueue.isValid()) { - surface.dispose(); - instance.dispose(); - fail("No present-capable graphics queue family was found"); + fail("Failed to create Vulkan logical device: " + VK.getLastError()); return; } - var queueFamily = device.getQueueFamily(true, true); - var logicalDevice = device.createDevice(queueFamily); - if (logicalDevice == null || !logicalDevice.isValid() || logicalDevice.graphicsQueue == null || !logicalDevice.graphicsQueue.isValid()) + commandPool = device.createCommandPool(queueFamily); + commandBuffer = commandPool != null ? commandPool.allocateCommandBuffer() : null; + imageAvailable = device.createSemaphore(); + renderFinished = device.createSemaphore(); + fence = device.createFence(true); + + if (commandPool == null || commandBuffer == null || imageAvailable == null || renderFinished == null || fence == null) { - surface.dispose(); - instance.dispose(); - fail("Failed to create Vulkan logical device: " + VK.getLastError()); + fail("Failed to create Vulkan frame synchronization resources: " + VK.getLastError()); return; } - if (!logicalDevice.graphicsQueue.waitIdle()) + swapchain = device.createSwapchain(surface, window.width, window.height); + if (swapchain == null || !swapchain.isValid() || swapchain.images.length == 0) { - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to wait for Vulkan graphics queue: " + VK.getLastError()); + fail("Failed to create Vulkan swapchain: " + VK.getLastError()); return; } - var semaphore = logicalDevice.createSemaphore(); - if (semaphore == null || !semaphore.isValid()) + if (!createSourceTexture() || !createGeometry() || !createDescriptorLayouts() || !createOffscreenPass() || !createOnscreenPass()) { - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to create Vulkan semaphore: " + VK.getLastError()); return; } + } - var commandPool = logicalDevice.createCommandPool(queueFamily); - if (commandPool == null || !commandPool.isValid()) + private function tryCreateRenderer():Void + { + if (device != null || !windowCreated || !preloadComplete || window == null || window.context == null || window.context.vulkan == null) { - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to create Vulkan command pool: " + VK.getLastError()); return; } - var commandBuffer = commandPool.allocateCommandBuffer(); - if (commandBuffer == null || !commandBuffer.isValid()) + createRenderer(window.context.vulkan); + } + + private function createSourceTexture():Bool + { + sourceTextureImage = device.createImage(2, 2, OFFSCREEN_FORMAT, VK.IMAGE_USAGE_TRANSFER_DST_BIT | VK.IMAGE_USAGE_SAMPLED_BIT); + if (sourceTextureImage == null || sourceTextureImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) { - commandPool.dispose(); - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to allocate Vulkan command buffer: " + VK.getLastError()); - return; + fail("Failed to create Vulkan texture image: " + VK.getLastError()); + return false; } - if (!commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) || !commandBuffer.end()) + var pixels = Bytes.alloc(16); + var values = [ + 0xFF, 0x90, 0x20, 0xFF, + 0x10, 0xD8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x20, 0x40, 0xFF, 0xFF + ]; + for (i in 0...values.length) { - commandBuffer.dispose(); - commandPool.dispose(); - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to record Vulkan command buffer: " + VK.getLastError()); - return; + pixels.set(i, values[i]); } - var fence = logicalDevice.createFence(); - if (fence == null || !fence.isValid()) + var staging = device.createStagingBuffer(Int64.ofInt(pixels.length), pixels); + if (staging == null) { - commandBuffer.dispose(); - commandPool.dispose(); - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to create Vulkan fence: " + VK.getLastError()); - return; + fail("Failed to create Vulkan texture staging buffer: " + VK.getLastError()); + return false; } - if (!logicalDevice.graphicsQueue.submit(commandBuffer, fence) || !fence.waitForever() || !fence.reset()) + if (!commandBuffer.reset() || !commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) + || !commandBuffer.pipelineBarrierImage(sourceTextureImage, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK.PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK.PIPELINE_STAGE_TRANSFER_BIT, 0, VK.ACCESS_TRANSFER_WRITE_BIT, VK.IMAGE_ASPECT_COLOR_BIT) + || !commandBuffer.copyBufferToImage(staging, sourceTextureImage, 2, 2) + || !commandBuffer.pipelineBarrierImage(sourceTextureImage, VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK.PIPELINE_STAGE_TRANSFER_BIT, VK.PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK.ACCESS_TRANSFER_WRITE_BIT, VK.ACCESS_SHADER_READ_BIT, + VK.IMAGE_ASPECT_COLOR_BIT) + || !commandBuffer.end()) { - fence.dispose(); - commandBuffer.dispose(); - commandPool.dispose(); - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to submit Vulkan command buffer: " + VK.getLastError()); - return; + staging.dispose(true); + fail("Failed to record Vulkan texture upload commands: " + VK.getLastError()); + return false; } - if (!logicalDevice.waitIdle()) + if (!fence.waitForever() || !fence.reset() || !device.graphicsQueue.submit(commandBuffer, fence) || !fence.waitForever()) { - fence.dispose(); - commandBuffer.dispose(); - commandPool.dispose(); - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); - fail("Failed to wait for Vulkan logical device: " + VK.getLastError()); - return; + staging.dispose(true); + fail("Failed to submit Vulkan texture upload: " + VK.getLastError()); + return false; + } + + staging.dispose(true); + + sourceTextureView = sourceTextureImage.createView(OFFSCREEN_FORMAT); + sourceTextureSampler = device.createSampler(VK.FILTER_NEAREST, VK.SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK.SAMPLER_MIPMAP_MODE_NEAREST); + + if (sourceTextureView == null || sourceTextureSampler == null) + { + fail("Failed to create Vulkan texture view/sampler: " + VK.getLastError()); + return false; } - fence.dispose(); - commandBuffer.dispose(); - commandPool.dispose(); - semaphore.dispose(); - logicalDevice.dispose(); - surface.dispose(); - instance.dispose(); + return true; } - private function complete():Void + private function createGeometry():Bool + { + if (!createQuadGeometry() || !createCubeGeometry()) + { + return false; + } + + uniformBuffer = device.createUniformBuffer(Int64.ofInt(64), + VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT); + if (uniformBuffer == null) + { + fail("Failed to create Vulkan uniform buffer: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createQuadGeometry():Bool + { + var vertices = Bytes.alloc(4 * 32); + var data = [ + -0.72, -0.72, 0.0, 1.0, 1.0, 1.0, 1.0, 0.86, + 0.72, -0.72, 1.0, 1.0, 1.0, 1.0, 1.0, 0.86, + 0.72, 0.72, 1.0, 0.0, 1.0, 1.0, 1.0, 0.86, + -0.72, 0.72, 0.0, 0.0, 1.0, 1.0, 1.0, 0.86 + ]; + for (i in 0...data.length) + { + vertices.setFloat(i * 4, data[i]); + } + + var indices = Bytes.alloc(6 * 2); + var indexData = [0, 1, 2, 2, 3, 0]; + for (i in 0...indexData.length) + { + indices.setUInt16(i * 2, indexData[i]); + } + + quadVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), + VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, vertices); + quadIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), + VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, indices); + + if (quadVertexBuffer == null || quadIndexBuffer == null) + { + fail("Failed to create Vulkan quad buffers: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createCubeGeometry():Bool + { + var vertexData = [ + -1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.85, 0.55, 1.0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0.85, 0.55, 1.0, + 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.85, 0.55, 1.0, + -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.85, 0.55, 1.0, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.55, 0.8, 1.0, 1.0, + -1.0, -1.0, -1.0, 1.0, 1.0, 0.55, 0.8, 1.0, 1.0, + -1.0, 1.0, -1.0, 1.0, 0.0, 0.55, 0.8, 1.0, 1.0, + 1.0, 1.0, -1.0, 0.0, 0.0, 0.55, 0.8, 1.0, 1.0, + -1.0, -1.0, -1.0, 0.0, 1.0, 0.75, 1.0, 0.65, 1.0, + -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 1.0, 0.65, 1.0, + -1.0, 1.0, 1.0, 1.0, 0.0, 0.75, 1.0, 0.65, 1.0, + -1.0, 1.0, -1.0, 0.0, 0.0, 0.75, 1.0, 0.65, 1.0, + 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.75, 0.6, 1.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 0.6, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 0.75, 0.6, 1.0, + 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.75, 0.6, 1.0, + -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.95, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 0.65, 0.95, 1.0, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 0.65, 0.95, 1.0, 1.0, + -1.0, 1.0, -1.0, 0.0, 0.0, 0.65, 0.95, 1.0, 1.0, + -1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.65, 0.75, 1.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.65, 0.75, 1.0, + 1.0, -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.75, 1.0, + -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.65, 0.75, 1.0 + ]; + + var indexData = [ + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4, + 8, 9, 10, 10, 11, 8, + 12, 13, 14, 14, 15, 12, + 16, 17, 18, 18, 19, 16, + 20, 21, 22, 22, 23, 20 + ]; + + var vertices = Bytes.alloc(vertexData.length * 4); + for (i in 0...vertexData.length) + { + vertices.setFloat(i * 4, vertexData[i]); + } + + var indices = Bytes.alloc(indexData.length * 2); + for (i in 0...indexData.length) + { + indices.setUInt16(i * 2, indexData[i]); + } + + cubeVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), + VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, vertices); + cubeIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), + VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, indices); + + if (cubeVertexBuffer == null || cubeIndexBuffer == null) + { + fail("Failed to create Vulkan cube buffers: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createDescriptorLayouts():Bool + { + offscreenDescriptorSetLayout = device.createDescriptorSetLayout([ + new VKDescriptorSetLayoutBinding(0, VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK.SHADER_STAGE_FRAGMENT_BIT) + ]); + cubeDescriptorSetLayout = device.createDescriptorSetLayout([ + new VKDescriptorSetLayoutBinding(0, VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK.SHADER_STAGE_VERTEX_BIT), + new VKDescriptorSetLayoutBinding(1, VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK.SHADER_STAGE_FRAGMENT_BIT) + ]); + descriptorPool = device.createDescriptorPool(2, [ + new VKDescriptorPoolSize(VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2), + new VKDescriptorPoolSize(VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) + ]); + + if (offscreenDescriptorSetLayout == null || cubeDescriptorSetLayout == null || descriptorPool == null) + { + fail("Failed to create Vulkan descriptor layouts: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createOffscreenPass():Bool + { + offscreenRenderPass = device.createRenderPass(OFFSCREEN_FORMAT, VK.FORMAT_UNDEFINED, VK.SAMPLE_COUNT_1_BIT, + VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, + VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + offscreenImage = device.createImage(OFFSCREEN_SIZE, OFFSCREEN_SIZE, OFFSCREEN_FORMAT, + VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_SAMPLED_BIT | VK.IMAGE_USAGE_TRANSFER_SRC_BIT); + + if (offscreenRenderPass == null || offscreenImage == null || offscreenImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + fail("Failed to create Vulkan offscreen render target: " + VK.getLastError()); + return false; + } + + offscreenView = offscreenImage.createView(OFFSCREEN_FORMAT); + offscreenSampler = device.createSampler(VK.FILTER_LINEAR, VK.SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK.SAMPLER_MIPMAP_MODE_LINEAR); + offscreenFramebuffer = offscreenView != null ? device.createFramebuffer(offscreenRenderPass, [offscreenView], OFFSCREEN_SIZE, OFFSCREEN_SIZE) : null; + + offscreenDescriptorSet = descriptorPool.allocate(offscreenDescriptorSetLayout); + offscreenPipelineLayout = device.createPipelineLayout([offscreenDescriptorSetLayout]); + quadVertexShader = device.createShaderModule(Assets.getBytes("Assets/shaders/quad.vert.spv")); + quadFragmentShader = device.createShaderModule(Assets.getBytes("Assets/shaders/quad.frag.spv")); + + if (offscreenView == null || offscreenSampler == null || offscreenFramebuffer == null || offscreenDescriptorSet == null + || offscreenPipelineLayout == null || quadVertexShader == null || quadFragmentShader == null + || !offscreenDescriptorSet.updateImage(0, sourceTextureView, sourceTextureSampler)) + { + fail("Failed to create Vulkan offscreen pipeline resources: " + VK.getLastError()); + return false; + } + + var info = new VKGraphicsPipelineInfo(); + info.blend = true; + info.cullMode = VK.CULL_MODE_NONE; + info.vertexBindings.push(new VKVertexBinding(0, 32, VK.VERTEX_INPUT_RATE_VERTEX)); + info.vertexAttributes.push(new VKVertexAttribute(0, 0, VK.FORMAT_R32G32_SFLOAT, 0)); + info.vertexAttributes.push(new VKVertexAttribute(1, 0, VK.FORMAT_R32G32_SFLOAT, 8)); + info.vertexAttributes.push(new VKVertexAttribute(2, 0, VK.FORMAT_R32G32B32A32_SFLOAT, 16)); + + offscreenPipeline = device.createGraphicsPipeline(offscreenRenderPass, offscreenPipelineLayout, quadVertexShader, quadFragmentShader, info); + if (offscreenPipeline == null) + { + fail("Failed to create Vulkan offscreen graphics pipeline: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createOnscreenPass():Bool + { + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, VK.SAMPLE_COUNT_1_BIT, + VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + if (renderPass == null || !createDepthResources() || !createFramebuffers()) + { + fail("Failed to create Vulkan onscreen render pass resources: " + VK.getLastError()); + return false; + } + + cubeDescriptorSet = descriptorPool.allocate(cubeDescriptorSetLayout); + cubePipelineLayout = device.createPipelineLayout([cubeDescriptorSetLayout]); + cubeVertexShader = device.createShaderModule(Assets.getBytes("Assets/shaders/cube.vert.spv")); + cubeFragmentShader = device.createShaderModule(Assets.getBytes("Assets/shaders/cube.frag.spv")); + + if (cubeDescriptorSet == null || cubePipelineLayout == null || cubeVertexShader == null || cubeFragmentShader == null + || !cubeDescriptorSet.updateBuffer(0, uniformBuffer, 64) || !cubeDescriptorSet.updateImage(1, offscreenView, offscreenSampler)) + { + fail("Failed to create Vulkan cube descriptor resources: " + VK.getLastError()); + return false; + } + + var info = new VKGraphicsPipelineInfo(); + info.depthTest = true; + info.depthWrite = true; + info.depthCompareOp = VK.COMPARE_OP_LESS; + info.cullMode = VK.CULL_MODE_BACK_BIT; + info.frontFace = VK.FRONT_FACE_CLOCKWISE; + info.vertexBindings.push(new VKVertexBinding(0, 36, VK.VERTEX_INPUT_RATE_VERTEX)); + info.vertexAttributes.push(new VKVertexAttribute(0, 0, VK.FORMAT_R32G32B32_SFLOAT, 0)); + info.vertexAttributes.push(new VKVertexAttribute(1, 0, VK.FORMAT_R32G32_SFLOAT, 12)); + info.vertexAttributes.push(new VKVertexAttribute(2, 0, VK.FORMAT_R32G32B32A32_SFLOAT, 20)); + + cubePipeline = device.createGraphicsPipeline(renderPass, cubePipelineLayout, cubeVertexShader, cubeFragmentShader, info); + if (cubePipeline == null) + { + fail("Failed to create Vulkan cube graphics pipeline: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createDepthResources():Bool + { + disposeDepthResources(); + + depthImage = device.createImage(swapchain.width, swapchain.height, DEPTH_FORMAT, VK.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + if (depthImage == null || depthImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + return false; + } + + depthView = depthImage.createView(DEPTH_FORMAT, VK.IMAGE_ASPECT_DEPTH_BIT); + return depthView != null; + } + + private function createFramebuffers():Bool + { + disposeSwapchainFramebuffers(); + + for (image in swapchain.images) + { + var imageView = image.createView(swapchain.format); + if (imageView == null) + { + fail("Failed to create Vulkan swapchain image view: " + VK.getLastError()); + return false; + } + + var framebuffer = device.createFramebuffer(renderPass, [imageView, depthView], swapchain.width, swapchain.height); + if (framebuffer == null) + { + imageView.dispose(); + fail("Failed to create Vulkan framebuffer: " + VK.getLastError()); + return false; + } + + imageViews.push(imageView); + framebuffers.push(framebuffer); + } + + return true; + } + + private function drawFrame():Bool + { + if (!fence.waitForever()) + { + fail("Failed to wait for Vulkan frame fence: " + VK.getLastError()); + return false; + } + + var acquired = swapchain.acquireNextImage(imageAvailable); + if (acquired.result == VK.ERROR_OUT_OF_DATE_KHR) + { + return recreateSwapchain(window.width, window.height); + } + if (!acquired.isSuccess()) + { + fail("Failed to acquire Vulkan swapchain image: " + VK.getLastError()); + return false; + } + + var framebuffer = framebuffers[acquired.imageIndex]; + if (framebuffer == null) + { + fail("Swapchain image did not have a framebuffer"); + return false; + } + + if (!updateCubeUniform()) + { + fail("Failed to update Vulkan uniform buffer: " + VK.getLastError()); + return false; + } + + if (!commandBuffer.reset() + || !commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) + || !commandBuffer.beginRenderPass(offscreenRenderPass, offscreenFramebuffer, OFFSCREEN_SIZE, OFFSCREEN_SIZE, 0.02, 0.04, 0.07, 1.0) + || !commandBuffer.setViewport(0, 0, OFFSCREEN_SIZE, OFFSCREEN_SIZE) + || !commandBuffer.setScissor(0, 0, OFFSCREEN_SIZE, OFFSCREEN_SIZE) + || !commandBuffer.bindPipeline(offscreenPipeline) + || !commandBuffer.bindDescriptorSet(offscreenPipelineLayout, offscreenDescriptorSet) + || !commandBuffer.bindVertexBuffer(quadVertexBuffer) + || !commandBuffer.bindIndexBuffer(quadIndexBuffer) + || !commandBuffer.drawIndexed(6) + || !commandBuffer.endRenderPass() + || !commandBuffer.pipelineBarrierImage(offscreenImage, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK.PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK.ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK.ACCESS_SHADER_READ_BIT, VK.IMAGE_ASPECT_COLOR_BIT) + || !commandBuffer.beginRenderPass(renderPass, framebuffer, swapchain.width, swapchain.height, 0.07, 0.08, 0.09, 1.0, 1.0) + || !commandBuffer.setViewport(0, 0, swapchain.width, swapchain.height) + || !commandBuffer.setScissor(0, 0, swapchain.width, swapchain.height) + || !commandBuffer.bindPipeline(cubePipeline) + || !commandBuffer.bindDescriptorSet(cubePipelineLayout, cubeDescriptorSet) + || !commandBuffer.bindVertexBuffer(cubeVertexBuffer) + || !commandBuffer.bindIndexBuffer(cubeIndexBuffer) + || !commandBuffer.drawIndexed(36) + || !commandBuffer.endRenderPass() + || !commandBuffer.end()) + { + fail("Failed to record Vulkan draw commands: " + VK.getLastError()); + return false; + } + + if (!fence.reset() || !device.graphicsQueue.submitSynced(commandBuffer, imageAvailable, renderFinished, fence) + || !fence.waitForever()) + { + fail("Failed to submit Vulkan draw commands: " + VK.getLastError()); + return false; + } + + var presentResult = device.graphicsQueue.present(swapchain, acquired.imageIndex, renderFinished); + if (presentResult == VK.ERROR_OUT_OF_DATE_KHR) + { + return recreateSwapchain(window.width, window.height); + } + if (presentResult != VK.SUCCESS && presentResult != VK.SUBOPTIMAL_KHR) + { + fail("Failed to present Vulkan swapchain image: " + VK.getLastError()); + return false; + } + + return true; + } + + private function updateCubeUniform():Bool + { + var aspect = swapchain.height > 0 ? swapchain.width / swapchain.height : 1.0; + var angle = Timer.stamp(); + var model = multiply(rotationY(angle), rotationX(angle * 0.61)); + var view = translation(0, 0, -4.25); + var projection = perspective(Math.PI / 3, aspect, 0.1, 100); + var mvp = multiply(projection, multiply(view, model)); + var bytes = Bytes.alloc(64); + + for (i in 0...16) + { + bytes.setFloat(i * 4, mvp[i]); + } + + return uniformBuffer.upload(bytes); + } + + private function recreateSwapchain(width:Int, height:Int):Bool { - if (renderer != null) + if (width <= 0 || height <= 0 || swapchain == null) + { + return false; + } + + if (!device.waitIdle()) { - renderer.dispose(); - renderer = null; + fail("Failed to idle Vulkan device before swapchain recreation: " + VK.getLastError()); + return false; } + disposeSwapchainResources(); + var oldSwapchain = swapchain; + swapchain = oldSwapchain.recreate(width, height); + oldSwapchain.dispose(); + + if (swapchain == null || !swapchain.isValid() || swapchain.images.length == 0) + { + fail("Failed to recreate Vulkan swapchain: " + VK.getLastError()); + return false; + } + + return createDepthResources() && createFramebuffers(); + } + + private function disposeSwapchainResources():Void + { + disposeSwapchainFramebuffers(); + disposeDepthResources(); + } + + private function disposeSwapchainFramebuffers():Void + { + for (framebuffer in framebuffers) + { + if (framebuffer != null) + { + framebuffer.dispose(); + } + } + framebuffers = []; + + for (imageView in imageViews) + { + if (imageView != null) + { + imageView.dispose(); + } + } + imageViews = []; + } + + private function disposeDepthResources():Void + { + if (depthView != null) + { + depthView.dispose(); + depthView = null; + } + if (depthImage != null) + { + depthImage.dispose(true); + depthImage = null; + } + } + + private function complete():Void + { + disposeRenderer(); + if (window != null) { window.close(); } + System.exit(0); } - private function fail(message:String):Void + private function disposeRenderer():Void { - trace("Vulkan smoke failed: " + message); - - if (renderer != null) + if (device != null && device.isValid()) { - renderer.dispose(); - renderer = null; + device.waitIdle(); } + disposeSwapchainResources(); + if (offscreenFramebuffer != null) offscreenFramebuffer.dispose(); + if (offscreenView != null) offscreenView.dispose(); + if (offscreenImage != null) offscreenImage.dispose(true); + if (offscreenSampler != null) offscreenSampler.dispose(); + if (cubeIndexBuffer != null) cubeIndexBuffer.dispose(true); + if (cubeVertexBuffer != null) cubeVertexBuffer.dispose(true); + if (quadIndexBuffer != null) quadIndexBuffer.dispose(true); + if (quadVertexBuffer != null) quadVertexBuffer.dispose(true); + if (uniformBuffer != null) uniformBuffer.dispose(true); + if (cubePipeline != null) cubePipeline.dispose(); + if (cubePipelineLayout != null) cubePipelineLayout.dispose(); + if (offscreenPipeline != null) offscreenPipeline.dispose(); + if (offscreenPipelineLayout != null) offscreenPipelineLayout.dispose(); + if (descriptorPool != null) descriptorPool.dispose(); + if (cubeDescriptorSetLayout != null) cubeDescriptorSetLayout.dispose(); + if (offscreenDescriptorSetLayout != null) offscreenDescriptorSetLayout.dispose(); + if (sourceTextureSampler != null) sourceTextureSampler.dispose(); + if (sourceTextureView != null) sourceTextureView.dispose(); + if (sourceTextureImage != null) sourceTextureImage.dispose(true); + if (cubeFragmentShader != null) cubeFragmentShader.dispose(); + if (cubeVertexShader != null) cubeVertexShader.dispose(); + if (quadFragmentShader != null) quadFragmentShader.dispose(); + if (quadVertexShader != null) quadVertexShader.dispose(); + if (renderPass != null) renderPass.dispose(); + if (offscreenRenderPass != null) offscreenRenderPass.dispose(); + if (fence != null) fence.dispose(); + if (renderFinished != null) renderFinished.dispose(); + if (imageAvailable != null) imageAvailable.dispose(); + if (commandBuffer != null) commandBuffer.dispose(); + if (commandPool != null) commandPool.dispose(); + if (swapchain != null) swapchain.dispose(); + if (device != null) device.dispose(); + if (surface != null) surface.dispose(); + if (instance != null) instance.dispose(); + + commandBuffer = null; + commandPool = null; + cubeDescriptorSet = null; + cubeDescriptorSetLayout = null; + cubeFragmentShader = null; + cubeIndexBuffer = null; + cubePipeline = null; + cubePipelineLayout = null; + cubeVertexBuffer = null; + cubeVertexShader = null; + descriptorPool = null; + device = null; + fence = null; + imageAvailable = null; + instance = null; + offscreenDescriptorSet = null; + offscreenDescriptorSetLayout = null; + offscreenFramebuffer = null; + offscreenImage = null; + offscreenPipeline = null; + offscreenPipelineLayout = null; + offscreenRenderPass = null; + offscreenSampler = null; + offscreenView = null; + quadFragmentShader = null; + quadIndexBuffer = null; + quadVertexBuffer = null; + quadVertexShader = null; + renderFinished = null; + renderPass = null; + sourceTextureImage = null; + sourceTextureSampler = null; + sourceTextureView = null; + surface = null; + swapchain = null; + uniformBuffer = null; + } + + private function fail(message:String):Void + { + trace("Vulkan smoke failed: " + message); + disposeRenderer(); System.exit(1); } + private static function identity():Array + { + return [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ]; + } + private static inline function isNonZero(value:Int64):Bool { return value.high != 0 || value.low != 0; } + + private static function multiply(a:Array, b:Array):Array + { + var result = []; + + for (column in 0...4) + { + for (row in 0...4) + { + var value = 0.0; + for (i in 0...4) + { + value += a[i * 4 + row] * b[column * 4 + i]; + } + result[column * 4 + row] = value; + } + } + + return result; + } + + private static function perspective(fovY:Float, aspect:Float, near:Float, far:Float):Array + { + var f = 1.0 / Math.tan(fovY * 0.5); + var result = [ + f / aspect, 0.0, 0.0, 0.0, + 0.0, -f, 0.0, 0.0, + 0.0, 0.0, far / (near - far), -1.0, + 0.0, 0.0, (far * near) / (near - far), 0.0 + ]; + return result; + } + + private static function rotationX(angle:Float):Array + { + var c = Math.cos(angle); + var s = Math.sin(angle); + var result = identity(); + result[5] = c; + result[6] = s; + result[9] = -s; + result[10] = c; + return result; + } + + private static function rotationY(angle:Float):Array + { + var c = Math.cos(angle); + var s = Math.sin(angle); + var result = identity(); + result[0] = c; + result[2] = -s; + result[8] = s; + result[10] = c; + return result; + } + + private static function translation(x:Float, y:Float, z:Float):Array + { + var result = identity(); + result[12] = x; + result[13] = y; + result[14] = z; + return result; + } } diff --git a/tests/vulkan-smoke/project.xml b/tests/vulkan-smoke/project.xml index 4752ae8640..47c1e61a7a 100644 --- a/tests/vulkan-smoke/project.xml +++ b/tests/vulkan-smoke/project.xml @@ -5,6 +5,7 @@ + From 9acbfe74c154d3897d8a89c94a70880e3784b66e Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 22 May 2026 15:00:48 -0400 Subject: [PATCH 14/76] Vulkan: add memory download and command helpers Add multiple Vulkan helpers and extended pipeline/command support. - Implement lime_vk_download_memory (and HL variant) to map and copy device memory to host Bytes. - Add lime_vk_reset_descriptor_pool (and HL variant) to reset descriptor pools. - Extend pipeline cache creation to accept initial data and add lime_vk_get_pipeline_cache_data to retrieve cache blobs (with HL variants). - Expand graphics pipeline state parsing to include stencil ops and per-attachment color write mask. - Add new command helpers: cmd bind descriptor set (extended), copy buffer<->image region variants, clear depth/stencil image, push constants, and enhanced blit image parameter handling. - Register new native primes and update NativeCFFI.hx to expose the added functions. - Minor fix: include VK_IMAGE_USAGE_TRANSFER_SRC_BIT when supported. These changes are intended to expose more/additional Vulkan functionality to the higher-level API and allow using pipeline caches, fine-grained copy/blit/clear operations, push constants, and descriptor pool management. --- project/src/ExternalInterface.cpp | 870 +++++++++++++++++- .../_internal/backend/native/NativeCFFI.hx | 112 ++- src/lime/graphics/vulkan/VK.hx | 8 + src/lime/graphics/vulkan/VKBuffer.hx | 5 + src/lime/graphics/vulkan/VKCommandBuffer.hx | 160 +++- src/lime/graphics/vulkan/VKDescriptorPool.hx | 13 + src/lime/graphics/vulkan/VKDevice.hx | 9 +- src/lime/graphics/vulkan/VKDeviceMemory.hx | 30 + .../graphics/vulkan/VKGraphicsPipelineInfo.hx | 32 + src/lime/graphics/vulkan/VKPipelineCache.hx | 18 + 10 files changed, 1216 insertions(+), 41 deletions(-) diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index dff828e2ab..45fd23893d 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -963,6 +963,11 @@ namespace lime { imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + } + if (capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { + + imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + } uint32_t imageCount = capabilities.minImageCount + 1; @@ -6488,6 +6493,89 @@ namespace lime { } + bool lime_vk_download_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, value bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + Bytes data (bytes); + if (!memory || !data.b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.length) { + + lastVKError = "Invalid Vulkan memory download range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (data.b + byteOffset, mappedData, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_download_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !bytes || !bytes->b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid Vulkan memory download range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (bytes->b + byteOffset, mappedData, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vk_create_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int sizeHigh, int sizeLow, int usage) { #ifdef LIME_VULKAN @@ -8595,6 +8683,66 @@ namespace lime { } + bool lime_vk_reset_descriptor_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, int poolLow, + int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkResetDescriptorPool vkResetDescriptorPool = + (PFN_vkResetDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetDescriptorPool"); + if (!vkResetDescriptorPool || !pool) return false; + + VkResult result = vkResetDescriptorPool (device, pool, (VkDescriptorPoolResetFlags)flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetDescriptorPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_descriptor_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int poolHigh, int poolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkResetDescriptorPool vkResetDescriptorPool = + (PFN_vkResetDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetDescriptorPool"); + if (!vkResetDescriptorPool || !pool) return false; + + VkResult result = vkResetDescriptorPool (device, pool, (VkDescriptorPoolResetFlags)flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetDescriptorPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vk_allocate_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, int poolLow, int layoutHigh, int layoutLow) { @@ -9018,7 +9166,8 @@ namespace lime { } - value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bytes, int byteOffset, + int byteLength) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); @@ -9031,6 +9180,20 @@ namespace lime { VkPipelineCacheCreateInfo createInfo; memset (&createInfo, 0, sizeof (createInfo)); createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + Bytes initialData (bytes); + if (initialData.b && byteLength > 0) { + + if (byteOffset < 0 || byteOffset + byteLength > initialData.length) { + + lastVKError = "Invalid Vulkan pipeline cache data range"; + return alloc_null (); + + } + + createInfo.initialDataSize = (size_t)byteLength; + createInfo.pInitialData = initialData.b + byteOffset; + + } VkPipelineCache cache = VK_NULL_HANDLE; VkResult result = vkCreatePipelineCache (device, &createInfo, 0, &cache); @@ -9052,7 +9215,7 @@ namespace lime { HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, - int deviceLow) { + int deviceLow, Bytes* bytes, int byteOffset, int byteLength) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; @@ -9065,6 +9228,19 @@ namespace lime { VkPipelineCacheCreateInfo createInfo; memset (&createInfo, 0, sizeof (createInfo)); createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + if (bytes && bytes->b && byteLength > 0) { + + if (byteOffset < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid Vulkan pipeline cache data range"; + return 0; + + } + + createInfo.initialDataSize = (size_t)byteLength; + createInfo.pInitialData = bytes->b + byteOffset; + + } VkPipelineCache cache = VK_NULL_HANDLE; VkResult result = vkCreatePipelineCache (device, &createInfo, 0, &cache); @@ -9085,6 +9261,92 @@ namespace lime { } + bool lime_vk_get_pipeline_cache_data (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow, value bytes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkGetPipelineCacheData vkGetPipelineCacheData = + (PFN_vkGetPipelineCacheData)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetPipelineCacheData"); + if (!vkGetPipelineCacheData || !cache) return false; + + size_t size = 0; + VkResult result = vkGetPipelineCacheData (device, cache, &size, 0); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetPipelineCacheData failed"; + return false; + + } + + Bytes data (bytes); + data.Resize ((int)size); + if (size > 0 && !data.b) return false; + + result = vkGetPipelineCacheData (device, cache, &size, data.b); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetPipelineCacheData failed"; + return false; + + } + + data.Value (bytes); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_get_pipeline_cache_data) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int cacheHigh, int cacheLow, Bytes* bytes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkGetPipelineCacheData vkGetPipelineCacheData = + (PFN_vkGetPipelineCacheData)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetPipelineCacheData"); + if (!vkGetPipelineCacheData || !cache || !bytes) return false; + + size_t size = 0; + VkResult result = vkGetPipelineCacheData (device, cache, &size, 0); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetPipelineCacheData failed"; + return false; + + } + + bytes->Resize ((int)size); + if (size > 0 && !bytes->b) return false; + + result = vkGetPipelineCacheData (device, cache, &size, bytes->b); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetPipelineCacheData failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + void lime_vk_destroy_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, int cacheLow) { @@ -9145,7 +9407,7 @@ namespace lime { static VkPipeline CreateManagedVulkanGraphicsPipeline (Window* targetWindow, VkInstance instance, VkDevice device, VkRenderPass renderPass, VkPipelineLayout layout, VkShaderModule vertexShader, VkShaderModule fragmentShader, const std::vector& state) { - if (state.size () < 19 || !renderPass || !layout || !vertexShader || !fragmentShader) { + if (state.size () < 35 || !renderPass || !layout || !vertexShader || !fragmentShader) { lastVKError = "Invalid Vulkan graphics pipeline state"; return VK_NULL_HANDLE; @@ -9171,6 +9433,22 @@ namespace lime { int dstAlphaBlendFactor = state[cursor++]; int alphaBlendOp = state[cursor++]; int dynamicStateFlags = state[cursor++]; + int colorWriteMask = state[cursor++]; + bool stencilTest = state[cursor++] != 0; + int frontFailOp = state[cursor++]; + int frontPassOp = state[cursor++]; + int frontDepthFailOp = state[cursor++]; + int frontCompareOp = state[cursor++]; + int frontCompareMask = state[cursor++]; + int frontWriteMask = state[cursor++]; + int frontReference = state[cursor++]; + int backFailOp = state[cursor++]; + int backPassOp = state[cursor++]; + int backDepthFailOp = state[cursor++]; + int backCompareOp = state[cursor++]; + int backCompareMask = state[cursor++]; + int backWriteMask = state[cursor++]; + int backReference = state[cursor++]; int bindingCount = state[cursor++]; if ((int)state.size () < cursor + bindingCount * 3 + 1) { @@ -9280,10 +9558,25 @@ namespace lime { depthStencil.depthTestEnable = depthTest ? VK_TRUE : VK_FALSE; depthStencil.depthWriteEnable = depthWrite ? VK_TRUE : VK_FALSE; depthStencil.depthCompareOp = (VkCompareOp)depthCompareOp; + depthStencil.stencilTestEnable = stencilTest ? VK_TRUE : VK_FALSE; + depthStencil.front.failOp = (VkStencilOp)frontFailOp; + depthStencil.front.passOp = (VkStencilOp)frontPassOp; + depthStencil.front.depthFailOp = (VkStencilOp)frontDepthFailOp; + depthStencil.front.compareOp = (VkCompareOp)frontCompareOp; + depthStencil.front.compareMask = (uint32_t)frontCompareMask; + depthStencil.front.writeMask = (uint32_t)frontWriteMask; + depthStencil.front.reference = (uint32_t)frontReference; + depthStencil.back.failOp = (VkStencilOp)backFailOp; + depthStencil.back.passOp = (VkStencilOp)backPassOp; + depthStencil.back.depthFailOp = (VkStencilOp)backDepthFailOp; + depthStencil.back.compareOp = (VkCompareOp)backCompareOp; + depthStencil.back.compareMask = (uint32_t)backCompareMask; + depthStencil.back.writeMask = (uint32_t)backWriteMask; + depthStencil.back.reference = (uint32_t)backReference; VkPipelineColorBlendAttachmentState colorAttachment; memset (&colorAttachment, 0, sizeof (colorAttachment)); - colorAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorAttachment.colorWriteMask = (VkColorComponentFlags)colorWriteMask; colorAttachment.blendEnable = blend ? VK_TRUE : VK_FALSE; colorAttachment.srcColorBlendFactor = (VkBlendFactor)srcColorBlendFactor; colorAttachment.dstColorBlendFactor = (VkBlendFactor)dstColorBlendFactor; @@ -9768,6 +10061,70 @@ namespace lime { } + bool lime_vk_cmd_bind_descriptor_set_ex (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, value state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet || packed.size () < 3) return false; + + int dynamicOffsetCount = packed[2]; + if ((int)packed.size () < 3 + dynamicOffsetCount) return false; + std::vector dynamicOffsets; + dynamicOffsets.reserve ((size_t)dynamicOffsetCount); + for (int i = 0; i < dynamicOffsetCount; ++i) dynamicOffsets.push_back ((uint32_t)packed[3 + i]); + + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)packed[0], layout, (uint32_t)packed[1], 1, &descriptorSet, + (uint32_t)dynamicOffsets.size (), dynamicOffsets.empty () ? 0 : dynamicOffsets.data ()); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_ex) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, hl_varray* state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet || packed.size () < 3) return false; + + int dynamicOffsetCount = packed[2]; + if ((int)packed.size () < 3 + dynamicOffsetCount) return false; + std::vector dynamicOffsets; + dynamicOffsets.reserve ((size_t)dynamicOffsetCount); + for (int i = 0; i < dynamicOffsetCount; ++i) dynamicOffsets.push_back ((uint32_t)packed[3 + i]); + + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)packed[0], layout, (uint32_t)packed[1], 1, &descriptorSet, + (uint32_t)dynamicOffsets.size (), dynamicOffsets.empty () ? 0 : dynamicOffsets.data ()); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vulkan_renderer_get_info (value handle) { if (val_is_null (handle)) return alloc_string (""); @@ -10183,6 +10540,162 @@ namespace lime { } + + bool lime_vk_cmd_copy_buffer_to_image_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, value state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = + (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdCopyBufferToImage || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), + (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, hl_varray* state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = + (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdCopyBufferToImage || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), + (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_cmd_copy_image_to_buffer_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, value state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer = + (PFN_vkCmdCopyImageToBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyImageToBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdCopyImageToBuffer || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyImageToBuffer (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], + (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_image_to_buffer_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, hl_varray* state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer = + (PFN_vkCmdCopyImageToBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyImageToBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdCopyImageToBuffer || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyImageToBuffer (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], + (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); @@ -10334,6 +10847,76 @@ namespace lime { } + bool lime_vk_cmd_clear_depth_stencil_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state, value clear) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage = + (PFN_vkCmdClearDepthStencilImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearDepthStencilImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdClearDepthStencilImage || !commandBuffer || packed.size () < 7 || clearValues.size () < 1) return false; + + VkClearDepthStencilValue depthStencil; + depthStencil.depth = (float)clearValues[0]; + depthStencil.stencil = (uint32_t)packed[1]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)packed[2]; + range.baseMipLevel = (uint32_t)packed[3]; + range.levelCount = (uint32_t)packed[4]; + range.baseArrayLayer = (uint32_t)packed[5]; + range.layerCount = (uint32_t)packed[6]; + vkCmdClearDepthStencilImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[0], + &depthStencil, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_depth_stencil_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state, hl_varray* clear) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage = + (PFN_vkCmdClearDepthStencilImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearDepthStencilImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdClearDepthStencilImage || !commandBuffer || packed.size () < 7 || clearValues.size () < 1) return false; + + VkClearDepthStencilValue depthStencil; + depthStencil.depth = (float)clearValues[0]; + depthStencil.stencil = (uint32_t)packed[1]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)packed[2]; + range.baseMipLevel = (uint32_t)packed[3]; + range.levelCount = (uint32_t)packed[4]; + range.baseArrayLayer = (uint32_t)packed[5]; + range.layerCount = (uint32_t)packed[6]; + vkCmdClearDepthStencilImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[0], + &depthStencil, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { @@ -10348,18 +10931,52 @@ namespace lime { VkImageBlit blit; memset (&blit, 0, sizeof (blit)); - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.layerCount = 1; - blit.srcOffsets[1].x = packed[0]; - blit.srcOffsets[1].y = packed[1]; - blit.srcOffsets[1].z = 1; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.layerCount = 1; - blit.dstOffsets[1].x = packed[0]; - blit.dstOffsets[1].y = packed[1]; - blit.dstOffsets[1].z = 1; - vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)packed[2], - (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)packed[3], 1, &blit, (VkFilter)packed[4]); + int sourceLayout = packed[2]; + int destinationLayout = packed[3]; + int filter = packed[4]; + if (packed.size () >= 21) { + + blit.srcOffsets[0].x = packed[0]; + blit.srcOffsets[0].y = packed[1]; + blit.srcOffsets[0].z = packed[2]; + blit.srcOffsets[1].x = packed[3]; + blit.srcOffsets[1].y = packed[4]; + blit.srcOffsets[1].z = packed[5]; + blit.dstOffsets[0].x = packed[6]; + blit.dstOffsets[0].y = packed[7]; + blit.dstOffsets[0].z = packed[8]; + blit.dstOffsets[1].x = packed[9]; + blit.dstOffsets[1].y = packed[10]; + blit.dstOffsets[1].z = packed[11]; + sourceLayout = packed[12]; + destinationLayout = packed[13]; + filter = packed[14]; + blit.srcSubresource.mipLevel = (uint32_t)packed[15]; + blit.dstSubresource.mipLevel = (uint32_t)packed[16]; + blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; + blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; + blit.srcSubresource.layerCount = (uint32_t)packed[19]; + blit.dstSubresource.layerCount = (uint32_t)packed[19]; + blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + + } else { + + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.layerCount = 1; + blit.srcOffsets[1].x = packed[0]; + blit.srcOffsets[1].y = packed[1]; + blit.srcOffsets[1].z = 1; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.layerCount = 1; + blit.dstOffsets[1].x = packed[0]; + blit.dstOffsets[1].y = packed[1]; + blit.dstOffsets[1].z = 1; + + } + vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)sourceLayout, + (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)destinationLayout, 1, &blit, + (VkFilter)filter); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -10383,18 +11000,52 @@ namespace lime { VkImageBlit blit; memset (&blit, 0, sizeof (blit)); - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.layerCount = 1; - blit.srcOffsets[1].x = packed[0]; - blit.srcOffsets[1].y = packed[1]; - blit.srcOffsets[1].z = 1; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.layerCount = 1; - blit.dstOffsets[1].x = packed[0]; - blit.dstOffsets[1].y = packed[1]; - blit.dstOffsets[1].z = 1; - vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)packed[2], - (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)packed[3], 1, &blit, (VkFilter)packed[4]); + int sourceLayout = packed[2]; + int destinationLayout = packed[3]; + int filter = packed[4]; + if (packed.size () >= 21) { + + blit.srcOffsets[0].x = packed[0]; + blit.srcOffsets[0].y = packed[1]; + blit.srcOffsets[0].z = packed[2]; + blit.srcOffsets[1].x = packed[3]; + blit.srcOffsets[1].y = packed[4]; + blit.srcOffsets[1].z = packed[5]; + blit.dstOffsets[0].x = packed[6]; + blit.dstOffsets[0].y = packed[7]; + blit.dstOffsets[0].z = packed[8]; + blit.dstOffsets[1].x = packed[9]; + blit.dstOffsets[1].y = packed[10]; + blit.dstOffsets[1].z = packed[11]; + sourceLayout = packed[12]; + destinationLayout = packed[13]; + filter = packed[14]; + blit.srcSubresource.mipLevel = (uint32_t)packed[15]; + blit.dstSubresource.mipLevel = (uint32_t)packed[16]; + blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; + blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; + blit.srcSubresource.layerCount = (uint32_t)packed[19]; + blit.dstSubresource.layerCount = (uint32_t)packed[19]; + blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + + } else { + + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.layerCount = 1; + blit.srcOffsets[1].x = packed[0]; + blit.srcOffsets[1].y = packed[1]; + blit.srcOffsets[1].z = 1; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.layerCount = 1; + blit.dstOffsets[1].x = packed[0]; + blit.dstOffsets[1].y = packed[1]; + blit.dstOffsets[1].z = 1; + + } + vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)sourceLayout, + (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)destinationLayout, 1, &blit, + (VkFilter)filter); return true; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -10403,6 +11054,58 @@ namespace lime { } + + bool lime_vk_cmd_push_constants (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, value state, value bytes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPushConstants vkCmdPushConstants = + (PFN_vkCmdPushConstants)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPushConstants"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + std::vector packed = GetVulkanIntVector (state); + Bytes data (bytes); + if (!vkCmdPushConstants || !commandBuffer || !layout || !data.b || packed.size () < 4) return false; + if (packed[2] < 0 || packed[3] < 0 || packed[2] + packed[3] > data.length) return false; + + vkCmdPushConstants (commandBuffer, layout, (VkShaderStageFlags)packed[0], (uint32_t)packed[1], (uint32_t)packed[3], data.b + packed[2]); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_push_constants) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, hl_varray* state, Bytes* bytes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPushConstants vkCmdPushConstants = + (PFN_vkCmdPushConstants)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPushConstants"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdPushConstants || !commandBuffer || !layout || !bytes || !bytes->b || packed.size () < 4) return false; + if (packed[2] < 0 || packed[3] < 0 || packed[2] + packed[3] > bytes->length) return false; + + vkCmdPushConstants (commandBuffer, layout, (VkShaderStageFlags)packed[0], (uint32_t)packed[1], (uint32_t)packed[3], bytes->b + packed[2]); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { if (val_is_null (handle)) return false; @@ -10570,7 +11273,8 @@ namespace lime { } - value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bytes, int byteOffset, + int byteLength) { return LimeVulkanUnavailableValue (); @@ -10578,7 +11282,7 @@ namespace lime { HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, - int deviceLow) { + int deviceLow, Bytes* bytes, int byteOffset, int byteLength) { return HLLimeVulkanUnavailableValue (); @@ -10601,6 +11305,22 @@ namespace lime { } + bool lime_vk_get_pipeline_cache_data (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow, value bytes) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_get_pipeline_cache_data) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int cacheHigh, int cacheLow, Bytes* bytes) { + + return LimeVulkanUnavailableBool (); + + } + + value lime_vk_create_graphics_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, int fragmentShaderHigh, int fragmentShaderLow, value state) { @@ -10717,6 +11437,22 @@ namespace lime { } + bool lime_vk_cmd_bind_descriptor_set_ex (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, value state) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_ex) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, hl_varray* state) { + + return LimeVulkanUnavailableBool (); + + } + + bool lime_vk_cmd_bind_vertex_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { @@ -10846,6 +11582,38 @@ namespace lime { } + bool lime_vk_cmd_copy_buffer_to_image_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, value state) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, hl_varray* state) { + + return LimeVulkanUnavailableBool (); + + } + + + bool lime_vk_cmd_copy_image_to_buffer_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, value state) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_image_to_buffer_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, hl_varray* state) { + + return LimeVulkanUnavailableBool (); + + } + + bool lime_vk_cmd_pipeline_barrier_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state) { @@ -10878,6 +11646,22 @@ namespace lime { } + bool lime_vk_cmd_clear_depth_stencil_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state, value clear) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_depth_stencil_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state, hl_varray* clear) { + + return LimeVulkanUnavailableBool (); + + } + + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { @@ -10894,6 +11678,22 @@ namespace lime { } + bool lime_vk_cmd_push_constants (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, value state, value bytes) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_push_constants) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, hl_varray* state, Bytes* bytes) { + + return LimeVulkanUnavailableBool (); + + } + + value lime_vulkan_renderer_create (value window, HxString applicationName) { lastVulkanRendererError = "Lime was built without lime-vulkan support"; @@ -11810,6 +12610,7 @@ namespace lime { DEFINE_PRIME11 (lime_vk_allocate_memory); DEFINE_PRIME7v (lime_vk_free_memory); DEFINE_PRIME12 (lime_vk_upload_memory); + DEFINE_PRIME12 (lime_vk_download_memory); DEFINE_PRIME8 (lime_vk_create_buffer); DEFINE_PRIME7v (lime_vk_destroy_buffer); DEFINE_PRIME7 (lime_vk_get_buffer_memory_requirements); @@ -11838,13 +12639,15 @@ namespace lime { DEFINE_PRIME7v (lime_vk_destroy_descriptor_set_layout); DEFINE_PRIME6 (lime_vk_create_descriptor_pool); DEFINE_PRIME7v (lime_vk_destroy_descriptor_pool); + DEFINE_PRIME8 (lime_vk_reset_descriptor_pool); DEFINE_PRIME9 (lime_vk_allocate_descriptor_set); DEFINE_PRIME14 (lime_vk_update_descriptor_set_image); DEFINE_PRIME13 (lime_vk_update_descriptor_set_buffer); DEFINE_PRIME8 (lime_vk_create_pipeline_layout); DEFINE_PRIME7v (lime_vk_destroy_pipeline_layout); - DEFINE_PRIME5 (lime_vk_create_pipeline_cache); + DEFINE_PRIME8 (lime_vk_create_pipeline_cache); DEFINE_PRIME7v (lime_vk_destroy_pipeline_cache); + DEFINE_PRIME8 (lime_vk_get_pipeline_cache_data); DEFINE_PRIME14 (lime_vk_create_graphics_pipeline); DEFINE_PRIME7v (lime_vk_destroy_pipeline); DEFINE_PRIME10 (lime_vk_queue_submit_synced); @@ -11852,6 +12655,7 @@ namespace lime { DEFINE_PRIME7 (lime_vk_cmd_end_render_pass); DEFINE_PRIME10 (lime_vk_cmd_bind_pipeline); DEFINE_PRIME13 (lime_vk_cmd_bind_descriptor_set); + DEFINE_PRIME12 (lime_vk_cmd_bind_descriptor_set_ex); DEFINE_PRIME12 (lime_vk_cmd_bind_vertex_buffer); DEFINE_PRIME12 (lime_vk_cmd_bind_index_buffer); DEFINE_PRIME13 (lime_vk_cmd_set_viewport); @@ -11860,9 +12664,13 @@ namespace lime { DEFINE_PRIME12 (lime_vk_cmd_draw_indexed); DEFINE_PRIME12 (lime_vk_cmd_copy_buffer); DEFINE_PRIME14 (lime_vk_cmd_copy_buffer_to_image); + DEFINE_PRIME12 (lime_vk_cmd_copy_buffer_to_image_region); + DEFINE_PRIME12 (lime_vk_cmd_copy_image_to_buffer_region); DEFINE_PRIME10 (lime_vk_cmd_pipeline_barrier_image); DEFINE_PRIME12 (lime_vk_cmd_clear_color_image); + DEFINE_PRIME11 (lime_vk_cmd_clear_depth_stencil_image); DEFINE_PRIME12 (lime_vk_cmd_blit_image); + DEFINE_PRIME11 (lime_vk_cmd_push_constants); DEFINE_PRIME0 (lime_vk_get_last_error); DEFINE_PRIME2 (lime_vulkan_renderer_create); DEFINE_PRIME1v (lime_vulkan_renderer_destroy); diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index f36431e453..4965f04ed3 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -424,6 +424,9 @@ class NativeCFFI @:cffi private static function lime_vk_upload_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + @:cffi private static function lime_vk_download_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + @:cffi private static function lime_vk_create_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic; @@ -511,6 +514,9 @@ class NativeCFFI @:cffi private static function lime_vk_destroy_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int):Void; + @:cffi private static function lime_vk_reset_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, poolHigh:Int, poolLow:Int, flags:Int):Bool; + @:cffi private static function lime_vk_allocate_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic; @@ -528,11 +534,14 @@ class NativeCFFI deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void; @:cffi private static function lime_vk_create_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int):Dynamic; + deviceLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Dynamic; @:cffi private static function lime_vk_destroy_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void; + @:cffi private static function lime_vk_get_pipeline_cache_data(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, cacheHigh:Int, cacheLow:Int, bytes:Dynamic):Bool; + @:cffi private static function lime_vk_create_graphics_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, fragmentShaderHigh:Int, fragmentShaderLow:Int, state:Array):Dynamic; @@ -557,6 +566,9 @@ class NativeCFFI deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, firstSet:Int):Bool; + @:cffi private static function lime_vk_cmd_bind_descriptor_set_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, state:Array):Bool; + @:cffi private static function lime_vk_cmd_bind_vertex_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool; @@ -582,14 +594,28 @@ class NativeCFFI deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, width:Int, height:Int, layout:Int):Bool; + @:cffi private static function lime_vk_cmd_copy_buffer_to_image_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, + state:Array):Bool; + + @:cffi private static function lime_vk_cmd_copy_image_to_buffer_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, bufferHigh:Int, bufferLow:Int, + state:Array):Bool; + @:cffi private static function lime_vk_cmd_pipeline_barrier_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; @:cffi private static function lime_vk_cmd_clear_color_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, layout:Int, aspectMask:Int, clear:Array):Bool; + @:cffi private static function lime_vk_cmd_clear_depth_stencil_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array, clear:Array):Bool; + @:cffi private static function lime_vk_cmd_blit_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_push_constants(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, state:Array, bytes:Dynamic):Bool; #end @:cffi private static function lime_vk_get_last_error():Dynamic; @@ -971,6 +997,8 @@ class NativeCFFI "lime_vk_free_memory", "oiiiiiiv", false)); private static var lime_vk_upload_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( "lime", "lime_vk_upload_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_download_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_download_memory", "oiiiiiiiioiib", false)); private static var lime_vk_create_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_buffer", "oiiiiiiio", false)); private static var lime_vk_destroy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1027,6 +1055,8 @@ class NativeCFFI "lime_vk_create_descriptor_pool", "oiiiioo", false)); private static var lime_vk_destroy_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_descriptor_pool", "oiiiiiiv", false)); + private static var lime_vk_reset_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_descriptor_pool", "oiiiiiiib", false)); private static var lime_vk_allocate_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_descriptor_set", "oiiiiiiiio", false)); private static var lime_vk_update_descriptor_set_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( @@ -1037,10 +1067,12 @@ class NativeCFFI "lime_vk_create_pipeline_layout", "oiiiioiio", false)); private static var lime_vk_destroy_pipeline_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_pipeline_layout", "oiiiiiiv", false)); - private static var lime_vk_create_pipeline_cache = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_pipeline_cache", "oiiiio", false)); + private static var lime_vk_create_pipeline_cache = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_pipeline_cache", "oiiiioiio", false)); private static var lime_vk_destroy_pipeline_cache = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_pipeline_cache", "oiiiiiiv", false)); + private static var lime_vk_get_pipeline_cache_data = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_get_pipeline_cache_data", "oiiiiiiob", false)); private static var lime_vk_create_graphics_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_graphics_pipeline", "oiiiiiiiiiiiioo", false)); private static var lime_vk_destroy_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1055,6 +1087,8 @@ class NativeCFFI "lime_vk_cmd_bind_pipeline", "oiiiiiiiiib", false)); private static var lime_vk_cmd_bind_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_descriptor_set_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_ex", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_bind_vertex_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_vertex_buffer", "oiiiiiiiiiiib", false)); private static var lime_vk_cmd_bind_index_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( @@ -1071,12 +1105,20 @@ class NativeCFFI cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_copy_buffer_to_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_copy_buffer_to_image_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image_region", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_copy_image_to_buffer_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_image_to_buffer_region", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_pipeline_barrier_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_pipeline_barrier_image", "oiiiiiiiiob", false)); private static var lime_vk_cmd_clear_color_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_color_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_clear_depth_stencil_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_depth_stencil_image", "oiiiiiiiioob", false)); private static var lime_vk_cmd_blit_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_blit_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_push_constants = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_push_constants", "oiiiiiiiioob", false)); #end private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_last_error", "o", false)); @@ -1322,6 +1364,7 @@ class NativeCFFI private static var lime_vk_allocate_memory = CFFI.load("lime", "lime_vk_allocate_memory", -1); private static var lime_vk_free_memory = CFFI.load("lime", "lime_vk_free_memory", -1); private static var lime_vk_upload_memory = CFFI.load("lime", "lime_vk_upload_memory", -1); + private static var lime_vk_download_memory = CFFI.load("lime", "lime_vk_download_memory", -1); private static var lime_vk_create_buffer = CFFI.load("lime", "lime_vk_create_buffer", -1); private static var lime_vk_destroy_buffer = CFFI.load("lime", "lime_vk_destroy_buffer", -1); private static var lime_vk_get_buffer_memory_requirements = CFFI.load("lime", "lime_vk_get_buffer_memory_requirements", -1); @@ -1350,6 +1393,7 @@ class NativeCFFI private static var lime_vk_destroy_descriptor_set_layout = CFFI.load("lime", "lime_vk_destroy_descriptor_set_layout", -1); private static var lime_vk_create_descriptor_pool = CFFI.load("lime", "lime_vk_create_descriptor_pool", -1); private static var lime_vk_destroy_descriptor_pool = CFFI.load("lime", "lime_vk_destroy_descriptor_pool", -1); + private static var lime_vk_reset_descriptor_pool = CFFI.load("lime", "lime_vk_reset_descriptor_pool", -1); private static var lime_vk_allocate_descriptor_set = CFFI.load("lime", "lime_vk_allocate_descriptor_set", -1); private static var lime_vk_update_descriptor_set_image = CFFI.load("lime", "lime_vk_update_descriptor_set_image", -1); private static var lime_vk_update_descriptor_set_buffer = CFFI.load("lime", "lime_vk_update_descriptor_set_buffer", -1); @@ -1357,6 +1401,7 @@ class NativeCFFI private static var lime_vk_destroy_pipeline_layout = CFFI.load("lime", "lime_vk_destroy_pipeline_layout", -1); private static var lime_vk_create_pipeline_cache = CFFI.load("lime", "lime_vk_create_pipeline_cache", -1); private static var lime_vk_destroy_pipeline_cache = CFFI.load("lime", "lime_vk_destroy_pipeline_cache", -1); + private static var lime_vk_get_pipeline_cache_data = CFFI.load("lime", "lime_vk_get_pipeline_cache_data", -1); private static var lime_vk_create_graphics_pipeline = CFFI.load("lime", "lime_vk_create_graphics_pipeline", -1); private static var lime_vk_destroy_pipeline = CFFI.load("lime", "lime_vk_destroy_pipeline", -1); private static var lime_vk_queue_submit_synced = CFFI.load("lime", "lime_vk_queue_submit_synced", -1); @@ -1364,6 +1409,7 @@ class NativeCFFI private static var lime_vk_cmd_end_render_pass = CFFI.load("lime", "lime_vk_cmd_end_render_pass", -1); private static var lime_vk_cmd_bind_pipeline = CFFI.load("lime", "lime_vk_cmd_bind_pipeline", -1); private static var lime_vk_cmd_bind_descriptor_set = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set", -1); + private static var lime_vk_cmd_bind_descriptor_set_ex = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set_ex", -1); private static var lime_vk_cmd_bind_vertex_buffer = CFFI.load("lime", "lime_vk_cmd_bind_vertex_buffer", -1); private static var lime_vk_cmd_bind_index_buffer = CFFI.load("lime", "lime_vk_cmd_bind_index_buffer", -1); private static var lime_vk_cmd_set_viewport = CFFI.load("lime", "lime_vk_cmd_set_viewport", -1); @@ -1372,9 +1418,13 @@ class NativeCFFI private static var lime_vk_cmd_draw_indexed = CFFI.load("lime", "lime_vk_cmd_draw_indexed", -1); private static var lime_vk_cmd_copy_buffer = CFFI.load("lime", "lime_vk_cmd_copy_buffer", -1); private static var lime_vk_cmd_copy_buffer_to_image = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image", -1); + private static var lime_vk_cmd_copy_buffer_to_image_region = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image_region", -1); + private static var lime_vk_cmd_copy_image_to_buffer_region = CFFI.load("lime", "lime_vk_cmd_copy_image_to_buffer_region", -1); private static var lime_vk_cmd_pipeline_barrier_image = CFFI.load("lime", "lime_vk_cmd_pipeline_barrier_image", -1); private static var lime_vk_cmd_clear_color_image = CFFI.load("lime", "lime_vk_cmd_clear_color_image", -1); + private static var lime_vk_cmd_clear_depth_stencil_image = CFFI.load("lime", "lime_vk_cmd_clear_depth_stencil_image", -1); private static var lime_vk_cmd_blit_image = CFFI.load("lime", "lime_vk_cmd_blit_image", -1); + private static var lime_vk_cmd_push_constants = CFFI.load("lime", "lime_vk_cmd_push_constants", -1); #end private static var lime_vk_get_last_error = CFFI.load("lime", "lime_vk_get_last_error", 0); private static var lime_vulkan_renderer_create = CFFI.load("lime", "lime_vulkan_renderer_create", 2); @@ -2166,6 +2216,13 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_download_memory") private static function lime_vk_download_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, + byteOffset:Int, byteLength:Int):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_create_buffer") private static function lime_vk_create_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic { @@ -2314,6 +2371,12 @@ class NativeCFFI @:hlNative("lime", "hl_vk_destroy_descriptor_pool") private static function lime_vk_destroy_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int):Void {} + @:hlNative("lime", "hl_vk_reset_descriptor_pool") private static function lime_vk_reset_descriptor_pool(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, flags:Int):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_allocate_descriptor_set") private static function lime_vk_allocate_descriptor_set(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic { @@ -2345,7 +2408,7 @@ class NativeCFFI instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} @:hlNative("lime", "hl_vk_create_pipeline_cache") private static function lime_vk_create_pipeline_cache(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Dynamic + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic { return null; } @@ -2353,6 +2416,12 @@ class NativeCFFI @:hlNative("lime", "hl_vk_destroy_pipeline_cache") private static function lime_vk_destroy_pipeline_cache(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void {} + @:hlNative("lime", "hl_vk_get_pipeline_cache_data") private static function lime_vk_get_pipeline_cache_data(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int, bytes:Bytes):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_create_graphics_pipeline") private static function lime_vk_create_graphics_pipeline(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, fragmentShaderHigh:Int, fragmentShaderLow:Int, @@ -2398,6 +2467,13 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set_ex") private static function lime_vk_cmd_bind_descriptor_set_ex(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, + layoutLow:Int, setHigh:Int, setLow:Int, state:hl.NativeArray):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_cmd_bind_vertex_buffer") private static function lime_vk_cmd_bind_vertex_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool @@ -2454,6 +2530,20 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_cmd_copy_buffer_to_image_region") private static function lime_vk_cmd_copy_buffer_to_image_region(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, + bufferLow:Int, imageHigh:Int, imageLow:Int, state:hl.NativeArray):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_copy_image_to_buffer_region") private static function lime_vk_cmd_copy_image_to_buffer_region(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, + imageLow:Int, bufferHigh:Int, bufferLow:Int, state:hl.NativeArray):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_cmd_pipeline_barrier_image") private static function lime_vk_cmd_pipeline_barrier_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:hl.NativeArray):Bool @@ -2468,12 +2558,26 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_cmd_clear_depth_stencil_image") private static function lime_vk_cmd_clear_depth_stencil_image(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, + imageLow:Int, state:hl.NativeArray, clear:hl.NativeArray):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_cmd_blit_image") private static function lime_vk_cmd_blit_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool { return false; } + + @:hlNative("lime", "hl_vk_cmd_push_constants") private static function lime_vk_cmd_push_constants(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, + state:hl.NativeArray, bytes:Bytes):Bool + { + return false; + } #end @:hlNative("lime", "hl_vk_get_last_error") private static function lime_vk_get_last_error():hl.Bytes diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx index 149ef3e60f..93e9a0137b 100644 --- a/src/lime/graphics/vulkan/VK.hx +++ b/src/lime/graphics/vulkan/VK.hx @@ -59,6 +59,8 @@ class VK public static inline var FENCE_CREATE_SIGNALED_BIT = 0x00000001; + public static inline var DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001; + public static inline var FORMAT_UNDEFINED = 0; public static inline var FORMAT_R8_UNORM = 9; public static inline var FORMAT_R8G8_UNORM = 16; @@ -122,6 +124,12 @@ class VK public static inline var IMAGE_ASPECT_STENCIL_BIT = 0x00000004; public static inline var IMAGE_ASPECT_METADATA_BIT = 0x00000008; + public static inline var COLOR_COMPONENT_R_BIT = 0x00000001; + public static inline var COLOR_COMPONENT_G_BIT = 0x00000002; + public static inline var COLOR_COMPONENT_B_BIT = 0x00000004; + public static inline var COLOR_COMPONENT_A_BIT = 0x00000008; + public static inline var COLOR_COMPONENT_RGBA_BITS = COLOR_COMPONENT_R_BIT | COLOR_COMPONENT_G_BIT | COLOR_COMPONENT_B_BIT | COLOR_COMPONENT_A_BIT; + public static inline var IMAGE_LAYOUT_UNDEFINED = 0; public static inline var IMAGE_LAYOUT_GENERAL = 1; public static inline var IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2; diff --git a/src/lime/graphics/vulkan/VKBuffer.hx b/src/lime/graphics/vulkan/VKBuffer.hx index d173be9ab9..2fbeb81a73 100644 --- a/src/lime/graphics/vulkan/VKBuffer.hx +++ b/src/lime/graphics/vulkan/VKBuffer.hx @@ -120,4 +120,9 @@ class VKBuffer { return memory != null && memory.upload(bytes, memoryOffset, byteOffset, byteLength); } + + public function download(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + return memory != null && memory.download(bytes, memoryOffset, byteOffset, byteLength); + } } diff --git a/src/lime/graphics/vulkan/VKCommandBuffer.hx b/src/lime/graphics/vulkan/VKCommandBuffer.hx index b3fe89118b..375748ca99 100644 --- a/src/lime/graphics/vulkan/VKCommandBuffer.hx +++ b/src/lime/graphics/vulkan/VKCommandBuffer.hx @@ -69,11 +69,23 @@ class VKCommandBuffer } public function bindDescriptorSet(layout:VKPipelineLayout, descriptorSet:VKDescriptorSet, firstSet:Int = 0, - bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS):Bool + bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS, dynamicOffsets:Array = null):Bool { #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && layout != null && layout.isValid() && descriptorSet != null && descriptorSet.isValid()) { + if (dynamicOffsets != null && dynamicOffsets.length > 0) + { + var state = [bindPoint, firstSet, dynamicOffsets.length]; + for (offset in dynamicOffsets) + { + state.push(offset); + } + return NativeCFFI.lime_vk_cmd_bind_descriptor_set_ex(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, + descriptorSet.handle.high, descriptorSet.handle.low, state); + } + return NativeCFFI.lime_vk_cmd_bind_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, descriptorSet.handle.high, descriptorSet.handle.low, bindPoint, firstSet); @@ -138,7 +150,41 @@ class VKCommandBuffer public function blitImage(source:VKImage, destination:VKImage, width:Int, height:Int, sourceLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destinationLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, filter:Int = VK.FILTER_LINEAR):Bool { - var state = [width, height, sourceLayout, destinationLayout, filter]; + return blitImageRegion(source, destination, width, height, sourceLayout, destinationLayout, filter); + } + + public function blitImageRegion(source:VKImage, destination:VKImage, sourceWidth:Int, sourceHeight:Int, + sourceLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destinationLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + filter:Int = VK.FILTER_LINEAR, destinationWidth:Int = -1, destinationHeight:Int = -1, sourceX:Int = 0, sourceY:Int = 0, + sourceZ:Int = 0, destinationX:Int = 0, destinationY:Int = 0, destinationZ:Int = 0, sourceDepth:Int = 1, destinationDepth:Int = 1, + sourceMipLevel:Int = 0, destinationMipLevel:Int = 0, sourceBaseArrayLayer:Int = 0, destinationBaseArrayLayer:Int = 0, layerCount:Int = 1, + aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + if (destinationWidth < 0) destinationWidth = sourceWidth; + if (destinationHeight < 0) destinationHeight = sourceHeight; + var state = [ + sourceX, + sourceY, + sourceZ, + sourceX + sourceWidth, + sourceY + sourceHeight, + sourceZ + sourceDepth, + destinationX, + destinationY, + destinationZ, + destinationX + destinationWidth, + destinationY + destinationHeight, + destinationZ + destinationDepth, + sourceLayout, + destinationLayout, + filter, + sourceMipLevel, + destinationMipLevel, + sourceBaseArrayLayer, + destinationBaseArrayLayer, + layerCount, + aspectMask + ]; #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && source != null && source.isValid() && destination != null && destination.isValid()) @@ -167,6 +213,24 @@ class VKCommandBuffer return false; } + public function clearDepthStencilImage(image:VKImage, layout:Int, depth:Float = 1, stencil:Int = 0, + aspectMask:Int = VK.IMAGE_ASPECT_DEPTH_BIT | VK.IMAGE_ASPECT_STENCIL_BIT, baseMipLevel:Int = 0, levelCount:Int = 1, + baseArrayLayer:Int = 0, layerCount:Int = 1):Bool + { + var state = [layout, stencil, aspectMask, baseMipLevel, levelCount, baseArrayLayer, layerCount]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_clear_depth_stencil_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, + state, [depth]); + } + #end + + return false; + } + public function copyBuffer(source:VKBuffer, destination:VKBuffer, size:Int64, sourceOffset:Int64 = null, destinationOffset:Int64 = null):Bool { if (sourceOffset == null) sourceOffset = Int64.ofInt(0); @@ -188,12 +252,75 @@ class VKCommandBuffer public function copyBufferToImage(buffer:VKBuffer, image:VKImage, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL):Bool { + return copyBufferToImageRegion(buffer, image, width, height, layout); + } + + public function copyBufferToImageRegion(buffer:VKBuffer, image:VKImage, width:Int, height:Int, + layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, + bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, mipLevel:Int = 0, baseArrayLayer:Int = 0, + layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + if (bufferOffset == null) bufferOffset = Int64.ofInt(0); + var state = [ + width, + height, + depth, + layout, + bufferOffset.high, + bufferOffset.low, + bufferRowLength, + bufferImageHeight, + imageX, + imageY, + imageZ, + mipLevel, + baseArrayLayer, + layerCount, + aspectMask + ]; + #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid() && image != null && image.isValid()) { - return NativeCFFI.lime_vk_cmd_copy_buffer_to_image(device.instance.context.__windowHandle, device.instance.handle.high, + return NativeCFFI.lime_vk_cmd_copy_buffer_to_image_region(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, - image.handle.high, image.handle.low, width, height, layout); + image.handle.high, image.handle.low, state); + } + #end + + return false; + } + + public function copyImageToBufferRegion(image:VKImage, buffer:VKBuffer, width:Int, height:Int, + layout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, + bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, mipLevel:Int = 0, baseArrayLayer:Int = 0, + layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + if (bufferOffset == null) bufferOffset = Int64.ofInt(0); + var state = [ + width, + height, + depth, + layout, + bufferOffset.high, + bufferOffset.low, + bufferRowLength, + bufferImageHeight, + imageX, + imageY, + imageZ, + mipLevel, + baseArrayLayer, + layerCount, + aspectMask + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_copy_image_to_buffer_region(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, + buffer.handle.high, buffer.handle.low, state); } #end @@ -292,6 +419,31 @@ class VKCommandBuffer return false; } + public function pushConstants(layout:VKPipelineLayout, stageFlags:Int, bytes:haxe.io.Bytes, offset:Int = 0, byteOffset:Int = 0, + byteLength:Int = -1):Bool + { + if (bytes == null || layout == null) + { + return false; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + var state = [stageFlags, offset, byteOffset, byteLength]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout.isValid()) + { + return NativeCFFI.lime_vk_cmd_push_constants(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, state, + bytes); + } + #end + + return false; + } + public function setScissor(x:Int, y:Int, width:Int, height:Int):Bool { #if (!macro && lime_cffi && lime_vulkan) diff --git a/src/lime/graphics/vulkan/VKDescriptorPool.hx b/src/lime/graphics/vulkan/VKDescriptorPool.hx index 3ec009bca9..e754efbb31 100644 --- a/src/lime/graphics/vulkan/VKDescriptorPool.hx +++ b/src/lime/graphics/vulkan/VKDescriptorPool.hx @@ -59,4 +59,17 @@ class VKDescriptorPool { return !VK.__isZero(handle); } + + public function reset(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_reset_descriptor_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } } diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx index 1107c728ea..6897091794 100644 --- a/src/lime/graphics/vulkan/VKDevice.hx +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -308,13 +308,18 @@ class VKDevice return null; } - public function createPipelineCache():VKPipelineCache + public function createPipelineCache(bytes:Bytes = null, byteOffset:Int = 0, byteLength:Int = -1):VKPipelineCache { + if (byteLength < 0 && bytes != null) + { + byteLength = bytes.length - byteOffset; + } + #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { var data:Dynamic = NativeCFFI.lime_vk_create_pipeline_cache(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low); + handle.high, handle.low, bytes, byteOffset, byteLength); var pipelineCacheHandle = VK.__makeHandle(data); if (!VK.__isZero(pipelineCacheHandle)) { diff --git a/src/lime/graphics/vulkan/VKDeviceMemory.hx b/src/lime/graphics/vulkan/VKDeviceMemory.hx index 5a739ec646..101b09ad20 100644 --- a/src/lime/graphics/vulkan/VKDeviceMemory.hx +++ b/src/lime/graphics/vulkan/VKDeviceMemory.hx @@ -82,4 +82,34 @@ class VKDeviceMemory return false; } + + /** + Copies host-visible memory into a Haxe `Bytes` buffer. Use this after an + image-to-buffer transfer for render target and texture capture paths. + **/ + public function download(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + if (memoryOffset == null) + { + memoryOffset = Int64.ofInt(0); + } + if (bytes == null) + { + return false; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_download_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, memoryOffset.high, memoryOffset.low, bytes, byteOffset, byteLength); + } + #end + + return false; + } } diff --git a/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx index c0733351b5..2763dcb000 100644 --- a/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx +++ b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx @@ -4,18 +4,34 @@ class VKGraphicsPipelineInfo { public var alphaBlendOp:Int = VK.BLEND_OP_ADD; public var colorBlendOp:Int = VK.BLEND_OP_ADD; + public var colorWriteMask:Int = VK.COLOR_COMPONENT_RGBA_BITS; public var cullMode:Int = VK.CULL_MODE_BACK_BIT; + public var backCompareMask:Int = -1; + public var backCompareOp:Int = VK.COMPARE_OP_ALWAYS; + public var backDepthFailOp:Int = VK.STENCIL_OP_KEEP; + public var backFailOp:Int = VK.STENCIL_OP_KEEP; + public var backPassOp:Int = VK.STENCIL_OP_KEEP; + public var backReference:Int = 0; + public var backWriteMask:Int = -1; public var depthCompareOp:Int = VK.COMPARE_OP_LESS; public var depthTest:Bool = false; public var depthWrite:Bool = false; public var dstAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; public var dstColorBlendFactor:Int = VK.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; public var dynamicStateFlags:Int = VK.DYNAMIC_STATE_VIEWPORT_BIT | VK.DYNAMIC_STATE_SCISSOR_BIT; + public var frontCompareMask:Int = -1; + public var frontCompareOp:Int = VK.COMPARE_OP_ALWAYS; + public var frontDepthFailOp:Int = VK.STENCIL_OP_KEEP; + public var frontFailOp:Int = VK.STENCIL_OP_KEEP; public var frontFace:Int = VK.FRONT_FACE_COUNTER_CLOCKWISE; + public var frontPassOp:Int = VK.STENCIL_OP_KEEP; + public var frontReference:Int = 0; + public var frontWriteMask:Int = -1; public var polygonMode:Int = VK.POLYGON_MODE_FILL; public var primitiveRestart:Bool = false; public var srcAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE; public var srcColorBlendFactor:Int = VK.BLEND_FACTOR_SRC_ALPHA; + public var stencilTest:Bool = false; public var topology:Int = VK.PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; public var vertexAttributes:Array; public var vertexBindings:Array; @@ -53,6 +69,22 @@ class VKGraphicsPipelineInfo dstAlphaBlendFactor, alphaBlendOp, dynamicStateFlags, + colorWriteMask, + stencilTest ? 1 : 0, + frontFailOp, + frontPassOp, + frontDepthFailOp, + frontCompareOp, + frontCompareMask, + frontWriteMask, + frontReference, + backFailOp, + backPassOp, + backDepthFailOp, + backCompareOp, + backCompareMask, + backWriteMask, + backReference, vertexBindings.length ]; diff --git a/src/lime/graphics/vulkan/VKPipelineCache.hx b/src/lime/graphics/vulkan/VKPipelineCache.hx index 69ea68dbe5..e690940e26 100644 --- a/src/lime/graphics/vulkan/VKPipelineCache.hx +++ b/src/lime/graphics/vulkan/VKPipelineCache.hx @@ -1,6 +1,7 @@ package lime.graphics.vulkan; import haxe.Int64; +import haxe.io.Bytes; #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; @@ -41,4 +42,21 @@ class VKPipelineCache { return !VK.__isZero(handle); } + + public function getData():Bytes + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var bytes = Bytes.alloc(0); + if (NativeCFFI.lime_vk_get_pipeline_cache_data(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, bytes)) + { + return bytes; + } + } + #end + + return null; + } } From b91b9ea5abb8b0781206e7d4db4922e823b0d1be Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 22 May 2026 16:37:58 -0400 Subject: [PATCH 15/76] Vulkan: Pack Vulkan render-pass params into state array Change the Vulkan render-pass/native bindings to accept a packed integer state array instead of many individual parameters. C/C++ and HL CFFI signatures updated to parse the state vector (including a new depthInitialLayout entry) and set attachment initial layouts accordingly. Also, I simplified VkImageBlit handling to require the full packed layout (21 ints) and removed the old fallback parsing. Removed the legacy lime_vk_cmd_copy_buffer_to_image bindings/definitions (use the region variant instead). Updated NativeCFFI prime/load signatures and VKDevice to build and pass the packed state array. --- project/src/ExternalInterface.cpp | 258 ++++++------------ .../_internal/backend/native/NativeCFFI.hx | 24 +- src/lime/graphics/vulkan/VKDevice.hx | 21 +- 3 files changed, 102 insertions(+), 201 deletions(-) diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 45fd23893d..607f8590da 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -7690,9 +7690,7 @@ namespace lime { } - value lime_vk_create_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int colorFormat, - int depthStencilFormat, int samples, int colorLoadOp, int colorStoreOp, int colorInitialLayout, int colorFinalLayout, int depthLoadOp, - int depthStoreOp, int depthFinalLayout) { + value lime_vk_create_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)val_data (window); @@ -7701,6 +7699,20 @@ namespace lime { PFN_vkCreateRenderPass vkCreateRenderPass = (PFN_vkCreateRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateRenderPass"); if (!vkCreateRenderPass) return alloc_null (); + std::vector packed = GetVulkanIntVector (state); + if (packed.size () < 11) return alloc_null (); + + int colorFormat = packed[0]; + int depthStencilFormat = packed[1]; + int samples = packed[2]; + int colorLoadOp = packed[3]; + int colorStoreOp = packed[4]; + int colorInitialLayout = packed[5]; + int colorFinalLayout = packed[6]; + int depthInitialLayout = packed[7]; + int depthFinalLayout = packed[8]; + int depthLoadOp = packed[9]; + int depthStoreOp = packed[10]; std::vector attachments; VkAttachmentDescription colorAttachment; @@ -7733,7 +7745,7 @@ namespace lime { depthAttachment.storeOp = (VkAttachmentStoreOp)depthStoreOp; depthAttachment.stencilLoadOp = (VkAttachmentLoadOp)depthLoadOp; depthAttachment.stencilStoreOp = (VkAttachmentStoreOp)depthStoreOp; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthAttachment.initialLayout = (VkImageLayout)depthInitialLayout; depthAttachment.finalLayout = (VkImageLayout)depthFinalLayout; attachments.push_back (depthAttachment); depthReference.attachment = 1; @@ -7786,8 +7798,7 @@ namespace lime { HL_PRIM vdynamic* HL_NAME(hl_vk_create_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, - int deviceLow, int colorFormat, int depthStencilFormat, int samples, int colorLoadOp, int colorStoreOp, int colorInitialLayout, - int colorFinalLayout, int depthLoadOp, int depthStoreOp, int depthFinalLayout) { + int deviceLow, hl_varray* state) { #ifdef LIME_VULKAN Window* targetWindow = (Window*)window->ptr; @@ -7796,6 +7807,20 @@ namespace lime { PFN_vkCreateRenderPass vkCreateRenderPass = (PFN_vkCreateRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateRenderPass"); if (!vkCreateRenderPass) return 0; + std::vector packed = GetHLVulkanIntVector (state); + if (packed.size () < 11) return 0; + + int colorFormat = packed[0]; + int depthStencilFormat = packed[1]; + int samples = packed[2]; + int colorLoadOp = packed[3]; + int colorStoreOp = packed[4]; + int colorInitialLayout = packed[5]; + int colorFinalLayout = packed[6]; + int depthInitialLayout = packed[7]; + int depthFinalLayout = packed[8]; + int depthLoadOp = packed[9]; + int depthStoreOp = packed[10]; std::vector attachments; VkAttachmentDescription colorAttachment; @@ -7828,7 +7853,7 @@ namespace lime { depthAttachment.storeOp = (VkAttachmentStoreOp)depthStoreOp; depthAttachment.stencilLoadOp = (VkAttachmentLoadOp)depthLoadOp; depthAttachment.stencilStoreOp = (VkAttachmentStoreOp)depthStoreOp; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthAttachment.initialLayout = (VkImageLayout)depthInitialLayout; depthAttachment.finalLayout = (VkImageLayout)depthFinalLayout; attachments.push_back (depthAttachment); depthReference.attachment = 1; @@ -10479,68 +10504,6 @@ namespace lime { } - - bool lime_vk_cmd_copy_buffer_to_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, int height, int layout) { - -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)val_data (window); - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = - (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - if (!vkCmdCopyBufferToImage || !commandBuffer) return false; - - VkBufferImageCopy region; - memset (®ion, 0, sizeof (region)); - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.width = (uint32_t)width; - region.imageExtent.height = (uint32_t)height; - region.imageExtent.depth = 1; - vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), - (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, 1, ®ion); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif - - } - - - HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, - int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, - int height, int layout) { - -#ifdef LIME_VULKAN - Window* targetWindow = (Window*)window->ptr; - VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); - VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); - PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = - (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); - VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); - if (!vkCmdCopyBufferToImage || !commandBuffer) return false; - - VkBufferImageCopy region; - memset (®ion, 0, sizeof (region)); - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.width = (uint32_t)width; - region.imageExtent.height = (uint32_t)height; - region.imageExtent.depth = 1; - vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), - (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, 1, ®ion); - return true; -#else - lastVKError = "Lime was built without lime-vulkan support"; - return false; -#endif - - } - - bool lime_vk_cmd_copy_buffer_to_image_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, value state) { @@ -10927,53 +10890,33 @@ namespace lime { PFN_vkCmdBlitImage vkCmdBlitImage = (PFN_vkCmdBlitImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBlitImage"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); std::vector packed = GetVulkanIntVector (state); - if (!vkCmdBlitImage || !commandBuffer || packed.size () < 5) return false; + if (!vkCmdBlitImage || !commandBuffer || packed.size () < 21) return false; VkImageBlit blit; memset (&blit, 0, sizeof (blit)); - int sourceLayout = packed[2]; - int destinationLayout = packed[3]; - int filter = packed[4]; - if (packed.size () >= 21) { - - blit.srcOffsets[0].x = packed[0]; - blit.srcOffsets[0].y = packed[1]; - blit.srcOffsets[0].z = packed[2]; - blit.srcOffsets[1].x = packed[3]; - blit.srcOffsets[1].y = packed[4]; - blit.srcOffsets[1].z = packed[5]; - blit.dstOffsets[0].x = packed[6]; - blit.dstOffsets[0].y = packed[7]; - blit.dstOffsets[0].z = packed[8]; - blit.dstOffsets[1].x = packed[9]; - blit.dstOffsets[1].y = packed[10]; - blit.dstOffsets[1].z = packed[11]; - sourceLayout = packed[12]; - destinationLayout = packed[13]; - filter = packed[14]; - blit.srcSubresource.mipLevel = (uint32_t)packed[15]; - blit.dstSubresource.mipLevel = (uint32_t)packed[16]; - blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; - blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; - blit.srcSubresource.layerCount = (uint32_t)packed[19]; - blit.dstSubresource.layerCount = (uint32_t)packed[19]; - blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; - blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; - - } else { - - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.layerCount = 1; - blit.srcOffsets[1].x = packed[0]; - blit.srcOffsets[1].y = packed[1]; - blit.srcOffsets[1].z = 1; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.layerCount = 1; - blit.dstOffsets[1].x = packed[0]; - blit.dstOffsets[1].y = packed[1]; - blit.dstOffsets[1].z = 1; - - } + blit.srcOffsets[0].x = packed[0]; + blit.srcOffsets[0].y = packed[1]; + blit.srcOffsets[0].z = packed[2]; + blit.srcOffsets[1].x = packed[3]; + blit.srcOffsets[1].y = packed[4]; + blit.srcOffsets[1].z = packed[5]; + blit.dstOffsets[0].x = packed[6]; + blit.dstOffsets[0].y = packed[7]; + blit.dstOffsets[0].z = packed[8]; + blit.dstOffsets[1].x = packed[9]; + blit.dstOffsets[1].y = packed[10]; + blit.dstOffsets[1].z = packed[11]; + int sourceLayout = packed[12]; + int destinationLayout = packed[13]; + int filter = packed[14]; + blit.srcSubresource.mipLevel = (uint32_t)packed[15]; + blit.dstSubresource.mipLevel = (uint32_t)packed[16]; + blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; + blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; + blit.srcSubresource.layerCount = (uint32_t)packed[19]; + blit.dstSubresource.layerCount = (uint32_t)packed[19]; + blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)sourceLayout, (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)destinationLayout, 1, &blit, (VkFilter)filter); @@ -10996,53 +10939,33 @@ namespace lime { PFN_vkCmdBlitImage vkCmdBlitImage = (PFN_vkCmdBlitImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBlitImage"); VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); std::vector packed = GetHLVulkanIntVector (state); - if (!vkCmdBlitImage || !commandBuffer || packed.size () < 5) return false; + if (!vkCmdBlitImage || !commandBuffer || packed.size () < 21) return false; VkImageBlit blit; memset (&blit, 0, sizeof (blit)); - int sourceLayout = packed[2]; - int destinationLayout = packed[3]; - int filter = packed[4]; - if (packed.size () >= 21) { - - blit.srcOffsets[0].x = packed[0]; - blit.srcOffsets[0].y = packed[1]; - blit.srcOffsets[0].z = packed[2]; - blit.srcOffsets[1].x = packed[3]; - blit.srcOffsets[1].y = packed[4]; - blit.srcOffsets[1].z = packed[5]; - blit.dstOffsets[0].x = packed[6]; - blit.dstOffsets[0].y = packed[7]; - blit.dstOffsets[0].z = packed[8]; - blit.dstOffsets[1].x = packed[9]; - blit.dstOffsets[1].y = packed[10]; - blit.dstOffsets[1].z = packed[11]; - sourceLayout = packed[12]; - destinationLayout = packed[13]; - filter = packed[14]; - blit.srcSubresource.mipLevel = (uint32_t)packed[15]; - blit.dstSubresource.mipLevel = (uint32_t)packed[16]; - blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; - blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; - blit.srcSubresource.layerCount = (uint32_t)packed[19]; - blit.dstSubresource.layerCount = (uint32_t)packed[19]; - blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; - blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; - - } else { - - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.layerCount = 1; - blit.srcOffsets[1].x = packed[0]; - blit.srcOffsets[1].y = packed[1]; - blit.srcOffsets[1].z = 1; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.layerCount = 1; - blit.dstOffsets[1].x = packed[0]; - blit.dstOffsets[1].y = packed[1]; - blit.dstOffsets[1].z = 1; - - } + blit.srcOffsets[0].x = packed[0]; + blit.srcOffsets[0].y = packed[1]; + blit.srcOffsets[0].z = packed[2]; + blit.srcOffsets[1].x = packed[3]; + blit.srcOffsets[1].y = packed[4]; + blit.srcOffsets[1].z = packed[5]; + blit.dstOffsets[0].x = packed[6]; + blit.dstOffsets[0].y = packed[7]; + blit.dstOffsets[0].z = packed[8]; + blit.dstOffsets[1].x = packed[9]; + blit.dstOffsets[1].y = packed[10]; + blit.dstOffsets[1].z = packed[11]; + int sourceLayout = packed[12]; + int destinationLayout = packed[13]; + int filter = packed[14]; + blit.srcSubresource.mipLevel = (uint32_t)packed[15]; + blit.dstSubresource.mipLevel = (uint32_t)packed[16]; + blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; + blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; + blit.srcSubresource.layerCount = (uint32_t)packed[19]; + blit.dstSubresource.layerCount = (uint32_t)packed[19]; + blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)sourceLayout, (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)destinationLayout, 1, &blit, (VkFilter)filter); @@ -11564,24 +11487,6 @@ namespace lime { } - - bool lime_vk_cmd_copy_buffer_to_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, - int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, int height, int layout) { - - return LimeVulkanUnavailableBool (); - - } - - - HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, - int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, int width, - int height, int layout) { - - return LimeVulkanUnavailableBool (); - - } - - bool lime_vk_cmd_copy_buffer_to_image_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, value state) { @@ -12627,7 +12532,7 @@ namespace lime { DEFINE_PRIME10 (lime_vk_create_image_view); DEFINE_PRIME7v (lime_vk_destroy_image_view); DEFINE_PRIME14 (lime_vk_create_image_view_ex); - DEFINE_PRIME15 (lime_vk_create_render_pass); + DEFINE_PRIME6 (lime_vk_create_render_pass); DEFINE_PRIME7v (lime_vk_destroy_render_pass); DEFINE_PRIME11 (lime_vk_create_framebuffer); DEFINE_PRIME7v (lime_vk_destroy_framebuffer); @@ -12663,7 +12568,6 @@ namespace lime { DEFINE_PRIME11 (lime_vk_cmd_draw); DEFINE_PRIME12 (lime_vk_cmd_draw_indexed); DEFINE_PRIME12 (lime_vk_cmd_copy_buffer); - DEFINE_PRIME14 (lime_vk_cmd_copy_buffer_to_image); DEFINE_PRIME12 (lime_vk_cmd_copy_buffer_to_image_region); DEFINE_PRIME12 (lime_vk_cmd_copy_image_to_buffer_region); DEFINE_PRIME10 (lime_vk_cmd_pipeline_barrier_image); diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index 4965f04ed3..d543f2f19f 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -478,8 +478,7 @@ class NativeCFFI layerCount:Int):Dynamic; @:cffi private static function lime_vk_create_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - colorFormat:Int, depthStencilFormat:Int, samples:Int, colorLoadOp:Int, colorStoreOp:Int, colorInitialLayout:Int, colorFinalLayout:Int, - depthLoadOp:Int, depthStoreOp:Int, depthFinalLayout:Int):Dynamic; + state:Array):Dynamic; @:cffi private static function lime_vk_destroy_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int):Void; @@ -590,10 +589,6 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_copy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; - @:cffi private static function lime_vk_cmd_copy_buffer_to_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, width:Int, - height:Int, layout:Int):Bool; - @:cffi private static function lime_vk_cmd_copy_buffer_to_image_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; @@ -1031,8 +1026,8 @@ class NativeCFFI "lime_vk_destroy_image_view", "oiiiiiiv", false)); private static var lime_vk_create_image_view_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( cpp.Prime._loadPrime("lime", "lime_vk_create_image_view_ex", "oiiiiiiiiiiiiio", false)); - private static var lime_vk_create_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( - cpp.Prime._loadPrime("lime", "lime_vk_create_render_pass", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_create_render_pass = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>( + cpp.Prime._loadPrime("lime", "lime_vk_create_render_pass", "oiiiioo", false)); private static var lime_vk_destroy_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_render_pass", "oiiiiiiv", false)); private static var lime_vk_create_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Int->cpp.Object>( @@ -1103,8 +1098,6 @@ class NativeCFFI "lime_vk_cmd_draw_indexed", "oiiiiiiiiiiib", false)); private static var lime_vk_cmd_copy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_copy_buffer_to_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image", "oiiiiiiiiiiiiib", false)); private static var lime_vk_cmd_copy_buffer_to_image_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image_region", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_copy_image_to_buffer_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( @@ -1417,7 +1410,6 @@ class NativeCFFI private static var lime_vk_cmd_draw = CFFI.load("lime", "lime_vk_cmd_draw", -1); private static var lime_vk_cmd_draw_indexed = CFFI.load("lime", "lime_vk_cmd_draw_indexed", -1); private static var lime_vk_cmd_copy_buffer = CFFI.load("lime", "lime_vk_cmd_copy_buffer", -1); - private static var lime_vk_cmd_copy_buffer_to_image = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image", -1); private static var lime_vk_cmd_copy_buffer_to_image_region = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image_region", -1); private static var lime_vk_cmd_copy_image_to_buffer_region = CFFI.load("lime", "lime_vk_cmd_copy_image_to_buffer_region", -1); private static var lime_vk_cmd_pipeline_barrier_image = CFFI.load("lime", "lime_vk_cmd_pipeline_barrier_image", -1); @@ -2315,8 +2307,7 @@ class NativeCFFI } @:hlNative("lime", "hl_vk_create_render_pass") private static function lime_vk_create_render_pass(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, colorFormat:Int, depthStencilFormat:Int, samples:Int, colorLoadOp:Int, - colorStoreOp:Int, colorInitialLayout:Int, colorFinalLayout:Int, depthLoadOp:Int, depthStoreOp:Int, depthFinalLayout:Int):Dynamic + instanceLow:Int, deviceHigh:Int, deviceLow:Int, state:hl.NativeArray):Dynamic { return null; } @@ -2523,13 +2514,6 @@ class NativeCFFI return false; } - @:hlNative("lime", "hl_vk_cmd_copy_buffer_to_image") private static function lime_vk_cmd_copy_buffer_to_image(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, - bufferLow:Int, imageHigh:Int, imageLow:Int, width:Int, height:Int, layout:Int):Bool - { - return false; - } - @:hlNative("lime", "hl_vk_cmd_copy_buffer_to_image_region") private static function lime_vk_cmd_copy_buffer_to_image_region(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, state:hl.NativeArray):Bool diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx index 6897091794..46103482d9 100644 --- a/src/lime/graphics/vulkan/VKDevice.hx +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -368,15 +368,28 @@ class VKDevice samples:Int = VK.SAMPLE_COUNT_1_BIT, colorLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, colorStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, colorInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, colorFinalLayout:Int = VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE, - depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL):VKRenderPass + depthInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, + depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE):VKRenderPass { #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { + var state = [ + colorFormat, + depthStencilFormat, + samples, + colorLoadOp, + colorStoreOp, + colorInitialLayout, + colorFinalLayout, + depthInitialLayout, + depthFinalLayout, + depthLoadOp, + depthStoreOp + ]; var data:Dynamic = NativeCFFI.lime_vk_create_render_pass(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, colorFormat, depthStencilFormat, samples, colorLoadOp, colorStoreOp, colorInitialLayout, colorFinalLayout, - depthLoadOp, depthStoreOp, depthFinalLayout); + handle.high, handle.low, state); var renderPassHandle = VK.__makeHandle(data); if (!VK.__isZero(renderPassHandle)) { From d129177b082105336e609c471e3f19dd4c5d8d1c Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Sun, 24 May 2026 23:49:10 -0400 Subject: [PATCH 16/76] Add Vulkan bootstrap logging and vk error details --- project/src/ExternalInterface.cpp | 72 +++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 607f8590da..81fdf8ad8a 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -60,6 +60,7 @@ #include #include +#include #include #include @@ -76,6 +77,28 @@ namespace lime { static std::string lastVKError; + static void LogVulkanNativeBootstrap (const char* message) { + +#ifdef LIME_VULKAN + ::FILE* file = ::fopen ("lime-vulkan-native.log", "a"); + if (file) { + + ::fprintf (file, "%s\n", message ? message : ""); + ::fclose (file); + + } +#endif + + } + + + static void LogVulkanNativeBootstrap (const std::string& message) { + + LogVulkanNativeBootstrap (message.c_str ()); + + } + + static uint64_t CombineVulkanHandle (int high, int low) { return ((uint64_t)(uint32_t)high << 32) | (uint32_t)low; @@ -343,9 +366,11 @@ namespace lime { static bool CreateManagedVulkanDevice (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const std::vector& requestedExtensions, VkDevice* outDevice, VkQueue* outQueue) { + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: begin"); if (!targetWindow || !instance || !physicalDevice || !outDevice || !outQueue) { lastVKError = "Missing Vulkan instance, physical device, or output device"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing input"); return false; } @@ -354,9 +379,11 @@ namespace lime { *outQueue = VK_NULL_HANDLE; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: acquired vkGetInstanceProcAddr"); if (!vkGetInstanceProcAddr) { lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing vkGetInstanceProcAddr"); return false; } @@ -367,19 +394,23 @@ namespace lime { (PFN_vkEnumerateDeviceExtensionProperties)vkGetInstanceProcAddr (instance, "vkEnumerateDeviceExtensionProperties"); PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: loaded device creation procs"); if (!vkCreateDevice || !vkGetDeviceProcAddr || !vkEnumerateDeviceExtensionProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { lastVKError = "Missing required Vulkan device creation functions"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing required procs"); return false; } uint32_t queueFamilyCount = 0; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: query queue family count"); vkGetPhysicalDeviceQueueFamilyProperties (physicalDevice, &queueFamilyCount, 0); if (queueFamilyIndex >= queueFamilyCount) { lastVKError = "Invalid Vulkan queue family index"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: invalid queue family index"); return false; } @@ -400,10 +431,12 @@ namespace lime { } uint32_t extensionCount = 0; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: enumerate device extension count"); VkResult extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, 0); if (extensionResult != VK_SUCCESS) { lastVKError = "Could not enumerate Vulkan device extensions"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: extension count enumeration failed"); return false; } @@ -411,10 +444,12 @@ namespace lime { std::vector availableExtensions (extensionCount); if (extensionCount > 0) { + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: enumerate device extensions"); extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, availableExtensions.data ()); if (extensionResult != VK_SUCCESS) { lastVKError = "Could not enumerate Vulkan device extensions"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: extension enumeration failed"); return false; } @@ -444,6 +479,7 @@ namespace lime { if (!extensionSupported) { lastVKError = std::string ("Vulkan physical device does not support ") + requestedExtensions[i]; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: requested extension missing"); return false; } @@ -490,24 +526,29 @@ namespace lime { createInfo.ppEnabledExtensionNames = deviceExtensions.empty () ? 0 : deviceExtensions.data (); VkResult result = vkCreateDevice (physicalDevice, &createInfo, 0, outDevice); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: returned from vkCreateDevice"); if (result != VK_SUCCESS) { lastVKError = "vkCreateDevice failed"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: vkCreateDevice failed"); return false; } PFN_vkGetDeviceQueue vkGetDeviceQueue = (PFN_vkGetDeviceQueue)vkGetDeviceProcAddr (*outDevice, "vkGetDeviceQueue"); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: loaded vkGetDeviceQueue"); if (!vkGetDeviceQueue) { PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (*outDevice, "vkDestroyDevice"); if (vkDestroyDevice) vkDestroyDevice (*outDevice, 0); *outDevice = VK_NULL_HANDLE; lastVKError = "Missing Vulkan device queue function"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing vkGetDeviceQueue"); return false; } + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: get device queue"); vkGetDeviceQueue (*outDevice, queueFamilyIndex, 0, outQueue); if (!*outQueue) { @@ -515,11 +556,13 @@ namespace lime { if (vkDestroyDevice) vkDestroyDevice (*outDevice, 0); *outDevice = VK_NULL_HANDLE; lastVKError = "Failed to get Vulkan device queue"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: device queue was null"); return false; } lastVKError.clear (); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: success"); return true; } @@ -5097,23 +5140,36 @@ namespace lime { value extensions) { #ifdef LIME_VULKAN + LogVulkanNativeBootstrap ("lime_vk_create_device: begin"); + if (val_is_null (window)) { + + lastVKError = "Missing Lime window for Vulkan device creation"; + LogVulkanNativeBootstrap ("lime_vk_create_device: null window"); + return alloc_null (); + + } Window* targetWindow = (Window*)val_data (window); VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + LogVulkanNativeBootstrap ("lime_vk_create_device: decoded handles"); std::vector deviceExtensions = GetVulkanDeviceExtensions (extensions); + LogVulkanNativeBootstrap ("lime_vk_create_device: decoded extensions"); VkDevice device = VK_NULL_HANDLE; VkQueue queue = VK_NULL_HANDLE; if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + LogVulkanNativeBootstrap ("lime_vk_create_device: CreateManagedVulkanDevice failed"); return alloc_null (); } + LogVulkanNativeBootstrap ("lime_vk_create_device: create result object"); value result = alloc_empty_object (); alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); alloc_field (result, val_id ("queue"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); alloc_field (result, val_id ("queueFamilyIndex"), alloc_int (queueFamilyIndex)); + LogVulkanNativeBootstrap ("lime_vk_create_device: success"); return result; #else lastVKError = "Lime was built without lime-vulkan support"; @@ -6223,7 +6279,9 @@ namespace lime { VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); if (result != VK_SUCCESS) { - lastVKError = "vkQueueSubmit failed"; + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; return false; } @@ -6260,7 +6318,9 @@ namespace lime { VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); if (result != VK_SUCCESS) { - lastVKError = "vkQueueSubmit failed"; + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; return false; } @@ -9794,7 +9854,9 @@ namespace lime { VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); if (result != VK_SUCCESS) { - lastVKError = "vkQueueSubmit failed"; + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; return false; } @@ -9842,7 +9904,9 @@ namespace lime { VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); if (result != VK_SUCCESS) { - lastVKError = "vkQueueSubmit failed"; + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; return false; } From 01789c0ce0912464ed319ac1009555ac6d3b74ae Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Mon, 25 May 2026 03:17:34 -0400 Subject: [PATCH 17/76] Vulkan: MSAA/resolve support Add multisampling and color-resolve support across the Vulkan backend and tests. Expose framebuffer sample count limits from the native ExternalInterface, parse and store them on VKPhysicalDevice, and add helper methods (getMaxUsableSampleCount, supportsSampleCount). Extend render-pass creation to accept resolve attachment parameters and construct a resolve attachment/subpass pResolveAttachments when needed, and propagate resolveFormat into VKRenderPass. Add multisample state fields to VKGraphicsPipelineInfo and wire rasterizationSamples, sample shading, sample mask, and alpha-to-coverage/one into pipeline creation. Update the example test (vulkan-smoke) to request MSAA, create transient MSAA color attachments, include them in framebuffers, and handle resource creation/disposal. Also increase packed data size checks where appropriate. --- project/src/ExternalInterface.cpp | 90 ++++++++++++++++++- src/lime/graphics/vulkan/VKDevice.hx | 14 ++- .../graphics/vulkan/VKGraphicsPipelineInfo.hx | 12 +++ src/lime/graphics/vulkan/VKPhysicalDevice.hx | 46 ++++++++++ src/lime/graphics/vulkan/VKRenderPass.hx | 6 +- tests/vulkan-smoke/Source/Main.hx | 71 +++++++++++++-- 6 files changed, 225 insertions(+), 14 deletions(-) diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 81fdf8ad8a..59a2978fd9 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -4914,6 +4914,10 @@ namespace lime { const int id_vendorID = val_id ("vendorID"); const int id_deviceID = val_id ("deviceID"); const int id_deviceType = val_id ("deviceType"); + const int id_framebufferColorSampleCounts = val_id ("framebufferColorSampleCounts"); + const int id_framebufferDepthSampleCounts = val_id ("framebufferDepthSampleCounts"); + const int id_framebufferNoAttachmentsSampleCounts = val_id ("framebufferNoAttachmentsSampleCounts"); + const int id_framebufferStencilSampleCounts = val_id ("framebufferStencilSampleCounts"); const int id_queueFamilies = val_id ("queueFamilies"); const int id_index = val_id ("index"); @@ -4972,6 +4976,10 @@ namespace lime { alloc_field (deviceObject, id_vendorID, alloc_int (properties.vendorID)); alloc_field (deviceObject, id_deviceID, alloc_int (properties.deviceID)); alloc_field (deviceObject, id_deviceType, alloc_int (properties.deviceType)); + alloc_field (deviceObject, id_framebufferColorSampleCounts, alloc_int ((int)properties.limits.framebufferColorSampleCounts)); + alloc_field (deviceObject, id_framebufferDepthSampleCounts, alloc_int ((int)properties.limits.framebufferDepthSampleCounts)); + alloc_field (deviceObject, id_framebufferNoAttachmentsSampleCounts, alloc_int ((int)properties.limits.framebufferNoAttachmentsSampleCounts)); + alloc_field (deviceObject, id_framebufferStencilSampleCounts, alloc_int ((int)properties.limits.framebufferStencilSampleCounts)); alloc_field (deviceObject, id_queueFamilies, queueFamilyArray); val_array_set_i (devices, i, deviceObject); @@ -5062,6 +5070,10 @@ namespace lime { const int id_vendorID = hl_hash_utf8 ("vendorID"); const int id_deviceID = hl_hash_utf8 ("deviceID"); const int id_deviceType = hl_hash_utf8 ("deviceType"); + const int id_framebufferColorSampleCounts = hl_hash_utf8 ("framebufferColorSampleCounts"); + const int id_framebufferDepthSampleCounts = hl_hash_utf8 ("framebufferDepthSampleCounts"); + const int id_framebufferNoAttachmentsSampleCounts = hl_hash_utf8 ("framebufferNoAttachmentsSampleCounts"); + const int id_framebufferStencilSampleCounts = hl_hash_utf8 ("framebufferStencilSampleCounts"); const int id_queueFamilies = hl_hash_utf8 ("queueFamilies"); const int id_index = hl_hash_utf8 ("index"); @@ -5122,6 +5134,10 @@ namespace lime { hl_dyn_seti (deviceObject, id_vendorID, &hlt_i32, properties.vendorID); hl_dyn_seti (deviceObject, id_deviceID, &hlt_i32, properties.deviceID); hl_dyn_seti (deviceObject, id_deviceType, &hlt_i32, properties.deviceType); + hl_dyn_seti (deviceObject, id_framebufferColorSampleCounts, &hlt_i32, properties.limits.framebufferColorSampleCounts); + hl_dyn_seti (deviceObject, id_framebufferDepthSampleCounts, &hlt_i32, properties.limits.framebufferDepthSampleCounts); + hl_dyn_seti (deviceObject, id_framebufferNoAttachmentsSampleCounts, &hlt_i32, properties.limits.framebufferNoAttachmentsSampleCounts); + hl_dyn_seti (deviceObject, id_framebufferStencilSampleCounts, &hlt_i32, properties.limits.framebufferStencilSampleCounts); hl_dyn_setp (deviceObject, id_queueFamilies, &hlt_array, queueFamilyArray); } @@ -7760,7 +7776,7 @@ namespace lime { "vkCreateRenderPass"); if (!vkCreateRenderPass) return alloc_null (); std::vector packed = GetVulkanIntVector (state); - if (packed.size () < 11) return alloc_null (); + if (packed.size () < 16) return alloc_null (); int colorFormat = packed[0]; int depthStencilFormat = packed[1]; @@ -7773,6 +7789,11 @@ namespace lime { int depthFinalLayout = packed[8]; int depthLoadOp = packed[9]; int depthStoreOp = packed[10]; + int resolveFormat = packed[11]; + int resolveLoadOp = packed[12]; + int resolveStoreOp = packed[13]; + int resolveInitialLayout = packed[14]; + int resolveFinalLayout = packed[15]; std::vector attachments; VkAttachmentDescription colorAttachment; @@ -7795,6 +7816,7 @@ namespace lime { VkAttachmentReference depthReference; memset (&depthReference, 0, sizeof (depthReference)); bool hasDepth = depthStencilFormat != VK_FORMAT_UNDEFINED; + bool hasResolve = resolveFormat != VK_FORMAT_UNDEFINED; if (hasDepth) { VkAttachmentDescription depthAttachment; @@ -7813,11 +7835,32 @@ namespace lime { } + VkAttachmentReference resolveReference; + memset (&resolveReference, 0, sizeof (resolveReference)); + if (hasResolve) { + + VkAttachmentDescription resolveAttachment; + memset (&resolveAttachment, 0, sizeof (resolveAttachment)); + resolveAttachment.format = (VkFormat)resolveFormat; + resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + resolveAttachment.loadOp = (VkAttachmentLoadOp)resolveLoadOp; + resolveAttachment.storeOp = (VkAttachmentStoreOp)resolveStoreOp; + resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + resolveAttachment.initialLayout = (VkImageLayout)resolveInitialLayout; + resolveAttachment.finalLayout = (VkImageLayout)resolveFinalLayout; + attachments.push_back (resolveAttachment); + resolveReference.attachment = (uint32_t)(attachments.size () - 1); + resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + } + VkSubpassDescription subpass; memset (&subpass, 0, sizeof (subpass)); subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorReference; + subpass.pResolveAttachments = hasResolve ? &resolveReference : 0; subpass.pDepthStencilAttachment = hasDepth ? &depthReference : 0; VkSubpassDependency dependency; @@ -7868,7 +7911,7 @@ namespace lime { "vkCreateRenderPass"); if (!vkCreateRenderPass) return 0; std::vector packed = GetHLVulkanIntVector (state); - if (packed.size () < 11) return 0; + if (packed.size () < 16) return 0; int colorFormat = packed[0]; int depthStencilFormat = packed[1]; @@ -7881,6 +7924,11 @@ namespace lime { int depthFinalLayout = packed[8]; int depthLoadOp = packed[9]; int depthStoreOp = packed[10]; + int resolveFormat = packed[11]; + int resolveLoadOp = packed[12]; + int resolveStoreOp = packed[13]; + int resolveInitialLayout = packed[14]; + int resolveFinalLayout = packed[15]; std::vector attachments; VkAttachmentDescription colorAttachment; @@ -7903,6 +7951,7 @@ namespace lime { VkAttachmentReference depthReference; memset (&depthReference, 0, sizeof (depthReference)); bool hasDepth = depthStencilFormat != VK_FORMAT_UNDEFINED; + bool hasResolve = resolveFormat != VK_FORMAT_UNDEFINED; if (hasDepth) { VkAttachmentDescription depthAttachment; @@ -7921,11 +7970,32 @@ namespace lime { } + VkAttachmentReference resolveReference; + memset (&resolveReference, 0, sizeof (resolveReference)); + if (hasResolve) { + + VkAttachmentDescription resolveAttachment; + memset (&resolveAttachment, 0, sizeof (resolveAttachment)); + resolveAttachment.format = (VkFormat)resolveFormat; + resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + resolveAttachment.loadOp = (VkAttachmentLoadOp)resolveLoadOp; + resolveAttachment.storeOp = (VkAttachmentStoreOp)resolveStoreOp; + resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + resolveAttachment.initialLayout = (VkImageLayout)resolveInitialLayout; + resolveAttachment.finalLayout = (VkImageLayout)resolveFinalLayout; + attachments.push_back (resolveAttachment); + resolveReference.attachment = (uint32_t)(attachments.size () - 1); + resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + } + VkSubpassDescription subpass; memset (&subpass, 0, sizeof (subpass)); subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorReference; + subpass.pResolveAttachments = hasResolve ? &resolveReference : 0; subpass.pDepthStencilAttachment = hasDepth ? &depthReference : 0; VkSubpassDependency dependency; @@ -9492,7 +9562,7 @@ namespace lime { static VkPipeline CreateManagedVulkanGraphicsPipeline (Window* targetWindow, VkInstance instance, VkDevice device, VkRenderPass renderPass, VkPipelineLayout layout, VkShaderModule vertexShader, VkShaderModule fragmentShader, const std::vector& state) { - if (state.size () < 35 || !renderPass || !layout || !vertexShader || !fragmentShader) { + if (state.size () < 41 || !renderPass || !layout || !vertexShader || !fragmentShader) { lastVKError = "Invalid Vulkan graphics pipeline state"; return VK_NULL_HANDLE; @@ -9534,6 +9604,12 @@ namespace lime { int backCompareMask = state[cursor++]; int backWriteMask = state[cursor++]; int backReference = state[cursor++]; + int rasterizationSamples = state[cursor++]; + bool sampleShading = state[cursor++] != 0; + int minSampleShading = state[cursor++]; + int sampleMask = state[cursor++]; + bool alphaToCoverage = state[cursor++] != 0; + bool alphaToOne = state[cursor++] != 0; int bindingCount = state[cursor++]; if ((int)state.size () < cursor + bindingCount * 3 + 1) { @@ -9635,7 +9711,13 @@ namespace lime { VkPipelineMultisampleStateCreateInfo multisample; memset (&multisample, 0, sizeof (multisample)); multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisample.rasterizationSamples = (VkSampleCountFlagBits)rasterizationSamples; + multisample.sampleShadingEnable = sampleShading ? VK_TRUE : VK_FALSE; + multisample.minSampleShading = (float)minSampleShading / 1000000.0f; + VkSampleMask sampleMaskValue = (VkSampleMask)sampleMask; + multisample.pSampleMask = sampleMask != 0 ? &sampleMaskValue : 0; + multisample.alphaToCoverageEnable = alphaToCoverage ? VK_TRUE : VK_FALSE; + multisample.alphaToOneEnable = alphaToOne ? VK_TRUE : VK_FALSE; VkPipelineDepthStencilStateCreateInfo depthStencil; memset (&depthStencil, 0, sizeof (depthStencil)); diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx index 46103482d9..2d20ab4d0d 100644 --- a/src/lime/graphics/vulkan/VKDevice.hx +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -370,7 +370,10 @@ class VKDevice colorFinalLayout:Int = VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, depthInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE):VKRenderPass + depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE, + resolveFormat:Int = VK.FORMAT_UNDEFINED, resolveLoadOp:Int = VK.ATTACHMENT_LOAD_OP_DONT_CARE, + resolveStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, resolveInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, + resolveFinalLayout:Int = VK.IMAGE_LAYOUT_PRESENT_SRC_KHR):VKRenderPass { #if (!macro && lime_cffi && lime_vulkan) if (isValid()) @@ -386,14 +389,19 @@ class VKDevice depthInitialLayout, depthFinalLayout, depthLoadOp, - depthStoreOp + depthStoreOp, + resolveFormat, + resolveLoadOp, + resolveStoreOp, + resolveInitialLayout, + resolveFinalLayout ]; var data:Dynamic = NativeCFFI.lime_vk_create_render_pass(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, handle.low, state); var renderPassHandle = VK.__makeHandle(data); if (!VK.__isZero(renderPassHandle)) { - return new VKRenderPass(this, renderPassHandle, colorFormat, depthStencilFormat, samples); + return new VKRenderPass(this, renderPassHandle, colorFormat, depthStencilFormat, samples, resolveFormat); } } #end diff --git a/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx index 2763dcb000..527a44ada0 100644 --- a/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx +++ b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx @@ -29,6 +29,12 @@ class VKGraphicsPipelineInfo public var frontWriteMask:Int = -1; public var polygonMode:Int = VK.POLYGON_MODE_FILL; public var primitiveRestart:Bool = false; + public var rasterizationSamples:Int = VK.SAMPLE_COUNT_1_BIT; + public var sampleShading:Bool = false; + public var minSampleShading:Float = 0; + public var sampleMask:Int = 0; + public var alphaToCoverage:Bool = false; + public var alphaToOne:Bool = false; public var srcAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE; public var srcColorBlendFactor:Int = VK.BLEND_FACTOR_SRC_ALPHA; public var stencilTest:Bool = false; @@ -85,6 +91,12 @@ class VKGraphicsPipelineInfo backCompareMask, backWriteMask, backReference, + rasterizationSamples, + sampleShading ? 1 : 0, + Std.int(minSampleShading * 1000000), + sampleMask, + alphaToCoverage ? 1 : 0, + alphaToOne ? 1 : 0, vertexBindings.length ]; diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx index 7958b2ce5a..fd390ae95f 100644 --- a/src/lime/graphics/vulkan/VKPhysicalDevice.hx +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -23,6 +23,10 @@ class VKPhysicalDevice public var deviceID(default, null):Int; public var deviceType(default, null):Int; public var deviceTypeName(default, null):String; + public var framebufferColorSampleCounts(default, null):Int; + public var framebufferDepthSampleCounts(default, null):Int; + public var framebufferNoAttachmentsSampleCounts(default, null):Int; + public var framebufferStencilSampleCounts(default, null):Int; public var isDiscrete(default, null):Bool; public var supportsPresent(default, null):Bool; public var queueFamilies(default, null):Array; @@ -39,6 +43,10 @@ class VKPhysicalDevice vendorID = data.vendorID; deviceID = data.deviceID; deviceType = data.deviceType; + framebufferColorSampleCounts = data.framebufferColorSampleCounts; + framebufferDepthSampleCounts = data.framebufferDepthSampleCounts; + framebufferNoAttachmentsSampleCounts = data.framebufferNoAttachmentsSampleCounts; + framebufferStencilSampleCounts = data.framebufferStencilSampleCounts; deviceTypeName = switch (deviceType) { case 1: "integrated-gpu"; @@ -123,4 +131,42 @@ class VKPhysicalDevice { return getQueueFamily(requireGraphics, requirePresent, requireCompute, requireTransfer) != null; } + + public function getMaxUsableSampleCount(requireDepth:Bool = false, requireStencil:Bool = false):Int + { + var counts = framebufferColorSampleCounts; + if (requireDepth) + { + counts &= framebufferDepthSampleCounts; + } + if (requireStencil) + { + counts &= framebufferStencilSampleCounts; + } + + for (sampleCount in [VK.SAMPLE_COUNT_64_BIT, VK.SAMPLE_COUNT_32_BIT, VK.SAMPLE_COUNT_16_BIT, VK.SAMPLE_COUNT_8_BIT, + VK.SAMPLE_COUNT_4_BIT, VK.SAMPLE_COUNT_2_BIT]) + { + if ((counts & sampleCount) != 0) + { + return sampleCount; + } + } + + return VK.SAMPLE_COUNT_1_BIT; + } + + public function supportsSampleCount(samples:Int, requireDepth:Bool = false, requireStencil:Bool = false):Bool + { + var counts = framebufferColorSampleCounts; + if (requireDepth) + { + counts &= framebufferDepthSampleCounts; + } + if (requireStencil) + { + counts &= framebufferStencilSampleCounts; + } + return (counts & samples) != 0; + } } diff --git a/src/lime/graphics/vulkan/VKRenderPass.hx b/src/lime/graphics/vulkan/VKRenderPass.hx index bcbf0ec83f..8a7ddfe95c 100644 --- a/src/lime/graphics/vulkan/VKRenderPass.hx +++ b/src/lime/graphics/vulkan/VKRenderPass.hx @@ -14,16 +14,20 @@ class VKRenderPass public var depthStencilFormat(default, null):Int; public var device(default, null):VKDevice; public var handle(default, null):Int64; + public var hasResolve(default, null):Bool; + public var resolveFormat(default, null):Int; public var samples(default, null):Int; @:allow(lime.graphics.vulkan.VKDevice) - private function new(device:VKDevice, handle:Int64, colorFormat:Int, depthStencilFormat:Int, samples:Int) + private function new(device:VKDevice, handle:Int64, colorFormat:Int, depthStencilFormat:Int, samples:Int, resolveFormat:Int) { this.device = device; this.handle = handle; this.colorFormat = colorFormat; this.depthStencilFormat = depthStencilFormat; this.samples = samples; + this.resolveFormat = resolveFormat; + this.hasResolve = resolveFormat != VK.FORMAT_UNDEFINED; } public function dispose():Void diff --git a/tests/vulkan-smoke/Source/Main.hx b/tests/vulkan-smoke/Source/Main.hx index 3e65452a09..fd63e61ba6 100644 --- a/tests/vulkan-smoke/Source/Main.hx +++ b/tests/vulkan-smoke/Source/Main.hx @@ -43,7 +43,10 @@ class Main extends Application private static inline var DEPTH_FORMAT = VK.FORMAT_D32_SFLOAT; private static inline var OFFSCREEN_FORMAT = VK.FORMAT_R8G8B8A8_UNORM; private static inline var OFFSCREEN_SIZE = 256; + private static inline var REQUESTED_MSAA_SAMPLES = VK.SAMPLE_COUNT_4_BIT; + private var colorImage:VKImage; + private var colorView:VKImageView; private var commandBuffer:VKCommandBuffer; private var commandPool:VKCommandPool; private var cubeDescriptorSet:VKDescriptorSet; @@ -82,6 +85,7 @@ class Main extends Application private var queueFamily:VKQueueFamilyInfo; private var renderFinished:VKSemaphore; private var renderPass:VKRenderPass; + private var msaaSamples:Int = VK.SAMPLE_COUNT_1_BIT; private var sourceTextureImage:VKImage; private var sourceTextureSampler:VKSampler; private var sourceTextureView:VKImageView; @@ -187,6 +191,7 @@ class Main extends Application fail("No present-capable graphics queue family was found"); return; } + msaaSamples = physicalDevice.supportsSampleCount(REQUESTED_MSAA_SAMPLES, true) ? REQUESTED_MSAA_SAMPLES : VK.SAMPLE_COUNT_1_BIT; queueFamily = physicalDevice.getQueueFamily(true, true); device = physicalDevice.createDevice(queueFamily); @@ -485,9 +490,22 @@ class Main extends Application private function createOnscreenPass():Bool { - renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, VK.SAMPLE_COUNT_1_BIT, - VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); - if (renderPass == null || !createDepthResources() || !createFramebuffers()) + if (msaaSamples != VK.SAMPLE_COUNT_1_BIT) + { + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, msaaSamples, + VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_DONT_CARE, VK.IMAGE_LAYOUT_UNDEFINED, + VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK.IMAGE_LAYOUT_UNDEFINED, + VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK.ATTACHMENT_LOAD_OP_CLEAR, + VK.ATTACHMENT_STORE_OP_DONT_CARE, swapchain.format, VK.ATTACHMENT_LOAD_OP_DONT_CARE, + VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + } + else + { + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, VK.SAMPLE_COUNT_1_BIT, + VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + } + + if (renderPass == null || !createColorResources() || !createDepthResources() || !createFramebuffers()) { fail("Failed to create Vulkan onscreen render pass resources: " + VK.getLastError()); return false; @@ -511,6 +529,7 @@ class Main extends Application info.depthCompareOp = VK.COMPARE_OP_LESS; info.cullMode = VK.CULL_MODE_BACK_BIT; info.frontFace = VK.FRONT_FACE_CLOCKWISE; + info.rasterizationSamples = msaaSamples; info.vertexBindings.push(new VKVertexBinding(0, 36, VK.VERTEX_INPUT_RATE_VERTEX)); info.vertexAttributes.push(new VKVertexAttribute(0, 0, VK.FORMAT_R32G32B32_SFLOAT, 0)); info.vertexAttributes.push(new VKVertexAttribute(1, 0, VK.FORMAT_R32G32_SFLOAT, 12)); @@ -526,11 +545,33 @@ class Main extends Application return true; } + private function createColorResources():Bool + { + disposeColorResources(); + + if (msaaSamples == VK.SAMPLE_COUNT_1_BIT) + { + return true; + } + + colorImage = device.createImage(swapchain.width, swapchain.height, swapchain.format, + VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, 1, 1, 1, VK.IMAGE_TYPE_2D, + VK.IMAGE_TILING_OPTIMAL, msaaSamples); + if (colorImage == null || colorImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + return false; + } + + colorView = colorImage.createView(swapchain.format); + return colorView != null; + } + private function createDepthResources():Bool { disposeDepthResources(); - depthImage = device.createImage(swapchain.width, swapchain.height, DEPTH_FORMAT, VK.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + depthImage = device.createImage(swapchain.width, swapchain.height, DEPTH_FORMAT, VK.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + 1, 1, 1, VK.IMAGE_TYPE_2D, VK.IMAGE_TILING_OPTIMAL, msaaSamples); if (depthImage == null || depthImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) { return false; @@ -553,7 +594,8 @@ class Main extends Application return false; } - var framebuffer = device.createFramebuffer(renderPass, [imageView, depthView], swapchain.width, swapchain.height); + var attachments = msaaSamples != VK.SAMPLE_COUNT_1_BIT ? [colorView, depthView, imageView] : [imageView, depthView]; + var framebuffer = device.createFramebuffer(renderPass, attachments, swapchain.width, swapchain.height); if (framebuffer == null) { imageView.dispose(); @@ -692,12 +734,13 @@ class Main extends Application return false; } - return createDepthResources() && createFramebuffers(); + return createColorResources() && createDepthResources() && createFramebuffers(); } private function disposeSwapchainResources():Void { disposeSwapchainFramebuffers(); + disposeColorResources(); disposeDepthResources(); } @@ -722,6 +765,20 @@ class Main extends Application imageViews = []; } + private function disposeColorResources():Void + { + if (colorView != null) + { + colorView.dispose(); + colorView = null; + } + if (colorImage != null) + { + colorImage.dispose(true); + colorImage = null; + } + } + private function disposeDepthResources():Void { if (depthView != null) @@ -792,6 +849,8 @@ class Main extends Application commandBuffer = null; commandPool = null; + colorImage = null; + colorView = null; cubeDescriptorSet = null; cubeDescriptorSetLayout = null; cubeFragmentShader = null; From 0c3d568df9837b8ea6dcc2abcc3f9628bb880605 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 26 May 2026 02:23:22 -0400 Subject: [PATCH 18/76] Enable Vulkan by default for Windows/Linux builds Add Vulkan support to C++ Windows and Linux builds and CI. CI: install libvulkan-dev and adjust workflow steps to build the default Vulkan-enabled Lime (remove explicit -D lime-vulkan flags). Build/config: add lime-vulkan defines in include.xml and set LIME_VULKAN for windows/linux in project/Build.xml (respecting no-vulkan/apple/winrt exclusions). Tests: remove the explicit lime-vulkan haxedef from tests/vulkan-smoke/project.xml. README: document that native Vulkan is included in standard Windows and Linux C++ Lime builds and note Apple still requires explicit Vulkan builds/MoltenVK. --- .github/workflows/main.yml | 10 +++++----- README.md | 4 ++-- include.xml | 2 ++ project/Build.xml | 1 + tests/vulkan-smoke/project.xml | 1 - 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7965bbfae6..5aa78cd755 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev g++-multilib gcc-multilib libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev g++-multilib gcc-multilib libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev - uses: krdlab/setup-haxe@v2 with: @@ -110,7 +110,7 @@ jobs: run: | sudo add-apt-repository ppa:haxe/releases -y sudo apt-get update - sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev # krdlab/setup-haxe doesn't support arm64 linux # so this is our workaround for now @@ -218,9 +218,9 @@ jobs: haxelib run lime rebuild tools -nocolor -verbose -nocffi haxelib run lime setup -alias -y -nocffi - - name: Rebuild Lime (Linux Vulkan) + - name: Rebuild Lime (Linux default Vulkan) run: | - lime rebuild linux -64 -release -nocolor -verbose -nocffi -D lime-vulkan + lime rebuild linux -64 -release -nocolor -verbose -nocffi - name: Build Vulkan smoke test app working-directory: tests/vulkan-smoke @@ -242,7 +242,7 @@ jobs: - name: Build HelloWorld Vulkan sample run: | lime create HelloWorld -verbose -nocolor - lime build HelloWorld linux -release -verbose -nocolor -D lime-vulkan --window-render-type=vulkan + lime build HelloWorld linux -release -verbose -nocolor --window-render-type=vulkan macos: runs-on: macos-14 diff --git a/README.md b/README.md index a703f9140a..3585d2f17b 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ Lime does not include a renderer, but exposes the current context: * Vulkan The GL context is based upon the WebGL standard, implemented for both OpenGL and OpenGL ES as needed. -Native Vulkan support currently focuses on window/bootstrap helpers and a minimal validation renderer for backend verification, not a full high-level renderer. -The native Vulkan bootstrap and validation renderer are currently opt-in and require building Lime with the `lime-vulkan` define plus Vulkan headers available to the native toolchain. +Native Vulkan support exposes an explicit Vulkan API layer for renderer backends, including native window/swapchain integration and resource/command primitives. +Native Vulkan support is included in standard Windows and Linux C++ Lime builds, including the matching Haxe API define. Apple targets still require an explicit Vulkan-enabled build and MoltenVK packaging. To request a Vulkan window, use the standard `RenderContextType.VULKAN` context selection, set `` in project XML, or use `--window-render-type=vulkan`. The in-repo `tests/vulkan-smoke` project is used as the current Vulkan CI smoke app. diff --git a/include.xml b/include.xml index 04f641e3c6..e38f58019f 100644 --- a/include.xml +++ b/include.xml @@ -24,6 +24,8 @@ + + diff --git a/project/Build.xml b/project/Build.xml index a1a5b48d2c..8924eb073d 100755 --- a/project/Build.xml +++ b/project/Build.xml @@ -36,6 +36,7 @@ + diff --git a/tests/vulkan-smoke/project.xml b/tests/vulkan-smoke/project.xml index 47c1e61a7a..d23af8f962 100644 --- a/tests/vulkan-smoke/project.xml +++ b/tests/vulkan-smoke/project.xml @@ -8,7 +8,6 @@ - From 0e4b7d4c974204047c8f1b30fbcc3be282fedfb9 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 26 May 2026 04:23:39 -0400 Subject: [PATCH 19/76] Vulkan: mapped memory & descriptor helpers Introduce managed Vulkan mapped memory support and several Vulkan convenience helpers. Tracks mapped memory in a ManagedVulkanMappedMemory map, prevents double-mapping, automatically unmaps on vkFreeMemory, and exposes map/unmap/write/flush/invalidate operations. Add UpdateManagedVulkanDescriptorSets to batch-update descriptor sets, plus command helpers (dynamic descriptor set bind, draw indirect, draw indexed indirect, clear attachments). Export new device limit fields (maxPushConstantsSize, minStorageBufferOffsetAlignment, minUniformBufferOffsetAlignment, nonCoherentAtomSize) and update Haxe NativeCFFI bindings/primes for new functions. --- project/src/ExternalInterface.cpp | 844 ++++++++++++++++++ .../_internal/backend/native/NativeCFFI.hx | 127 +++ src/lime/graphics/vulkan/VKBuffer.hx | 28 + src/lime/graphics/vulkan/VKCommandBuffer.hx | 60 ++ src/lime/graphics/vulkan/VKDescriptorWrite.hx | 115 +++ src/lime/graphics/vulkan/VKDevice.hx | 33 + src/lime/graphics/vulkan/VKDeviceMemory.hx | 142 +++ src/lime/graphics/vulkan/VKPhysicalDevice.hx | 8 + src/lime/graphics/vulkan/VKUploadRing.hx | 106 +++ src/lime/graphics/vulkan/VKUploadSlice.hx | 23 + 10 files changed, 1486 insertions(+) create mode 100644 src/lime/graphics/vulkan/VKDescriptorWrite.hx create mode 100644 src/lime/graphics/vulkan/VKUploadRing.hx create mode 100644 src/lime/graphics/vulkan/VKUploadSlice.hx diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 59a2978fd9..e5673f0ea0 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #ifdef LIME_SDL_SOUND @@ -136,6 +137,34 @@ namespace lime { } + struct ManagedVulkanMappedMemory { + + VkDevice device; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; + void* data; + + }; + + + static std::unordered_map mappedVulkanMemory; + + + static uint64_t GetManagedVulkanMappedMemoryKey (VkDeviceMemory memory) { + + return (uint64_t)(uintptr_t)memory; + + } + + + static VkDeviceSize NormalizeVulkanRangeSize (uint64_t size) { + + return size == 0 ? VK_WHOLE_SIZE : (VkDeviceSize)size; + + } + + static bool CreateManagedVulkanInstance (Window* targetWindow, const char* applicationName, VkInstance* outInstance) { if (!targetWindow || !outInstance) { @@ -363,6 +392,88 @@ namespace lime { } + static bool UpdateManagedVulkanDescriptorSets (Window* targetWindow, VkInstance instance, VkDevice device, const std::vector& packed) { + + if (packed.empty ()) return true; + + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets) return false; + + int writeCount = packed[0]; + if (writeCount < 0) return false; + + std::vector bufferInfos; + std::vector imageInfos; + std::vector descriptorWrites; + bufferInfos.reserve ((size_t)writeCount); + imageInfos.reserve ((size_t)writeCount); + descriptorWrites.reserve ((size_t)writeCount); + + size_t index = 1; + for (int i = 0; i < writeCount; ++i) { + + if (index >= packed.size ()) return false; + int kind = packed[index++]; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.descriptorCount = 1; + + if (kind == 0) { + + if (index + 11 > packed.size ()) return false; + write.dstSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (packed[index], packed[index + 1]); + write.dstBinding = (uint32_t)packed[index + 2]; + write.dstArrayElement = (uint32_t)packed[index + 3]; + write.descriptorType = (VkDescriptorType)packed[index + 4]; + + VkDescriptorBufferInfo bufferInfo; + memset (&bufferInfo, 0, sizeof (bufferInfo)); + bufferInfo.buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (packed[index + 5], packed[index + 6]); + bufferInfo.offset = (VkDeviceSize)CombineVulkanHandle (packed[index + 7], packed[index + 8]); + bufferInfo.range = NormalizeVulkanRangeSize (CombineVulkanHandle (packed[index + 9], packed[index + 10])); + bufferInfos.push_back (bufferInfo); + write.pBufferInfo = &bufferInfos[bufferInfos.size () - 1]; + index += 11; + + } else if (kind == 1) { + + if (index + 10 > packed.size ()) return false; + write.dstSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (packed[index], packed[index + 1]); + write.dstBinding = (uint32_t)packed[index + 2]; + write.dstArrayElement = (uint32_t)packed[index + 3]; + write.descriptorType = (VkDescriptorType)packed[index + 4]; + + VkDescriptorImageInfo imageInfo; + memset (&imageInfo, 0, sizeof (imageInfo)); + imageInfo.imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (packed[index + 5], packed[index + 6]); + imageInfo.sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (packed[index + 7], packed[index + 8]); + imageInfo.imageLayout = (VkImageLayout)packed[index + 9]; + imageInfos.push_back (imageInfo); + write.pImageInfo = &imageInfos[imageInfos.size () - 1]; + index += 10; + + } else { + + lastVKError = "Invalid Vulkan descriptor write kind"; + return false; + + } + + if (!write.dstSet) return false; + descriptorWrites.push_back (write); + + } + + vkUpdateDescriptorSets (device, (uint32_t)descriptorWrites.size (), descriptorWrites.empty () ? 0 : descriptorWrites.data (), 0, 0); + lastVKError.clear (); + return true; + + } + + static bool CreateManagedVulkanDevice (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const std::vector& requestedExtensions, VkDevice* outDevice, VkQueue* outQueue) { @@ -4918,6 +5029,10 @@ namespace lime { const int id_framebufferDepthSampleCounts = val_id ("framebufferDepthSampleCounts"); const int id_framebufferNoAttachmentsSampleCounts = val_id ("framebufferNoAttachmentsSampleCounts"); const int id_framebufferStencilSampleCounts = val_id ("framebufferStencilSampleCounts"); + const int id_maxPushConstantsSize = val_id ("maxPushConstantsSize"); + const int id_minStorageBufferOffsetAlignment = val_id ("minStorageBufferOffsetAlignment"); + const int id_minUniformBufferOffsetAlignment = val_id ("minUniformBufferOffsetAlignment"); + const int id_nonCoherentAtomSize = val_id ("nonCoherentAtomSize"); const int id_queueFamilies = val_id ("queueFamilies"); const int id_index = val_id ("index"); @@ -4980,6 +5095,12 @@ namespace lime { alloc_field (deviceObject, id_framebufferDepthSampleCounts, alloc_int ((int)properties.limits.framebufferDepthSampleCounts)); alloc_field (deviceObject, id_framebufferNoAttachmentsSampleCounts, alloc_int ((int)properties.limits.framebufferNoAttachmentsSampleCounts)); alloc_field (deviceObject, id_framebufferStencilSampleCounts, alloc_int ((int)properties.limits.framebufferStencilSampleCounts)); + alloc_field (deviceObject, id_maxPushConstantsSize, alloc_int ((int)properties.limits.maxPushConstantsSize)); + alloc_field (deviceObject, id_minStorageBufferOffsetAlignment, + CreateVulkanHandleValue ((uint64_t)properties.limits.minStorageBufferOffsetAlignment)); + alloc_field (deviceObject, id_minUniformBufferOffsetAlignment, + CreateVulkanHandleValue ((uint64_t)properties.limits.minUniformBufferOffsetAlignment)); + alloc_field (deviceObject, id_nonCoherentAtomSize, CreateVulkanHandleValue ((uint64_t)properties.limits.nonCoherentAtomSize)); alloc_field (deviceObject, id_queueFamilies, queueFamilyArray); val_array_set_i (devices, i, deviceObject); @@ -5074,6 +5195,10 @@ namespace lime { const int id_framebufferDepthSampleCounts = hl_hash_utf8 ("framebufferDepthSampleCounts"); const int id_framebufferNoAttachmentsSampleCounts = hl_hash_utf8 ("framebufferNoAttachmentsSampleCounts"); const int id_framebufferStencilSampleCounts = hl_hash_utf8 ("framebufferStencilSampleCounts"); + const int id_maxPushConstantsSize = hl_hash_utf8 ("maxPushConstantsSize"); + const int id_minStorageBufferOffsetAlignment = hl_hash_utf8 ("minStorageBufferOffsetAlignment"); + const int id_minUniformBufferOffsetAlignment = hl_hash_utf8 ("minUniformBufferOffsetAlignment"); + const int id_nonCoherentAtomSize = hl_hash_utf8 ("nonCoherentAtomSize"); const int id_queueFamilies = hl_hash_utf8 ("queueFamilies"); const int id_index = hl_hash_utf8 ("index"); @@ -5138,6 +5263,13 @@ namespace lime { hl_dyn_seti (deviceObject, id_framebufferDepthSampleCounts, &hlt_i32, properties.limits.framebufferDepthSampleCounts); hl_dyn_seti (deviceObject, id_framebufferNoAttachmentsSampleCounts, &hlt_i32, properties.limits.framebufferNoAttachmentsSampleCounts); hl_dyn_seti (deviceObject, id_framebufferStencilSampleCounts, &hlt_i32, properties.limits.framebufferStencilSampleCounts); + hl_dyn_seti (deviceObject, id_maxPushConstantsSize, &hlt_i32, properties.limits.maxPushConstantsSize); + hl_dyn_setp (deviceObject, id_minStorageBufferOffsetAlignment, &hlt_dynobj, + HLCreateVulkanHandleValue ((uint64_t)properties.limits.minStorageBufferOffsetAlignment)); + hl_dyn_setp (deviceObject, id_minUniformBufferOffsetAlignment, &hlt_dynobj, + HLCreateVulkanHandleValue ((uint64_t)properties.limits.minUniformBufferOffsetAlignment)); + hl_dyn_setp (deviceObject, id_nonCoherentAtomSize, &hlt_dynobj, + HLCreateVulkanHandleValue ((uint64_t)properties.limits.nonCoherentAtomSize)); hl_dyn_setp (deviceObject, id_queueFamilies, &hlt_array, queueFamilyArray); } @@ -6452,6 +6584,16 @@ namespace lime { PFN_vkFreeMemory vkFreeMemory = (PFN_vkFreeMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFreeMemory"); if (vkFreeMemory) { + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped != mappedVulkanMemory.end ()) { + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (vkUnmapMemory) vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + + } + vkFreeMemory (device, memory, 0); lastVKError.clear (); @@ -6475,6 +6617,16 @@ namespace lime { PFN_vkFreeMemory vkFreeMemory = (PFN_vkFreeMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFreeMemory"); if (vkFreeMemory) { + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped != mappedVulkanMemory.end ()) { + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (vkUnmapMemory) vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + + } + vkFreeMemory (device, memory, 0); lastVKError.clear (); @@ -6652,6 +6804,392 @@ namespace lime { } + bool lime_vk_map_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, int sizeHigh, int sizeLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + VkDeviceSize size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + if (!memory) return false; + + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + if (mappedVulkanMemory.find (mapKey) != mappedVulkanMemory.end ()) { + + lastVKError.clear (); + return true; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + if (!vkMapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, offset, size, (VkMemoryMapFlags)flags, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + ManagedVulkanMappedMemory mapped; + mapped.device = device; + mapped.memory = memory; + mapped.offset = offset; + mapped.size = size; + mapped.data = mappedData; + mappedVulkanMemory[mapKey] = mapped; + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_map_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + VkDeviceSize size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + if (!memory) return false; + + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + if (mappedVulkanMemory.find (mapKey) != mappedVulkanMemory.end ()) { + + lastVKError.clear (); + return true; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + if (!vkMapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, offset, size, (VkMemoryMapFlags)flags, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + ManagedVulkanMappedMemory mapped; + mapped.device = device; + mapped.memory = memory; + mapped.offset = offset; + mapped.size = size; + mapped.data = mappedData; + mappedVulkanMemory[mapKey] = mapped; + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + void lime_vk_unmap_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped == mappedVulkanMemory.end ()) return; + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkUnmapMemory) return; + + vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + lastVKError.clear (); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_unmap_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped == mappedVulkanMemory.end ()) return; + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkUnmapMemory) return; + + vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + lastVKError.clear (); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_write_mapped_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, value bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Bytes data (bytes); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !data.b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.length) { + + lastVKError = "Invalid mapped Vulkan memory write range"; + return false; + + } + + std::unordered_map::iterator mapped = mappedVulkanMemory.find (GetManagedVulkanMappedMemoryKey (memory)); + if (mapped == mappedVulkanMemory.end ()) { + + lastVKError = "Vulkan memory is not mapped"; + return false; + + } + + if (offset < mapped->second.offset) { + + lastVKError = "Mapped Vulkan memory write offset is outside the mapped range"; + return false; + + } + + uint64_t relativeOffset = offset - mapped->second.offset; + if (mapped->second.size != VK_WHOLE_SIZE && relativeOffset + (uint64_t)byteLength > (uint64_t)mapped->second.size) { + + lastVKError = "Mapped Vulkan memory write exceeds the mapped range"; + return false; + + } + + memcpy ((unsigned char*)mapped->second.data + relativeOffset, data.b + byteOffset, byteLength); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_write_mapped_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !bytes || !bytes->b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid mapped Vulkan memory write range"; + return false; + + } + + std::unordered_map::iterator mapped = mappedVulkanMemory.find (GetManagedVulkanMappedMemoryKey (memory)); + if (mapped == mappedVulkanMemory.end ()) { + + lastVKError = "Vulkan memory is not mapped"; + return false; + + } + + if (offset < mapped->second.offset) { + + lastVKError = "Mapped Vulkan memory write offset is outside the mapped range"; + return false; + + } + + uint64_t relativeOffset = offset - mapped->second.offset; + if (mapped->second.size != VK_WHOLE_SIZE && relativeOffset + (uint64_t)byteLength > (uint64_t)mapped->second.size) { + + lastVKError = "Mapped Vulkan memory write exceeds the mapped range"; + return false; + + } + + memcpy ((unsigned char*)mapped->second.data + relativeOffset, bytes->b + byteOffset, byteLength); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_flush_mapped_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, + int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges = + (PFN_vkFlushMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFlushMappedMemoryRanges"); + if (!vkFlushMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkFlushMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkFlushMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_flush_mapped_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges = + (PFN_vkFlushMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFlushMappedMemoryRanges"); + if (!vkFlushMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkFlushMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkFlushMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_invalidate_mapped_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, + int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges = + (PFN_vkInvalidateMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkInvalidateMappedMemoryRanges"); + if (!vkInvalidateMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkInvalidateMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkInvalidateMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_invalidate_mapped_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges = + (PFN_vkInvalidateMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkInvalidateMappedMemoryRanges"); + if (!vkInvalidateMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkInvalidateMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkInvalidateMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vk_create_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int sizeHigh, int sizeLow, int usage) { #ifdef LIME_VULKAN @@ -9144,6 +9682,37 @@ namespace lime { } + bool lime_vk_update_descriptor_sets (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value writes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + return UpdateManagedVulkanDescriptorSets (targetWindow, instance, device, GetVulkanIntVector (writes)); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_sets) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* writes) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + return UpdateManagedVulkanDescriptorSets (targetWindow, instance, device, GetHLVulkanIntVector (writes)); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vk_create_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value setLayouts, int pushConstantStages, int pushConstantSize) { @@ -10296,6 +10865,56 @@ namespace lime { } + bool lime_vk_cmd_bind_descriptor_set_dynamic_offset (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int dynamicOffset, int firstSet, + int bindPoint) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + uint32_t offset = (uint32_t)dynamicOffset; + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 1, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_dynamic_offset) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, + int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, + int dynamicOffset, int firstSet, int bindPoint) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + uint32_t offset = (uint32_t)dynamicOffset; + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 1, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + value lime_vulkan_renderer_get_info (value handle) { if (val_is_null (handle)) return alloc_string (""); @@ -10590,6 +11209,99 @@ namespace lime { } + + bool lime_vk_cmd_draw_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndirect vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndirect vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_cmd_draw_indexed_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect = + (PFN_vkCmdDrawIndexedIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDrawIndexedIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndexedIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndexedIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, + int stride) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect = + (PFN_vkCmdDrawIndexedIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDrawIndexedIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndexedIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndexedIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + value lime_vulkan_renderer_get_last_error () { return alloc_string (lastVulkanRendererError.c_str ()); @@ -11026,6 +11738,128 @@ namespace lime { } + bool lime_vk_cmd_clear_attachments (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, value state, value clear) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearAttachments vkCmdClearAttachments = + (PFN_vkCmdClearAttachments)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearAttachments"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdClearAttachments || !commandBuffer || packed.size () < 8 || clearValues.size () < 5) return false; + + VkClearAttachment attachments[2]; + memset (attachments, 0, sizeof (attachments)); + uint32_t attachmentCount = 0; + + if (packed[0] != 0) { + + attachments[attachmentCount].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + attachments[attachmentCount].colorAttachment = 0; + attachments[attachmentCount].clearValue.color.float32[0] = (float)clearValues[0]; + attachments[attachmentCount].clearValue.color.float32[1] = (float)clearValues[1]; + attachments[attachmentCount].clearValue.color.float32[2] = (float)clearValues[2]; + attachments[attachmentCount].clearValue.color.float32[3] = (float)clearValues[3]; + attachmentCount++; + + } + + if (packed[1] != 0 || packed[2] != 0) { + + attachments[attachmentCount].aspectMask = 0; + if (packed[1] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (packed[2] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + attachments[attachmentCount].clearValue.depthStencil.depth = (float)clearValues[4]; + attachments[attachmentCount].clearValue.depthStencil.stencil = (uint32_t)packed[7]; + attachmentCount++; + + } + + if (attachmentCount == 0) return true; + + VkClearRect rect; + memset (&rect, 0, sizeof (rect)); + rect.rect.offset.x = packed[3]; + rect.rect.offset.y = packed[4]; + rect.rect.extent.width = (uint32_t)packed[5]; + rect.rect.extent.height = (uint32_t)packed[6]; + rect.baseArrayLayer = 0; + rect.layerCount = 1; + vkCmdClearAttachments (commandBuffer, attachmentCount, attachments, 1, &rect); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_attachments) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, hl_varray* state, hl_varray* clear) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearAttachments vkCmdClearAttachments = + (PFN_vkCmdClearAttachments)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearAttachments"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdClearAttachments || !commandBuffer || packed.size () < 8 || clearValues.size () < 5) return false; + + VkClearAttachment attachments[2]; + memset (attachments, 0, sizeof (attachments)); + uint32_t attachmentCount = 0; + + if (packed[0] != 0) { + + attachments[attachmentCount].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + attachments[attachmentCount].colorAttachment = 0; + attachments[attachmentCount].clearValue.color.float32[0] = (float)clearValues[0]; + attachments[attachmentCount].clearValue.color.float32[1] = (float)clearValues[1]; + attachments[attachmentCount].clearValue.color.float32[2] = (float)clearValues[2]; + attachments[attachmentCount].clearValue.color.float32[3] = (float)clearValues[3]; + attachmentCount++; + + } + + if (packed[1] != 0 || packed[2] != 0) { + + attachments[attachmentCount].aspectMask = 0; + if (packed[1] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (packed[2] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + attachments[attachmentCount].clearValue.depthStencil.depth = (float)clearValues[4]; + attachments[attachmentCount].clearValue.depthStencil.stencil = (uint32_t)packed[7]; + attachmentCount++; + + } + + if (attachmentCount == 0) return true; + + VkClearRect rect; + memset (&rect, 0, sizeof (rect)); + rect.rect.offset.x = packed[3]; + rect.rect.offset.y = packed[4]; + rect.rect.extent.width = (uint32_t)packed[5]; + rect.rect.extent.height = (uint32_t)packed[6]; + rect.baseArrayLayer = 0; + rect.layerCount = 1; + vkCmdClearAttachments (commandBuffer, attachmentCount, attachments, 1, &rect); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { @@ -12662,6 +13496,11 @@ namespace lime { DEFINE_PRIME7v (lime_vk_free_memory); DEFINE_PRIME12 (lime_vk_upload_memory); DEFINE_PRIME12 (lime_vk_download_memory); + DEFINE_PRIME12 (lime_vk_map_memory); + DEFINE_PRIME7v (lime_vk_unmap_memory); + DEFINE_PRIME12 (lime_vk_write_mapped_memory); + DEFINE_PRIME11 (lime_vk_flush_mapped_memory); + DEFINE_PRIME11 (lime_vk_invalidate_mapped_memory); DEFINE_PRIME8 (lime_vk_create_buffer); DEFINE_PRIME7v (lime_vk_destroy_buffer); DEFINE_PRIME7 (lime_vk_get_buffer_memory_requirements); @@ -12694,6 +13533,7 @@ namespace lime { DEFINE_PRIME9 (lime_vk_allocate_descriptor_set); DEFINE_PRIME14 (lime_vk_update_descriptor_set_image); DEFINE_PRIME13 (lime_vk_update_descriptor_set_buffer); + DEFINE_PRIME6 (lime_vk_update_descriptor_sets); DEFINE_PRIME8 (lime_vk_create_pipeline_layout); DEFINE_PRIME7v (lime_vk_destroy_pipeline_layout); DEFINE_PRIME8 (lime_vk_create_pipeline_cache); @@ -12707,18 +13547,22 @@ namespace lime { DEFINE_PRIME10 (lime_vk_cmd_bind_pipeline); DEFINE_PRIME13 (lime_vk_cmd_bind_descriptor_set); DEFINE_PRIME12 (lime_vk_cmd_bind_descriptor_set_ex); + DEFINE_PRIME14 (lime_vk_cmd_bind_descriptor_set_dynamic_offset); DEFINE_PRIME12 (lime_vk_cmd_bind_vertex_buffer); DEFINE_PRIME12 (lime_vk_cmd_bind_index_buffer); DEFINE_PRIME13 (lime_vk_cmd_set_viewport); DEFINE_PRIME11 (lime_vk_cmd_set_scissor); DEFINE_PRIME11 (lime_vk_cmd_draw); DEFINE_PRIME12 (lime_vk_cmd_draw_indexed); + DEFINE_PRIME13 (lime_vk_cmd_draw_indirect); + DEFINE_PRIME13 (lime_vk_cmd_draw_indexed_indirect); DEFINE_PRIME12 (lime_vk_cmd_copy_buffer); DEFINE_PRIME12 (lime_vk_cmd_copy_buffer_to_image_region); DEFINE_PRIME12 (lime_vk_cmd_copy_image_to_buffer_region); DEFINE_PRIME10 (lime_vk_cmd_pipeline_barrier_image); DEFINE_PRIME12 (lime_vk_cmd_clear_color_image); DEFINE_PRIME11 (lime_vk_cmd_clear_depth_stencil_image); + DEFINE_PRIME9 (lime_vk_cmd_clear_attachments); DEFINE_PRIME12 (lime_vk_cmd_blit_image); DEFINE_PRIME11 (lime_vk_cmd_push_constants); DEFINE_PRIME0 (lime_vk_get_last_error); diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index d543f2f19f..a706695109 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -427,6 +427,21 @@ class NativeCFFI @:cffi private static function lime_vk_download_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + @:cffi private static function lime_vk_map_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_unmap_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int):Void; + + @:cffi private static function lime_vk_write_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + + @:cffi private static function lime_vk_flush_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; + + @:cffi private static function lime_vk_invalidate_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; + @:cffi private static function lime_vk_create_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic; @@ -526,6 +541,9 @@ class NativeCFFI @:cffi private static function lime_vk_update_descriptor_set_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool; + @:cffi private static function lime_vk_update_descriptor_sets(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + writes:Array):Bool; + @:cffi private static function lime_vk_create_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setLayouts:Array, pushConstantStages:Int, pushConstantSize:Int):Dynamic; @@ -568,6 +586,10 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_bind_descriptor_set_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, state:Array):Bool; + @:cffi private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset(handle:Dynamic, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, + dynamicOffset:Int, firstSet:Int, bindPoint:Int):Bool; + @:cffi private static function lime_vk_cmd_bind_vertex_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool; @@ -586,6 +608,13 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_draw_indexed(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, firstIndex:Int, vertexOffset:Int, firstInstance:Int):Bool; + @:cffi private static function lime_vk_cmd_draw_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw_indexed_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, + stride:Int):Bool; + @:cffi private static function lime_vk_cmd_copy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; @@ -606,6 +635,9 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_clear_depth_stencil_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array, clear:Array):Bool; + @:cffi private static function lime_vk_cmd_clear_attachments(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, state:Array, clear:Array):Bool; + @:cffi private static function lime_vk_cmd_blit_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; @@ -994,6 +1026,16 @@ class NativeCFFI "lime", "lime_vk_upload_memory", "oiiiiiiiioiib", false)); private static var lime_vk_download_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( "lime", "lime_vk_download_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_map_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_map_memory", "oiiiiiiiiiiib", false)); + private static var lime_vk_unmap_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_unmap_memory", "oiiiiiiv", false)); + private static var lime_vk_write_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_write_mapped_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_flush_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_flush_mapped_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_invalidate_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_invalidate_mapped_memory", "oiiiiiiiiiib", false)); private static var lime_vk_create_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_buffer", "oiiiiiiio", false)); private static var lime_vk_destroy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1058,6 +1100,8 @@ class NativeCFFI cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_image", "oiiiiiiiiiiiiib", false)); private static var lime_vk_update_descriptor_set_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_buffer", "oiiiiiiiiiiiib", false)); + private static var lime_vk_update_descriptor_sets = new cpp.CallableInt->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_update_descriptor_sets", "oiiiiob", false)); private static var lime_vk_create_pipeline_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_pipeline_layout", "oiiiioiio", false)); private static var lime_vk_destroy_pipeline_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1084,6 +1128,8 @@ class NativeCFFI cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set", "oiiiiiiiiiiiib", false)); private static var lime_vk_cmd_bind_descriptor_set_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_ex", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_bind_descriptor_set_dynamic_offset = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_dynamic_offset", "oiiiiiiiiiiiiib", false)); private static var lime_vk_cmd_bind_vertex_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_vertex_buffer", "oiiiiiiiiiiib", false)); private static var lime_vk_cmd_bind_index_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( @@ -1096,6 +1142,10 @@ class NativeCFFI "lime_vk_cmd_draw", "oiiiiiiiiiib", false)); private static var lime_vk_cmd_draw_indexed = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indexed", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_draw_indirect", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indexed_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( + "lime", "lime_vk_cmd_draw_indexed_indirect", "oiiiiiiiiiiiib", false)); private static var lime_vk_cmd_copy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_copy_buffer_to_image_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( @@ -1108,6 +1158,8 @@ class NativeCFFI cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_color_image", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_clear_depth_stencil_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_depth_stencil_image", "oiiiiiiiioob", false)); + private static var lime_vk_cmd_clear_attachments = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( + cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_attachments", "oiiiiiioob", false)); private static var lime_vk_cmd_blit_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( cpp.Prime._loadPrime("lime", "lime_vk_cmd_blit_image", "oiiiiiiiiiiob", false)); private static var lime_vk_cmd_push_constants = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( @@ -1358,6 +1410,11 @@ class NativeCFFI private static var lime_vk_free_memory = CFFI.load("lime", "lime_vk_free_memory", -1); private static var lime_vk_upload_memory = CFFI.load("lime", "lime_vk_upload_memory", -1); private static var lime_vk_download_memory = CFFI.load("lime", "lime_vk_download_memory", -1); + private static var lime_vk_map_memory = CFFI.load("lime", "lime_vk_map_memory", -1); + private static var lime_vk_unmap_memory = CFFI.load("lime", "lime_vk_unmap_memory", -1); + private static var lime_vk_write_mapped_memory = CFFI.load("lime", "lime_vk_write_mapped_memory", -1); + private static var lime_vk_flush_mapped_memory = CFFI.load("lime", "lime_vk_flush_mapped_memory", -1); + private static var lime_vk_invalidate_mapped_memory = CFFI.load("lime", "lime_vk_invalidate_mapped_memory", -1); private static var lime_vk_create_buffer = CFFI.load("lime", "lime_vk_create_buffer", -1); private static var lime_vk_destroy_buffer = CFFI.load("lime", "lime_vk_destroy_buffer", -1); private static var lime_vk_get_buffer_memory_requirements = CFFI.load("lime", "lime_vk_get_buffer_memory_requirements", -1); @@ -1390,6 +1447,7 @@ class NativeCFFI private static var lime_vk_allocate_descriptor_set = CFFI.load("lime", "lime_vk_allocate_descriptor_set", -1); private static var lime_vk_update_descriptor_set_image = CFFI.load("lime", "lime_vk_update_descriptor_set_image", -1); private static var lime_vk_update_descriptor_set_buffer = CFFI.load("lime", "lime_vk_update_descriptor_set_buffer", -1); + private static var lime_vk_update_descriptor_sets = CFFI.load("lime", "lime_vk_update_descriptor_sets", -1); private static var lime_vk_create_pipeline_layout = CFFI.load("lime", "lime_vk_create_pipeline_layout", -1); private static var lime_vk_destroy_pipeline_layout = CFFI.load("lime", "lime_vk_destroy_pipeline_layout", -1); private static var lime_vk_create_pipeline_cache = CFFI.load("lime", "lime_vk_create_pipeline_cache", -1); @@ -1403,18 +1461,22 @@ class NativeCFFI private static var lime_vk_cmd_bind_pipeline = CFFI.load("lime", "lime_vk_cmd_bind_pipeline", -1); private static var lime_vk_cmd_bind_descriptor_set = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set", -1); private static var lime_vk_cmd_bind_descriptor_set_ex = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set_ex", -1); + private static var lime_vk_cmd_bind_descriptor_set_dynamic_offset = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set_dynamic_offset", -1); private static var lime_vk_cmd_bind_vertex_buffer = CFFI.load("lime", "lime_vk_cmd_bind_vertex_buffer", -1); private static var lime_vk_cmd_bind_index_buffer = CFFI.load("lime", "lime_vk_cmd_bind_index_buffer", -1); private static var lime_vk_cmd_set_viewport = CFFI.load("lime", "lime_vk_cmd_set_viewport", -1); private static var lime_vk_cmd_set_scissor = CFFI.load("lime", "lime_vk_cmd_set_scissor", -1); private static var lime_vk_cmd_draw = CFFI.load("lime", "lime_vk_cmd_draw", -1); private static var lime_vk_cmd_draw_indexed = CFFI.load("lime", "lime_vk_cmd_draw_indexed", -1); + private static var lime_vk_cmd_draw_indirect = CFFI.load("lime", "lime_vk_cmd_draw_indirect", -1); + private static var lime_vk_cmd_draw_indexed_indirect = CFFI.load("lime", "lime_vk_cmd_draw_indexed_indirect", -1); private static var lime_vk_cmd_copy_buffer = CFFI.load("lime", "lime_vk_cmd_copy_buffer", -1); private static var lime_vk_cmd_copy_buffer_to_image_region = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image_region", -1); private static var lime_vk_cmd_copy_image_to_buffer_region = CFFI.load("lime", "lime_vk_cmd_copy_image_to_buffer_region", -1); private static var lime_vk_cmd_pipeline_barrier_image = CFFI.load("lime", "lime_vk_cmd_pipeline_barrier_image", -1); private static var lime_vk_cmd_clear_color_image = CFFI.load("lime", "lime_vk_cmd_clear_color_image", -1); private static var lime_vk_cmd_clear_depth_stencil_image = CFFI.load("lime", "lime_vk_cmd_clear_depth_stencil_image", -1); + private static var lime_vk_cmd_clear_attachments = CFFI.load("lime", "lime_vk_cmd_clear_attachments", -1); private static var lime_vk_cmd_blit_image = CFFI.load("lime", "lime_vk_cmd_blit_image", -1); private static var lime_vk_cmd_push_constants = CFFI.load("lime", "lime_vk_cmd_push_constants", -1); #end @@ -2215,6 +2277,37 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_map_memory") private static function lime_vk_map_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, + sizeLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_unmap_memory") private static function lime_vk_unmap_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} + + @:hlNative("lime", "hl_vk_write_mapped_memory") private static function lime_vk_write_mapped_memory(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, + bytes:Bytes, byteOffset:Int, byteLength:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_flush_mapped_memory") private static function lime_vk_flush_mapped_memory(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, + sizeHigh:Int, sizeLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_invalidate_mapped_memory") private static function lime_vk_invalidate_mapped_memory(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, + sizeHigh:Int, sizeLow:Int):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_create_buffer") private static function lime_vk_create_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic { @@ -2388,6 +2481,12 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_update_descriptor_sets") private static function lime_vk_update_descriptor_sets(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, writes:hl.NativeArray):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_create_pipeline_layout") private static function lime_vk_create_pipeline_layout(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setLayouts:hl.NativeArray, pushConstantStages:Int, pushConstantSize:Int):Dynamic @@ -2465,6 +2564,13 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set_dynamic_offset") private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset( + handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, + layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, dynamicOffset:Int, firstSet:Int, bindPoint:Int):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_cmd_bind_vertex_buffer") private static function lime_vk_cmd_bind_vertex_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool @@ -2507,6 +2613,20 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_cmd_draw_indirect") private static function lime_vk_cmd_draw_indirect(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, + offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_cmd_draw_indexed_indirect") private static function lime_vk_cmd_draw_indexed_indirect(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, + bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_cmd_copy_buffer") private static function lime_vk_cmd_copy_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool @@ -2549,6 +2669,13 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_vk_cmd_clear_attachments") private static function lime_vk_cmd_clear_attachments(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, + state:hl.NativeArray, clear:hl.NativeArray):Bool + { + return false; + } + @:hlNative("lime", "hl_vk_cmd_blit_image") private static function lime_vk_cmd_blit_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool diff --git a/src/lime/graphics/vulkan/VKBuffer.hx b/src/lime/graphics/vulkan/VKBuffer.hx index 2fbeb81a73..de31962199 100644 --- a/src/lime/graphics/vulkan/VKBuffer.hx +++ b/src/lime/graphics/vulkan/VKBuffer.hx @@ -116,6 +116,34 @@ class VKBuffer return !VK.__isZero(handle); } + public function map(offset:Int64 = null, size:Int64 = null, flags:Int = 0):Bool + { + return memory != null && memory.map(offset, size, flags); + } + + public function unmap():Void + { + if (memory != null) + { + memory.unmap(); + } + } + + public function writeBytes(bytes:Bytes, srcOffset:Int = 0, length:Int = -1, dstOffset:Int64 = null):Bool + { + return memory != null && memory.writeBytes(bytes, srcOffset, length, dstOffset); + } + + public function flush(offset:Int64 = null, size:Int64 = null):Bool + { + return memory != null && memory.flush(offset, size); + } + + public function invalidate(offset:Int64 = null, size:Int64 = null):Bool + { + return memory != null && memory.invalidate(offset, size); + } + public function upload(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool { return memory != null && memory.upload(bytes, memoryOffset, byteOffset, byteLength); diff --git a/src/lime/graphics/vulkan/VKCommandBuffer.hx b/src/lime/graphics/vulkan/VKCommandBuffer.hx index 375748ca99..12638f2e2a 100644 --- a/src/lime/graphics/vulkan/VKCommandBuffer.hx +++ b/src/lime/graphics/vulkan/VKCommandBuffer.hx @@ -95,6 +95,21 @@ class VKCommandBuffer return false; } + public function bindDescriptorSetDynamicOffset(layout:VKPipelineLayout, descriptorSet:VKDescriptorSet, dynamicOffset:Int, firstSet:Int = 0, + bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout != null && layout.isValid() && descriptorSet != null && descriptorSet.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_descriptor_set_dynamic_offset(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, + descriptorSet.handle.high, descriptorSet.handle.low, dynamicOffset, firstSet, bindPoint); + } + #end + + return false; + } + public function bindIndexBuffer(buffer:VKBuffer, offset:Int64 = null, indexType:Int = VK.INDEX_TYPE_UINT16):Bool { if (offset == null) @@ -231,6 +246,23 @@ class VKCommandBuffer return false; } + public function clearAttachments(color:Bool, depth:Bool, stencil:Bool, x:Int, y:Int, width:Int, height:Int, red:Float = 0, + green:Float = 0, blue:Float = 0, alpha:Float = 0, depthValue:Float = 1, stencilValue:Int = 0):Bool + { + var state = [color ? 1 : 0, depth ? 1 : 0, stencil ? 1 : 0, x, y, width, height, stencilValue]; + var clear = [red, green, blue, alpha, depthValue]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_clear_attachments(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, state, clear); + } + #end + + return false; + } + public function copyBuffer(source:VKBuffer, destination:VKBuffer, size:Int64, sourceOffset:Int64 = null, destinationOffset:Int64 = null):Bool { if (sourceOffset == null) sourceOffset = Int64.ofInt(0); @@ -353,6 +385,34 @@ class VKCommandBuffer return false; } + public function drawIndirect(buffer:VKBuffer, offset:Int64, drawCount:Int, stride:Int):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw_indirect(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + offset.high, offset.low, drawCount, stride); + } + #end + + return false; + } + + public function drawIndexedIndirect(buffer:VKBuffer, offset:Int64, drawCount:Int, stride:Int):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw_indexed_indirect(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + offset.high, offset.low, drawCount, stride); + } + #end + + return false; + } + public function end():Bool { #if (!macro && lime_cffi && lime_vulkan) diff --git a/src/lime/graphics/vulkan/VKDescriptorWrite.hx b/src/lime/graphics/vulkan/VKDescriptorWrite.hx new file mode 100644 index 0000000000..5768a76244 --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorWrite.hx @@ -0,0 +1,115 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +/** + A single descriptor write used by `VKDevice.updateDescriptorSets()`. +**/ +class VKDescriptorWrite +{ + private static inline var KIND_BUFFER = 0; + private static inline var KIND_IMAGE = 1; + + public var arrayElement:Int; + public var binding:Int; + public var buffer:VKBuffer; + public var descriptorSet:VKDescriptorSet; + public var descriptorType:Int; + public var imageLayout:Int; + public var imageView:VKImageView; + public var offset:Int64; + public var range:Int64; + public var sampler:VKSampler; + + private var kind:Int; + + public function new() + { + arrayElement = 0; + binding = 0; + descriptorType = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER; + imageLayout = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + kind = KIND_BUFFER; + offset = Int64.ofInt(0); + range = Int64.ofInt(0); + } + + public static function forBuffer(descriptorSet:VKDescriptorSet, binding:Int, buffer:VKBuffer, range:Int64 = null, + offset:Int64 = null, descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, arrayElement:Int = 0):VKDescriptorWrite + { + var write = new VKDescriptorWrite(); + write.kind = KIND_BUFFER; + write.descriptorSet = descriptorSet; + write.binding = binding; + write.buffer = buffer; + write.range = range != null ? range : Int64.ofInt(0); + write.offset = offset != null ? offset : Int64.ofInt(0); + write.descriptorType = descriptorType; + write.arrayElement = arrayElement; + return write; + } + + public static function forImage(descriptorSet:VKDescriptorSet, binding:Int, imageView:VKImageView, sampler:VKSampler = null, + imageLayout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arrayElement:Int = 0):VKDescriptorWrite + { + var write = new VKDescriptorWrite(); + write.kind = KIND_IMAGE; + write.descriptorSet = descriptorSet; + write.binding = binding; + write.imageView = imageView; + write.sampler = sampler; + write.imageLayout = imageLayout; + write.descriptorType = descriptorType; + write.arrayElement = arrayElement; + return write; + } + + @:allow(lime.graphics.vulkan.VKDevice) + private function pack(result:Array):Bool + { + if (descriptorSet == null || !descriptorSet.isValid()) + { + return false; + } + + if (kind == KIND_IMAGE) + { + if (imageView == null || !imageView.isValid()) + { + return false; + } + var samplerHandle = (sampler != null && sampler.isValid()) ? sampler.handle : Int64.ofInt(0); + result.push(KIND_IMAGE); + result.push(descriptorSet.handle.high); + result.push(descriptorSet.handle.low); + result.push(binding); + result.push(arrayElement); + result.push(descriptorType); + result.push(imageView.handle.high); + result.push(imageView.handle.low); + result.push(samplerHandle.high); + result.push(samplerHandle.low); + result.push(imageLayout); + return true; + } + + if (buffer == null || !buffer.isValid()) + { + return false; + } + result.push(KIND_BUFFER); + result.push(descriptorSet.handle.high); + result.push(descriptorSet.handle.low); + result.push(binding); + result.push(arrayElement); + result.push(descriptorType); + result.push(buffer.handle.high); + result.push(buffer.handle.low); + result.push(offset.high); + result.push(offset.low); + result.push(range.high); + result.push(range.low); + return true; + } +} diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx index 2d20ab4d0d..28e375114e 100644 --- a/src/lime/graphics/vulkan/VKDevice.hx +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -151,6 +151,12 @@ class VKDevice VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, bytes); } + public inline function createUploadRing(byteCapacity:Int, usage:Int = VK.BUFFER_USAGE_TRANSFER_SRC_BIT, + properties:Int = VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT):VKUploadRing + { + return new VKUploadRing(this, byteCapacity, usage, properties); + } + public inline function createStorageBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer { return createBufferWithMemory(size, VK.BUFFER_USAGE_STORAGE_BUFFER_BIT, properties, bytes); @@ -224,6 +230,33 @@ class VKDevice return null; } + public function updateDescriptorSets(writes:Array):Bool + { + if (writes == null || writes.length == 0) + { + return true; + } + + var packed = [writes.length]; + for (write in writes) + { + if (write == null || !write.pack(packed)) + { + return false; + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + return NativeCFFI.lime_vk_update_descriptor_sets(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, packed); + } + #end + + return false; + } + public function createFramebuffer(renderPass:VKRenderPass, attachments:Array, width:Int, height:Int, layers:Int = 1):VKFramebuffer { if (renderPass == null || !renderPass.isValid() || attachments == null || attachments.length == 0) diff --git a/src/lime/graphics/vulkan/VKDeviceMemory.hx b/src/lime/graphics/vulkan/VKDeviceMemory.hx index 101b09ad20..39dc6ad5ee 100644 --- a/src/lime/graphics/vulkan/VKDeviceMemory.hx +++ b/src/lime/graphics/vulkan/VKDeviceMemory.hx @@ -17,6 +17,9 @@ class VKDeviceMemory public var device(default, null):VKDevice; public var handle(default, null):Int64; public var memoryTypeIndex(default, null):Int; + public var mapped(default, null):Bool = false; + public var mappedOffset(default, null):Int64 = Int64.ofInt(0); + public var mappedSize(default, null):Int64 = Int64.ofInt(0); public var properties(default, null):Int; public var size(default, null):Int64; @@ -32,6 +35,11 @@ class VKDeviceMemory public function dispose():Void { + if (mapped) + { + unmap(); + } + #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { @@ -52,6 +60,140 @@ class VKDeviceMemory return !VK.__isZero(handle); } + /** + Maps host-visible memory and keeps it mapped for repeated writes or + readback. Passing `size` as `null` maps the rest of the allocation. + **/ + public function map(offset:Int64 = null, size:Int64 = null, flags:Int = 0):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + if (size == null) + { + size = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var result = NativeCFFI.lime_vk_map_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, + size.low, flags); + if (result) + { + mapped = true; + mappedOffset = offset; + mappedSize = size; + } + return result; + } + #end + + return false; + } + + public function unmap():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (mapped && isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_unmap_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + mapped = false; + mappedOffset = Int64.ofInt(0); + mappedSize = Int64.ofInt(0); + } + + /** + Copies bytes into a currently mapped range without unmapping. This is the + hot-path companion to `upload()` for dynamic vertex/uniform streaming. + **/ + public function writeBytes(bytes:Bytes, srcOffset:Int = 0, length:Int = -1, dstOffset:Int64 = null):Bool + { + if (bytes == null || !mapped) + { + return false; + } + if (dstOffset == null) + { + dstOffset = mappedOffset; + } + if (length < 0) + { + length = bytes.length - srcOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_write_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, dstOffset.high, dstOffset.low, bytes, + srcOffset, length); + } + #end + + return false; + } + + public function flush(offset:Int64 = null, size:Int64 = null):Bool + { + if (!mapped) + { + return false; + } + if (offset == null) + { + offset = mappedOffset; + } + if (size == null) + { + size = mappedSize; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_flush_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, + size.low); + } + #end + + return false; + } + + public function invalidate(offset:Int64 = null, size:Int64 = null):Bool + { + if (!mapped) + { + return false; + } + if (offset == null) + { + offset = mappedOffset; + } + if (size == null) + { + size = mappedSize; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_invalidate_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, + size.low); + } + #end + + return false; + } + /** Copies bytes into host-visible memory. This maps and unmaps internally, which is convenient for staging/uniform data and avoids exposing unsafe diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx index fd390ae95f..c05a23fc4f 100644 --- a/src/lime/graphics/vulkan/VKPhysicalDevice.hx +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -28,6 +28,10 @@ class VKPhysicalDevice public var framebufferNoAttachmentsSampleCounts(default, null):Int; public var framebufferStencilSampleCounts(default, null):Int; public var isDiscrete(default, null):Bool; + public var maxPushConstantsSize(default, null):Int; + public var minStorageBufferOffsetAlignment(default, null):Int64; + public var minUniformBufferOffsetAlignment(default, null):Int64; + public var nonCoherentAtomSize(default, null):Int64; public var supportsPresent(default, null):Bool; public var queueFamilies(default, null):Array; @@ -47,6 +51,10 @@ class VKPhysicalDevice framebufferDepthSampleCounts = data.framebufferDepthSampleCounts; framebufferNoAttachmentsSampleCounts = data.framebufferNoAttachmentsSampleCounts; framebufferStencilSampleCounts = data.framebufferStencilSampleCounts; + maxPushConstantsSize = data.maxPushConstantsSize; + minStorageBufferOffsetAlignment = VK.__makeHandle(data.minStorageBufferOffsetAlignment); + minUniformBufferOffsetAlignment = VK.__makeHandle(data.minUniformBufferOffsetAlignment); + nonCoherentAtomSize = VK.__makeHandle(data.nonCoherentAtomSize); deviceTypeName = switch (deviceType) { case 1: "integrated-gpu"; diff --git a/src/lime/graphics/vulkan/VKUploadRing.hx b/src/lime/graphics/vulkan/VKUploadRing.hx new file mode 100644 index 0000000000..772c7f6933 --- /dev/null +++ b/src/lime/graphics/vulkan/VKUploadRing.hx @@ -0,0 +1,106 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; + +/** + A persistently mapped host-visible ring buffer for staging dynamic uploads. +**/ +class VKUploadRing +{ + public var buffer(default, null):VKBuffer; + public var byteCapacity(default, null):Int; + public var device(default, null):VKDevice; + public var frameIndex(default, null):Int = 0; + public var head(default, null):Int = 0; + + public function new(device:VKDevice, byteCapacity:Int, usage:Int = VK.BUFFER_USAGE_TRANSFER_SRC_BIT, + properties:Int = VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT) + { + this.device = device; + this.byteCapacity = byteCapacity; + + if (device != null && byteCapacity > 0) + { + buffer = device.createBufferWithMemory(Int64.ofInt(byteCapacity), usage | VK.BUFFER_USAGE_TRANSFER_SRC_BIT, properties); + if (buffer != null && !buffer.map(Int64.ofInt(0), Int64.ofInt(byteCapacity))) + { + buffer.dispose(true); + buffer = null; + } + } + } + + public function beginFrame(frameIndex:Int):Void + { + this.frameIndex = frameIndex; + head = 0; + } + + public function reserve(byteCount:Int, alignment:Int):VKUploadSlice + { + if (!isValid() || byteCount <= 0) + { + return null; + } + if (alignment <= 0) + { + alignment = 1; + } + + var aligned = __align(head, alignment); + if (aligned + byteCount > byteCapacity) + { + return null; + } + + head = aligned + byteCount; + return new VKUploadSlice(buffer, Int64.ofInt(aligned), byteCount, frameIndex); + } + + public function writeBytes(slice:VKUploadSlice, bytes:Bytes, srcOffset:Int = 0, length:Int = -1):Bool + { + if (slice == null || slice.buffer != buffer || bytes == null) + { + return false; + } + if (length < 0) + { + length = bytes.length - srcOffset; + } + if (length < 0 || length > slice.size) + { + return false; + } + return buffer.writeBytes(bytes, srcOffset, length, slice.offset); + } + + public function flush():Bool + { + return isValid() ? buffer.flush(Int64.ofInt(0), Int64.ofInt(0)) : false; + } + + public function invalidate():Bool + { + return isValid() ? buffer.invalidate(Int64.ofInt(0), Int64.ofInt(0)) : false; + } + + public function dispose():Void + { + if (buffer != null) + { + buffer.dispose(true); + buffer = null; + } + } + + public inline function isValid():Bool + { + return buffer != null && buffer.isValid(); + } + + private inline function __align(value:Int, alignment:Int):Int + { + return Std.int((value + alignment - 1) / alignment) * alignment; + } +} diff --git a/src/lime/graphics/vulkan/VKUploadSlice.hx b/src/lime/graphics/vulkan/VKUploadSlice.hx new file mode 100644 index 0000000000..b0d9b0d8c9 --- /dev/null +++ b/src/lime/graphics/vulkan/VKUploadSlice.hx @@ -0,0 +1,23 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +/** + A reserved range in a `VKUploadRing`. +**/ +class VKUploadSlice +{ + public var buffer(default, null):VKBuffer; + public var frameIndex(default, null):Int; + public var offset(default, null):Int64; + public var size(default, null):Int; + + @:allow(lime.graphics.vulkan.VKUploadRing) + private function new(buffer:VKBuffer, offset:Int64, size:Int, frameIndex:Int) + { + this.buffer = buffer; + this.offset = offset; + this.size = size; + this.frameIndex = frameIndex; + } +} From 9fe4452ca93e2c3a7a0d836132d5a4691467b325 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 26 May 2026 08:01:53 -0400 Subject: [PATCH 20/76] Vulkan: cache device proc addresses Add managedVulkanDeviceProcCache to store PFN_vkVoidFunction lookups per VkDevice and a ClearManagedVulkanDeviceProcCache helper. --- project/src/ExternalInterface.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index e5673f0ea0..dc906f4c13 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -149,6 +149,7 @@ namespace lime { static std::unordered_map mappedVulkanMemory; + static std::unordered_map > managedVulkanDeviceProcCache; static uint64_t GetManagedVulkanMappedMemoryKey (VkDeviceMemory memory) { @@ -165,6 +166,13 @@ namespace lime { } + static void ClearManagedVulkanDeviceProcCache (VkDevice device) { + + if (device) managedVulkanDeviceProcCache.erase ((uint64_t)(uintptr_t)device); + + } + + static bool CreateManagedVulkanInstance (Window* targetWindow, const char* applicationName, VkInstance* outInstance) { if (!targetWindow || !outInstance) { @@ -356,13 +364,24 @@ namespace lime { static PFN_vkVoidFunction GetManagedVulkanDeviceProc (Window* targetWindow, VkInstance instance, VkDevice device, const char* name) { - if (!targetWindow || !instance || !device) { + if (!targetWindow || !instance || !device || !name) { lastVKError = "Missing Vulkan window, instance, or device"; return 0; } + uint64_t deviceKey = (uint64_t)(uintptr_t)device; + std::string procName (name); + std::unordered_map >::iterator deviceCache = + managedVulkanDeviceProcCache.find (deviceKey); + if (deviceCache != managedVulkanDeviceProcCache.end ()) { + + std::unordered_map::iterator procCache = deviceCache->second.find (procName); + if (procCache != deviceCache->second.end ()) return procCache->second; + + } + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); if (!vkGetInstanceProcAddr) { @@ -379,14 +398,15 @@ namespace lime { } - PFN_vkVoidFunction proc = vkGetDeviceProcAddr (device, name); + PFN_vkVoidFunction proc = vkGetDeviceProcAddr (device, procName.c_str ()); if (!proc) { - lastVKError = std::string ("Missing Vulkan device function: ") + name; + lastVKError = std::string ("Missing Vulkan device function: ") + procName; return 0; } + managedVulkanDeviceProcCache[deviceKey][procName] = proc; return proc; } @@ -5376,6 +5396,7 @@ namespace lime { PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); if (vkDestroyDevice) { + ClearManagedVulkanDeviceProcCache (device); vkDestroyDevice (device, 0); } @@ -5402,6 +5423,7 @@ namespace lime { PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); if (vkDestroyDevice) { + ClearManagedVulkanDeviceProcCache (device); vkDestroyDevice (device, 0); } From c653ae33be5a3f1bec62e24b6f9a891ee5973ff8 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 27 May 2026 03:22:23 -0400 Subject: [PATCH 21/76] Vulkan: Android support First pass --- .github/workflows/main.yml | 5 +++++ project/Build.xml | 2 +- src/lime/tools/ProjectXMLParser.hx | 8 +++++++- .../android/template/app/src/main/AndroidManifest.xml | 4 ++++ tools/platforms/AndroidPlatform.hx | 3 +++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5aa78cd755..24efa86ab4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -538,6 +538,11 @@ jobs: run: | lime create SimpleAudio -verbose -nocolor -eval lime build SimpleAudio android -release -verbose -nocolor -eval + + - name: Build Vulkan smoke test app + working-directory: tests/vulkan-smoke + run: | + lime build android -release -verbose -nocolor -eval ios: runs-on: macos-14 steps: diff --git a/project/Build.xml b/project/Build.xml index 8924eb073d..28a39cd0b6 100755 --- a/project/Build.xml +++ b/project/Build.xml @@ -36,7 +36,7 @@ - + diff --git a/src/lime/tools/ProjectXMLParser.hx b/src/lime/tools/ProjectXMLParser.hx index 63ca4d5bb6..faa9d6ae10 100644 --- a/src/lime/tools/ProjectXMLParser.hx +++ b/src/lime/tools/ProjectXMLParser.hx @@ -1985,7 +1985,13 @@ class ProjectXMLParser extends HXProject Reflect.setField(windows[id], name, Std.string(value)); case "render-type", "context-type": - Reflect.setField(windows[id], "renderType", Std.string(value).toLowerCase()); + var renderType = Std.string(value).toLowerCase(); + Reflect.setField(windows[id], "renderType", renderType); + if (renderType == "vulkan") + { + defines.set("lime-vulkan", ""); + haxedefs.set("lime-vulkan", ""); + } case "allow-high-dpi": Reflect.setField(windows[id], "allowHighDPI", value == "true"); diff --git a/templates/android/template/app/src/main/AndroidManifest.xml b/templates/android/template/app/src/main/AndroidManifest.xml index ed3640a1f5..c435998b5d 100644 --- a/templates/android/template/app/src/main/AndroidManifest.xml +++ b/templates/android/template/app/src/main/AndroidManifest.xml @@ -1,7 +1,11 @@ + ::if ANDROID_VULKAN:: + + ::else:: + ::end:: ::foreach ANDROID_PERMISSIONS:: diff --git a/tools/platforms/AndroidPlatform.hx b/tools/platforms/AndroidPlatform.hx index ebdad5f110..91057bc452 100644 --- a/tools/platforms/AndroidPlatform.hx +++ b/tools/platforms/AndroidPlatform.hx @@ -441,6 +441,9 @@ class AndroidPlatform extends PlatformTarget context.ANDROID_ENABLE_JETIFIER = project.config.getString("android.enableJetifier", "false"); context.ANDROID_GRADLE_PROPERTIES = project.config.getKeyValueArray("android.gradle-properties"); context.ANDROID_DISPLAY_CUTOUT = project.config.getString("android.layoutInDisplayCutoutMode", "default"); + context.ANDROID_VULKAN = project.window.renderType != null && project.window.renderType.toLowerCase() == "vulkan"; + context.ANDROID_VULKAN_REQUIRED = project.config.getBool("android.vulkan-required", true); + context.ANDROID_VULKAN_VERSION = project.config.getString("android.vulkan-version", "0x400003"); context.ANDROID_MANIFEST = project.config.getKeyValueArray("android.manifest", { "android:versionCode": project.meta.buildNumber, From 88769f618053a05b33206149a96601fa7a7944b7 Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Fri, 29 May 2026 14:00:18 -0700 Subject: [PATCH 22/76] Window: updated gamepad mappings from: https://github.com/gabomdq/SDL_GameControllerDB/ Seems to have been a while. Last commit for mappings in Lime that I found was: 314e0204283dfebe463ec909b28b6c26f2ca93a0 --- src/lime/ui/Window.hx | 2412 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 2230 insertions(+), 182 deletions(-) diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index b53f65b2af..b9ce4fdd22 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -241,203 +241,2251 @@ class Window if (id != -1 && application != null) application.__seedFrameConfiguration(__attributes); #if windows var mappings = [ - "8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", - "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", - "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", - "0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", - "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows", - "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows", - "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows", - "4c05c405000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows", - "4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows", - "4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows", - "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13", - "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows", - "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows", - "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows", - "28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7", - "ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9", - "8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5", - "79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows", - "4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows", - "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows", - "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows", - - "10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows", - - "4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows", - "0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - - "2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows", - "10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows", - "63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8", - "02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8", - "ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11", - "341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows", - "c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1", - "100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows", - "79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows" + "03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", + "03000000fa190000918d000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", + "03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows", + "03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000060d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000070d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000c82d00001930000000000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows", + "03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows", + "03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows", + "03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00002090000000000000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows", + "03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows", + "03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows", + "03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows", + "03000000c82d00006928000000000000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows", + "03000000c82d00002590000000000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows", + "03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000131000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows", + "03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001130000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001330000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001260000000000000,8BitDo Ultimate 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001c30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows", + "030000006f0e00008801000000000000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows", + "0300000008100000e501000000000000,Anbernic Game Pad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000020500000913000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500000710000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500004610000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000190e00000110000000000000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Windows", + "03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows", + "03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000006a0e00001140000000000000,Atari CX Controller,a:b0,leftx:a0,lefty:a1,platform:Windows", + "03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows", + "03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows", + "03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "030000008a3500000402000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows", + "030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows", + "030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "030000000d0500000308000000000000,Belkin Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows", + "03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000000055000000000000,Betop BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000790000000700000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000808300000300000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows", + "030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows", + "030000005a1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows", + "030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows", + "030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows", + "030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows", + "030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows", + "030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000a306000022f6000000000000,Cyborg V.3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows", + "030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000151a00006222000000000000,Dual Plus PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows", + "030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows", + "03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows", + "030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000bc2000000091000000000000,EasySMX Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows", + "03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "03000095090000010000000000000000,Elecom JC-U609,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows", + "0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows", + "03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows", + "030000006e0500000520000000000000,Elecom P301U PlayStation Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "03000000250900000218000000000000,Elecom PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows", + "03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000062000001801000000000000,EMS TrioLinker Plus II,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Windows", + "03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows", + "03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00008101000000000000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows", + "03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows", + "03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows", + "03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows", + "03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows", + "03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows", + "0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows", + "03000000790000004618000000000000,GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows", + "03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows", + "03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows", + "03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000ac0500004d04000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500002210000000000000,GameSir G7 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000ac0500001a06000000000000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500000410000000000000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000373500009410000000000000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows", + "030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d11800000094000000000000,Google Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows", + "030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows", + "030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows", + "03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000008a2e0000dd10000000000000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Windows", + "030000008a2e0000df10000000000000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Windows", + "030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows", + "030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows", + "03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006201000000000000,Hori Fighting Commander Octa,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006401000000000000,Hori Fighting Commander Octa,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00008800000000000000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows", + "030000000d0f00008700000000000000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows", + "030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows", + "030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows", + "030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002301000000000000,Hori PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "030000000d0f00001100000000000000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000000d0f00000202000000000000,Horipad O Nintendo Switch 2 Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc2:b2,paddle1:b5,paddle2:b15,paddle3:b18,paddle4:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows", + "03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows", + "03000000790000004e95000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows", + "03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows", + "03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000242e00000a20000000000000,Hyperkin Scout Premium SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows", + "03000000f00300008d04000000000000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:-a2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:+a5,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows", + "03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows", + "03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows", + "03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows", + "03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows", + "03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows", + "03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows", + "03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows", + "03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows", + "03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows", + "03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows", + "030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows", + "030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows", + "03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000008b0100002301000000000000,Joytech JS-112,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a2,lefty:a3,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a0,righty:a1,start:b9,x:b0,y:b1,platform:Windows", + "03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows", + "03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows", + "03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows", + "03000000c4ac00001c80000000000000,KidzPlay Adventure PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows", + "030000006d04000011c2000000000000,Logitech WingMan Cordless,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows", + "030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows", + "03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700008031000000000000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows", + "030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000008f0e00001330000000000000,Mayflash Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows", + "03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000004318000000000000,Mayflash GameCube Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows", + "0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000242f0000f400000000000000,Mayflash N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows", + "03000000242f0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows", + "03000000790000007918000000000000,Mayflash N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows", + "030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows", + "0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows", + "030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows", + "030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows", + "030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows", + "03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows", + "03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000004523000015e0000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000491900000904000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows", + "03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows", + "03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows", + "03000000c9110000f055000000000000,Nacon GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000c21100000791000000000000,Nacon GC101 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006b140000010c000000000000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "0300000085320000190d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows", + "0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows", + "03000000921200004b46000000000000,NES Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows", + "03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows", + "03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows", + "03000000790000004518000000000000,NEXiLUX GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows", + "03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows", + "03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000ec110000e1a7000000000000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows", + "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000007e0500007320000000000000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Windows", + "030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows", + "030000007e0500001720000000000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Windows", + "03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows", + "03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows", + "030000005509000000b4000000000000,NVIDIA Virtual,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000004b120000014d000000000000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c00000288000000000000,Nyko Airflo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows", + "030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows", + "03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00008901000000000000,PDP Realmz Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows", + "03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d620000013a7000000000000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d62000002640000000000000,PowerA OPS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000d62000003340000000000000,PowerA OPS Pro Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000250900000088000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows", + "030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows", + "030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows", + "03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows", + "030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows", + "03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c0500005f0e000000000000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows", + "03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows", + "03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows", + "03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows", + "03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows", + "03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows", + "030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows", + "030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows", + "030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows", + "030000009b280000d000000000000000,Raphnet Dreamcast Adapter,a:b1,b:b0,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,lefttrigger:+a5,leftx:a0,lefty:a1,righttrigger:+a2,start:b3,x:b5,y:b4,platform:Windows", + "030000009b2800006200000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows", + "030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows", + "030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows", + "030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows", + "030000009b2800003c00000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800006100000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800006400000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows", + "030000009b2800004400000000000000,Raphnet PlayStation Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows", + "030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows", + "030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "030000009b2800002600000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800002e00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800002f00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows", + "030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows", + "03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "0300000032150000a602000000000000,Razer Huntsman V3 Pro,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows", + "03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000921200004547000000000000,Retro Bit Sega Genesis Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows", + "03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows", + "03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000632500007805000000000000,Retro Fighters Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows", + "03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Windows", + "0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows", + "0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows", + "03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows", + "030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00008701000000000000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000830500000052000000000000,Rockfire CosmoVoyager,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b10,leftshoulder:b6,lefttrigger:b7,misc1:b11,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000830500007030000000000000,Rockfire Space Ranger,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b9,righttrigger:b8,start:b2,x:b3,y:b4,platform:Windows", + "03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b0000181a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows", + "030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001311000000000000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows", + "03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000a306000023f6000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows", + "03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows", + "03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows", + "03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows", + "03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001001000000000000,Saitek P480 Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows", + "03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000a30600002106000000000000,Saitek PS1000 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Windows", + "03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows", + "03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows", + "03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows", + "03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows", + "030000009d0d00001130000000000000,Sanwa PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows", + "03000000630600000201000000000000,Sanwa Virtua Grip,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,x:b0,y:b1,platform:Windows", + "03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows", + "03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,leftshoulder:b6,lefttrigger:b7,back:b8,start:b9,x:b3,y:b0,platform:Windows", + "03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows", + "0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows", + "03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows", + "03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows", + "03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows", + "03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows", + "03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows", + "03000000d9040000160f000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000fe1400002a23000000000000,Sony PlayStation Adapter,a:b0,b:b1,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,x:b2,y:b3,platform:Windows", + "030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows", + "03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows", + "030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows", + "03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows", + "030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows", + "03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows", + "030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000e40a00000307000000000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows", + "03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows", + "03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows", + "03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows", + "03000000790000001c18000000000000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000790000002601000000000000,TGZ Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows", + "030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f0400000ed0000000000000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows", + "030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000004f04000003d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:-a3,leftx:a0,lefty:a1,paddle1:b6,paddle2:b7,rightshoulder:b5,rightstick:b11,righttrigger:-a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f04000008d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f04000009d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000011000000200000000000000,ThundeRobot G30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000571d00002100000000000000,Tomee NES Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows", + "03000000571d00002000000000000000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d60600002a00000000000000,Trust 850F,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows", + "030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows", + "03000000580400000a10000000000000,Trust Sight Fighter,a:b0,b:b1,x:b3,y:b4,back:b5,start:b2,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b8,righttrigger:b9,platform:Windows", + "030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows", + "03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows", + "03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows", + "03000000300f00000701000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000341a00002308000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000666600000188000000000000,USB Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000006b1400000203000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000790000000a00000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000b404000081c6000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000b50700001503000000000000,USB Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000882800000305000000000000,V5 Game Pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,x:b2,y:b3,platform:Windows", + "03000000790000001a18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000001b18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows", + "03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows", + "03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000a102000000000000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows", + "03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000450c00002043000000000000,Xeox SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000e0ff00000201000000000000,Xiaomi Black Shark (L),back:b0,dpdown:b11,dpleft:b9,dpright:b10,dpup:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,platform:Windows", + "03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000c0160000e105000000000000,XinMo Dual Arcade,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows", + "030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows", + "03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000073500000400000000000000,Zenaim Arcade Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", + "03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", ]; Gamepad.addMappings(mappings); #elseif mac var mappings = [ - "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", - "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", - "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", - "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", - "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", - "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", - "4c05000000000000c405000000000000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X", - "4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X", - "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", - "891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X", - "4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X", - "8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X", - "4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - - "AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", - "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X", - - "83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X", - "bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X", - "79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X", - "5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4", - - "5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X", - "79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X", - "2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X", - "351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X", - "b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X", - "81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X", - "10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X", - "d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7", - "0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4" + "030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000c82d00001930000000000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00001930000000020000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00001930000001000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Mac OS X", + "03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X", + "03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00002590000000010000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00002690000000010000,8BitDo NEOGEO,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b10,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00003028000000010000,8Bitdo SFC30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001d30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001130000000020000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001330000000020000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001330000001000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X", + "0300000008100000e501000019040000,Anbernic Handheld,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X", + "03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X", + "030000006a0e00001140000001000000,Atari CX Wireless Controller,a:b0,leftx:a0,lefty:a1,platform:Mac OS X", + "03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X", + "03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X", + "03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X", + "030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X", + "030000008a3500000402000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000008a3500000302000000010000,Backbone One PlayStation Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X", + "03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X", + "03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000501d00009e61000001000000,CoreOrbits GamerPad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X", + "030000006f0e00008401000003010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X", + "03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000790000004618000000010000,GameCube Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X", + "03000000ac0500001a06000002020000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000373500000411000023000000,GameSir X4A Xbox Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X", + "03000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X", + "030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008800000000010000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008700000000010000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X", + "030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000aa00000072050000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000000d0f00000002000017010000,Hori Split Pad Fit,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000c100000072050000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000f600000000010000,Horipad Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X", + "03000000790000004e95000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X", + "03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X", + "03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X", + "03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X", + "030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000006d04000019c2000000000000,Logitech Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000019c2000000020000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000000000000,Logitech F310,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000006d0400001ac2000004000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "0300000049190000020400001b010000,Manba One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000008f0e00001330000011010000,Mayflash Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X", + "03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X", + "03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X", + "0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000008f0e00001030000011010000,Mayflash Saturn Adapter,a:b0,b:b2,dpdown:b28,dpleft:b30,dpright:b26,dpup:b24,leftshoulder:b10,lefttrigger:b14,rightshoulder:b12,righttrigger:b4,start:b18,x:b6,y:b8,platform:Mac OS X", + "0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X", + "03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X", + "03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X", + "03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X", + "030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X", + "030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X", + "030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X", + "030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X", + "030000004523000015e0000072050000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X", + "03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000853200008906000000010000,Nacon Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000921200004b46000003020000,NES Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X", + "030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000ec110000e1a7000001010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000920000010020000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X", + "050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X", + "030000007e0500007320000001010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Mac OS X", + "030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X", + "030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X", + "030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X", + "0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000100800000300000006010000,PlayStation Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000d620000011a7000010050000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", + "030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", + "030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", + "030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "0300004b4c0500005f0e000000010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000005e040000e002000001000000,PXN P30 Pro Mobile,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000222c00000225000000010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000009b2800005600000020020000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Mac OS X", + "030000009b2800008000000022020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Mac OS X", + "030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000921200004547000000020000,Retro Bit Sega Genesis Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X", + "03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X", + "0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Mac OS X", + "03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X", + "030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X", + "030000006f0e00008701000005010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000e804000000a000001b010000,Samsung EIGP20,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b11,leftx:a1,lefty:a3,rightshoulder:b12,rightx:a4,righty:a5,start:b16,x:b7,y:b9,platform:Mac OS X", + "03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X", + "03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X", + "03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X", + "03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X", + "030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X", + "030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X", + "030000004c050000da0c000000010000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000004c0500003713000000010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X", + "03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X", + "03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X", + "05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X", + "050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X", + "03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X", + "03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X", + "03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X", + "03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X", + "03000000790000001c18000000010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X", + "030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X", + "030000004f0400000ed0000000020000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X", + "03000000571d00002100000021000000,Tomee NES Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X", + "03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000571d00002000000021000000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X", + "03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c0160000e105000000040000,Ultimate Atari Fight Stick,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,platform:Mac OS X", + "03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X", + "030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X", + "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X", + "030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X", + "03000000c62400003a54000000000000,Xbox One PowerA Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000022050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000220b000021050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", ]; Gamepad.addMappings(mappings); #elseif linux var mappings = [ - "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", - "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", - "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", - "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux", - "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", - "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00001930000011010000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "05000000c82d00001930000001000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000631000000010000,8BitDo Adapter 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux", + "03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux", + "03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000a20000000020000,8BitDo M30 Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00002090000011010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux", + "03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00006928000011010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux", + "03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000960000011010000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux", + "03000000c82d00000060000011010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux", + "030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000631000010010000,8BitDo Ultimate,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000631000014010000,8BitDo Ultimate,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000760000011010000,8BitDo Ultimate,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001130000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001230000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001330000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux", + "05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00003901000013020000,Afterglow Prismatic Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00001302000000010000,Afterglow Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00003901000020060000,Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000100000008200000011010000,Akishop Customs PS360,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000007c1800000006000010010000,Alienware Dual Compatible Game PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux", + "05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "0300000008100000e501000001010000,Anbernic Handheld,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux", + "03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000190e00000110000010010000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Linux", + "03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux", + "05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux", + "03000000050b00000579000011010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000006a0e00001140000010010000,Atari CX Controller,a:b0,leftx:a0,lefty:a1,platform:Linux", + "03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "03000000503200000110000011010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "05000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "05000000503200000110000044010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "05000000503200000110000046010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux", + "03000000503200000210000011010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000045010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000046010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux", + "030000008a3500000201000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008a3500000202000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008a3500000302000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008a3500000402000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000bc2000004d50000011010000,Beitong A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000000d0500000308000010010000,Belkin Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux", + "05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000300e000011010000,Brook Audio Fighting Board PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000310e000011010000,Brook Audio Fighting Board PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000d81d00000b00000010010000,Buffalo BSGP1601,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Linux", + "03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux", + "030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux", + "03000000632500007a05000001020000,Cosmic Byte Ares Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux", + "03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux", + "030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux", + "030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux", + "03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000852100000201000010010000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000defa000001c0000000000000,Flydigi Vader 5 Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,misc2:b12,misc3:b13,misc4:b14,misc5:b19,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000ac0500001a06000011010000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000373500000410000044010000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000373500009410000010010000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000f0250000c283000010010000,Gioteck VX2 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux", + "190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux", + "190000004b4800000011000000010000,GO-Super Gamepad,a:b0,b:b1,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b3,y:b2,platform:Linux", + "03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d11800000094000011010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "05000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000001010000,GPD Win Max 2 6800U Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux", + "030000008f0e00001200000010010000,GreenAsia Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "0500000047532067616d657061640000,GS Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000008a2e0000dd10000011010000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Linux", + "030000008a2e0000df10000011010000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Linux", + "06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux", + "03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f00005001000009040000,Hori Fighting Commander Octa Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux", + "030000000d0f00008800000011010000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00008700000011010000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux", + "030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f0000aa00000011010000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000000d0f00008501000017010000,Hori Split Pad Fit,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f0000c100000011010000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f0000ab01000011010000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000000d0f00009601000091000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000000d0f0000f600000001000000,Horipad Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000341a000005f7000010010000,HuiJia GameCube Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux", + "05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux", + "03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux", + "03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux", + "03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000f00300008d04000000010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux", + "03000000d80400004aea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux", + "03000000d80400004bea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux", + "030000008a2e0000d910000011010000,icedragon.io STAC2 Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux", + "030000008a2e0000e910000011010000,icedragon.io STAC2 Dance Pad,a:b8,b:b9,back:b12,x:b10,y:b11,platform:Linux", + "030000008f0e00001330000001010000,iCode Retro Adapter,b:b3,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b1,start:b7,x:b2,y:b0,platform:Linux", + "050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux", + "03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux", + "03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux", + "03000000fd0500000030000000010000,InterAct GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Linux", + "03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux", + "0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux", + "050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux", + "030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux", + "03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000242f00002d00000011010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux", + "03000000314100001935000000010000,LeadJoy Xeno Plus,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a4,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d0400001dc2000014400000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d0400001ec2000019200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d0400001ec2000020200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d04000019c2000011010000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d0400001fc2000005030000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d04000019c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux", + "030000006d04000011c2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux", + "05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000380700008031000011010000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008081000011010000,Mad Catz FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000380700001888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700003888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700001647000010040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000120c00000500000000010000,Manta DualShock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "030000008f0e00001330000010010000,Mayflash Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux", + "0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000008f0e00001030000010010000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux", + "0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux", + "03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux", + "03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux", + "030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux", + "030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux", + "030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux", + "030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux", + "030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000005e0400008902000021010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000d102000001010000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000dd02000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000008040000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea0200000f050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b000014050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000016050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000017050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b000001050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux", + "03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "05000000e80400006e0400001b010000,Mocute 053X M59,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000d6200000e589000001000000,Moga 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "05000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux", + "030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux", + "030000006b1400000906000014010000,Nacon Asymmetric PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "0300000085320000030c000011010000,Nacon GC100,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000853200000706000012010000,Nacon GC100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006b140000010c000010010000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "05000000853200000503000000010000,Nacon MGX Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "0300000085320000160d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000004518000010010000,NEXiLUX GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux", + "060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000004618000010010000,Nintendo GameCube Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux", + "03000000ec110000e1a7000010010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux", + "060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "050000004c69632050726f20436f6e00,Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux", + "030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux", + "030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux", + "05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "050000005a1d00000218000003000000,Nokia GC 5000,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000007e0500007320000011010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Linux", + "030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux", + "050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux", + "050000007e0500001920000001800000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux", + "030000007e0500001e20000011810000,NSO Sega Genesis Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,platform:Linux", + "030000007e0500001720000011810000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux", + "050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux", + "050000007e0500001720000001800000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux", + "03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux", + "05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux", + "030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000451300000830000010010000,Nyko CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux", + "19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux", + "05000000362800000100000002010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux", + "05000000362800000100000003010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux", + "05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux", + "03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux", + "03000000ff1100003133000010010000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00008501000011010000,PDP Fightpad Pro Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00002f01000011010000,PDP Wired PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000f102000000000000,PDP Xbox Atomic,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000540000001010000,PowerA Advantage Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d620000013a7000011010000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d620000014a7000011010000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux", + "03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000520000050010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000b20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000250900000017000010010000,PS SS N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux", + "03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000120c0000160e000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", - "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", - "030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux", - "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux", - "030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux", - "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5", - "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", - "030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux", - "030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux", - "030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4", - "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7", - "0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux", - "0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux", - "030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1", - "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5", - "030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", - "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux", - "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", - "060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux", - "050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux", - "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a3,rightx:a1,righty:a4", - "03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13", - "05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2", - "05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2", - "030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux", - "03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1", - "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16", - "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1", - "030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7", - "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux", - "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux", - "03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux", - "03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux", - "03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux", - "03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux", - "03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux", - "030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux", - "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7", - "05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1", - - "03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1", - "030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5", - - "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5", - "03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7", - "03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5", - "05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - - "030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux", - "030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - - "030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5", - - "05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1", - "030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux", - "03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5", - "05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5", - - "03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1" + "030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000005f1400003102000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "0300004b4c0500005f0e000011010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000f20d000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000f20d000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux", + "03000000222c00000225000011010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00000025000011010000,Qanba Dragon Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick PS5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux", + "03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux", + "030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux", + "030000009b2800006500000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "030000009b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "03000000401700007f05000001010000,Raphnet GC and N64 Adapter,a:b5,b:b3,back:b8,dpdown:b10,dpleft:b12,dpright:b11,dpup:b9,leftshoulder:b6,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:-a5,rightx:a2,righty:a3,start:b1,x:b4,y:b2,platform:Linux", + "030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "030000009b2800003c00000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800006100000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800006300000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800006400000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux", + "030000009b2800008000000001010000,Raphnet Wii Classic Adapter V3,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux", + "03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "0300000032150000140a000001010000,Razer Wolverine Ultimate Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux", + "0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux", + "190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux", + "0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux", + "00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux", + "03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Linux", + "030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00008701000011010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00001311000011010000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Linux", + "03000000a306000023f6000011010000,Saitek Cyborg PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux", + "03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux", + "03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux", + "03000000a30600000d5f000010010000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux", + "03000000a30600000c04000011010000,Saitek P2900,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux", + "03000000a306000018f5000010010000,Saitek P3200 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux", + "03000000a30600000b04000000010000,Saitek P990 Dual Analog,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux", + "03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux", + "03000000952e00004b43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000952e00004d43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000952e00004e43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux", + "03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux", + "03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux", + "03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000632500002605000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000632500007505000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000bc2000000055000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000250900000500000000010000,SmartJoy PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux", + "030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000790000002601000011010000,SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux", + "050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000666600006706000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux", + "03000000d9040000160f000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux", + "030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "05000000381000001214000001000000,SteelSeries Free,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a2,righttrigger:a3,platform:Linux", + "050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux", + "03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux", + "030000001f08000001e4000010010000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux", + "0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux", + "030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux", + "03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux", + "03000000ba2200000701000001010000,Technology Innovation PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux", + "03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux", + "030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000020b3000010010000,Thrustmaster Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000023b3000000010000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000004f0400000ed0000011010000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux", + "030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux", + "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux", + "030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000004f04000008d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000004f04000009d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux", + "03000000bd12000015d0000010010000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux", + "030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000680a00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "03000000780300000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", + "03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", + "03000000100800000100000010010000,Twin PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux", + "03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "03000000790000000600000007010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux", + "03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux", + "03000000de2800000112000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800000112000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux", + "03000000de2800000211000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800000211000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux", + "03000000de2800004211000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800004211000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux", + "03000000de280000fc11000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "05000000de2800000212000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800000512000010010000,Valve Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux", + "03000000de2800000512000011010000,Valve Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux", + "03000000790000001a18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000001b18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux", + "030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000002010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000014010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000047010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000072050000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400009102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000030060000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00001503000000020000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "0000000058626f782047616d65706100,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000006f0e00001304000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000001030000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000200b000017050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000200b000023050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000220b000017050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000015050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000017050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000ea02000016050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000011050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000014050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000007050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000017050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "060000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux", + "03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux", + "030000005e0400008e02000020010000,XInput Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000120c0000100e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000101e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000182e000011010000,Zeroplus PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000002201000011010000,ZhiXu GuliKit D,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + ]; + Gamepad.addMappings(mappings); + #elseif android + var mappings = [ + "38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android", + "34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android", + "38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android", + "38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android", + "32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android", + "38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android", + "64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android", + "66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android", + "66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android", + "38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android", + "61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android", + "62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android", + "33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android", + "38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android", + "05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android", + "38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android", + "32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android", + "38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "61333362366131643730353063616330,8BitDo Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android", + "38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android", + "61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android", + "05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android", + "33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android", + "63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android", + "4c696e757820342e31392e3137322077,Anbernic Handheld,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android", + "35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,start:b6,platform:Android", + "32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4f64696e20436f6e74726f6c6c657200,AYN Odin,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b14,dpright:b13,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:+a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android", + "4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android", + "30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android", + "05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "476f6f676c65204c4c43205374616469,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "5374616469614e3848532d6532633400,Google Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android", + "65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b18,platform:Android", + "31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "30306539356238653637313730656134,Horipad Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android", + "62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android", + "31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android", + "5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android", + "64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android", + "532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android", + "65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android", + "33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android", + "35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android", + "4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android", + "38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "39373064396565646338333134303131,Joy-Con (R),a:b1,b:b2,back:b5,leftstick:b8,leftx:a1~,lefty:a0,start:b6,x:b0,y:b3,platform:Android", + "4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android", + "64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33373336396634316434323337666361,Logitech RumblePad 2,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android", + "416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android", + "6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android", + "436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android", + "4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android", + "535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android", + "30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android", + "39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android", + "31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android", + "37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android", + "64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b9,x:b2,y:b3,platform:Android", + "33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android", + "30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android", + "32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4d4f42415041442050726f2d48440000,Mobapad Chitu HD,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android", + "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android", + "31316661666466633938376335383661,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,start:b6,x:b3,y:b2,platform:Android", + "34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android", + "36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android", + "4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android", + "534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "050000005509000003720000cf7f3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005509000010720000ffff3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005509000014720000df7f3f00,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "050000005509000014720000df7f3f80,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android", + "4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android", + "506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android", + "61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android", + "32666633663735353234363064386132,PS2 Controller,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android", + "050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android", + "31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "050000004c050000e60c0000fffe3f80,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b2,y:b17,platform:Android", + "050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android", + "5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android", + "32417865732031314b6579732047616d,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android", + "61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android", + "526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64633735616665613536653363336132,Retroid Pocket,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b19,paddle2:b20,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b6,platform:Android", + "37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android", + "5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android", + "526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android", + "64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android", + "37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android", + "32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android", + "38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android", + "61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android", + "30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android", + "66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android", + "5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android", + "5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "62653335326261303663356263626339,Sony PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android", + "536f6e7920496e746572616374697665,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "576972656c65737320436f6e74726f6c,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android", + "63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android", + "0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android", + "35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android", + "33313930373536613937326534303931,Taito Egret II Mini Control Panel,a:b25,b:b23,back:b27,guide:b30,leftx:a0,lefty:a1,rightshoulder:b21,righttrigger:b22,start:b28,x:b29,y:b24,platform:Android", + "54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android", + "38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android", + "050000004f0400000ed00000fffe3f00,Thrustmaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android", + "05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android", + "05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android", + "30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android", + "33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android", + "050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65353331386662343338643939643636,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65613532386633373963616462363038,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e04000091020000ff073f00,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "050000005e04000091020000ff073f80,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000e00200000ffe3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000e00200000ffe3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000e0020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000e0020000ffff3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000fd020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android", + "35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65316262316265373335666131623538,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000120b000000783f80,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000001727000044310000ffff3f00,XiaoMi Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android", ]; Gamepad.addMappings(mappings); #elseif (ios || tvos) var mappings = [ + "05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", + "05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", + "05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", + "05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,", + "05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,", + "05000000ac05000004000000a8986d04,8BitDo Micro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,", + "05000000ac05000004000000fd216d04,8BitDo Pro 2,a:b3,b:b2,back:b6,dpdown:b9,dpleft:b10,dpright:b11,dpup:b12,guide:b4,leftshoulder:b13,leftstick:b14,lefttrigger:+a2,leftx:a0,lefty:a1~,paddle1:b1,paddle2:b0,rightshoulder:b16,rightstick:b17,righttrigger:+a5,rightx:a3,righty:a4~,start:b5,x:b8,y:b7,", + "05000000ac05000004000000209f6d04,8Bitdo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,", + "05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,", + "050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,", "4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,", + "050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,", + "050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,", + "050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,", + "050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,", + "050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,", + "050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,", + "050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,", + "050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,", + "05000000ac050000040000008e586d04,PlayStation VR2 Sense Controller (L),+leftx:+a3,+lefty:+a1,-leftx:+a2,-lefty:+a4,back:b2,leftstick:b4,lefttrigger:+a7,paddle2:b3,x:b0,y:b1,", + "05000000ac050000040000000eb86d04,PlayStation VR2 Sense Controller (R),+rightx:+a3,+righty:+a1,-rightx:+a2,-righty:+a4,a:b0,b:b1,paddle1:b3,rightstick:b4,righttrigger:+a7,start:b2,", + "050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", + "050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,", + "050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", + "05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", + "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", + "05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", + "05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", + "050000005e040000050b0000df070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000005e040000050b0000ff070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000005e040000e0020000df070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000005e040000e0020000ff070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3," "4d466947616d65706164030000000000,MFi Apple TV Remote,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,", ]; From ea029fb253ab728adc7344e5d6f33cbd18997723 Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Fri, 29 May 2026 14:15:29 -0700 Subject: [PATCH 23/76] Missed a comma --- src/lime/ui/Window.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index b9ce4fdd22..7fe8d2a1c3 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -2485,7 +2485,7 @@ class Window "050000005e040000e0020000df070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "050000005e040000e0020000ff070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", - "050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3," + "050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "4d466947616d65706164030000000000,MFi Apple TV Remote,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,", ]; From 17d95bd7c1df7433a668447f836b14c3a3ad3b46 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 03:43:17 -0400 Subject: [PATCH 24/76] Fix GL cleanup and skip invisible windows --- project/src/backend/sdl/SDLWindow.cpp | 46 +++++++++++++++---- .../backend/native/NativeApplication.hx | 1 + 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/project/src/backend/sdl/SDLWindow.cpp b/project/src/backend/sdl/SDLWindow.cpp index 522556fcf8..5d42c30bc3 100644 --- a/project/src/backend/sdl/SDLWindow.cpp +++ b/project/src/backend/sdl/SDLWindow.cpp @@ -475,6 +475,24 @@ namespace lime { } + if (sdlRenderer) { + + SDL_DestroyRenderer (sdlRenderer); + sdlRenderer = 0; + + } else if (context) { + + if (SDL_GL_GetCurrentContext () == context) { + + SDL_GL_MakeCurrent (sdlWindow, NULL); + + } + + SDL_GL_DeleteContext (context); + context = 0; + + } + if (sdlWindow) { #if defined (HX_WINDOWS) && !defined (HX_WINRT) @@ -486,16 +504,6 @@ namespace lime { } - if (sdlRenderer) { - - SDL_DestroyRenderer (sdlRenderer); - - } else if (context) { - - SDL_GL_DeleteContext (context); - - } - } @@ -544,6 +552,24 @@ namespace lime { RestoreResizeEventHook (sdlWindow); #endif + if (sdlRenderer) { + + SDL_DestroyRenderer (sdlRenderer); + sdlRenderer = 0; + + } else if (context) { + + if (SDL_GL_GetCurrentContext () == context) { + + SDL_GL_MakeCurrent (sdlWindow, NULL); + + } + + SDL_GL_DeleteContext (context); + context = 0; + + } + SDL_DestroyWindow (sdlWindow); sdlWindow = 0; diff --git a/src/lime/_internal/backend/native/NativeApplication.hx b/src/lime/_internal/backend/native/NativeApplication.hx index 1be8e8df77..a6478bba2d 100644 --- a/src/lime/_internal/backend/native/NativeApplication.hx +++ b/src/lime/_internal/backend/native/NativeApplication.hx @@ -462,6 +462,7 @@ class NativeApplication for (window in parent.__windows) { if (window == null) continue; + if (!window.visible) continue; // parent.renderer = renderer; switch (renderEventInfo.type) { From e5273f49884a226a693174c88e682f85971d7acd Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 03:44:39 -0400 Subject: [PATCH 25/76] Use renderer window attribute; update parser Standardize the window attribute name to renderer. ProjectXMLParser now recognizes "renderer" and sets the window renderType. README and tests/vulkan-smoke/project.xml updated to use . --- .github/workflows/main.yml | 9 --------- README.md | 2 +- src/lime/tools/ProjectXMLParser.hx | 2 +- tests/vulkan-smoke/project.xml | 2 +- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 24efa86ab4..60e98fe5be 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -235,15 +235,6 @@ jobs: fi SDL_AUDIODRIVER=dummy xvfb-run -a Export/linux/bin/LimeVulkanSmoke - - name: Install samples - run: | - haxelib git lime-samples https://github.com/openfl/lime-samples --quiet - - - name: Build HelloWorld Vulkan sample - run: | - lime create HelloWorld -verbose -nocolor - lime build HelloWorld linux -release -verbose -nocolor --window-render-type=vulkan - macos: runs-on: macos-14 steps: diff --git a/README.md b/README.md index 3585d2f17b..167628b285 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Lime does not include a renderer, but exposes the current context: The GL context is based upon the WebGL standard, implemented for both OpenGL and OpenGL ES as needed. Native Vulkan support exposes an explicit Vulkan API layer for renderer backends, including native window/swapchain integration and resource/command primitives. Native Vulkan support is included in standard Windows and Linux C++ Lime builds, including the matching Haxe API define. Apple targets still require an explicit Vulkan-enabled build and MoltenVK packaging. -To request a Vulkan window, use the standard `RenderContextType.VULKAN` context selection, set `` in project XML, or use `--window-render-type=vulkan`. +To request a Vulkan window, use the standard `RenderContextType.VULKAN` context selection or set `` in project XML. The in-repo `tests/vulkan-smoke` project is used as the current Vulkan CI smoke app. Lime provides a unified audio API, but also provides access to OpenAL for advanced audio on native targets. diff --git a/src/lime/tools/ProjectXMLParser.hx b/src/lime/tools/ProjectXMLParser.hx index faa9d6ae10..e535b37f5e 100644 --- a/src/lime/tools/ProjectXMLParser.hx +++ b/src/lime/tools/ProjectXMLParser.hx @@ -1984,7 +1984,7 @@ class ProjectXMLParser extends HXProject case "parameters", "title": Reflect.setField(windows[id], name, Std.string(value)); - case "render-type", "context-type": + case "renderer": var renderType = Std.string(value).toLowerCase(); Reflect.setField(windows[id], "renderType", renderType); if (renderType == "vulkan") diff --git a/tests/vulkan-smoke/project.xml b/tests/vulkan-smoke/project.xml index d23af8f962..ef66f4b29a 100644 --- a/tests/vulkan-smoke/project.xml +++ b/tests/vulkan-smoke/project.xml @@ -9,6 +9,6 @@ - + From 2ac936ce29584a473d0f013b42a73827cddaa6b1 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 04:39:51 -0400 Subject: [PATCH 26/76] Vulkan: Keep non-Vulkan native builds isolated --- project/Build.xml | 6 +-- project/src/ExternalInterface.cpp | 82 +++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/project/Build.xml b/project/Build.xml index 28a39cd0b6..84ef070811 100755 --- a/project/Build.xml +++ b/project/Build.xml @@ -35,15 +35,13 @@ - + - - - + diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index dc906f4c13..43ff2ea8a3 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -12166,6 +12166,21 @@ namespace lime { } + bool lime_vk_update_descriptor_sets (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value writes) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_sets) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* writes) { + + return LimeVulkanUnavailableBool (); + + } + + value lime_vk_create_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value setLayouts, int pushConstantStages, int pushConstantSize) { @@ -12378,6 +12393,24 @@ namespace lime { } + bool lime_vk_cmd_bind_descriptor_set_dynamic_offset (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int dynamicOffset, int firstSet, + int bindPoint) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_dynamic_offset) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, + int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, + int dynamicOffset, int firstSet, int bindPoint) { + + return LimeVulkanUnavailableBool (); + + } + + bool lime_vk_cmd_bind_vertex_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { @@ -12474,6 +12507,39 @@ namespace lime { } + bool lime_vk_cmd_draw_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { + + return LimeVulkanUnavailableBool (); + + } + + + bool lime_vk_cmd_draw_indexed_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, + int stride) { + + return LimeVulkanUnavailableBool (); + + } + + bool lime_vk_cmd_copy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { @@ -12569,6 +12635,22 @@ namespace lime { } + bool lime_vk_cmd_clear_attachments (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, value state, value clear) { + + return LimeVulkanUnavailableBool (); + + } + + + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_attachments) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, hl_varray* state, hl_varray* clear) { + + return LimeVulkanUnavailableBool (); + + } + + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { From 9524adbc5f200c6e9459f97b4d6dcbc32ff119dd Mon Sep 17 00:00:00 2001 From: dPavlenko Date: Thu, 16 Apr 2026 11:22:17 +0300 Subject: [PATCH 27/76] ios template: added identity settings and 'update to recommended settings' changes to xcode project --- .../{{app.file}}.xcodeproj/project.pbxproj | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj b/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj index 001a200690..58b6be5022 100644 --- a/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj +++ b/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj @@ -214,6 +214,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 0920; TargetAttributes = { 1D6058900D05DD3D006BFB54 = { @@ -272,23 +273,39 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = ::CURRENT_ARCHS::; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ::if (OBJC_ARC):: CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ::end:: + CURRENT_PROJECT_VERSION = "::APP_BUILD_NUMBER::"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; + MARKETING_VERSION = "::APP_VERSION::"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "::config.ios.identity::"; ::if (IOS_PROVISIONING_PROFILE)::PROVISIONING_PROFILE = "::IOS_PROVISIONING_PROFILE::";::end:: COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -306,6 +323,7 @@ IPHONEOS_DEPLOYMENT_TARGET = ::DEPLOYMENT::; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; TARGETED_DEVICE_FAMILY = "::TARGET_DEVICES::"; ::THUMB_SUPPORT:: VALID_ARCHS = "::VALID_ARCHS::"; @@ -317,23 +335,39 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = ::CURRENT_ARCHS::; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ::if (OBJC_ARC):: CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ::end:: + CURRENT_PROJECT_VERSION = "::APP_BUILD_NUMBER::"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; + MARKETING_VERSION = "::APP_VERSION::"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "::config.ios.identity::"; ::if (IOS_PROVISIONING_PROFILE)::PROVISIONING_PROFILE = "::IOS_PROVISIONING_PROFILE::";::end:: /* COMPRESS_PNG_FILES = NO; */ COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -346,6 +380,8 @@ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; /* PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES; */ SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; TARGETED_DEVICE_FAMILY = "::TARGET_DEVICES::"; ::THUMB_SUPPORT:: VALID_ARCHS = "::VALID_ARCHS::"; @@ -356,6 +392,7 @@ 1D6058940D05DD3E006BFB54 /* Debug */ = {/* Build configuration list for PBXNativeTarget "::APP_TITLE::" */ isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ::if (IOS_LAUNCH_STORYBOARD == null)::ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;::end:: CODE_SIGN_ENTITLEMENTS = "::APP_FILE::/::APP_FILE::.entitlements"; @@ -407,6 +444,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "::APP_PACKAGE::"; PRODUCT_NAME = "$(TARGET_NAME)"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; WRAPPER_EXTENSION = app; }; name = Debug; @@ -460,6 +498,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "::APP_PACKAGE::"; PRODUCT_NAME = "$(TARGET_NAME)"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; WRAPPER_EXTENSION = app; }; name = Release; From 2e1d2217c5769e4fc53980d815b049acb6a63031 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Thu, 14 May 2026 18:57:31 +0200 Subject: [PATCH 28/76] Add support for VAOs on macOS --- .../src/graphics/opengl/OpenGLBindings.cpp | 60 ++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/project/src/graphics/opengl/OpenGLBindings.cpp b/project/src/graphics/opengl/OpenGLBindings.cpp index dbcc4f1aec..d571b3d87d 100644 --- a/project/src/graphics/opengl/OpenGLBindings.cpp +++ b/project/src/graphics/opengl/OpenGLBindings.cpp @@ -531,6 +531,12 @@ namespace lime { void lime_gl_bind_vertex_array (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glBindVertexArrayAPPLE) { + glBindVertexArrayAPPLE (vertexArray); + } + else + #endif if (glBindVertexArray) { glBindVertexArray (vertexArray); } @@ -542,6 +548,12 @@ namespace lime { HL_PRIM void HL_NAME(hl_gl_bind_vertex_array) (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glBindVertexArrayAPPLE) { + glBindVertexArrayAPPLE (vertexArray); + } + else + #endif if (glBindVertexArray) { glBindVertexArray (vertexArray); } @@ -1200,6 +1212,12 @@ namespace lime { GLuint id = 0; #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glGenVertexArraysAPPLE) { + glGenVertexArraysAPPLE (1, &id); + } + else + #endif if (glGenVertexArrays) { glGenVertexArrays (1, &id); } @@ -1213,6 +1231,12 @@ namespace lime { GLuint id = 0; #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glGenVertexArraysAPPLE) { + glGenVertexArraysAPPLE (1, &id); + } + else + #endif if (glGenVertexArrays) { glGenVertexArrays (1, &id); } @@ -1401,6 +1425,12 @@ namespace lime { void lime_gl_delete_vertex_array (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glDeleteVertexArraysAPPLE) { + glDeleteVertexArraysAPPLE (1, (GLuint*)&vertexArray); + } + else + #endif if (glDeleteVertexArrays) { glDeleteVertexArrays (1, (GLuint*)&vertexArray); } @@ -1412,6 +1442,12 @@ namespace lime { HL_PRIM void HL_NAME(hl_gl_delete_vertex_array) (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glDeleteVertexArraysAPPLE) { + glDeleteVertexArraysAPPLE (1, (GLuint*)&vertexArray); + } + else + #endif if (glDeleteVertexArrays) { glDeleteVertexArrays (1, (GLuint*)&vertexArray); } @@ -3880,7 +3916,17 @@ namespace lime { bool lime_gl_is_vertex_array (int handle) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) - return glIsVertexArray ? glIsVertexArray (handle) : false; + #if defined (HX_MACOS) + if (glIsVertexArrayAPPLE) { + return glIsVertexArrayAPPLE (handle); + } + else + #endif + if (glIsVertexArray) { + return glIsVertexArray (handle); + } + + return false; #else return false; #endif @@ -3891,7 +3937,17 @@ namespace lime { HL_PRIM bool HL_NAME(hl_gl_is_vertex_array) (int handle) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) - return glIsVertexArray ? glIsVertexArray (handle) : false; + #if defined (HX_MACOS) + if (glIsVertexArrayAPPLE) { + return glIsVertexArrayAPPLE (handle); + } + else + #endif + if (glIsVertexArray) { + return glIsVertexArray (handle); + } + + return false; #else return false; #endif From 3b861489fa34356c2d7809dc76d647b7aa0aa697 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Thu, 14 May 2026 19:21:05 +0200 Subject: [PATCH 29/76] Fix GC not picking up some GL objects on desktop --- .../src/graphics/opengl/OpenGLBindings.cpp | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/project/src/graphics/opengl/OpenGLBindings.cpp b/project/src/graphics/opengl/OpenGLBindings.cpp index d571b3d87d..4bcd72a01c 100644 --- a/project/src/graphics/opengl/OpenGLBindings.cpp +++ b/project/src/graphics/opengl/OpenGLBindings.cpp @@ -228,10 +228,13 @@ namespace lime { if (glIsRenderbuffer (id)) glDeleteRenderbuffers (1, &id); break; - #ifdef LIME_GLES3_API + #if defined(LIME_GLES3_API) || !defined(LIME_GLES) case TYPE_SAMPLER: - if (glIsSampler (id)) glDeleteSamplers (1, &id); + if (glIsSampler && glIsSampler (id)) { + if (glDeleteSamplers) + glDeleteSamplers (1, &id); + } break; #endif @@ -245,10 +248,20 @@ namespace lime { if (glIsTexture (id)) glDeleteTextures (1, &id); break; - #ifdef LIME_GLES3_API + #if defined(LIME_GLES3_API) || !defined(LIME_GLES) case TYPE_VERTEX_ARRAY_OBJECT: - - if (glIsVertexArray (id)) glDeleteVertexArrays (1, &id); + + #if defined(HX_MACOS) + if (glIsVertexArrayAPPLE && glIsVertexArrayAPPLE (id)) { + if (glDeleteVertexArraysAPPLE) + glDeleteVertexArraysAPPLE (1, &id); + } + else + #endif + if (glIsVertexArray && glIsVertexArray (id)) { + if (glDeleteVertexArrays) + glDeleteVertexArrays (1, &id); + } break; #endif From 07c2c7ce17c403dc3fc0a0bc89af56e4e9506b62 Mon Sep 17 00:00:00 2001 From: MAJigsaw77 <77043862+MAJigsaw77@users.noreply.github.com> Date: Thu, 17 Jul 2025 20:43:42 +0300 Subject: [PATCH 30/76] Don't use `ReplaceVistaIcon` on windows `cpp` target anymore. --- templates/windows/resource/ApplicationMain.rc | 2 ++ tools/platforms/WindowsPlatform.hx | 13 +++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/templates/windows/resource/ApplicationMain.rc b/templates/windows/resource/ApplicationMain.rc index 2d12ca8ef6..23139f7fc4 100644 --- a/templates/windows/resource/ApplicationMain.rc +++ b/templates/windows/resource/ApplicationMain.rc @@ -1,5 +1,7 @@ #include "winres.h" +IDI_ICON1 ICON "ApplicationMain.ico" + LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK VS_VERSION_INFO VERSIONINFO diff --git a/tools/platforms/WindowsPlatform.hx b/tools/platforms/WindowsPlatform.hx index f9f9aa58fd..8db17eff27 100644 --- a/tools/platforms/WindowsPlatform.hx +++ b/tools/platforms/WindowsPlatform.hx @@ -602,6 +602,8 @@ class WindowsPlatform extends PlatformTarget if (noOutput) return; + IconHelper.createWindowsIcon(icons, Path.combine(targetDirectory + "/obj", "ApplicationMain.ico")); + CPPHelper.compile(project, targetDirectory + "/obj", flags); System.copyFile(targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : "") + ".exe", executablePath); @@ -630,19 +632,14 @@ class WindowsPlatform extends PlatformTarget if (noOutput) return; + IconHelper.createWindowsIcon(icons, Path.combine(targetDirectory + "/obj", "ApplicationMain.ico")); + CPPHelper.compile(project, targetDirectory + "/obj", flags.concat(["-Dstatic_link"])); + CPPHelper.compile(project, targetDirectory + "/obj", flags, "BuildMain.xml"); System.copyFile(targetDirectory + "/obj/Main" + (project.debug ? "-debug" : "") + ".exe", executablePath); } - - var iconPath = Path.combine(applicationDirectory, "icon.ico"); - - if (IconHelper.createWindowsIcon(icons, iconPath) && System.hostPlatform == WINDOWS) - { - var templates = [Haxelib.getPath(new Haxelib(#if lime "lime" #else "hxp" #end)) + "/templates"].concat(project.templatePaths); - System.runCommand("", System.findTemplate(templates, "bin/ReplaceVistaIcon.exe"), [executablePath, iconPath, "1"], true, true); - } } } } From 13a9b79ec7e586bec11aedf1ab545514b5fd4273 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Tue, 2 Jun 2026 17:56:12 +0200 Subject: [PATCH 31/76] Implement OpenAL audio capture extension (#1965) * Implement OpenAL audio capture extension * OpenALAudioContext: wrap import in conditional * Fix OpenAL capture default-device handling The follow-up change makes the capture API accept a null device name for the default input device and fixes the ALC string path for capture/default-device queries. --------- Co-authored-by: Chris Speciale --- project/src/media/openal/OpenALBindings.cpp | 113 +++++++++++++++++- .../_internal/backend/native/NativeCFFI.hx | 41 +++++++ src/lime/media/OpenALAudioContext.hx | 41 ++++++- src/lime/media/openal/ALC.hx | 48 ++++++++ 4 files changed, 238 insertions(+), 5 deletions(-) diff --git a/project/src/media/openal/OpenALBindings.cpp b/project/src/media/openal/OpenALBindings.cpp index a26c5c679a..2bf26d5a6f 100644 --- a/project/src/media/openal/OpenALBindings.cpp +++ b/project/src/media/openal/OpenALBindings.cpp @@ -170,6 +170,7 @@ namespace lime { } */ + void lime_al_auxf (value aux, int param, float value) { #ifdef LIME_OPENALSOFT @@ -3379,7 +3380,7 @@ namespace lime { value lime_alc_get_string (value device, int param) { - ALCdevice* alcDevice = (ALCdevice*)val_data (device); + ALCdevice* alcDevice = val_is_null (device) ? NULL : (ALCdevice*)val_data (device); const char* result = alcGetString (alcDevice, param); return result ? alloc_string (result) : alloc_null (); @@ -3388,8 +3389,13 @@ namespace lime { HL_PRIM vbyte* HL_NAME(hl_alc_get_string) (HL_CFFIPointer* device, int param) { +<<<<<<< HEAD + ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : NULL; +======= ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : 0; +>>>>>>> origin/develop const char* result = alcGetString (alcDevice, param); + if (!result) return 0; int length = strlen (result); char* _result = (char*)malloc (length + 1); strcpy (_result, result); @@ -3512,6 +3518,101 @@ namespace lime { } + value lime_alc_capture_open_device (HxString devicename, int frequency, int format, int buffersize) { + + ALCdevice* alcDevice = alcCaptureOpenDevice (devicename.__s, frequency, format, buffersize); + + value ptr = CFFIPointer (alcDevice, gc_alc_object); + alcObjects[alcDevice] = ptr; + return ptr; + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_alc_capture_open_device) (hl_vstring* devicename, int frequency, int format, int buffersize) { + + ALCdevice* alcDevice = alcCaptureOpenDevice (devicename ? (char*)hl_to_utf8 ((const uchar*)devicename->bytes) : 0, frequency, format, buffersize); + + HL_CFFIPointer* ptr = HLCFFIPointer (alcDevice, (hl_finalizer)hl_gc_alc_object); + alcObjects[alcDevice] = ptr; + return ptr; + + } + + + bool lime_alc_capture_close_device (value device) { + + al_gc_mutex.Lock (); + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + alcObjects.erase (alcDevice); + al_gc_mutex.Unlock (); + + return alcCaptureCloseDevice (alcDevice); + + } + + + HL_PRIM bool HL_NAME(hl_alc_capture_close_device) (HL_CFFIPointer* device) { + + al_gc_mutex.Lock (); + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcObjects.erase (alcDevice); + al_gc_mutex.Unlock (); + + return alcCaptureCloseDevice (alcDevice); + + } + + + void lime_alc_capture_start (value device) { + + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + alcCaptureStart (alcDevice); + + } + + + HL_PRIM void HL_NAME(hl_alc_capture_start) (HL_CFFIPointer* device) { + + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcCaptureStart (alcDevice); + + } + + + void lime_alc_capture_stop (value device) { + + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + alcCaptureStop (alcDevice); + + } + + + HL_PRIM void HL_NAME(hl_alc_capture_stop) (HL_CFFIPointer* device) { + + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcCaptureStop (alcDevice); + + } + + + void lime_alc_capture_samples (value device, value buffer, int samples) { + + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + Bytes bytes (buffer); + alcCaptureSamples (alcDevice, bytes.b, samples); + + } + + + HL_PRIM void HL_NAME(hl_alc_capture_samples) (HL_CFFIPointer* device, Bytes* buffer, int samples) { + + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcCaptureSamples (alcDevice, buffer->b, samples); + + } + + DEFINE_PRIME3v (lime_al_auxf); @@ -3628,6 +3729,11 @@ namespace lime { DEFINE_PRIME1v (lime_alc_process_context); DEFINE_PRIME1v (lime_alc_resume_device); DEFINE_PRIME1v (lime_alc_suspend_context); + DEFINE_PRIME4 (lime_alc_capture_open_device); + DEFINE_PRIME1 (lime_alc_capture_close_device); + DEFINE_PRIME1v (lime_alc_capture_start); + DEFINE_PRIME1v (lime_alc_capture_stop); + DEFINE_PRIME3v (lime_alc_capture_samples); #define _TBYTES _OBJ (_I32 _BYTES) @@ -3752,6 +3858,11 @@ namespace lime { DEFINE_HL_PRIM (_VOID, hl_alc_process_context, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_alc_resume_device, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_alc_suspend_context, _TCFFIPOINTER); + DEFINE_HL_PRIM (_TCFFIPOINTER, hl_alc_capture_open_device, _STRING _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_alc_capture_close_device, _TCFFIPOINTER); + DEFINE_HL_PRIM (_VOID, hl_alc_capture_start, _TCFFIPOINTER); + DEFINE_HL_PRIM (_VOID, hl_alc_capture_stop, _TCFFIPOINTER); + DEFINE_HL_PRIM (_VOID, hl_alc_capture_samples, _TCFFIPOINTER _TBYTES _I32); } diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index a706695109..af16f05912 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -3092,6 +3092,16 @@ class NativeCFFI @:cffi private static function lime_alc_suspend_context(context:CFFIPointer):Void; + @:cffi private static function lime_alc_capture_open_device(devicename:String, frequency:Int, format:Int, buffersize:Int):CFFIPointer; + + @:cffi private static function lime_alc_capture_close_device(device:CFFIPointer):Bool; + + @:cffi private static function lime_alc_capture_start(device:CFFIPointer):Void; + + @:cffi private static function lime_alc_capture_stop(device:CFFIPointer):Void; + + @:cffi private static function lime_alc_capture_samples(device:CFFIPointer, buffer:Dynamic, samples:Int):Void; + @:cffi private static function lime_al_gen_filter():CFFIPointer; @:cffi private static function lime_al_filteri(filter:CFFIPointer, param:Int, value:Dynamic):Void; @@ -3259,6 +3269,16 @@ class NativeCFFI private static var lime_alc_resume_device = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_resume_device", "ov", false)); private static var lime_alc_suspend_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_suspend_context", "ov", false)); + private static var lime_alc_capture_open_device = new cpp.CallableInt->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_capture_open_device", + "siiio", false)); + private static var lime_alc_capture_close_device = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_alc_capture_close_device", "ob", + false)); + private static var lime_alc_capture_start = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_start", "ov", + false)); + private static var lime_alc_capture_stop = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_stop", "ov", + false)); + private static var lime_alc_capture_samples = new cpp.Callablecpp.Object->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_samples", + "ooiv", false)); private static var lime_al_gen_filter = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_filter", "o", false)); private static var lime_al_filteri = new cpp.CallableInt->cpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_filteri", "oiov", false)); @@ -3379,6 +3399,11 @@ class NativeCFFI private static var lime_alc_process_context = CFFI.load("lime", "lime_alc_process_context", 1); private static var lime_alc_resume_device = CFFI.load("lime", "lime_alc_resume_device", 1); private static var lime_alc_suspend_context = CFFI.load("lime", "lime_alc_suspend_context", 1); + private static var lime_alc_capture_open_device = CFFI.load("lime", "lime_alc_capture_open_device", 4); + private static var lime_alc_capture_close_device = CFFI.load("lime", "lime_alc_capture_close_device", 1); + private static var lime_alc_capture_start = CFFI.load("lime", "lime_alc_capture_start", 1); + private static var lime_alc_capture_stop = CFFI.load("lime", "lime_alc_capture_stop", 1); + private static var lime_alc_capture_samples = CFFI.load("lime", "lime_alc_capture_samples", 3); private static var lime_al_gen_filter = CFFI.load("lime", "lime_al_gen_filter", 0); private static var lime_al_filteri = CFFI.load("lime", "lime_al_filteri", 3); private static var lime_al_filterf = CFFI.load("lime", "lime_al_filterf", 3); @@ -3735,6 +3760,22 @@ class NativeCFFI @:hlNative("lime", "hl_alc_suspend_context") private static function lime_alc_suspend_context(context:ALContext):Void {} + @:hlNative("lime", "hl_alc_capture_open_device") private static function lime_alc_capture_open_device(devicename:String, frequency:Int, format:Int, buffersize:Int):CFFIPointer + { + return null; + } + + @:hlNative("lime", "hl_alc_capture_close_device") private static function lime_alc_capture_close_device(device:ALDevice):Bool + { + return false; + } + + @:hlNative("lime", "hl_alc_capture_start") private static function lime_alc_capture_start(device:ALDevice):Void {} + + @:hlNative("lime", "hl_alc_capture_stop") private static function lime_alc_capture_stop(device:ALDevice):Void {} + + @:hlNative("lime", "hl_alc_capture_samples") private static function lime_alc_capture_samples(device:ALDevice, buffer:Bytes, samples:Int):Void {} + @:hlNative("lime", "hl_al_gen_filter") private static function lime_al_gen_filter():CFFIPointer { return null; diff --git a/src/lime/media/OpenALAudioContext.hx b/src/lime/media/OpenALAudioContext.hx index d731f72397..c0eeb6b4e6 100644 --- a/src/lime/media/OpenALAudioContext.hx +++ b/src/lime/media/OpenALAudioContext.hx @@ -8,6 +8,7 @@ import lime.media.openal.ALContext; import lime.media.openal.ALDevice; import lime.media.openal.ALSource; import lime.utils.ArrayBufferView; +import haxe.io.Bytes; #if !lime_debug @:fileXml('tags="haxe,release"') @@ -90,6 +91,9 @@ class OpenALAudioContext public var ENUMERATE_ALL_EXT:Int = 1; public var DEFAULT_ALL_DEVICES_SPECIFIER:Int = 0x1012; public var ALL_DEVICES_SPECIFIER:Int = 0x1013; + public var CAPTURE_DEVICE_SPECIFIER:Int = 0x310; + public var CAPTURE_DEFAULT_DEVICE_SPECIFIER:Int = 0x311; + public var CAPTURE_SAMPLES:Int = 0x312; @:noCompletion private function new() {} @@ -403,14 +407,18 @@ class OpenALAudioContext public function getString(param:Int, device:ALDevice = null):String { - if (device == null) + if (device != null) { - return AL.getString(param); + return ALC.getString(device, param); } - else + + if (param == DEFAULT_DEVICE_SPECIFIER || param == DEVICE_SPECIFIER || param == ALC.EXTENSIONS || param == DEFAULT_ALL_DEVICES_SPECIFIER + || param == ALL_DEVICES_SPECIFIER || param == CAPTURE_DEVICE_SPECIFIER || param == CAPTURE_DEFAULT_DEVICE_SPECIFIER) { - return ALC.getString(device, param); + return ALC.getString(cast null, param); } + + return AL.getString(param); } public function isBuffer(buffer:ALBuffer):Bool @@ -587,5 +595,30 @@ class OpenALAudioContext { ALC.suspendContext(context); } + + public function captureOpenDevice(deviceName:String = null, frequency:Int, format:Int, bufferSize:Int):ALDevice + { + return ALC.captureOpenDevice(deviceName, frequency, format, bufferSize); + } + + public function captureCloseDevice(device:ALDevice):Bool + { + return ALC.captureCloseDevice(device); + } + + public function captureStart(device:ALDevice):Void + { + ALC.captureStart(device); + } + + public function captureStop(device:ALDevice):Void + { + ALC.captureStop(device); + } + + public function captureSamples(device:ALDevice, buffer:Bytes, samples:Int):Void + { + ALC.captureSamples(device, buffer, samples); + } } #end diff --git a/src/lime/media/openal/ALC.hx b/src/lime/media/openal/ALC.hx index 4cd4379d21..7e2cc43ef7 100644 --- a/src/lime/media/openal/ALC.hx +++ b/src/lime/media/openal/ALC.hx @@ -4,6 +4,7 @@ package lime.media.openal; import lime._internal.backend.native.NativeCFFI; import lime.system.CFFI; import lime.system.CFFIPointer; +import haxe.io.Bytes; #if !lime_debug @:fileXml('tags="haxe,release"') @@ -33,6 +34,9 @@ class ALC public static inline var ENUMERATE_ALL_EXT:Int = 1; public static inline var DEFAULT_ALL_DEVICES_SPECIFIER:Int = 0x1012; public static inline var ALL_DEVICES_SPECIFIER:Int = 0x1013; + public static inline var CAPTURE_DEVICE_SPECIFIER:Int = 0x310; + public static inline var CAPTURE_DEFAULT_DEVICE_SPECIFIER:Int = 0x311; + public static inline var CAPTURE_SAMPLES:Int = 0x312; public static function closeDevice(device:ALDevice):Bool { @@ -202,5 +206,49 @@ class ALC NativeCFFI.lime_alc_suspend_context(context); #end } + + public static function captureOpenDevice(deviceName:String = null, frequency:Int, format:Int, bufferSize:Int):ALDevice + { + #if (lime_cffi && lime_openal && !macro) + var handle = NativeCFFI.lime_alc_capture_open_device(deviceName, frequency, format, bufferSize); + + if (handle != null) + { + return new ALDevice(handle); + } + #end + + return null; + } + + public static function captureCloseDevice(device:ALDevice):Bool + { + #if (lime_cffi && lime_openal && !macro) + return NativeCFFI.lime_alc_capture_close_device(device); + #end + + return false; + } + + public static function captureStart(device:ALDevice):Void + { + #if (lime_cffi && lime_openal && !macro) + NativeCFFI.lime_alc_capture_start(device); + #end + } + + public static function captureStop(device:ALDevice):Void + { + #if (lime_cffi && lime_openal && !macro) + NativeCFFI.lime_alc_capture_stop(device); + #end + } + + public static function captureSamples(device:ALDevice, buffer:Bytes, samples:Int):Void + { + #if (lime_cffi && lime_openal && !macro) + NativeCFFI.lime_alc_capture_samples(device, buffer, samples); + #end + } } #end From b1e2671f84f860defadfa063f2b0f7ed9b8c34b6 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 12:04:36 -0400 Subject: [PATCH 32/76] Fix leftover OpenAL merge markers --- project/src/media/openal/OpenALBindings.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/project/src/media/openal/OpenALBindings.cpp b/project/src/media/openal/OpenALBindings.cpp index 2bf26d5a6f..50fac5b710 100644 --- a/project/src/media/openal/OpenALBindings.cpp +++ b/project/src/media/openal/OpenALBindings.cpp @@ -3389,11 +3389,7 @@ namespace lime { HL_PRIM vbyte* HL_NAME(hl_alc_get_string) (HL_CFFIPointer* device, int param) { -<<<<<<< HEAD ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : NULL; -======= - ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : 0; ->>>>>>> origin/develop const char* result = alcGetString (alcDevice, param); if (!result) return 0; int length = strlen (result); From f220607d5730911d0de532035a03bb2555d87fbc Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 12:25:29 -0400 Subject: [PATCH 33/76] Fix Windows cpp icon resource handling 07c2c7ce switched Windows cpp builds from post-link icon patching with ReplaceVistaIcon to embedding ApplicationMain.ico through ApplicationMain.rc. That introduced two separate regressions. The resource template referenced ApplicationMain.ico unconditionally, so builds failed with RC2135 when icon generation did not produce a file. Static cpp builds also dropped the resource at the final Main link step, so the generated icon and metadata never made it into the executable. Generate the Windows icon before copying the resource template, set HAS_ICON from createWindowsIcon, gate the ICON stanza in ApplicationMain.rc, and include the rc file group in the static cpp Main link. --- templates/cpp/static/BuildMain.xml | 1 + templates/windows/resource/ApplicationMain.rc | 2 +- tools/platforms/WindowsPlatform.hx | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/templates/cpp/static/BuildMain.xml b/templates/cpp/static/BuildMain.xml index dd135172ce..33c486449b 100644 --- a/templates/cpp/static/BuildMain.xml +++ b/templates/cpp/static/BuildMain.xml @@ -17,6 +17,7 @@ + ::foreach ndlls:: diff --git a/templates/windows/resource/ApplicationMain.rc b/templates/windows/resource/ApplicationMain.rc index 23139f7fc4..2b36d4781f 100644 --- a/templates/windows/resource/ApplicationMain.rc +++ b/templates/windows/resource/ApplicationMain.rc @@ -1,6 +1,6 @@ #include "winres.h" -IDI_ICON1 ICON "ApplicationMain.ico" +::if (HAS_ICON)::IDI_ICON1 ICON "ApplicationMain.ico"::end:: LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK diff --git a/tools/platforms/WindowsPlatform.hx b/tools/platforms/WindowsPlatform.hx index 8db17eff27..3bc28d3110 100644 --- a/tools/platforms/WindowsPlatform.hx +++ b/tools/platforms/WindowsPlatform.hx @@ -1016,6 +1016,12 @@ class WindowsPlatform extends PlatformTarget } else if (targetType == "cpp") { + var windowsIcons = project.icons; + if (windowsIcons.length == 0) + { + windowsIcons = [new Icon(System.findTemplate(project.templatePaths, "default/icon.svg"))]; + } + context.HAS_ICON = IconHelper.createWindowsIcon(windowsIcons, Path.combine(targetDirectory + "/obj", "ApplicationMain.ico")); ProjectHelper.recursiveSmartCopyTemplate(project, "windows/resource", targetDirectory + "/obj", context); if (project.targetFlags.exists("static")) From ad09934eacfb6067c0ca213f7d7b85719321c9da Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 12:25:29 -0400 Subject: [PATCH 34/76] Rebuild tools --- run.n | Bin 141709 -> 142270 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/run.n b/run.n index deae46fd3a0e9af590e7ea899b554b6db46fd883..1436727e319e0e8446f9709a519888e51b356224 100644 GIT binary patch delta 22977 zcmaic2S5~87w(=}dhcb2zJP!Thzi(tvA4CCSV2@!EU1XRpwSqk(Wn!>iJHV-6HS7O zvG?A4)YuXgdyk1mec#z#WS8If-k;wy-zoRpb9#3nsS@$8t6Eak=&H6=6$~8Me+Za_1f`nobjeYr z9Ja0FZ*P((YqC*TS^U8k#tL$VHaQ6F-#>%4&f>lvW~&Oc>If%wBahE^tJ`PRMK-m z$u^06;2h(GO9Z?Mg>2O!**P8D#@!N98{=?jGHrBT2ZBz-ZJru2b&oWv|Gt`NQ-&I{MVIKlG;O+R5`gy z)oLlJY1Ql0tyjN6L)1o+v_An(ViJ{o4#R@GCBpb2h+3`cm7A}&QRU?J&z7Q-Aikn> zbkqjDWZ14UNDh+`AgHU6h$tjk5stATm6K81_NpP-1(`jE_mUbX!x^cZq>cbmo^sVO zAaW$b`E2KG^q)DTpjUQ&zOlo30=DiYhN+STiyHDrjihB;eRySk_W zN^duEP_~MUR64ILa;j0-zM3(s1nEBj$v*`omPxY|RA+k-8d#&MO6r<|y7>(RY&8y{ zH$okdJ!D8$?`-K$PEf+O>5Y<9$gSm|4q5q7eAr*CN zqiSgw)Felml&Vsz9ieMDFh4u1XCG+;YwaLtFk(=?^k-?(y8Q?C>?gUUA-C#j2(K-Z zEM^BY5z2DsRC=Xcbq=Jd%0JH0l2)gLxm1pENQd3PbOfMQW#{!mzS;eUWFs1WH+`T04bsyA_|P1?14Etv_`nJTDj_?FWlb{y7NqKGx?i|T_X@b zCech%m^5V4fk_UNVN517Q5qqK_Dw=hD=&8>D3al z?-;FQa-7LcCihtJf=N&-#89ObWPO;706`#OSq1F6hV(snbcQr#xSLyqOKZe500c8j zi-84UxdR6E&mNGSSCHLH`j&Nvlof7`>|VBpqZP^vw+hj=T@kCRs!853%s;)tdiKf6 z50h$jg?=iNf1s8ex+!(seG3!1A&_R>AqdGrB1zS?2a^IOc}#McIL+3FJ%4%bC%?v4U(P>-(47u$2gF_Ve&JxJDJ>NtzQmEG!sJ(v`cclp*g{@874NV zK_56QP)gjZMgG(W!naHs=fb>sE;K80!ERyp0F%o~9gheX>I>-3#HX(^&?DZrMqiY} zUS;ghsG)3DDay|t$$ba(2i(>lPRCFRvW4O;aRn|-zb&6)OfVYR>~NI6n3hf z1M_lndrRw>b5Zrl8j;;Uw?{(XAp`TI`C}ooQ4Pu}=!4_y}oHx9LT<}-v- zFd3xP=OBZW4DXgCl(pWKJjP5xo^!tdS<7U%z9!~|Yng-%I4T&Nd4F*EY ziHXu&mL2&LvKLHjr$eE}0-7kb29zevfN&0zi%d$GwEN0f>T!t(vvJGj4Ww+7plcY{ zMFo(IcqUu z)+kH;D!A-jsB)0zFIL$}=}VOhei^h@N%4=iKeG%;X65)MJCvD=<0OPL-8EU|3pzj2Wyu+__LpL(3M8GV3;Jr_2fLCJoxC zya@bg2uB?(8?Ev4ENzM-Ct)`ANW`~k4$4LuzDgEX8lG`5TSGl@$ZJ+W`u4cdf06Z@| zsKf?kyVO1eJmU}&o;#$>3kr|>a|D9+M}USfnSK;xI}@*CAh}Go9#d`wMHRXn z2cF2}=y9aE&g2ENvrYhQXR`Gqh{I{fWG0bJ;+a%sQin+kCRwLpC!GPQ%jATD zUXYz{X?6RK5*!wq=ve{-7gdA7L$msqI;h1mdsUshUdC*Cm!KqbO353fdzfC^Q8)Rm1|*P?b_Uh&DTt}f?&|*_rS=>mu|2~dk<-K zAlQ5GjxBTGpzJ)XNk)uLR)FVDSXg}`}$M;C7A5qKx z&Lb%O9xIK%cs_eQLA(jkv=+I3Q$P9joWXpy%*9^rE^PCM%E-FJ1>=u>igxowQSfzw_0~zr<)fS zsnd1VE#9ol(cRYR)SDM?R(?ziY_rf-Wfz|xhsWd;Cd1>>FZ zJ5^jer%iS$UFT6cT?hVu2L6lw8It-s-QT(%I^F7bOq2gn7x`7c?=I;wilip}sL}`r zmCmjelNb=UgZ8S)IxkRTH8}w!F9f60oU~K99aQEu4eq@XPIWCp2H|1nVW*mBtfBoO zKijBuzs}vLi$*zS>sriMozN~i%~mxd1!S_$4%Dt{{=FKJt96@oSEFI=H3BK@Vr*1> zb-(Jq4?&garl5Irx*5lr6a_ZhO7`jTDxF_IymG}5?J)^rU0)`7x>34&x+2f!HPGvl zl;*9f74}I~aqUh<-evR>@a?z}@v6niTa%~6tL(NWe+f|wT|-^dobPpOQIFffBRBkO zW0Yo~QX_Ty(KeAfJ0w99wt>%5Q=`};QS}-LuEsgIsrbLOYjs5rTh()Neeu$SKN z1!9Mq)^|y9$QtCJa!Uf=*!&DLKX=-j*HVDZ*;uYKM?>z&OOlHb;;REyg;fz{8H$S^)!NB~HyrQ(iW~8W9{sliN@kvqa7nS`ZBDC(# z!z&m{wCQy3zTttvPcmp`7&MUvZTFLHRT~VNufzlgDL`a)B2VvktMUlg7I@vvX)fw zno}lP-@_dag|cmNFr4jO^8azRv@E5;=qx_YmQ*UZm{q1R`J7!|pePHM2GcTS`_j;m z@)0j9GdB1+D{q!2(oCcIayGYNb0ul128xQxFUzVZ50|>wa_z2EUM`E0m!VbAE>jKK zZqo~P{(|Pb{k46lA$)7jMy2a=tqsCkExK1Fjeic8c6C{1n|cI5u*RsAastJKR0>GW z7`5?oXX$8;U%26c$y3yqhFF8P@?$4WXDJH_!nJE|`X4rEuLNJ$Z^-d45sNY@+-H4` zlO{sD(<~5~O(<9yvCyA>Qf4l!WSjiJpjiu~vCRfznWkS>tSJ{S zX={#W>=T1!2U!ov3mBG#yuPsYeddF5)2(M(Qgc57MFlfiqq63}P zn)PK#3@Uh4JXXbFwc4Ou-x%N1+iW5BvoUD4pmJm{Yq7mSvz5h4^6DW<>|z(C&6)t)We9#Zr13UAG@3mM ztqS!)HnE7atN@h^50sO8{gkvdZnRiwv?j{UwvFwLl9L86yG=QsntjTsHG0~oY+jQ| z`xVWPJ?Vfl?#Dn70eMV)@$Y)dzk zlSjgosvDcob1}<-v^MA&??if-6rmj0ScBf9jzg93VsBc_wO!P_I1jr+m6EkRz-d{A z?5B?CfiA2(-R@WPY*P#JkHz1Q;!1c2px- z$=Fe!f|MmYzVxsd&+BvCG^-W;&i5Y^CMn}~`TE9M6>oiy2*e+!tlahUN0StNv%4Kp zP30l_)l6l=-dNcpH&nY-MHTJayM`QFB7-XigWO6Pxj&2=DmM=Ke2}$Kip?@_<^F!( zmJMO6ox82m^II9+Wh3)u(oD}=86C~c&)ZUOWwbIeD<^HQcq^l^iTS?ocaFC*(o3{y z^RC@9luY7@O>U^PJP;JlZVcL?t-o>Jkgv{gFxgkRclA-edfBoJCs=)X;8W_TxF7Ua zbO#e9xeK75GT@*qbrYGNlfN?i;1|?W2|6?ubl#zm57GBib{z_(zE&j~pu9U2R!%lh zsdYF4vdqK2AJPt1#vYCd>&xX`JoxAhL*m=r;{rNJCCl>Fa%qhXA(6V8!c8fiN~J?d z6t1EWQyw3r!%5UxMW$%Hi-sMUFWHQPbBx_Ek?Ty(Md`=)6ULeS$*NSS)H)dyJ)Y~O zY=ZK0m}1aeC=*OEJV5WBpo}{iOus7&PNvdC2z)ieWBbuS0A*(`R_sZpBFw;t@G#HrYVCj zbo#jB>V*{N8Avfq%C~8wzNJ*Y>8&JR4ELXDj!_hJOiE}DLEGC6(? zlZQ_Y@*E}TQa6Pz`zpU&@>P~x@}^lz@uf6n<0Us+OnS0Vq{~_KjneCKrnj|Q)_$v; zzr3HiDc@bmr}>JH?CTNed&X99$XI|?s**uoUCPfe@oP%?@h1MqQa<0r|5VEN zGVyCm`3@$2T`Aw##Q$8%*D&&}`OZgBJUsTF_nE3UjytJ&1O@=1c;9}6$ zd$y(ehNsv(${UoY*H_afWx>uV!%UqsfIlzLjMRB{i7+34R+>DZJ zNF*)7{QTf%L)uwXlh@hX{&Y9jBrLB~>_mM6sF4`)4 znyPp$<25@_iGA-ZsU-1>2l*E@e;-cf4Cc(D?Iu{?tpgWAyZiIR7_6rqiWd__*?y=j zKXKBILL`4l>3-LT0>mz7s$866PpL$aBF}*ueV8LFO3Hgo*fGV|9B8TZ!9fx`@O7@H z|6@YL-{=vQO`ejA;pq^$TdZjrF4#DK>q_xh8TPxa z&>GRli-N?@p5z6*$CILHwYcj^!M>bHS)VYSIo660FV4jx?G%Lm)Qf(nmg0yv>8WM0 zvk&dJgLHBOs!WT;rUukibeCzI-!&_bQw*`=bKK;eVr&p4i|8P#^M5fYh5_n+aq)&= z8p6-mP%2T=wPG(VjUqZ(JUtSxYiv=`Jtc8ND@BS$QPiAziN{eCWP11&M?{l7*2g0&~qDf|o6%{Br#Ny1v+a8Mp7;L^4H!F}np|@4q>oTXMfxR)Ge&8wt-e@)JL&kzMi7 zN>qn@###kssDx<7iNgt`^)09IlZ+}UkrtqRen=!g&+*o248eQCF(@g_YWv{ZuQ_l&p*pd7707vmip5TAY$h-O0^j&>9cB z)k))v6Q(@dIt`zL|KBPRRFxc1hkRTX`l=LW!jWkfqjO3&4xPq}6Ybv99nRnky1cA@ z*XIO8@o71CiUf0Cds_4ttimzA2&h8^|$`XPywpe-!)ea~(ta0O#p~XzIR(z9! zK_kTN6q+CQ|IA*4Jd+wA`h_*f#?A)k6E1aCbct_M$r-Z@Qzc1WYIH|SId6aV;3S-DP(Kfg=+@_iTa+vSk^NQ! zHM?5;Q3K(w5$|e{3{F!M!)J|1tx3t?`qreGSXJKCL|%46Q;Xsdbc0${yU@ zKDOc3E#taxk__K@;@{3vKK?`0CXw-Ack33PsbfoJ;Y-&Y>5N;Ke6^L>bWCLNhtw_V zHT@4+Sefb42j3T$V}TDaFHzZg??Q7axMSjS{oH$TP{li9j?ZJHqkk!YHpzWeiM-}l{qoZK&?N+UV%N99KT-K3J z+94T_%pzTnxqYV?p~teaQ>@ZcKJ6Ak>D19-50cI_$h*aubkyx`F+ZKAOZz2(Gk&aS zTZdXAk0o^|Kh!!8TnbJ}w#(4^NjU+y_f>(VE(X~i$reCx|AzOiW*U+;VdOgFK- zE``_}LU!WY+9ZoV>rx6G6`Fd~L|RN@VHmo4VLfWXN^{g+J$lw5BXv_iL?w|$vWZs9I?7FMbq!%RAa1I)@$07Ecp^w7H-~>>9VNY z1oNZu5s!-%`HI-xgeuS<;$9O96Std?XO&Gk{{N2&Wm8U~eAOx>p44hIrKVy*Q%baz zZ$gRtT0e2TDJ`PE#Gqz0hi(BRU}{;<&?I?$AUUE53{ZLCx?LhHy*7NYDoW6dz+_qc;cro|0g{=5`2g+k_ zEj!X)EQ&szC|<1VM3qCAmakUJK9W;U+~`C}VrM5x_x-P2m}-OUNh16`x_eS*LWdK> zJ5v?UcUETE@_SxtWp$S3N8_#uyZlT^r52xbL8UAcE4omqSko1wbG5kDg`z}kH}Vv6 zSE|9tU6Lh{)0G;~f8xik6bz%oT`3da7oqG6KekYb=iMkM*rE=Mw@qa$Ul!Jx_zbE< z*F@(Gs)k8;W(L(J8*w}Xe!Gc;OiJ~(NWLk@3kNnN8j(p|L`-)|5a_BEFw$bX(-ABr zFPU=^!C9Eto%!J}T4h1ht$0KhttQ!3tx|2}>8;Y&2H6eF-W(U)+=6izwR=(p&lP3C z8DB;i`;7RyC(W~7Si)p4aiSmGx9^3DSR{t@LKBwsB6qR27i#ODUgUUE+%l=|~HZ>6EvMB*gD2w!eDOh;t&^$cW=1@Z)i%CJR85vzUW3pzE z_$7zx`B+RSCQUufGS*bD=v~^4Eaw=b&9Y^h0*fNbA!1K&>eNh&swhok-l1SVvdF-6 zTCj}0_wSf<nCX7)uqi~<^$8mB6~$R13|AD^#y|KG}2uJyl3YZrUw(;W&=hl(!}>fou@ zHgWt90n}yOBTyd$Tu%fRU=n%#hTQFVlEw6Rwt%{!t0oVn_0ZfIN@vC9;p8EX45PN5 zjjgkin~22WIC@H^4jtDO^T@>E*cmhvTZYpr(_C#JL-DU8=rak@w9!~2jkCRhT8Q{D zG!^I1;xS~PR>Ed1rBh?kXDmff8`Gn$m^PMl)J|+2M&aWASj-{qiv!1Dvqs%T{X#0h z=F5CUS~Old;LGG>OtoI7CdEM6H3( zPePM+7y8d=uT36Gh*umT4iECxZKPXr_hO`~Oz?s$;EA>{`}0fcfd_o2xY}Y@PRtTrbQI3l`sU5>z;vEY`ifF~m-7~<>@v1Y6&n!& zRf+LU-jnhde-imPnjSksq}Xy7?p*e>#`iO4!~$`j*Cc zY~Prq*^q3T*#KXcqmM5&O2yT0$sHlVVjB828;ZZ@QPqz+Er!#163s6D{X3dMA2ks} zf1t3BYmitY_WXd|s3KnfK>yaVZtqPw9=I*FZs<)p5%Sm8<@d9Bg7G**zytEHKt)!&h{sfvKm8cq3E=lPJej0vc=?KGsoa9 z`m7;Oubozvli?!o64Tbu2CseP<@;HlRQ&0WlxatI#m!%-89f#WMbwv`h;NJNS>b=0 z{|x$dHeb1`uB0~Nb&rWbKVi+QN@lood5G2wpDLNvVaM--WhMr_QE7r+^L=z?Y3I)P zfapppPb$Wl#h~YR_hx9cW0gVQxpSe>uqPWbG3X2Z+8;H;#=V_w;3bEZObq&~bDYB< znamO<23>#ibCCHt1nMtX&BUM^WPY-k@1tcV2K|!RwXc|oBX zN$f^tCI)@44Hr(EA>W9YVKY_HYk1|wNoHcu^YPdWd6hClUZh~xp6!^RZVi|2nBfqY z)-L4XWtOg5pMD!oJF-(I2K{HLU%xZMvA=iy&kTRP zvZtaM&J5hQ-weOJ;Ca*xLwl;o3^&Idj)u?f?6Z3fqtk@T_iD&2FzB`2+e2)G0e7DM z2g7!lnPesgJ--NtPJf4F1x0F!W-Oc}w5=*`1p}xApwR2*4fvrF(f)Vo>S% zyA%jY^xkj#`U2e5A8NegI>0^s-?!UU1Gul}i!*=+diRwJUIRSTf0kQp1Mo;sZKI!w z%BRRTtR#htextNpkM;aA1d=WWO@%22%@Z+k2Ss#ws=ts~o83Rt^Y=`e8(4Bn%M_`9 zx?t}?6|bFmw-? zC==7k?a_>vWqC#;j41{$$&l#Xc;H2Y_RHQ;Cp$~}F(nl__zE24*+07+1&(2y+P?@l zt8zug?QS@7$>WVSdD&OR&OHcWE9aG9&iMKsvX4q+1ODm>#z~AD{pf)6r(Buw?y9R! z11AfYy||aGB9iu^qgG*!Y4pie8DF~i>8rAstBGtFODX0|zTb-+Q%y|J??>0~g}*eT zhv*0PWvQy0EUKQlzAF$GHQ0hbdjhV-`0?c`7%*~e#+5owJ6M)dXU?d`KJ-<+XtIxj z3e(x_RjnYdjXI3^!>Y0*bs?I98$|0`Z7|q?@g~<}`;b?`dw}aRZZ>!TM!MX9v2jJ? z3cz<+rNeHj{$VfERFc{d8hoAMuTqslSQ?j6KFTx{tq)U#I~y5{YbFbui1_^&cMV1J z{S;76*Hjch7t0CCePW^KuRo06fs}b_Mxy)gxEg6FuE3Rtbv6bPyDm~l%*TAa!8a-8 zd^HzM5By(p{_=8-sB+dVNNl-Ap-n#KoWF4~o3}+Y zW#&hSONS}QbtH?QPm&HH)=@%zgc`e!W|6soV?@Uzq%R!HqN87T41?9DjGNu*z}5d5 z;|E^d?*LC>{BV!f75FR04lVZ{238nrw*GMycpl>_Guzh&Uck8M(&L@L8ySD)u!-%9 z8S{4zz*`y586^CU;)UQg5r341xo&5fIlLWW-BIf3y30beTlgG9EA3&?(3Au&*IqIH z7&W4O;@~mdpAZtW$cM$N5(fcZ{h}YVmx%I5)O=yEJxA7?1l`a~HTO<9Hm{UZ9OOzFr${PPo-<^Oajj^r&Y3#=F!!Y1) zUGDP&QKR_CC2S+8k+^gj?*|(fJ71w&R6UL-$i?3`@(`>fD!gRc8OCwK&SuKEs9K8rsL&)o5c4f7Dag2P3uRJdH87CW5+r zjhgrta(No|cy^qN|LKL_o}&1liR#z!9%C}A%$v5)Mb>rlcAdhaytFO*VD+V#aGeGf zPG^z1NoFuMH_2Cw%}p|sapD0j*Y_;O=JSBUIJN$59CYNb8Mlj#vX#?!7C_iu9< z=ROT}fczWAhp*M+wf|ej(^Cr<@u6WJGxw@w?+2dG`26vSI3URj7*DufUkCgh<3h#b z7VtvGogd}%PIj5mrrxDXz{?pAcvjy7c!kkEE`j^kO2*gE8zEGF1ElwF?R7ig>CEWkMW?tHa`MBz&N$n3~sf9j4u{WAI)R+Ff%vzujIYK5yqQB zt8pzHWn8OgYbW4ij7_I9mHt@2nf$5SahBPR{Ed%-Cm09+wL69T_b4U9KGJe8ed7ktZuq^BA496t^YvKa9<1z<(K=r^mO9 z_id}j9Yu}H9DUB3SAPN9GhSyXax5_v$_~u@aPJ`x6&J>Hg#jl~*@JQMtnT-KJsD42 zy0IE?5My&ig)%l*R6Jv2Md1v|ICbhzd##UB7^*tUio~=O5+$T`uD>oBb*P_htO#LA@y8 zevHqBE#Mx|pK;weKP3VWVBGLR_c-8zjEk$SMZAUbAZBX5OvEB54`%$yit9W|^BH%} ztjdiwgz-jA0Qd6(#vN*I;VwLsapJ~9-1UYr9=)q6_p0HH%@s9*vALo~GB#J#D8@6p za7`KH(ae}@c?@H7ON?b~Zi#V>@4uSDB`ajCfAoy6HO4a@dCfBxcmiXaxkGsXe=63N zP|b*m5b^5FPyH81|JZ9pWvlZ6Ptw@x zTBH6?%vMX8=XXYCemV1t_9mS-^DCKui?5f={A%Xw#-*#x{Ey84wd(XaGryMkwuNWT zqQh&{_{m$$)e-388e6gX9@TeU$7*v~eiqL6aW45q)OmqBv7GyOL-nf|b{~hTB9mwx zi`E-)8-16=@wdyaUpBzcM{cz~zmUycW+Uffx>c2n83*j!!Bgob#^$B-Hxc!K!Ygcs z2*2DrylzpDL1sqpG5LLUBPy%H&88|0V?B8NY;=LMXoOE9W1b+k-;Ivl7kr+C zxw$m%ayeYG$l+oyrKN2Tm?vuXyx;a&N z(Yj&b@g{qmd5r2i`yAE!K>Yn25j`~3ZsH5_q(_XSU7uPwdnO8AP#e$Z5LvuH zmtTk%FR4cSNo~7-wD+q_sf7(ed5d!V-(v3H6e7C3qzd8xf7?4|+aUjKoj3mZ5$~e; zD+(6P|3zsAy~M#h;cv40NR-`PQNo;^lC8<85Jo;9%Us-hMH&llCt>*ijq*SKJR@Z8 zJF*p;SCnkSjz#Bx2(y!nA5@m=X1*fV@a^SlV_P|Xi_uw3gYtfvmcXWVTCvL#}m3 zWBX{?FGrQ*$CTqol;cN=&)y)cSC%>9mghgR^*PgYRI>HY^X0~3(p##=YG*gg-|a(j znib>zqpt2&3O5^(@t&&t?DMRM7kgH!7vjwuq`Cec{b$fyva|O1Lacd@Z{fCoMDg!? zNC|0at#zIX1$}Nav9EPB(Yl;f4)?KKAR%=cvP+ib+X zlmFvE#N*G=%o!tDSGi`p7(-HWVCq*h-fA0VCq!ANgSs~U7?H`h2mVkQzKJ=^nSCNj z9v`Ik_BFrMR!2&cuD2w43U}^#KO%*7^#qCQl2lEs#UDiz_CVH!3Br435w4ah^8Ds2 zrsI$5;I}@7_{sW*KJ67^Rdt-gvg3yH_|UqAY3sPQb=0;UGwvFP^@Ke%vXNq3jN*6Q z_MZ44{>-MdB_;N?AvzJ1J z-cGW$=hry~xtW+|CxwQ$C>Kh*a(q+K1!kUY%86Tv(RNa>xM(K@Qlc>{vBN>KE&VGF z|Fcjgl|^ggVEPFJ-br(a#&nKh+DD6W&T&gdJ4lH(N&L$5gVrVzC)P5Sa>YUi{NyXx zL2|HON2-}~X$1`~9m^a{z-iWk9f1Sw2i5_fQGT!#cOCF1xQ2xw$+3JcH7&{_dOJ!U zR7;F-lqykevD{H=EM_`M?&7VZR6*=BBkyqjtBBa5q;p3z(y#UNC)H$89g|4(c9LR6 zwzCv2esPj~#5_i~8J%E+t9BoJS()UF;aS}Ug2@nwJVsj>En)P8(M3j4E}7VHs}v^waglsQFkY#PO0Ga(GU@?@?<$dBIDV`s`B7^z%LyIm zgsap7Us#snFwxCTN~E?Hf}=?8$ls^%k-fdCBK7W);|E!X4>Eh_Q!;Ibs&zhX z{Itb*+P5$}@j=?TOj_@Z>PpI4jau90=NA>VlYijf?BmZx=uhlTIjpYewUXN9+i)Da(w5B8V5i`_k?5hT`lN&Q7lZz)o`EQwhj z*dt_mOZ}zBY7=wBTN*D4JuoYE@j(R|QQ-%)q!bk&@R2^3#6W*3%&sJ&k3s&N^9V8F zDHiyPGK{}$(hBx8wHT&;MANud!^Fw}G{u)Dd^JG&i>8~J<*z{LGki{VN+X4cDH=3f znk>19%OPmnEnxAv2vk+XNe!A!D?{)~EQ*2cC&1!64Qzv4VLMfp{4sSHTXdH!jlzeV zLxYfRV31^M!*_QgHdsm$D}yk7t_?=-8OS;O2^JqKXN4fZkYK3p1*4~QVzfI5=xZP; z8sB(2!{8)~qe38d4gng%rVSarWzz{Ei05cXspn#_lAgp9N5uLd1Qk);l#MnNifU#> z$51FzO^UCe5P6|+wU15enoVAZViR>S48t%n3`^roF*r<$c01Lh-wV9qF|Hf(ES6QF z*+!K(!e)vIzYmjoh{fS({fXgHsI=c)lD*;hdC=FQcLYAD7$<&+z>vMBMGlW6q?$BW zRMg@jL~pHBOZvu!f3{RX9MwwR_(bx$R!WoRmC0O1i%87b^G(@}jzo2>SBq25XsnH3 zXoENvDbZkZG#8Q*4{j&m1> VFgF%19*VG7H0UGIJyxppe*n%60c!vN delta 22694 zcmaic2V9iL^Y_gjz4vkt<=`kHND~B6@36PCpvEMKAP6Xmh}cU+lW4HS_NZ&@4SNkL z_TI(bjj_do1$!*9y)(}pa!2z1{>jIAzEgH~p6$EO9=k7F{CeKPu5HuS?S3bag#%755W^QH`J~Ci) z#EE8Mg?36AW4o0y89J_k|HANJ2)nA30VH-DkSSv;{m^y?k!M7l{n0+aU#Bj}$?G9w zjs4MaF_Be7Y*c8`he&V$CKwWc$SDxX!9Zls5vdo1qyv$tRH8$X$Zcf(2av_tLxki5~rY#F-~B=$6KZ)P8i8TpF4&7+~A_`R`cHBZ0mN zF*4><2TP$Z5@cg3gdP}bpRE4<(|csG-|Aq3`DB~eJW__awaf3EUck1XSYohR*ll9W zQPU>9dqH1j6DMO>Q0=t&EwfodoJ=maL|wDK1zG9cd$Qi7HA6wuA^8RDw>W*$M!9{v z_htu?WzXU;Jj-|_?(xV56KNwZwT^?e;&p3JNEF{#2eGRSL?4@|8oM=U7nq1%1 zOw2bcw|^E!Lyw$nC5vx_$*(pN2ivstYTFp``lguTdQ*%7J4IICY&F(~AL}Mwx6u@i zXok9pMCKA%Lu4nBG9uTBJR$Oth)r`OUPQu()F;xiIp$#93W>56vcW{ciNq3VN{SDy zus&P2Ml=rz2AnrAH<#^ejg?^iiDZH(GF!D38fPGnaC_63rVqx$hmeH!$Xq!v_}$-1Ori~41dPfS6wE(K%Rog!-NU2X2BU`Wsn z1sA%B-R%7eo24V(oPpBjnTWD8F@t3|7O|5=-eh8W$1Fs3u+_7+M6!t;L}Wo0YRiaR zC&IE(`#p{vYz!g5@rr%uf&Oat#FufD^-Ld<6_L|7qTRp&`2z=p_Z%X(lTC9F0=oA^ z>k=ZLd!ie84kqcEgKWPXWPczsRn$26+msSKMC5pm*vBEv^*LH$Ba~V-mX6R1RV~GJ z4$&P{xd{8`qLYbz5KSfWtPiqwc}QyIVQ6g-VLgY3v)Lq@l8x!CP|VH^LDR=W#7mAbab-hg=Irw@nJIG_fho*n-TUTc=k#D%#MwxNmYb6i-m8D# zJeKqW%1mVW=>vL}Gmk`-B9uplQ#e-SY1RcZz9S#krfkBA*WfAy++7_C!sK& z$Z#SPh#WwIiAP3YfGyg!Y05545~sSj7dD%W%CS?B@F|$|_*6uH5P40+V;YhOBF(0u zb_}6ugccE6Hw`1*PvjD@e-V01S~C$@8zP<}vNedriP*hBRu})J^W zr=X=tbW}`SOnmJ+F>&FMGLxt}@sR{r=nQmfHxq-mkacNTD><@O-LC9AKH3iLl~r8wI?f~{OBo^bbO zD^`h*+*8eC*P{Bsda<2{yVv>kG82=?@VYW2kx{Yqh?TK(8_*(7{Ly1I+xWW};Tg^L zZxXwEMvEn$DeTN<(NW=V6T1~{UTwve=eSMOC;}Ygw_%0{w_(e>wH<@lv_l-AP_jom z#F>hoUVV4cJMNO1;RqEKC1Y21Azwk{?JiLvG-S5B#jZk4R%@>~PH4gw>=RE5by@yF z(aI~Ih=rqnI%Js95UdSF`*m#&PZ#3hp06WO5vd&j}>$h%6!U z50N%yBJ&O`oL7d}CoxSwB4dd4KZU3rkv6B1{B{OqYlv(nvWv(eBIk(QB=YhM z+KFe8oF`I#7G+=31Raq;r%9`+e~nHFdGPCe7}I%gI1&%rM2cOPB2 zeHFJWXxeXJdTymwdtX#4J=oy;VuI2)Vlmm;$c!vblFVGzFfUWe<=uUJk)Q`yshS63 zk+OY2#|Icr<^z-tAv7Hc28PQ6Gg^+p$Ed0x=)sf_ylnZk)NNS>eUl5)IY*Jw1T3j5YzqZn-8f#_{i%;%4K#n_7)ap8j zd^&B}eSh5}pYLQcJDg+3tJSIM#oN_EBh>hxRls~PJYFcg0y47!1tb|uL>*0nr8-(& z+(Z)VX@PpNl)wxVj2&daINjYsnrO_{DbYkWU#(uJ&Xa80s#mG6snxUZ4;!!kT|Jw! z6feX(B;}jR%)$z4;$v(bB7uGVuhK^ZlSoNm3IdDRJZkMfe*8CQ<)T~`mj%tiA??b%q{Am0L)9>cG9ZwPC*W) zvPpH2j8&Tm-WabrKFBW`I1Wc86149siXw@;t+ zyiD;-zc~(r`xf-ZZCR6?f~@WX`W6f=nNV=qjqQC}k~uEQ9VUslmc_tiF=cg_S+?Sd zRxt&kLY1!YSJ_(+4%U{d65-Kf?GtS+tzxQH5ujCdJJV6NS*w`FZ}$R$x5IhKJftk! zR8}At?G`0^YZbE$&3-dvW{XW0)puc9#T)}^NRd`CSDe16w)k|B2PU6npi?X`WEP4a z7uAGCV(?;B=wbuK6Rql+WBT#UA=+}Sf>$XvW!R(OH!*dIH!Kmw#a&D+w2GzTm&G3T zisC9Wt(&#zxumv}LEO5Ov-K%QEHO;Eta{2YF?^}H*nP31(~K&W&cjUcyQSW+T!dm@ zUEWiQJ(!!7s4fnLfnuknez1acJ``6~TCHM*0VA2GI<7PjQIV|@*A@ph>L8chyQdhh zRdxM!z}}5mTlc4%`)Zxo&TNPB=UT=5szjSm@>;8yY#`~;gvn%LMX}0`JS6N@s5W9n zE7tIh0=Rgm4%_laGRw9nNmZh)86GHDE1B5nO*~PuPLf3FBxTv|e%cUSEP)fT>8PTf zSt*iP78?4gR^M?yu2o(4zNOim?au8-LqJ_?RA30}T)IEoj4f}^jk6aeffSQwghSKk zCR#r&ODxyA$tAZ3dqjXt=Eh1MFE;^LC_Z1|3X4Uvl~LF{;#UUSmTMK`w5n0C=*VWp zCUN3wUvbJxguc0*Ote}RnTDRW8CV%N z&+Ud9gQC?cj5Iq8&5SfV#nY=i#Z#-YV5%6iIzXwIXJ~3vR%ICq#eOM#Zr=xoL2Fsn zJ7SRYs6Tp&g@?@T6$1>NEEVsr4zyz(*zNK&S|_uu*^Y{XqWc;R92CD@lLm*x(ly=T zuqdnzfTJaeYt;ZJ#KLv+;FRdS-q-u|)@*C^er8hvOEon?GK9FT*+ ztu43!R$$e8-YeG%40vCEJg@QCVe5>`5d$qYYe6oq+~pf(N^(_9iyEQH@*)%(nHAk5 zH#(C}yEi`HjEq>cqZ62lf9|*>QFrmg&Xax)M#;2-V>Mnb{Hx+fMC;^#e0 zKoA@6o#?Qp>XkQT+bPzFH}`(|FJYwUv)|RVhEZIbGW_xNLc|vPH~eRklK2Ci05^ZX z9uz?o{SJi)2DxF`S7nXmQj&FOHCVRA46bXnLOap(h!UELqmR3Ml_iPa>SfO2gd?u) znxd_0=C1Ew-AnBzNX&G`d#NpS%=}*SEbpZzmaF1t z-+ZJk|2Z3nb)l*F?1+~ixzVZyCe5yNsN z>y9=TZI9VP3ZF6#+{Nf);~+!adF%(I3CDfDhTTg{Kkf@TMz4}9&OffKCd(7AANNPu zm*cKq)8>obCu%5j=tURzE4!_Y__TkdM`u=ETp$-Ji>d&4&o$tuOKDXp9RPg8YVgtJ z;aVvjgq}3X$=}J!wN56y-&$<-6qs{~TiG0D@&jtI_bN*+o;nNI$(Emqfsx|%GhRW3 zR4i3Po0~^!i=mitS_ZN$xNc{0q6QoBj%}1JjnY)ZL&Ym(G zFFIcN{=XF?uhg;r6;lji1tuNj_r$YzoW*lj{M;uSdD)cVSni*%6{d(*SN&mXNv*46 z!BRw%iWgd8y14UNS7C-x0&PT4*D3aEpHQO7V$2`@Fh%_Kk9cQew>TUMGsVS!qyraC zuBZKnc9uBk`e8^B8~j-Sv&9X6o`tzs9Ihh2;R*A^jW?WekUMmv4$K!n-e`@*+2Upg zq;qb1HCSL2&!&vs*lZV8lkGy;qH408C|fMPz8O$x(Em1NY(ue2HPfvqTT)F{in68E zWLr??R!z1UWyRHGn^3mwtIU#?dYdvzgyrJGTmFSBP=S?Xkvi9n;iN9CtmG%@_*Iqs zC>_7Lk}uHlYbyCn9ly4c@2un3Rq`!#{Q62hLE_sB8!821I)jasypN9my^?p(@gQihb@xI&MSziUL+_^8zOfoHDkH z>+URuabnV6flLlOeF?aT6aQ)kdrHp#We0G$ zZ=nqht+&P7nC`at<)JH5*GE0zZpjaid>K3_nfD|Me9Mh|Y4Ode2=)RCm>3Cp96nO z{Q38G`1^h}++LiaS4kgm)#|J|zPDgO;AyBc6Q@u=&|WRr^3I z8O?7WNi25#Vl6iQqJZ{d>X!hUI$zb&T<<29eX)iwWLWazixPBM@fd*Jdg#i)-|icF z6V?7-B5L3q{Y`0827#tuOU#u=*nq2bgyzrD{%^3N-Pp88F5q6e!W?=6sJNpgH2*qe z*W~GzpoHMkA1z@i`|2ZteE6_PDQOhPq*0|aY+x4H8%%?#Hn>=>ZwFyGr{vf{h2gA9 zdy%y~+a9`^3JJK*=11)zNDrUeLno6Id0pXtEvRo_EhG5k^e^)UfjnSa`ELSIKx$F%d=cS18qx-UEr`8N^=Fk^*Em| zz%{oUM%ff;Lq=uW348b?FX;b2bkV$R7})a8-tZ2VmbUYO{(#Q|zECcQ8>MShFbrT< zX>cHZcVR*T?<;~k?-B$}p*vp`1YWv_Tj_-$FbBxw*Mp%ktl-KT5bTtNbyD@-Sd$|E zz6N;vEUyyM0&98|i#D83uK}9yY@@VUsSZMqY7$nA14vOcuDXSu974duHOI(8Hv{+L z;UTE(O@aBDWGjW<{D%;zWzrjMX$@@V-MS`1Cp>bMa6ypu8 znS#HkV}x~)kOrfH#f4(^aQD^0dS1hE$&rMeEHVyU z^}|Z@IA{Yi`HVQ2Bc?C&uo=Af^!sF%;USGgQh+Psp{dh~sw&=^-J)D8%;R6;aR{7G zh3tu*6Y4^QtC7_dv|5N|!=Vrx*G>Uj(9r~NfQ6LO9UF+1(<0-d!=07B?O2)6CX27C z3!!eQlhDy(V@t(lDm=jiqrA-R5+KwZZI=8yGd?T<{5VcVxef-gZOZn;;%XlcK3uGa z%i}eCMLjIKHN31IzS3G=Q4a*r=W0k@a@`}!~iO!=ewxZpPBmJOgLB=DF9 z(4f$ihAGvZx$={n@7(@!B-U*= zN&Gc++s3UvVirbbJyPtp9?>P&Wz9b~0Jj>t>;jipgd4}CT|cKrGDcLu^w#y&FbVt8 z2{pd!c3zGTwuA99HOfph;L46>a6yAiM-9#|yLg@k`~5CHTLa$CyNv2&6E2EF_;C%W z*={E7sd;!J#KRumBM~C;F)I-YU>~<`2;W)k$D~uV!am-+Ar|L8KE5IR$__E!I*0}H z#75XickyYBpupES4{b|g?4^p|TxnvLYGd)OI!7ZCWOSTAfgG*i$XysOIeVuJ;QD7=8qDG_O zb(=x774pTYzhK=M&RGpPZwdwfPHbY7xSr8Gm%{fp#reviIgaY4JfS(%#p!B5b65t2 zOR9R^ri?&r?1mFfMgR&7TXlv?RzPF+MWcGj!g1|VHHm|8xtfF(K+?36KYl&mi z6~4D6&PB$vRZ+Td6-5ju8Gdiit+F2CbnL+~f;egFD=k9((~}eyTMrg}-=zEzE$srIu|V0N@@EZwomv zmCtGm)8PSk7zt|LyB+-GT5jyu&87%XLU~jO`0};BU{xB{9z4Jxg$)90 zgVOawwP560!2x*sKiH{jbp=P>qzlAi@?l+|w$mpg+brR;ZoZYLE7sxK!kfSE0%`0E z_#bZBt8P?08}(1poWQUDwWdCd@XTfs}$HZ}FO5NuS!vK5K z#=%+e#jvVsQY$FsUl(=XF~N^3dqFgJ=mnN0sY?ZaV(YQg;oPSe__GWJ?}ksF*bAKO zhMgIz(rj0km!-zzVw(H)f+&8gHw3#JDmNY(vsVg%RN5X)2$G(1VYtrTz(;4j4_{u9 z3+4HZr6S3^A@j51j7Mr@Lu-YLHM~xNJOOk6-aeJ_3D8Ad1A-LB2Fce#xGz@Eb=x4AmeK8CM zGo5b855V<0XvMpZgz?atmyZN3XnAZQBtjGZTOs)4?ofKP<2wsM4ecomKkhXOyM0n= zt5LWD!=65HGz`GUqtUp}OW~Lwxf+i9#2pco_VXDVn)V zh75dQ26b#ragMJ%gB``UPX=F~LUd5=Q1{+fn;-f5)!2UuOWmj70Oo3Z(x!c)+v}!J zg*vXqw4|vznXOWV`1_-(T>6mry!t_(fr}d4cN$o`8Xx)@>3dAWCGQ>%A_Vdk)36~( zIDp@phAUzT2f2+ks(+k_bRl9I$Q+Kh~EkUJaak@|>jahE|nF!8K z2AXJw>)>(vK`VYb9Eb7z%L)vl#tfM1GQlWEY5O{{^yCbf#^6`pZ59Olrv>jj4}{W^ zSH*D$Wxt=ay<6ysNRGkIR56{hlT zOR$Yh<};VTKln~kTI1TJw9~4kwRnwbMM~>tVv0vv{Qgp0T)J>&F|>r~yjL-_f*BM~ zBJZ*sr@$>s!JgM$jFVogWpD;K7nb7+V-`JvN;fQrwgA7CV(mPFub&|1$;Cg9`?0z5 zX(wF13Kz)51;>4T=3+Si-`2l~_gf9h|828G>LLHzrkFqZKm9D%^~V1h&r0574URZ- z`S>+(?(0EcspK8D@Ud$lz-gyZ`KH?7{$uA_*zB~gx_m#$BTGxxL7EvZOr1AFYk17l zHbXCX!jEr;mxUh`AGDhFCX?-D*W;Seq)0@o8NK>#Ej`@3%txh%FT}LEXxE(Vh-fvE zQU{&pxTy6~`sjmpGzdwfj8;Qm`1Me-Bb63E4i!p<8DvOAt0{E*rc4i8^sqKTFIl7{ zqSf4(VXZ{T7?Kdts&nx%+-Sv>tV&&{~hB@O0_Aj^p?A(v_PM@1xUBP&PfdpEOs@pdx zmY~Oj7a!3OZ#u~YB3cc7IY&uHl5{N1+y=jxS*_O41qNLI9N>TN0d3+DP4hs<1IQoK zJWPHWg5bC&yZ2fr1Z7e)LU2-(H=xWO!3B-YiPf~Nyr_wsU-BBkRX%zzC=0J4G?mP8 zEm2-42ia>H`dW$L4-M_75nR`da4Wck;7?7C&5$qzH#8q!9wBg3^US8bOmPjj-x~TL z8%yA)ZW>t!CON!?Hn%l#k)Prb+|jH#lSkk$O=oQ;fwa4tq?ZrwAiAfaTOkPUYpy-Y zgL17*L$_B@@IXT+*$B!t$6D+mhYvMx?stks@JK^vWC$K>>{rbF2f-7~n4D5NJ*v<^ z$Do&d^a*fPme-+Izg78OPc`&C1SMUxir^xx;u-I^3s*Qt_JMtu=bFoD4JeNn8oJt~ zxP{Ym<%Vr5%Ix&Hyyj8+amxLhci0a#;0+)B z67!t2AMD_*F8>XL-$}S8#g0DSS4Q)XE}EBGMWhss0?`Lt{3$;2kNY9XR)*bB^QL5{ z3(kRNJox~q3e8bu6jhw5BoRoVk4>;3OfxyAvm{JMTZpX))0q}xYr=Gvh1iBL^-ILI zgz4l8u^r(aDO<693igCYXd<6@BjZ5~omL_CBuwX2h`k8^(Wo7UD0ma5yFwVQuCN3j z;4dn0LTh&rj~MD61UHY}v7c{Aq3cf9^mQVb@(Bl_F;nX79mf83=zNtIKfM==L+Irt zdf{P&+zugXPbdMAlikxve^;dm#9*X4NE}ffN>K+j=?J&4`T`k*m5S_(I$%CGl zS0#zp*~Xl|wa*hR>XHRrw?bTx@UuT^V;>Ug6R!2$grij{8|ZWCeFPh;nh!eyUWFPm zdt2X&N+ppnUDT>d(hx;OcwsBTxkcYATGhlJfoGDLrfEMdc0r*L+55cpK7hC};nw~7 zVCNT_5SAu6dV9S7RoMy0Ybr8zqf1;<)ZiTt51FhIqNOym(zd86@O{_7&z`Kb(mYDi z7QE|G?1fGF$fMv=n{!^outZBE8tWAz(bFw-1ZoFI2dQs8u-np z;8Wwje0{*HE!BK!`S4>>RCE9Bstxcbx52mNf4QQIF?v_+F=`E6ebMtBh;I@%>P5Az zIs!j+3wI|?x%N0H3dyTx_4sb}Xta*&gdA2})kqdchpt#1q^N9yoe3wssdE|ST?hw6 z@Cw9TB^x}RMVv~Q&TSE=5vGr`k{8`MZe{m{Z}|P=kZRkFY;==@kj|4%K$>lL66pqG zA(QVq0fClTD56Tt=8sQ6W7{5NaUyRkPI>rUtzH@U1=D34g;KR`&g7F?ff&ttwxpJX zs#->lu4VKfy;kT=RzdAw9M)U)A^y4Nvr4`%@z&3})Yj|!5kJ!X*BCwDpZJ!;jvUhS z1BrKAV!2Px59Zbp8 zKj=*5|1;qyPTd|L{)KSG0To_r6ebb2Xm{{9;%S5xJO9K%NcfF#?J3_hKs<+V$+c&D z5pO0u*M@BjFXm#b!V|)O-Wh`HDd8Dm<-^B8 zh+h!yv-T9O}{RN1(eMKUD_^-M8BGmVLOQM^(-=Cq9*nQ8<1Fhea?AMoPEfLH3 zoQt5c1zc!rYL<15K@sC8E<&Ow{w||(Fc(Y+>m8f&fJ;yx%y{}GXd7itnie@xxL^`+ z+b`4H-oBNp){^kRrJ^5VD}&V5{1&CQ;ghc5U5doZps=+yP}}hym!W>TJ&AlKSkQdx zK-gh;2)(l-;b*_zp*hcq@ao++2|E-1;XyV<;X>F(o=kEN!oN6QrieTV>qik^)fK^rsx{j`H)Ee*1l}!Ydi>keFYi^DN&At#(n&mBc553(W@3#RuZZjG?aYr zHSo75b=4f;$EW;(W2urm{sGP|N#1?q^{JX;mC#7#&tF{oYQQb7;rECD?spBFW}rbZ zLA>uZ2n`B0jDr}>ihAFg352TR2-d}+6INzZLzhi3#o=LZtPA0fZ{yq|>6`7Xn_z;IQE-DJH*k1N4{4)L|mJ2?*#|w zn`jKTxsF{smJhlP>49}f@NYJcY4WIB`tdrhD4-d)zJVVV zo0rzV0r#M8KQieuv>8-RfRc7SD2)(s?@=B2gsS*({V$85x=PU*@F};!)ZRFwVY-6Wdq{aQR8=jH;kv5Rd+@!3Cx#>GO`2uAJVh`5 zOU0kmD1PI$s~X+<}KaLx-~3zT!h z$8R>K<-sh%zs40VqJ6|~#5}5yk9ct{|*$BP$tK-i1kpt4MaQZ3hL~ zt|t6xTNhKrYY5x8p2c;uu$HiXpR|s!t`Km(U2R44>Uxst_e&cH>-S3=3G4SuzZ2H) zmr4lh_DhArCSpeD_Dh=yzYK4^51noytlvA864vjXwi4FwowgCaQ*S=4nfDS-ZeY6~ z@d3im3wtRMA0(WAcl%SshY81JPNG^nLikGIufwU!9wX+?;T5!cI8J!0Z!DF<3BvWe zCs`pbBdpt~$uuW>Poe8{CrM^HbQ|psPZ9RMyT1-K&QnEesAHSbbLWKAnVLCV}FV?(zJ%V2AJc+{gt-Xl& z0%83maffg_w?Jy=_X%$)*-4Q+B%B$21h<*OBf|7sCd7{s;~u8>jN8aOCxv3yDryWb z36J}=`&q=V2rqhD2lrjV--MgT{7s|Y8^WsPFYri3cuQEnJA6l2KT3Wid}voJH57&? zKAP;+Z|@>DBfMT)Vp*;&6wHZP@Th{iiZ$VxT#MUM!JcsG)NYRuI}rY9>6Tc;0%3hY z`4H9@6#kG=Ur<`17U8(@Yw1)Vobb6b53z292*Lv!G!YO-5gt`&{SCEAO_S;VfijMF?&hh+M_E1hm>hUW)gMR`5Kq0@H1L)?h)*_dP+ewq

rmqI#@qn7avspu#URhL;$*^fN{6@$VLH64YDry5v}fFFnb#9V7n6z*)*4itW3g#3(9DnmqmEQcDG=}*@T}zX&i{S2jPp# zxzqyi7p5{zqZw->5a$qXcDY+k#JvfZ#;(J73x!-_>ir#obDhwK@VCovQ7_FSoSYUz zmDQK<7KI13^L)ac>+PT>+>da?mSfcP@S-PH(!N&Is`?Yw7t{d4`hprrSYJ?s2v6xk zC8ZSx6QeKXA%yicF_f^rCWaAy{I-bRY&c=f)0cG0F@o^Wn~oufe;{l!b0Br#k^JT( zsOL}L(rA*Vr)FH)p9dvWHAxrBrH#Bh>2X&?R$)7?#pgOQi?{8HjSWkZObUq*bRnu&5fzk>L?E6-ij^Q(yOSa|*dHh6_x z`$SXY#t>}c3RC|02{f@?O=|tS;7#KS+@GxF&nv){&#C}BlXa-pZM$|M3+pA7{Q~b} z*Q(B9Hjq$dva!-M?3c?~)J}dU*Shmop@guPo1p+_vb-&6o6AVJlgUVaq=2tt!`0+xU&AxP;omKR?A26rF9QZo6DM zUTH+q>ZdXL9nFs5@%Ro@VI;bBJ29Hf)6w<N z0yXQ?lv-aGXSn)r+;6RZ0c||bl3YLcog=K@Af2ZinwwlekuJ!-FVW{k$-n*FUm|gU zu6z;Wj4l~ubeVs7g&9422_5Li*IzTbT9uJZosZF7<7uz(V>@0Adxe*_uInOilwF(V ztv?MM-XMoR+ukIRzF2PYDX$?FZtEhO5UZ6{MRrFLx^!A{{U3Dnmw}_ZR0MNf?~|za zjv^Z79}wQ^-u)=|dx>Re`UdY&m!nMg`VHRT>pzqNbNu8Kfs2=3ipm0bL}C{{_6<1M zRv2XRlo!8&4*t(jWbmC{cwUWvA>EYl=IuY?MZbD)!71whO7XIqhgW>$TZr}hKa=sc zZ^4^SAY%6p%pCuffLpx9Ye8xMtxKhJcxA{@7wO7(VEZ2)^4{Y8Ss%JsB)!i+X!U=V zz&oh~{CVs55dANg@A;s2_!WBRdvNmKUhT!VRpU$bMQQsFZoiiDp*n(qgl8X%KVrvD`wZsp=UWYnHvU1s&;;L&pZbUe5pK#n zLT*1zk*R71n8JUU8AfEu`_YSp12gCAKjZ!Usa*XDa4r+9xt}RsLQ7-J)cufSD1Ik2 z`~w0~kK*&F;3+@J%;iz-)@Q4m@vzT$tUzA)voBy~XY7OzL#-E02r4={!RuMoN}$G! zCae~9AIBNfn3Jz@>T1=gVs!nmi5ER9DW#KVXMSbH0`_Yoo$Y z?B-K}MSI3gp7cr8JS#lVI4P=cqS~fOY>c;R@3&#cQO#>He5Wz^N04;ldJ|Q3zlzVG znBT-dd4^T$C`Y^RZ-QT-^r{?EmCA9LnfMl0C%a9U1$N~;6HG;2ng1zg z=H???Or%Dqb7pFSnKrcTXsPNrV&qK{k2GPSJi?TDnSbtj@U&jy1xl$Ix$L$}*PzU> z>G@HY@wZf}l9#^6TeMU8Let9p+M6+3eM{uIruZHU&7}9(fEL&^0}UGOQ`DsQ!ab{@ z>jBmH{Azq|HGWVvzMvYP$CJ%jC`ROG#-hw4p65QMc=M=5N##>vjs-TAuh9!!EOd9@ z@mgY{HB;(-*Nh(^iSy$57TBZcGmchhRV|;^e5VETg^v7*1@q?PESQsDQZ@ONeWMIhc>x3OW)I3+4=7@kMc-P>9= z%*F3L{#8L-GSsL0780GVne%f!5;f3?_$(V1!hLO+J-4@GPW%q0;@^B_-EEl*UatZ> zrsP_}4SBjP=CIF(`SDT|@Hd2>5DK+LORau`A=&}jvJ5ec1&C0~AytvL;p*{C;WTEm?2($2u^9zj%4GmUvW<3Q9gz~@}K8ToY;5p zE#K$FRPded@xAVmtb25k9;JJoSWjTr7@zNi6LSq0mdl#Rb?;0Dwr!2>9D=P?qbW7 zirCeQje%!;ufTlxHZSJN=Xo<5ZsUh-;t8>_-sni_jVQ;P+43?06`hDZ<%M=B3g*m< zkj38tGz`XWxWk*d<6TH>IKKR)Hyh?6btzhie*NPkf)5|%gALx4_wix1`Bfhr7?%2C zZM*m)nyN(9j?h*gMB@o{CfOlGc){|PFRRCM$h^K1Rrp21j}Jz~@JhlW%Jp|8b7lA; zUt-FU;YXC%EW>SZ!1nfIZVaynNV-mbXcza9ZknH@~vdHyVjck{<#cOv21c&k$q9VO8u9sY=z*Y(HW1x2b@1{|co{rDyoMmSA{ zwf(n>Eruz4Rsf5GANZL77DDq&5IR-{vU)I$r_e*>vjSOty!6;Ah{c-Ey7-M!E6gCX zc>M7j%Ie{5M=9$yL0CE)cv2|V{R6~oqnzLNMMf2jiuF20Dq^-yub54WwK~PcU>rz~ z=&)-I=F1N2jXEQPo3_(6F?LS4OlNeN@F^X352=PP>g;EsoL$g6x*Ea)aQh@V@~w&Z hx-M}h;oCa-D#CXNCqg-Q2*t-kveLjKJ~fop`hTn9r?3D3 From f34a0a5a230dea4a119afebfacb752d93b855f15 Mon Sep 17 00:00:00 2001 From: Rafi Date: Mon, 1 Jun 2026 16:20:26 +0100 Subject: [PATCH 35/76] Remove the old hxcpp compile cache + bump Haxe from 4.3.6 to 4.3.7 --- .github/workflows/main.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 60e98fe5be..b37d7d7c2a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -135,10 +135,6 @@ jobs: haxelib install hxp --quiet haxelib install utest --quiet - - name: Enable HXCPP compile cache - run: | - echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV - - name: Rebuild Lime tools run: | haxelib dev lime ${{ github.workspace }} @@ -786,7 +782,7 @@ jobs: runs-on: windows-latest strategy: matrix: - haxe-version: [4.0.5, 4.1.5, 4.2.5, 4.3.6] + haxe-version: [4.0.5, 4.1.5, 4.2.5, 4.3.7] steps: - uses: actions/checkout@v6 @@ -940,7 +936,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - haxe-version: [3.4.7, 4.0.5, 4.1.5, 4.2.5, 4.3.6] + haxe-version: [3.4.7, 4.0.5, 4.1.5, 4.2.5, 4.3.7] steps: - uses: actions/checkout@v6 From 42785a2ea1be40320b633b387a54b0f377a0913a Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 13:15:01 -0400 Subject: [PATCH 36/76] Expose input event timestamps without breaking listeners This follows the direction discussed in #1802 without changing existing input callback signatures or adding a second set of precise events. Store the current dispatch timestamp on lime.app.Event, add an internal timestamped dispatch path for backends, and forward native and HTML5 key/gamepad timestamps through the existing event objects so callers can read values like window.onKeyDown.timestamp inside the current callback. Add unit coverage for dispatch-time fallback, explicit timestamp injection, and nested dispatch restoration. Closes #1802. --- project/include/ui/GamepadEvent.h | 3 +- project/include/ui/KeyEvent.h | 3 +- project/src/ExternalInterface.cpp | 4 +- project/src/backend/sdl/SDLApplication.cpp | 6 ++ project/src/ui/GamepadEvent.cpp | 7 +- project/src/ui/KeyEvent.cpp | 7 +- .../backend/html5/HTML5Application.hx | 17 ++-- .../backend/native/NativeApplication.hx | 23 +++-- src/lime/_internal/macros/EventMacro.hx | 99 ++++++++++++++++--- src/lime/app/Event.hx | 14 +++ tests/unit/src/TestMain.hx | 3 +- tests/unit/src/app/EventTest.hx | 68 +++++++++++++ 12 files changed, 216 insertions(+), 38 deletions(-) create mode 100644 tests/unit/src/app/EventTest.hx diff --git a/project/include/ui/GamepadEvent.h b/project/include/ui/GamepadEvent.h index 607ef9cfc8..5543da20c2 100644 --- a/project/include/ui/GamepadEvent.h +++ b/project/include/ui/GamepadEvent.h @@ -28,6 +28,7 @@ namespace lime { int id; GamepadEventType type; double axisValue; + int timestamp; static ValuePointer* callback; static ValuePointer* eventObject; @@ -42,4 +43,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/include/ui/KeyEvent.h b/project/include/ui/KeyEvent.h index 28e6fcc6fd..8d5ac047c0 100644 --- a/project/include/ui/KeyEvent.h +++ b/project/include/ui/KeyEvent.h @@ -25,6 +25,7 @@ namespace lime { int modifier; KeyEventType type; int windowID; + int timestamp; static ValuePointer* callback; static ValuePointer* eventObject; @@ -39,4 +40,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index c2ddcc6867..0e52b3da2a 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -13597,9 +13597,9 @@ namespace lime { #define _TCLIPBOARD_EVENT _OBJ (_I32) #define _TDISPLAYMODE _OBJ (_I32 _I32 _I32 _I32) #define _TDROP_EVENT _OBJ (_BYTES _I32) - #define _TGAMEPAD_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64) + #define _TGAMEPAD_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64 _I32) #define _TJOYSTICK_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64 _F64) - #define _TKEY_EVENT _OBJ (_F64 _I32 _I32 _I32) + #define _TKEY_EVENT _OBJ (_F64 _I32 _I32 _I32 _I32) #define _TMOUSE_EVENT _OBJ (_I32 _F64 _F64 _I32 _I32 _F64 _F64 _I32) #define _TORIENTATION_EVENT _OBJ (_I32 _I32 _I32) #define _TRECTANGLE _OBJ (_F64 _F64 _F64 _F64) diff --git a/project/src/backend/sdl/SDLApplication.cpp b/project/src/backend/sdl/SDLApplication.cpp index 821648774e..5b089f52b2 100644 --- a/project/src/backend/sdl/SDLApplication.cpp +++ b/project/src/backend/sdl/SDLApplication.cpp @@ -826,6 +826,7 @@ namespace lime gamepadEvent.type = GAMEPAD_AXIS_MOVE; gamepadEvent.axis = event->caxis.axis; gamepadEvent.id = event->caxis.which; + gamepadEvent.timestamp = event->common.timestamp; if (event->caxis.value > -analogAxisDeadZone && event->caxis.value < analogAxisDeadZone) { @@ -852,6 +853,7 @@ namespace lime gamepadEvent.type = GAMEPAD_BUTTON_DOWN; gamepadEvent.button = event->cbutton.button; gamepadEvent.id = event->cbutton.which; + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); break; @@ -861,6 +863,7 @@ namespace lime gamepadEvent.type = GAMEPAD_BUTTON_UP; gamepadEvent.button = event->cbutton.button; gamepadEvent.id = event->cbutton.which; + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); break; @@ -872,6 +875,7 @@ namespace lime gamepadEvent.type = GAMEPAD_CONNECT; gamepadEvent.id = SDLGamepad::GetInstanceID(event->cdevice.which); + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); } @@ -883,6 +887,7 @@ namespace lime gamepadEvent.type = GAMEPAD_DISCONNECT; gamepadEvent.id = event->cdevice.which; + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); SDLGamepad::Disconnect(event->cdevice.which); @@ -1002,6 +1007,7 @@ namespace lime keyEvent.keyCode = event->key.keysym.sym; keyEvent.modifier = event->key.keysym.mod; + keyEvent.timestamp = event->common.timestamp; keyEvent.windowID = event->key.windowID; if (keyEvent.type == KEY_DOWN) diff --git a/project/src/ui/GamepadEvent.cpp b/project/src/ui/GamepadEvent.cpp index 64fa1c5384..6c4b3fd74b 100644 --- a/project/src/ui/GamepadEvent.cpp +++ b/project/src/ui/GamepadEvent.cpp @@ -11,6 +11,7 @@ namespace lime { static double id_axis; static int id_button; static int id_id; + static int id_timestamp; static int id_type; static int id_value; static bool init = false; @@ -22,6 +23,7 @@ namespace lime { axisValue = 0; button = 0; id = 0; + timestamp = 0; type = GAMEPAD_AXIS_MOVE; } @@ -38,6 +40,7 @@ namespace lime { id_axis = val_id ("axis"); id_button = val_id ("button"); id_id = val_id ("id"); + id_timestamp = val_id ("timestamp"); id_type = val_id ("type"); id_value = val_id ("axisValue"); init = true; @@ -49,6 +52,7 @@ namespace lime { alloc_field (object, id_axis, alloc_int (event->axis)); alloc_field (object, id_button, alloc_int (event->button)); alloc_field (object, id_id, alloc_int (event->id)); + alloc_field (object, id_timestamp, alloc_int (event->timestamp)); alloc_field (object, id_type, alloc_int (event->type)); alloc_field (object, id_value, alloc_float (event->axisValue)); @@ -59,6 +63,7 @@ namespace lime { eventObject->axis = event->axis; eventObject->button = event->button; eventObject->id = event->id; + eventObject->timestamp = event->timestamp; eventObject->type = event->type; eventObject->axisValue = event->axisValue; @@ -71,4 +76,4 @@ namespace lime { } -} \ No newline at end of file +} diff --git a/project/src/ui/KeyEvent.cpp b/project/src/ui/KeyEvent.cpp index 42acd15560..871d8d1146 100644 --- a/project/src/ui/KeyEvent.cpp +++ b/project/src/ui/KeyEvent.cpp @@ -10,6 +10,7 @@ namespace lime { static double id_keyCode; static int id_modifier; + static int id_timestamp; static int id_type; static int id_windowID; static bool init = false; @@ -19,6 +20,7 @@ namespace lime { keyCode = 0; modifier = 0; + timestamp = 0; type = KEY_DOWN; windowID = 0; @@ -35,6 +37,7 @@ namespace lime { id_keyCode = val_id ("keyCode"); id_modifier = val_id ("modifier"); + id_timestamp = val_id ("timestamp"); id_type = val_id ("type"); id_windowID = val_id ("windowID"); init = true; @@ -45,6 +48,7 @@ namespace lime { alloc_field (object, id_keyCode, alloc_float (event->keyCode)); alloc_field (object, id_modifier, alloc_int (event->modifier)); + alloc_field (object, id_timestamp, alloc_int (event->timestamp)); alloc_field (object, id_type, alloc_int (event->type)); alloc_field (object, id_windowID, alloc_int (event->windowID)); @@ -54,6 +58,7 @@ namespace lime { eventObject->keyCode = event->keyCode; eventObject->modifier = event->modifier; + eventObject->timestamp = event->timestamp; eventObject->type = event->type; eventObject->windowID = event->windowID; @@ -66,4 +71,4 @@ namespace lime { } -} \ No newline at end of file +} diff --git a/src/lime/_internal/backend/html5/HTML5Application.hx b/src/lime/_internal/backend/html5/HTML5Application.hx index e451eb3545..356683065c 100644 --- a/src/lime/_internal/backend/html5/HTML5Application.hx +++ b/src/lime/_internal/backend/html5/HTML5Application.hx @@ -11,6 +11,7 @@ import lime.media.AudioManager; import lime.system.Orientation; import lime.system.Sensor; import lime.system.SensorType; +import lime.system.System; import lime.ui.GamepadAxis; import lime.ui.KeyCode; import lime.ui.KeyModifier; @@ -444,10 +445,11 @@ class HTML5Application var keyCode = cast convertKeyCode(event.keyCode != null ? event.keyCode : event.which); var modifier = (event.shiftKey ? (KeyModifier.SHIFT) : 0) | (event.ctrlKey ? (KeyModifier.CTRL) : 0) | (event.altKey ? (KeyModifier.ALT) : 0) | (event.metaKey ? (KeyModifier.META) : 0); + var timestamp = Std.int(event.timeStamp); if (event.type == "keydown") { - parent.window.onKeyDown.dispatch(keyCode, modifier); + @:privateAccess parent.window.onKeyDown.__dispatchWithTimestamp(timestamp, keyCode, modifier); if (parent.window.onKeyDown.canceled && event.cancelable) { @@ -456,7 +458,7 @@ class HTML5Application } else { - parent.window.onKeyUp.dispatch(keyCode, modifier); + @:privateAccess parent.window.onKeyUp.__dispatchWithTimestamp(timestamp, keyCode, modifier); if (parent.window.onKeyUp.canceled && event.cancelable) { @@ -601,18 +603,19 @@ class HTML5Application for (i in 0...data.buttons.length) { value = data.buttons[i].value; + var timestamp = System.getTimer(); if (value != cache.buttons[i]) { if (i == 6) { joystick.onAxisMove.dispatch(data.axes.length, value); - if (gamepad != null) gamepad.onAxisMove.dispatch(GamepadAxis.TRIGGER_LEFT, value); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(timestamp, GamepadAxis.TRIGGER_LEFT, value); } else if (i == 7) { joystick.onAxisMove.dispatch(data.axes.length + 1, value); - if (gamepad != null) gamepad.onAxisMove.dispatch(GamepadAxis.TRIGGER_RIGHT, value); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(timestamp, GamepadAxis.TRIGGER_RIGHT, value); } else { @@ -649,11 +652,11 @@ class HTML5Application if (value > 0) { - gamepad.onButtonDown.dispatch(button); + @:privateAccess gamepad.onButtonDown.__dispatchWithTimestamp(timestamp, button); } else { - gamepad.onButtonUp.dispatch(button); + @:privateAccess gamepad.onButtonUp.__dispatchWithTimestamp(timestamp, button); } } } @@ -667,7 +670,7 @@ class HTML5Application if (data.axes[i] != cache.axes[i]) { joystick.onAxisMove.dispatch(i, data.axes[i]); - if (gamepad != null) gamepad.onAxisMove.dispatch(i, data.axes[i]); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(System.getTimer(), i, data.axes[i]); cache.axes[i] = data.axes[i]; } } diff --git a/src/lime/_internal/backend/native/NativeApplication.hx b/src/lime/_internal/backend/native/NativeApplication.hx index a6478bba2d..ba9ba37d72 100644 --- a/src/lime/_internal/backend/native/NativeApplication.hx +++ b/src/lime/_internal/backend/native/NativeApplication.hx @@ -292,13 +292,14 @@ class NativeApplication { case AXIS_MOVE: var gamepad = Gamepad.devices.get(gamepadEventInfo.id); - if (gamepad != null) gamepad.onAxisMove.dispatch(gamepadEventInfo.axis, gamepadEventInfo.axisValue); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(gamepadEventInfo.timestamp, gamepadEventInfo.axis, + gamepadEventInfo.axisValue); case BUTTON_DOWN: var gamepad = Gamepad.devices.get(gamepadEventInfo.id); - if (gamepad != null) gamepad.onButtonDown.dispatch(gamepadEventInfo.button); + if (gamepad != null) @:privateAccess gamepad.onButtonDown.__dispatchWithTimestamp(gamepadEventInfo.timestamp, gamepadEventInfo.button); case BUTTON_UP: var gamepad = Gamepad.devices.get(gamepadEventInfo.id); - if (gamepad != null) gamepad.onButtonUp.dispatch(gamepadEventInfo.button); + if (gamepad != null) @:privateAccess gamepad.onButtonUp.__dispatchWithTimestamp(gamepadEventInfo.timestamp, gamepadEventInfo.button); case CONNECT: Gamepad.__connect(gamepadEventInfo.id); @@ -345,9 +346,9 @@ class NativeApplication switch (type) { case KEY_DOWN: - window.onKeyDown.dispatch(keyCode, modifier); + @:privateAccess window.onKeyDown.__dispatchWithTimestamp(keyEventInfo.timestamp, keyCode, modifier); case KEY_UP: - window.onKeyUp.dispatch(keyCode, modifier); + @:privateAccess window.onKeyUp.__dispatchWithTimestamp(keyEventInfo.timestamp, keyCode, modifier); } #if (windows || linux) @@ -777,19 +778,21 @@ class NativeApplication public var id:Int; public var type:GamepadEventType; public var axisValue:Float; + public var timestamp:Int; - public function new(type:GamepadEventType = null, id:Int = 0, button:Int = 0, axis:Int = 0, value:Float = 0) + public function new(type:GamepadEventType = null, id:Int = 0, button:Int = 0, axis:Int = 0, value:Float = 0, timestamp:Int = 0) { this.type = type; this.id = id; this.button = button; this.axis = axis; this.axisValue = value; + this.timestamp = timestamp; } public function clone():GamepadEventInfo { - return new GamepadEventInfo(type, id, button, axis, axisValue); + return new GamepadEventInfo(type, id, button, axis, axisValue, timestamp); } } @@ -844,18 +847,20 @@ class NativeApplication public var modifier:Int; public var type:KeyEventType; public var windowID:Int; + public var timestamp:Int; - public function new(type:KeyEventType = null, windowID:Int = 0, keyCode:Float = 0, modifier:Int = 0) + public function new(type:KeyEventType = null, windowID:Int = 0, keyCode:Float = 0, modifier:Int = 0, timestamp:Int = 0) { this.type = type; this.windowID = windowID; this.keyCode = keyCode; this.modifier = modifier; + this.timestamp = timestamp; } public function clone():KeyEventInfo { - return new KeyEventInfo(type, windowID, keyCode, modifier); + return new KeyEventInfo(type, windowID, keyCode, modifier, timestamp); } } diff --git a/src/lime/_internal/macros/EventMacro.hx b/src/lime/_internal/macros/EventMacro.hx index ba42ce3b6c..4071ce5841 100644 --- a/src/lime/_internal/macros/EventMacro.hx +++ b/src/lime/_internal/macros/EventMacro.hx @@ -89,30 +89,82 @@ class EventMacro var dispatch = macro { + var previousTimestamp = __timestamp; + __timestamp = lime.system.System.getTimer(); canceled = false; - var listeners = __listeners; - var repeat = __repeat; - var i = 0; - - while (i < listeners.length) + try { - listeners[i]($a{argNames}); + var listeners = __listeners; + var repeat = __repeat; + var i = 0; - if (!repeat[i]) - { - this.remove(cast listeners[i]); - } - else + while (i < listeners.length) { - i++; + listeners[i]($a{argNames}); + + if (!repeat[i]) + { + this.remove(cast listeners[i]); + } + else + { + i++; + } + + if (canceled) + { + break; + } } + } + catch (e:Dynamic) + { + __timestamp = previousTimestamp; + throw e; + } + + __timestamp = previousTimestamp; + } + + var timestampDispatch = macro + { + var previousTimestamp = __timestamp; + __timestamp = timestamp; + canceled = false; + + try + { + var listeners = __listeners; + var repeat = __repeat; + var i = 0; - if (canceled) + while (i < listeners.length) { - break; + listeners[i]($a{argNames}); + + if (!repeat[i]) + { + this.remove(cast listeners[i]); + } + else + { + i++; + } + + if (canceled) + { + break; + } } } + catch (e:Dynamic) + { + __timestamp = previousTimestamp; + throw e; + } + + __timestamp = previousTimestamp; } var i = 0; @@ -122,7 +174,7 @@ class EventMacro { field = fields[i]; - if (field.name == "__listeners" || field.name == "dispatch") + if (field.name == "__listeners" || field.name == "dispatch" || field.name == "__dispatchWithTimestamp") { fields.remove(field); } @@ -152,6 +204,23 @@ class EventMacro }), pos: pos }); + fields.push( + { + name: "__dispatchWithTimestamp", + access: [APublic], + kind: FFun( + { + args: [{name: "timestamp", type: macro:Int}].concat(args), + expr: timestampDispatch, + params: [], + ret: macro:Void + }), + meta: [ + {name: ":dox", params: [macro hide], pos: pos}, + {name: ":noCompletion", pos: pos} + ], + pos: pos + }); var meta:Array = [ {name: ":dox", params: [macro hide], pos: pos}, diff --git a/src/lime/app/Event.hx b/src/lime/app/Event.hx index ed4a799279..fa8043d63c 100644 --- a/src/lime/app/Event.hx +++ b/src/lime/app/Event.hx @@ -30,10 +30,17 @@ class Event **/ public var canceled(default, null):Bool; + /** + The timestamp for the current dispatch, in milliseconds. + When read outside of a dispatch, this returns the current timer value. + **/ + public var timestamp(get, never):Int; + @:noCompletion @:dox(hide) public var __listeners:Array; @:noCompletion @:dox(hide) public var __repeat:Array; @:noCompletion private var __priorities:Array; + @:noCompletion private var __timestamp:Int; /** Creates a new Event instance @@ -45,6 +52,7 @@ class Event __listeners = new Array(); __priorities = new Array(); __repeat = new Array(); + __timestamp = -1; #end } @@ -89,6 +97,7 @@ class Event takes two `Int` arguments, like `dispatch (1, 2);` **/ public var dispatch:Dynamic; + @:noCompletion @:dox(hide) public var __dispatchWithTimestamp:Dynamic; // macro public function dispatch (ethis:Expr, args:Array):Void { // @@ -169,4 +178,9 @@ class Event __repeat.splice(0, len); #end } + + private function get_timestamp():Int + { + return (__timestamp != -1) ? __timestamp : lime.system.System.getTimer(); + } } diff --git a/tests/unit/src/TestMain.hx b/tests/unit/src/TestMain.hx index 6978eb8d6c..e5f15d054e 100644 --- a/tests/unit/src/TestMain.hx +++ b/tests/unit/src/TestMain.hx @@ -7,6 +7,7 @@ class TestMain extends Application { super(); var runner = new Runner(); + runner.addCase(new app.EventTest()); runner.addCase(new utils.ArrayBufferTest()); runner.addCase(new utils.UInt8ArrayTest()); runner.addCase(new utils.UInt16ArrayTest()); @@ -15,4 +16,4 @@ class TestMain extends Application { Report.create(runner); runner.run(); } -} \ No newline at end of file +} diff --git a/tests/unit/src/app/EventTest.hx b/tests/unit/src/app/EventTest.hx new file mode 100644 index 0000000000..87d7c07f0c --- /dev/null +++ b/tests/unit/src/app/EventTest.hx @@ -0,0 +1,68 @@ +package app; + +import lime.app.Event; +import lime.system.System; +import utest.Assert; +import utest.Test; + +class EventTest extends Test +{ + public function new() + { + super(); + } + + public function testTimestampUsesDispatchTime():Void + { + var event = new EventVoid>(); + var observed = -1; + var before = System.getTimer(); + + event.add(function(_) + { + observed = event.timestamp; + }); + + event.dispatch(1); + var after = System.getTimer(); + + Assert.isTrue(observed >= before); + Assert.isTrue(observed <= after); + } + + public function testExplicitTimestampIsVisible():Void + { + var event = new EventVoid>(); + var observed = -1; + + event.add(function(_) + { + observed = event.timestamp; + }); + + @:privateAccess event.__dispatchWithTimestamp(1234, 1); + Assert.equals(1234, observed); + } + + public function testNestedDispatchRestoresTimestamp():Void + { + var event = new EventVoid>(); + var timestamps:Array = []; + var nested = false; + + event.add(function(_) + { + timestamps.push(event.timestamp); + + if (!nested) + { + nested = true; + @:privateAccess event.__dispatchWithTimestamp(200, 2); + Assert.equals(100, event.timestamp); + } + }); + + @:privateAccess event.__dispatchWithTimestamp(100, 1); + Assert.same([100, 200], timestamps); + } +} From d5ee2a5437b09191901f09292c32034ba45a04e1 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 13:30:14 -0400 Subject: [PATCH 37/76] Fix Event.timestamp in doc generation Use a neutral fallback timestamp under lime_doc_gen instead of calling System.getTimer() outside of a live runtime context. This keeps the docs compile path working for the input timestamp change added in 42785a2e. --- src/lime/app/Event.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lime/app/Event.hx b/src/lime/app/Event.hx index fa8043d63c..f7fb92e030 100644 --- a/src/lime/app/Event.hx +++ b/src/lime/app/Event.hx @@ -181,6 +181,10 @@ class Event private function get_timestamp():Int { + #if lime_doc_gen + return (__timestamp != -1) ? __timestamp : 0; + #else return (__timestamp != -1) ? __timestamp : lime.system.System.getTimer(); + #end } } From 8c5a870e8663481fd90c3c639a6a177f442cdaf2 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Mon, 17 Mar 2025 18:04:43 +0000 Subject: [PATCH 38/76] Update pixman for llvm assembly fixes --- .../pixman/{config.h => pixman-config.h} | 41 ------------------- .../lib/custom/pixman/pixman/pixman-version.h | 6 +-- project/lib/pixman | 2 +- project/lib/pixman-files.xml | 1 + 4 files changed, 5 insertions(+), 45 deletions(-) rename project/lib/custom/pixman/{config.h => pixman-config.h} (86%) diff --git a/project/lib/custom/pixman/config.h b/project/lib/custom/pixman/pixman-config.h similarity index 86% rename from project/lib/custom/pixman/config.h rename to project/lib/custom/pixman/pixman-config.h index 0fa8ab453f..93286e08fb 100644 --- a/project/lib/custom/pixman/config.h +++ b/project/lib/custom/pixman/pixman-config.h @@ -15,9 +15,6 @@ 3. Update the version number(s) if they've changed. **/ -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - /* Whether we have alarm() */ #ifdef HX_LINUX #define HAVE_ALARM 1 @@ -32,13 +29,6 @@ /* #undef HAVE_BUILTIN_CLZ */ #endif -/* Define to 1 if you have the header file. */ -#ifndef HX_WINDOWS -#define HAVE_DLFCN_H 1 -#else -/* #undef HAVE_DLFCN_H */ -#endif - /* Whether we have FE_DIVBYZERO */ #ifdef HX_LINUX #define HAVE_FEDIVBYZERO 1 @@ -108,13 +98,6 @@ /* #undef HAVE_LIBPNG */ #endif -/* Define to 1 if you have the header file. */ -#ifdef HX_LINUX -#define HAVE_MEMORY_H 1 -#else -/* #undef HAVE_MEMORY_H */ -#endif - /* Whether we have mmap() */ #ifdef HX_LINUX #define HAVE_MMAP 1 @@ -200,24 +183,6 @@ /* Name of package */ #define PACKAGE "pixman" -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "pixman@lists.freedesktop.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "pixman" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "pixman 0.42.2" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "pixman" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.42.2" - /* enable output that can be piped to gnuplot */ /* #undef PIXMAN_GNUPLOT */ @@ -316,9 +281,6 @@ /* #undef USE_X86_MMX */ #endif -/* Version number of package */ -#define VERSION "0.42.2" - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD @@ -336,6 +298,3 @@ #ifndef __cplusplus /* #undef inline */ #endif - -/* Define to sqrt if you do not have the `sqrtf' function. */ -/* #undef sqrtf */ diff --git a/project/lib/custom/pixman/pixman/pixman-version.h b/project/lib/custom/pixman/pixman/pixman-version.h index 23d30b5500..5767975fcd 100644 --- a/project/lib/custom/pixman/pixman/pixman-version.h +++ b/project/lib/custom/pixman/pixman/pixman-version.h @@ -32,10 +32,10 @@ #endif #define PIXMAN_VERSION_MAJOR 0 -#define PIXMAN_VERSION_MINOR 40 -#define PIXMAN_VERSION_MICRO 1 +#define PIXMAN_VERSION_MINOR 44 +#define PIXMAN_VERSION_MICRO 2 -#define PIXMAN_VERSION_STRING "0.40.1" +#define PIXMAN_VERSION_STRING "0.44.2" #define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \ ((major) * 10000) \ diff --git a/project/lib/pixman b/project/lib/pixman index 37216a3283..46655e1567 160000 --- a/project/lib/pixman +++ b/project/lib/pixman @@ -1 +1 @@ -Subproject commit 37216a32839f59e8dcaa4c3951b3fcfc3f07852c +Subproject commit 46655e15671e1ca62d699821d75a85d341d7229c diff --git a/project/lib/pixman-files.xml b/project/lib/pixman-files.xml index ef98744568..3b902cafe7 100644 --- a/project/lib/pixman-files.xml +++ b/project/lib/pixman-files.xml @@ -73,6 +73,7 @@ + From ae54563cb0b798730f091956f729e1bbb4bab438 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Mon, 17 Mar 2025 18:09:46 +0000 Subject: [PATCH 39/76] Reenable pixman neon support for 32 bit arm Latest version of pixman has fixed support for compiling the neon assembly files with clang. Older android ndks required disabling the integrated assembler to build them but that workaround is no longer required. This also avoids the bug where older ndks didn't pass -march automatically to external assemblers. See: https://github.com/android/ndk/issues/906#issuecomment-462898046 --- project/lib/pixman-files.xml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/project/lib/pixman-files.xml b/project/lib/pixman-files.xml index 3b902cafe7..a318e8be49 100644 --- a/project/lib/pixman-files.xml +++ b/project/lib/pixman-files.xml @@ -3,15 +3,10 @@ - + -

- - -
- From 428e9459b294c8fbf3daa13adaeb40b6b818936f Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Mon, 17 Mar 2025 19:00:21 +0000 Subject: [PATCH 40/76] Fix pixman config for gcc android ndks GCC does not have syntax unified set explicitly, so pixman has to be able to set it. --- project/lib/custom/pixman/pixman-config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/project/lib/custom/pixman/pixman-config.h b/project/lib/custom/pixman/pixman-config.h index 93286e08fb..1270d937eb 100644 --- a/project/lib/custom/pixman/pixman-config.h +++ b/project/lib/custom/pixman/pixman-config.h @@ -217,6 +217,8 @@ /* #undef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR */ #endif +#define ASM_HAVE_SYNTAX_UNIFIED + /* use ARM A64_NEON assembly optimizations */ /* #undef USE_ARM_A64_NEON */ From 6051bc799450be26c0edc34510dc96312a08cc92 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Mon, 17 Mar 2025 19:25:40 +0000 Subject: [PATCH 41/76] Enable pixman neon support for arm64 Some older clang ndk's integrated assemblers have issues still with the arm64 assembly files. We can just continue disabling the integrated assembler there. The assembly is fine with the integrated assembler on versions r20 and above. --- project/lib/pixman-files.xml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/project/lib/pixman-files.xml b/project/lib/pixman-files.xml index a318e8be49..a580f14bc9 100644 --- a/project/lib/pixman-files.xml +++ b/project/lib/pixman-files.xml @@ -1,12 +1,13 @@ - - + + + @@ -17,6 +18,7 @@ + @@ -34,7 +36,9 @@ - + + + From 201b9e1ffe1c06937c902c46286123cc24e58d0d Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Sun, 11 Jan 2026 14:17:16 +0000 Subject: [PATCH 42/76] Fix pixman config for apple platforms --- project/lib/custom/pixman/pixman-config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/project/lib/custom/pixman/pixman-config.h b/project/lib/custom/pixman/pixman-config.h index 1270d937eb..02ffd50113 100644 --- a/project/lib/custom/pixman/pixman-config.h +++ b/project/lib/custom/pixman/pixman-config.h @@ -219,6 +219,10 @@ #define ASM_HAVE_SYNTAX_UNIFIED +#if defined(__APPLE__) +#define ASM_LEADING_UNDERSCORE 1 +#endif + /* use ARM A64_NEON assembly optimizations */ /* #undef USE_ARM_A64_NEON */ From f34259b57c7ee765f11cf868ae951ed37c43d97a Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Sun, 11 Jan 2026 15:48:24 +0000 Subject: [PATCH 43/76] Disable neon on armv7 ios again ios still has errors --- project/lib/pixman-files.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/lib/pixman-files.xml b/project/lib/pixman-files.xml index a580f14bc9..cd266b1f0a 100644 --- a/project/lib/pixman-files.xml +++ b/project/lib/pixman-files.xml @@ -1,7 +1,7 @@ - + From f94a2d5d03ff2a82d82b093e27b57cf080247815 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Tue, 2 Jun 2026 14:47:40 -0400 Subject: [PATCH 44/76] Add polling AudioInput API Introduce Lime-level AudioInput and AudioInputDevice classes so frameworks can poll raw PCM capture data without changing existing event contracts. The native backend uses the existing OpenAL capture bindings to expose support checks, default device lookup, start/stop, sample availability, and Bytes reads. HTML5 and Flash compile as unsupported stubs for now, and the docs import list includes the new media types. --- docs/ImportAll.hx | 2 + .../backend/flash/FlashAudioInput.hx | 49 ++++ .../backend/html5/HTML5AudioInput.hx | 49 ++++ .../backend/native/NativeAudioInput.hx | 275 ++++++++++++++++++ src/lime/media/AudioInput.hx | 195 +++++++++++++ src/lime/media/AudioInputDevice.hx | 39 +++ 6 files changed, 609 insertions(+) create mode 100644 src/lime/_internal/backend/flash/FlashAudioInput.hx create mode 100644 src/lime/_internal/backend/html5/HTML5AudioInput.hx create mode 100644 src/lime/_internal/backend/native/NativeAudioInput.hx create mode 100644 src/lime/media/AudioInput.hx create mode 100644 src/lime/media/AudioInputDevice.hx diff --git a/docs/ImportAll.hx b/docs/ImportAll.hx index a5032842a4..d1fbcc89cf 100644 --- a/docs/ImportAll.hx +++ b/docs/ImportAll.hx @@ -122,6 +122,8 @@ import lime.media.vorbis.VorbisInfo; import lime.media.AudioBuffer; import lime.media.AudioContext; import lime.media.AudioContextType; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; import lime.media.AudioManager; import lime.media.AudioSource; import lime.media.FlashAudioContext; diff --git a/src/lime/_internal/backend/flash/FlashAudioInput.hx b/src/lime/_internal/backend/flash/FlashAudioInput.hx new file mode 100644 index 0000000000..ec3e0a4fb2 --- /dev/null +++ b/src/lime/_internal/backend/flash/FlashAudioInput.hx @@ -0,0 +1,49 @@ +package lime._internal.backend.flash; + +import haxe.io.Bytes; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; + +class FlashAudioInput +{ + private var parent:AudioInput; + + public static function getDefaultDevice():AudioInputDevice + { + return null; + } + + public static function getDevices():Array + { + return []; + } + + public static function isSupported():Bool + { + return false; + } + + public function new(parent:AudioInput) + { + this.parent = parent; + } + + public function dispose():Void {} + + public function getSamplesAvailable():Int + { + return 0; + } + + public function read(buffer:Bytes, samples:Int):Int + { + return 0; + } + + public function start():Bool + { + return false; + } + + public function stop():Void {} +} diff --git a/src/lime/_internal/backend/html5/HTML5AudioInput.hx b/src/lime/_internal/backend/html5/HTML5AudioInput.hx new file mode 100644 index 0000000000..525a8033a4 --- /dev/null +++ b/src/lime/_internal/backend/html5/HTML5AudioInput.hx @@ -0,0 +1,49 @@ +package lime._internal.backend.html5; + +import haxe.io.Bytes; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; + +class HTML5AudioInput +{ + private var parent:AudioInput; + + public static function getDefaultDevice():AudioInputDevice + { + return null; + } + + public static function getDevices():Array + { + return []; + } + + public static function isSupported():Bool + { + return false; + } + + public function new(parent:AudioInput) + { + this.parent = parent; + } + + public function dispose():Void {} + + public function getSamplesAvailable():Int + { + return 0; + } + + public function read(buffer:Bytes, samples:Int):Int + { + return 0; + } + + public function start():Bool + { + return false; + } + + public function stop():Void {} +} diff --git a/src/lime/_internal/backend/native/NativeAudioInput.hx b/src/lime/_internal/backend/native/NativeAudioInput.hx new file mode 100644 index 0000000000..813a146684 --- /dev/null +++ b/src/lime/_internal/backend/native/NativeAudioInput.hx @@ -0,0 +1,275 @@ +package lime._internal.backend.native; + +import haxe.io.Bytes; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; +#if (!lime_doc_gen || lime_openal) +import lime.media.openal.AL; +import lime.media.openal.ALC; +import lime.media.openal.ALDevice; +#end + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end +@:access(lime.media.AudioInput) +class NativeAudioInput +{ + private var disposed:Bool; + private var handle:#if (!lime_doc_gen || lime_openal) ALDevice #else Dynamic #end; + private var parent:AudioInput; + private var started:Bool; + + public static function getDefaultDevice():AudioInputDevice + { + #if (!lime_doc_gen || lime_openal) + var name = ALC.getString(null, ALC.CAPTURE_DEFAULT_DEVICE_SPECIFIER); + + if (name == null || name == "") + { + return null; + } + + return new AudioInputDevice(name, name, true); + #else + return null; + #end + } + + public static function getDevices():Array + { + #if (!lime_doc_gen || lime_openal) + var defaultDevice = getDefaultDevice(); + var defaultName = defaultDevice != null ? defaultDevice.name : null; + var devices = parseDeviceList(ALC.getString(null, ALC.CAPTURE_DEVICE_SPECIFIER), defaultName); + + if (devices.length == 0 && defaultDevice != null) + { + devices.push(defaultDevice); + } + + return devices; + #else + return []; + #end + } + + public static function isSupported():Bool + { + return getDefaultDevice() != null || getDevices().length > 0; + } + + public function new(parent:AudioInput) + { + this.parent = parent; + + open(); + } + + public function dispose():Void + { + if (disposed) + { + return; + } + + stop(); + + #if (!lime_doc_gen || lime_openal) + if (handle != null) + { + ALC.captureCloseDevice(handle); + handle = null; + } + #end + + disposed = true; + } + + public function getSamplesAvailable():Int + { + #if (!lime_doc_gen || lime_openal) + if (handle == null) + { + return 0; + } + + var values = ALC.getIntegerv(handle, ALC.CAPTURE_SAMPLES, 1); + + if (values != null && values.length > 0) + { + return values[0]; + } + #end + + return 0; + } + + public function read(buffer:Bytes, samples:Int):Int + { + #if (!lime_doc_gen || lime_openal) + if (!started || handle == null || buffer == null || samples <= 0) + { + return 0; + } + + var available = getSamplesAvailable(); + + if (available <= 0) + { + return 0; + } + + var samplesToRead = samples < available ? samples : available; + var frameSize = getFrameSize(); + + if (frameSize <= 0) + { + return 0; + } + + var maxSamples = Std.int(buffer.length / frameSize); + + if (samplesToRead > maxSamples) + { + samplesToRead = maxSamples; + } + + if (samplesToRead <= 0) + { + return 0; + } + + ALC.captureSamples(handle, buffer, samplesToRead); + return samplesToRead; + #end + + return 0; + } + + public function start():Bool + { + #if (!lime_doc_gen || lime_openal) + if (disposed) + { + return false; + } + + if (handle == null) + { + open(); + } + + if (handle == null) + { + return false; + } + + ALC.captureStart(handle); + started = true; + return true; + #else + return false; + #end + } + + public function stop():Void + { + #if (!lime_doc_gen || lime_openal) + if (started && handle != null) + { + ALC.captureStop(handle); + } + #end + + started = false; + } + + private function getFormat():Int + { + #if (!lime_doc_gen || lime_openal) + if (parent.channels == 1) + { + if (parent.bitsPerSample == 8) + { + return AL.FORMAT_MONO8; + } + else if (parent.bitsPerSample == 16) + { + return AL.FORMAT_MONO16; + } + } + else if (parent.channels == 2) + { + if (parent.bitsPerSample == 8) + { + return AL.FORMAT_STEREO8; + } + else if (parent.bitsPerSample == 16) + { + return AL.FORMAT_STEREO16; + } + } + #end + + return 0; + } + + private function getFrameSize():Int + { + return Std.int((parent.channels * parent.bitsPerSample) / 8); + } + + private function open():Void + { + #if (!lime_doc_gen || lime_openal) + if (handle != null) + { + return; + } + + var format = getFormat(); + + if (format == 0) + { + return; + } + + var deviceName = parent.device != null && !parent.device.isDefault ? parent.device.id : null; + handle = ALC.captureOpenDevice(deviceName, parent.sampleRate, format, parent.bufferSize); + #end + } + + private static function parseDeviceList(value:String, defaultName:String):Array + { + var devices = []; + + if (value == null || value == "") + { + return devices; + } + + var hasDefault = false; + var names = value.split(String.fromCharCode(0)); + + for (name in names) + { + if (name == null || name == "") + { + continue; + } + + var isDefault = name == defaultName; + hasDefault = hasDefault || isDefault; + devices.push(new AudioInputDevice(name, name, isDefault)); + } + + if (!hasDefault && defaultName != null && defaultName != "") + { + devices.unshift(new AudioInputDevice(defaultName, defaultName, true)); + } + + return devices; + } +} diff --git a/src/lime/media/AudioInput.hx b/src/lime/media/AudioInput.hx new file mode 100644 index 0000000000..8a7d604daf --- /dev/null +++ b/src/lime/media/AudioInput.hx @@ -0,0 +1,195 @@ +package lime.media; + +import haxe.io.Bytes; +import lime.app.Event; + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end +/** + The `AudioInput` class provides polling-based access to microphone or other + audio capture input. + + `AudioInput` reads raw PCM sample frames into a `Bytes` buffer. Use + `samplesAvailable` to determine how many sample frames can be read without + blocking, then call `read`. + + @see lime.media.AudioInputDevice + @see lime.media.AudioBuffer +**/ +class AudioInput +{ + /** + The backend's default audio input device, or `null` if capture is not + available. + **/ + public static var defaultDevice(get, never):AudioInputDevice; + + /** + The available audio input devices reported by the backend. + **/ + public static var devices(get, never):Array; + + /** + Whether audio input capture is supported by the current backend. + **/ + public static var isSupported(get, never):Bool; + + /** + The number of bits per sample used by this input. + **/ + public var bitsPerSample(default, null):Int; + + /** + The capture buffer size, in sample frames. + **/ + public var bufferSize(default, null):Int; + + /** + The number of capture channels. + **/ + public var channels(default, null):Int; + + /** + The audio input device used by this input. + **/ + public var device(default, null):AudioInputDevice; + + /** + An event that is dispatched if the backend reports that the input device + has disconnected. + **/ + public var onDisconnect = new EventVoid>(); + + /** + Whether this input is currently capturing. + **/ + public var running(default, null):Bool; + + /** + The capture sample rate, in Hz. + **/ + public var sampleRate(default, null):Int; + + /** + The number of sample frames currently available to read. + **/ + public var samplesAvailable(get, never):Int; + + @:noCompletion private var __backend:AudioInputBackend; + @:noCompletion private var __disposed:Bool; + + /** + Creates a new `AudioInput` instance. + + @param device The input device to use. If `null`, the backend default is used. + @param sampleRate The requested capture sample rate, in Hz. + @param channels The requested channel count. + @param bitsPerSample The requested bits per sample. + @param bufferSize The capture buffer size, in sample frames. + **/ + public function new(device:AudioInputDevice = null, sampleRate:Int = 44100, channels:Int = 1, bitsPerSample:Int = 16, bufferSize:Int = 4096) + { + this.device = device != null ? device : defaultDevice; + this.sampleRate = sampleRate > 0 ? sampleRate : 44100; + this.channels = channels; + this.bitsPerSample = bitsPerSample; + this.bufferSize = bufferSize > 0 ? bufferSize : 4096; + running = false; + + __backend = new AudioInputBackend(this); + } + + /** + Releases any resources used by this `AudioInput`. + **/ + public function dispose():Void + { + if (__disposed) + { + return; + } + + stop(); + __backend.dispose(); + __disposed = true; + } + + /** + Reads captured PCM sample frames into `buffer`. + + @param buffer The destination buffer. + @param samples The maximum number of sample frames to read. + @return The number of sample frames actually read. + **/ + public function read(buffer:Bytes, samples:Int):Int + { + if (__disposed) + { + return 0; + } + + return __backend.read(buffer, samples); + } + + /** + Starts audio capture. + **/ + public function start():Void + { + if (__disposed || running) + { + return; + } + + running = __backend.start(); + } + + /** + Stops audio capture. + **/ + public function stop():Void + { + if (__disposed || !running) + { + return; + } + + __backend.stop(); + running = false; + } + + @:noCompletion private static function get_defaultDevice():AudioInputDevice + { + return AudioInputBackend.getDefaultDevice(); + } + + @:noCompletion private static function get_devices():Array + { + return AudioInputBackend.getDevices(); + } + + @:noCompletion private static function get_isSupported():Bool + { + return AudioInputBackend.isSupported(); + } + + @:noCompletion private function get_samplesAvailable():Int + { + if (__disposed) + { + return 0; + } + + return __backend.getSamplesAvailable(); + } +} + +#if flash +@:noCompletion private typedef AudioInputBackend = lime._internal.backend.flash.FlashAudioInput; +#elseif (js && html5) +@:noCompletion private typedef AudioInputBackend = lime._internal.backend.html5.HTML5AudioInput; +#else +@:noCompletion private typedef AudioInputBackend = lime._internal.backend.native.NativeAudioInput; +#end diff --git a/src/lime/media/AudioInputDevice.hx b/src/lime/media/AudioInputDevice.hx new file mode 100644 index 0000000000..948fe799a9 --- /dev/null +++ b/src/lime/media/AudioInputDevice.hx @@ -0,0 +1,39 @@ +package lime.media; + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end +/** + The `AudioInputDevice` class describes an audio capture device that can be + used with `AudioInput`. + + @see lime.media.AudioInput +**/ +class AudioInputDevice +{ + /** + The backend identifier for this device, when one is available. + **/ + public var id(default, null):String; + + /** + Whether this device is the backend's default audio input device. + **/ + public var isDefault(default, null):Bool; + + /** + The user-visible name of this audio input device. + **/ + public var name(default, null):String; + + /** + Creates a new `AudioInputDevice` instance. + **/ + public function new(name:String = null, id:String = null, isDefault:Bool = false) + { + this.name = name; + this.id = id != null ? id : name; + this.isDefault = isDefault; + } +} From 1d813466b8aa1503fa222a630a58d821d5d7a523 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 01:02:46 -0400 Subject: [PATCH 45/76] Implement html5 audio input backend --- .../backend/html5/HTML5AudioInput.hx | 409 +++++++++++++++++- 1 file changed, 402 insertions(+), 7 deletions(-) diff --git a/src/lime/_internal/backend/html5/HTML5AudioInput.hx b/src/lime/_internal/backend/html5/HTML5AudioInput.hx index 525a8033a4..856ddd8aad 100644 --- a/src/lime/_internal/backend/html5/HTML5AudioInput.hx +++ b/src/lime/_internal/backend/html5/HTML5AudioInput.hx @@ -1,49 +1,444 @@ package lime._internal.backend.html5; import haxe.io.Bytes; +import js.Browser; import lime.media.AudioInput; import lime.media.AudioInputDevice; +private typedef AudioInputData = +{ + var bytes:Bytes; + var offset:Int; +} + +@:access(lime.media.AudioInput) class HTML5AudioInput { + private static inline var MAX_QUEUED_MS = 10000; + + private static var cachedDevices:Array; + private static var enumeratingDevices:Bool; + + private var audioContext:Dynamic; + private var buffers:Array; + private var disposed:Bool; + private var frameSize:Int; + private var mediaStream:Dynamic; private var parent:AudioInput; + private var processorNode:Dynamic; + private var queuedBytes:Int; + private var sourceNode:Dynamic; + private var starting:Bool; public static function getDefaultDevice():AudioInputDevice { - return null; + if (!isSupported()) + { + return null; + } + + return new AudioInputDevice("Default Audio Input", null, true); } public static function getDevices():Array { - return []; + refreshDevices(); + + if (cachedDevices != null) + { + return cachedDevices.copy(); + } + + var defaultDevice = getDefaultDevice(); + return defaultDevice != null ? [defaultDevice] : []; } public static function isSupported():Bool { - return false; + var navigator:Dynamic = Browser.navigator; + return navigator != null && navigator.mediaDevices != null && navigator.mediaDevices.getUserMedia != null; } public function new(parent:AudioInput) { this.parent = parent; + + buffers = []; + frameSize = getFrameSize(); + queuedBytes = 0; } - public function dispose():Void {} + public function dispose():Void + { + disposed = true; + stop(); + buffers.resize(0); + queuedBytes = 0; + } public function getSamplesAvailable():Int { - return 0; + if (frameSize <= 0) + { + return 0; + } + + return Std.int(queuedBytes / frameSize); } public function read(buffer:Bytes, samples:Int):Int { - return 0; + if (buffer == null || samples <= 0 || frameSize <= 0) + { + return 0; + } + + var samplesToRead = samples; + var available = getSamplesAvailable(); + var maxSamples = Std.int(buffer.length / frameSize); + + if (samplesToRead > available) + { + samplesToRead = available; + } + + if (samplesToRead > maxSamples) + { + samplesToRead = maxSamples; + } + + if (samplesToRead <= 0) + { + return 0; + } + + var bytesToRead = samplesToRead * frameSize; + var remaining = bytesToRead; + var writePosition = 0; + + while (remaining > 0 && buffers.length > 0) + { + var data = buffers[0]; + var availableBytes = data.bytes.length - data.offset; + var copyBytes = availableBytes < remaining ? availableBytes : remaining; + + buffer.blit(writePosition, data.bytes, data.offset, copyBytes); + + data.offset += copyBytes; + writePosition += copyBytes; + remaining -= copyBytes; + queuedBytes -= copyBytes; + + if (data.offset >= data.bytes.length) + { + buffers.shift(); + } + } + + return Std.int((bytesToRead - remaining) / frameSize); } public function start():Bool { + if (disposed || starting || parent.running || !isSupported() || !isFormatSupported()) + { + return parent.running; + } + + starting = true; + audioContext = createAudioContext(); + + if (audioContext == null) + { + starting = false; + return false; + } + + if (audioContext.resume != null) + { + audioContext.resume(); + } + + var constraints:Dynamic = + { + audio: + { + channelCount: parent.channels, + echoCancellation: false, + noiseSuppression: false, + autoGainControl: false + } + }; + + if (parent.sampleRate > 0) + { + constraints.audio.sampleRate = parent.sampleRate; + } + + if (parent.device != null && !parent.device.isDefault && parent.device.id != null && parent.device.id != "") + { + constraints.audio.deviceId = {exact: parent.device.id}; + } + + var navigator:Dynamic = Browser.navigator; + var promise:Dynamic = navigator.mediaDevices.getUserMedia(constraints); + + promise.then(function(stream) + { + if (disposed || !starting) + { + stopMediaStream(stream); + return; + } + + open(stream); + }, function(error) + { + starting = false; + parent.running = false; + }); + return false; } - public function stop():Void {} + public function stop():Void + { + starting = false; + parent.running = false; + + if (sourceNode != null) + { + sourceNode.disconnect(); + sourceNode = null; + } + + if (processorNode != null) + { + processorNode.disconnect(); + processorNode.onaudioprocess = null; + processorNode = null; + } + + if (audioContext != null && audioContext.close != null) + { + audioContext.close(); + audioContext = null; + } + + if (mediaStream != null) + { + stopMediaStream(mediaStream); + mediaStream = null; + } + } + + private function appendSamples(event:Dynamic):Void + { + var outputBuffer:Dynamic = event.outputBuffer; + + if (outputBuffer != null) + { + for (channel in 0...outputBuffer.numberOfChannels) + { + var output = outputBuffer.getChannelData(channel); + + for (frame in 0...outputBuffer.length) + { + output[frame] = 0; + } + } + } + + if (!parent.running || disposed || frameSize <= 0) + { + return; + } + + var inputBuffer:Dynamic = event.inputBuffer; + var frames:Int = inputBuffer.length; + var inputChannels:Int = inputBuffer.numberOfChannels; + var channelData:Array = []; + + for (channel in 0...parent.channels) + { + var sourceChannel = channel < inputChannels ? channel : 0; + channelData.push(inputBuffer.getChannelData(sourceChannel)); + } + + var bytes = Bytes.alloc(frames * frameSize); + var position = 0; + + for (frame in 0...frames) + { + for (channel in 0...parent.channels) + { + var sample:Float = channelData[channel][frame]; + + if (sample > 1) + { + sample = 1; + } + else if (sample < -1) + { + sample = -1; + } + + if (parent.bitsPerSample == 8) + { + bytes.set(position++, Std.int((sample * 0.5 + 0.5) * 255) & 0xFF); + } + else + { + var value = sample < 0 ? Std.int(sample * 32768) : Std.int(sample * 32767); + bytes.set(position++, value & 0xFF); + bytes.set(position++, (value >> 8) & 0xFF); + } + } + } + + buffers.push({bytes: bytes, offset: 0}); + queuedBytes += bytes.length; + trimQueue(); + } + + private function createAudioContext():Dynamic + { + var window:Dynamic = Browser.window; + var audioContextClass:Dynamic = window.AudioContext != null ? window.AudioContext : window.webkitAudioContext; + + if (audioContextClass == null) + { + return null; + } + + try + { + return untyped #if haxe4 js.Syntax.code #else __js__ #end ("new audioContextClass({ sampleRate: {0} })", parent.sampleRate); + } + catch (e:Dynamic) + { + return untyped #if haxe4 js.Syntax.code #else __js__ #end ("new audioContextClass()"); + } + } + + private function getFrameSize():Int + { + return Std.int((parent.channels * parent.bitsPerSample) / 8); + } + + private function getProcessorBufferSize():Int + { + var size = 256; + + while (size < parent.bufferSize && size < 16384) + { + size *= 2; + } + + return size; + } + + private function isFormatSupported():Bool + { + return (parent.channels == 1 || parent.channels == 2) && (parent.bitsPerSample == 8 || parent.bitsPerSample == 16); + } + + private function open(stream:Dynamic):Void + { + if (audioContext == null) + { + starting = false; + stopMediaStream(stream); + return; + } + + if (audioContext.sampleRate != null) + { + parent.sampleRate = Std.int(audioContext.sampleRate); + } + + mediaStream = stream; + sourceNode = audioContext.createMediaStreamSource(stream); + processorNode = audioContext.createScriptProcessor(getProcessorBufferSize(), parent.channels, parent.channels); + + processorNode.onaudioprocess = appendSamples; + sourceNode.connect(processorNode); + processorNode.connect(audioContext.destination); + + if (audioContext.resume != null) + { + audioContext.resume(); + } + + starting = false; + parent.running = true; + refreshDevices(); + } + + private static function refreshDevices():Void + { + if (enumeratingDevices || !isSupported()) + { + return; + } + + enumeratingDevices = true; + + var navigator:Dynamic = Browser.navigator; + var promise:Dynamic = navigator.mediaDevices.enumerateDevices(); + + promise.then(function(devices) + { + var result:Array = []; + var length:Int = devices.length; + + for (i in 0...length) + { + var device:Dynamic = devices[i]; + + if (device.kind == "audioinput") + { + var label:String = device.label != null && device.label != "" ? device.label : "Audio Input"; + result.push(new AudioInputDevice(label, device.deviceId, result.length == 0)); + } + } + + if (result.length > 0) + { + cachedDevices = result; + } + + enumeratingDevices = false; + }, function(error) + { + enumeratingDevices = false; + }); + } + + private function stopMediaStream(stream:Dynamic):Void + { + if (stream == null || stream.getTracks == null) + { + return; + } + + var tracks:Dynamic = stream.getTracks(); + var length:Int = tracks.length; + + for (i in 0...length) + { + tracks[i].stop(); + } + } + + private function trimQueue():Void + { + var maxQueuedBytes = Std.int((parent.sampleRate * MAX_QUEUED_MS / 1000) * frameSize); + + while (queuedBytes > maxQueuedBytes && buffers.length > 0) + { + var data = buffers.shift(); + queuedBytes -= data.bytes.length - data.offset; + } + } } From e0bd462b5de57f0872b6024c2e04ce455de9c3bd Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 01:03:06 -0400 Subject: [PATCH 46/76] Implement flash audio input b ackend --- .../backend/flash/FlashAudioInput.hx | 255 +++++++++++++++++- 1 file changed, 247 insertions(+), 8 deletions(-) diff --git a/src/lime/_internal/backend/flash/FlashAudioInput.hx b/src/lime/_internal/backend/flash/FlashAudioInput.hx index ec3e0a4fb2..59f0012252 100644 --- a/src/lime/_internal/backend/flash/FlashAudioInput.hx +++ b/src/lime/_internal/backend/flash/FlashAudioInput.hx @@ -1,49 +1,288 @@ package lime._internal.backend.flash; +import flash.events.SampleDataEvent; +import flash.media.Microphone; import haxe.io.Bytes; import lime.media.AudioInput; import lime.media.AudioInputDevice; +private typedef AudioInputData = +{ + var bytes:Bytes; + var offset:Int; +} + +@:access(lime.media.AudioInput) class FlashAudioInput { + private static inline var MAX_QUEUED_MS = 10000; + + private var buffers:Array; + private var frameSize:Int; + private var microphone:Microphone; private var parent:AudioInput; + private var queuedBytes:Int; public static function getDefaultDevice():AudioInputDevice { - return null; + if (!isSupported()) + { + return null; + } + + var microphone = Microphone.getMicrophone(); + + if (microphone != null) + { + return new AudioInputDevice(microphone.name, Std.string(microphone.index), true); + } + + var devices = getDevices(); + return devices.length > 0 ? devices[0] : null; } public static function getDevices():Array { - return []; + var devices:Array = []; + + if (!isSupported() || Microphone.names == null) + { + return devices; + } + + for (i in 0...Microphone.names.length) + { + var name = Std.string(Microphone.names[i]); + devices.push(new AudioInputDevice(name, Std.string(i), i == 0)); + } + + return devices; } public static function isSupported():Bool { - return false; + return Microphone.isSupported; } public function new(parent:AudioInput) { this.parent = parent; + + buffers = []; + frameSize = getFrameSize(); + queuedBytes = 0; } - public function dispose():Void {} + public function dispose():Void + { + stop(); + buffers.resize(0); + queuedBytes = 0; + } public function getSamplesAvailable():Int { - return 0; + if (frameSize <= 0) + { + return 0; + } + + return Std.int(queuedBytes / frameSize); } public function read(buffer:Bytes, samples:Int):Int { - return 0; + if (buffer == null || samples <= 0 || frameSize <= 0) + { + return 0; + } + + var samplesToRead = samples; + var available = getSamplesAvailable(); + var maxSamples = Std.int(buffer.length / frameSize); + + if (samplesToRead > available) + { + samplesToRead = available; + } + + if (samplesToRead > maxSamples) + { + samplesToRead = maxSamples; + } + + if (samplesToRead <= 0) + { + return 0; + } + + var bytesToRead = samplesToRead * frameSize; + var remaining = bytesToRead; + var writePosition = 0; + + while (remaining > 0 && buffers.length > 0) + { + var data = buffers[0]; + var availableBytes = data.bytes.length - data.offset; + var copyBytes = availableBytes < remaining ? availableBytes : remaining; + + buffer.blit(writePosition, data.bytes, data.offset, copyBytes); + + data.offset += copyBytes; + writePosition += copyBytes; + remaining -= copyBytes; + queuedBytes -= copyBytes; + + if (data.offset >= data.bytes.length) + { + buffers.shift(); + } + } + + return Std.int((bytesToRead - remaining) / frameSize); } public function start():Bool { - return false; + if (parent.running || !isSupported() || !isFormatSupported()) + { + return parent.running; + } + + var index = -1; + + if (parent.device != null && !parent.device.isDefault && parent.device.id != null) + { + var parsedIndex = Std.parseInt(parent.device.id); + + if (parsedIndex != null) + { + index = parsedIndex; + } + } + + microphone = Microphone.getMicrophone(index); + + if (microphone == null) + { + return false; + } + + microphone.rate = getMicrophoneRate(parent.sampleRate); + parent.sampleRate = microphone.rate * 1000; + + microphone.setLoopBack(false); + microphone.setSilenceLevel(0, -1); + microphone.setUseEchoSuppression(false); + microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, microphone_onSampleData); + + return true; + } + + public function stop():Void + { + parent.running = false; + + if (microphone != null) + { + microphone.removeEventListener(SampleDataEvent.SAMPLE_DATA, microphone_onSampleData); + microphone = null; + } + } + + private function appendSample(bytes:Bytes, position:Int, sample:Float):Int + { + if (sample > 1) + { + sample = 1; + } + else if (sample < -1) + { + sample = -1; + } + + if (parent.bitsPerSample == 8) + { + bytes.set(position++, Std.int((sample * 0.5 + 0.5) * 255) & 0xFF); + } + else + { + var value = sample < 0 ? Std.int(sample * 32768) : Std.int(sample * 32767); + bytes.set(position++, value & 0xFF); + bytes.set(position++, (value >> 8) & 0xFF); + } + + return position; + } + + private function getFrameSize():Int + { + return Std.int((parent.channels * parent.bitsPerSample) / 8); } - public function stop():Void {} + private function getMicrophoneRate(sampleRate:Int):Int + { + if (sampleRate >= 44100) + { + return 44; + } + else if (sampleRate >= 22050) + { + return 22; + } + else if (sampleRate >= 11025) + { + return 11; + } + else if (sampleRate >= 8000) + { + return 8; + } + + return 5; + } + + private function isFormatSupported():Bool + { + return (parent.channels == 1 || parent.channels == 2) && (parent.bitsPerSample == 8 || parent.bitsPerSample == 16); + } + + private function microphone_onSampleData(event:SampleDataEvent):Void + { + if (!parent.running || frameSize <= 0) + { + return; + } + + event.data.position = 0; + + var samples = Std.int(event.data.bytesAvailable / 4); + var bytes = Bytes.alloc(samples * frameSize); + var position = 0; + + for (i in 0...samples) + { + var sample = event.data.readFloat(); + + for (channel in 0...parent.channels) + { + position = appendSample(bytes, position, sample); + } + } + + buffers.push({bytes: bytes, offset: 0}); + queuedBytes += bytes.length; + trimQueue(); + } + + private function trimQueue():Void + { + var maxQueuedBytes = Std.int((parent.sampleRate * MAX_QUEUED_MS / 1000) * frameSize); + + while (queuedBytes > maxQueuedBytes && buffers.length > 0) + { + var data = buffers.shift(); + queuedBytes -= data.bytes.length - data.offset; + } + } } From 3593e6183033ab12f4c87775cd13aedc2af72044 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 01:04:03 -0400 Subject: [PATCH 47/76] account for async permissions in html5 --- src/lime/app/Event.hx | 2 +- src/lime/media/AudioInput.hx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lime/app/Event.hx b/src/lime/app/Event.hx index f7fb92e030..5c4b0a9daa 100644 --- a/src/lime/app/Event.hx +++ b/src/lime/app/Event.hx @@ -181,7 +181,7 @@ class Event private function get_timestamp():Int { - #if lime_doc_gen + #if (lime_doc_gen || macro) return (__timestamp != -1) ? __timestamp : 0; #else return (__timestamp != -1) ? __timestamp : lime.system.System.getTimer(); diff --git a/src/lime/media/AudioInput.hx b/src/lime/media/AudioInput.hx index 8a7d604daf..17446ff888 100644 --- a/src/lime/media/AudioInput.hx +++ b/src/lime/media/AudioInput.hx @@ -135,6 +135,9 @@ class AudioInput /** Starts audio capture. + + On backends that require asynchronous permission, such as HTML5, + `running` may become true after this method returns. **/ public function start():Void { @@ -151,7 +154,7 @@ class AudioInput **/ public function stop():Void { - if (__disposed || !running) + if (__disposed) { return; } From ebcd7c52e15ed92577c51bb26c8119d1ea9d2bf0 Mon Sep 17 00:00:00 2001 From: Sergei Sergeev Date: Sun, 11 Jan 2026 20:47:32 +0300 Subject: [PATCH 48/76] Fix perspective camera In a perspective projection matrix, the bottom-right element must be 0 to ensure correct perspective division. --- src/lime/math/Matrix4.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lime/math/Matrix4.hx b/src/lime/math/Matrix4.hx index 4c70f38066..ee479fbb78 100644 --- a/src/lime/math/Matrix4.hx +++ b/src/lime/math/Matrix4.hx @@ -416,7 +416,7 @@ abstract Matrix4(Float32Array) from Float32Array to Float32Array this[12] = 0; this[13] = 0; this[14] = -2 * zFar * zNear / (zFar - zNear); - this[15] = 1; + this[15] = 0; } /** From a23712a4033580a439913456cbe22d72854b0490 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 05:03:25 -0400 Subject: [PATCH 49/76] Add ALC extension presence support Expose alcIsExtensionPresent --- project/src/media/openal/OpenALBindings.cpp | 2 ++ src/lime/_internal/backend/native/NativeCFFI.hx | 10 ++++++++++ src/lime/media/OpenALAudioContext.hx | 9 +++++++-- src/lime/media/openal/ALC.hx | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/project/src/media/openal/OpenALBindings.cpp b/project/src/media/openal/OpenALBindings.cpp index 50fac5b710..73a4052cc0 100644 --- a/project/src/media/openal/OpenALBindings.cpp +++ b/project/src/media/openal/OpenALBindings.cpp @@ -3684,6 +3684,7 @@ namespace lime { DEFINE_PRIME1 (lime_al_is_effect); DEFINE_PRIME1 (lime_al_is_enabled); DEFINE_PRIME1 (lime_al_is_extension_present); + DEFINE_PRIME2 (lime_alc_is_extension_present); DEFINE_PRIME1 (lime_al_is_filter); DEFINE_PRIME1 (lime_al_is_source); DEFINE_PRIME4v (lime_al_listener3f); @@ -3813,6 +3814,7 @@ namespace lime { DEFINE_HL_PRIM (_BOOL, hl_al_is_effect, _TCFFIPOINTER); DEFINE_HL_PRIM (_BOOL, hl_al_is_enabled, _I32); DEFINE_HL_PRIM (_BOOL, hl_al_is_extension_present, _STRING); + DEFINE_HL_PRIM (_BOOL, hl_alc_is_extension_present, _TCFFIPOINTER _STRING); DEFINE_HL_PRIM (_BOOL, hl_al_is_filter, _TCFFIPOINTER); DEFINE_HL_PRIM (_BOOL, hl_al_is_source, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_al_listener3f, _I32 _F32 _F32 _F32); diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index af16f05912..bbb081e3d8 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -3016,6 +3016,8 @@ class NativeCFFI @:cffi private static function lime_al_is_extension_present(extname:String):Bool; + @:cffi private static function lime_alc_is_extension_present(device:CFFIPointer, extname:String):Bool; + @:cffi private static function lime_al_is_source(source:CFFIPointer):Bool; @:cffi private static function lime_al_listener3f(param:Int, value1:Float32, value2:Float32, value3:Float32):Void; @@ -3212,6 +3214,8 @@ class NativeCFFI private static var lime_al_is_enabled = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_enabled", "ib", false)); private static var lime_al_is_extension_present = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_extension_present", "sb", false)); + private static var lime_alc_is_extension_present = new cpp.CallableString->Bool>(cpp.Prime._loadPrime("lime", "lime_alc_is_extension_present", + "osb", false)); private static var lime_al_is_source = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_source", "ob", false)); private static var lime_al_listener3f = new cpp.Callablecpp.Float32->cpp.Float32->cpp.Float32->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listener3f", "ifffv", false)); @@ -3361,6 +3365,7 @@ class NativeCFFI private static var lime_al_is_buffer = CFFI.load("lime", "lime_al_is_buffer", 1); private static var lime_al_is_enabled = CFFI.load("lime", "lime_al_is_enabled", 1); private static var lime_al_is_extension_present = CFFI.load("lime", "lime_al_is_extension_present", 1); + private static var lime_alc_is_extension_present = CFFI.load("lime", "lime_alc_is_extension_present", 2); private static var lime_al_is_source = CFFI.load("lime", "lime_al_is_source", 1); private static var lime_al_listener3f = CFFI.load("lime", "lime_al_listener3f", 4); private static var lime_al_listener3i = CFFI.load("lime", "lime_al_listener3i", 4); @@ -3647,6 +3652,11 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_alc_is_extension_present") private static function lime_alc_is_extension_present(device:CFFIPointer, extname:String):Bool + { + return false; + } + @:hlNative("lime", "hl_al_is_source") private static function lime_al_is_source(source:CFFIPointer):Bool { return false; diff --git a/src/lime/media/OpenALAudioContext.hx b/src/lime/media/OpenALAudioContext.hx index c0eeb6b4e6..9d7b7d21a7 100644 --- a/src/lime/media/OpenALAudioContext.hx +++ b/src/lime/media/OpenALAudioContext.hx @@ -431,9 +431,14 @@ class OpenALAudioContext return AL.isEnabled(capability); } - public function isExtensionPresent(extname:String):Bool + public function isExtensionPresent(extname:String, device:ALDevice = null):Bool { - return AL.isExtensionPresent(extname); + if (extname == null) + { + return false; + } + + return device != null ? ALC.isExtensionPresent(device, extname) : AL.isExtensionPresent(extname); } public function isSource(source:ALSource):Bool diff --git a/src/lime/media/openal/ALC.hx b/src/lime/media/openal/ALC.hx index 7e2cc43ef7..80194c9afa 100644 --- a/src/lime/media/openal/ALC.hx +++ b/src/lime/media/openal/ALC.hx @@ -207,6 +207,20 @@ class ALC #end } + public static function isExtensionPresent(device:ALDevice, extname:String):Bool + { + if (extname == null) + { + return false; + } + + #if (lime_cffi && lime_openal && !macro) + return NativeCFFI.lime_alc_is_extension_present(device, extname); + #else + return false; + #end + } + public static function captureOpenDevice(deviceName:String = null, frequency:Int, format:Int, bufferSize:Int):ALDevice { #if (lime_cffi && lime_openal && !macro) From 2592aefabde82f43069c0284bd80e47a1632eb8e Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 05:03:49 -0400 Subject: [PATCH 50/76] including bindings --- project/src/media/openal/OpenALBindings.cpp | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/project/src/media/openal/OpenALBindings.cpp b/project/src/media/openal/OpenALBindings.cpp index 73a4052cc0..cd682d444d 100644 --- a/project/src/media/openal/OpenALBindings.cpp +++ b/project/src/media/openal/OpenALBindings.cpp @@ -2318,6 +2318,30 @@ namespace lime { } + bool lime_alc_is_extension_present (value device, HxString extname) { + + #ifdef LIME_OPENALSOFT + ALCdevice* alcDevice = val_is_null (device) ? NULL : (ALCdevice*)val_data (device); + return extname.__s ? alcIsExtensionPresent (alcDevice, extname.__s) : false; + #else + return false; + #endif + + } + + + HL_PRIM bool HL_NAME(hl_alc_is_extension_present) (HL_CFFIPointer* device, hl_vstring* extname) { + + #ifdef LIME_OPENALSOFT + ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : NULL; + return extname ? alcIsExtensionPresent (alcDevice, hl_to_utf8 (extname->bytes)) : false; + #else + return false; + #endif + + } + + bool lime_al_is_filter (value filter) { #ifdef LIME_OPENALSOFT From 88d151efa97b99e72962a01d87ac9e8456861c8a Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 05:47:54 -0400 Subject: [PATCH 51/76] Recover OpenAL audio after output device changes Recover native OpenAL playback when the active output device is disconnected. Some OpenAL implementations expose ALC_EXT_disconnect without newer device event or reopen extensions. In that case, active sources could stop producing audio after a headset or output device was unplugged, and they would not recover when another output became available. Track the current OpenAL context generation, poll ALC_CONNECTED as a low-cost compatibility fallback, and recreate the OpenAL context when the active device is lost. Active native AudioSource instances snapshot their playback state before recovery and restore their source handles, buffers, gain, pitch, position, time, loop count, and playing state afterward. Also remember the startup default output device and reopen it when it becomes the default again, so playback can move back from a fallback output to the original headset/device. If we migrate to a a higher version of OpenAL, we can make polling a pure fallback for MojoAL. --- .../backend/native/NativeAudioSource.hx | 116 ++++++++++ src/lime/media/AudioBuffer.hx | 1 + src/lime/media/AudioManager.hx | 215 ++++++++++++++++++ src/lime/media/openal/ALC.hx | 1 + 4 files changed, 333 insertions(+) diff --git a/src/lime/_internal/backend/native/NativeAudioSource.hx b/src/lime/_internal/backend/native/NativeAudioSource.hx index 363aa63117..1c19e1e757 100644 --- a/src/lime/_internal/backend/native/NativeAudioSource.hx +++ b/src/lime/_internal/backend/native/NativeAudioSource.hx @@ -32,6 +32,7 @@ class NativeAudioSource #if lime_openalsoft private static var hasDirectChannelsExt:Null; #end + private static var activeSources:Array = []; private var buffers:Array; private var bufferTimeBlocks:Array; @@ -48,6 +49,15 @@ class NativeAudioSource private var queuedBufferCount:Int; private var readArray:UInt8Array; private var readBuffer:Bytes; + private var recoveryCompleted:Bool; + private var recoveryGain:Float; + private var recoveryLength:Null; + private var recoveryLoops:Int; + private var recoveryPending:Bool; + private var recoveryPitch:Float; + private var recoveryPlaying:Bool; + private var recoveryPosition:Vector4; + private var recoveryTime:Int; private var sdlSoundStream:CFFIPointer; private var samples:Int; private var stream:Bool; @@ -64,10 +74,31 @@ class NativeAudioSource this.parent = parent; position = new Vector4(); + activeSources.push(this); + } + + @:allow(lime.media.AudioManager) + private static function prepareAudioContextRecovery():Void + { + for (source in activeSources.copy()) + { + source.prepareAudioContextRecoverySource(); + } + } + + @:allow(lime.media.AudioManager) + private static function restoreAudioContextRecovery():Void + { + for (source in activeSources.copy()) + { + source.restoreAudioContextRecoverySource(); + } } public function dispose():Void { + activeSources.remove(this); + if (handle != null) { stop(); @@ -195,8 +226,15 @@ class NativeAudioSource if (parent.buffer.__srcBuffer != null) { AL.bufferData(parent.buffer.__srcBuffer, format, parent.buffer.data, parent.buffer.data.length, parent.buffer.sampleRate); + parent.buffer.__srcBufferContext = AudioManager.__contextGeneration; } } + else if (parent.buffer.__srcBufferContext != AudioManager.__contextGeneration) + { + parent.buffer.__srcBuffer = null; + init(); + return; + } dataLength = parent.buffer.data.length; @@ -505,6 +543,84 @@ class NativeAudioSource queuedBufferCount = 0; } + private function prepareAudioContextRecoverySource():Void + { + if (parent.buffer == null) + { + recoveryPending = false; + return; + } + + recoveryPending = true; + recoveryCompleted = completed; + recoveryGain = getGain(); + recoveryLength = length; + recoveryLoops = loops; + recoveryPitch = getPitch(); + recoveryPlaying = playing; + recoveryPosition = getPosition().clone(); + recoveryTime = getCurrentTime(); + + if (streamTimer != null) + { + streamTimer.stop(); + streamTimer = null; + } + + if (timer != null) + { + timer.stop(); + timer = null; + } + + playing = false; + handle = null; + buffers = null; + bufferTimeBlocks = null; + queuedBufferCount = 0; + + if (parent.buffer != null) + { + parent.buffer.__srcBuffer = null; + parent.buffer.__srcBufferContext = 0; + } + + clearSDLSoundStream(); + clearVorbisStream(); + } + + private function restoreAudioContextRecoverySource():Void + { + if (!recoveryPending || parent.buffer == null) + { + return; + } + + recoveryPending = false; + completed = recoveryCompleted; + length = recoveryLength; + loops = recoveryLoops; + playing = false; + + init(); + + if (handle == null) + { + return; + } + + setGain(recoveryGain); + setPitch(recoveryPitch); + setPosition(recoveryPosition); + setCurrentTime(recoveryTime); + completed = recoveryCompleted; + + if (recoveryPlaying) + { + play(); + } + } + private function ensureReadBuffer(length:Int):Bool { if (length <= 0) diff --git a/src/lime/media/AudioBuffer.hx b/src/lime/media/AudioBuffer.hx index 8d3756d268..409739d212 100644 --- a/src/lime/media/AudioBuffer.hx +++ b/src/lime/media/AudioBuffer.hx @@ -70,6 +70,7 @@ class AudioBuffer @:noCompletion private var __srcAudio:#if (js && html5) Audio #else Dynamic #end; @:noCompletion private var __srcBuffer:#if lime_cffi ALBuffer #else Dynamic #end; + @:noCompletion private var __srcBufferContext:Int; @:noCompletion private var __srcCustom:Dynamic; @:noCompletion private var __srcHowl:#if lime_howlerjs Howl #else Dynamic #end; @:noCompletion private var __isDisposed:Bool; diff --git a/src/lime/media/AudioManager.hx b/src/lime/media/AudioManager.hx index 8a085f253d..023bf13696 100644 --- a/src/lime/media/AudioManager.hx +++ b/src/lime/media/AudioManager.hx @@ -2,6 +2,7 @@ package lime.media; import haxe.Timer; import lime._internal.backend.native.NativeCFFI; +import lime._internal.backend.native.NativeAudioSource; import lime.media.openal.AL; import lime.media.openal.ALC; import lime.media.openal.ALContext; @@ -18,6 +19,14 @@ import js.Browser; class AudioManager { public static var context:AudioContext; + @:noCompletion public static var __contextGeneration(default, null):Int; + private static inline var OUTPUT_DEVICE_POLL_TIME:Int = 1000; + private static var outputDevice:ALDevice; + private static var outputDeviceHasDisconnectExt:Bool; + private static var outputDeviceName:String; + private static var outputDevicePreferredName:String; + private static var outputDeviceRecovering:Bool; + private static var outputDeviceTimer:Timer; public static function init(context:AudioContext = null) { @@ -39,12 +48,14 @@ class AudioManager var ctx = alc.createContext(device); alc.makeContextCurrent(ctx); alc.processContext(ctx); + __contextGeneration++; } } #end } AudioManager.context = context; + setupOutputDeviceRecovery(); #if (lime_cffi && !macro && lime_openal && (ios || tvos || mac)) var timer = new Timer(100); @@ -77,6 +88,8 @@ class AudioManager public static function shutdown():Void { #if !lime_doc_gen + stopOutputDeviceRecovery(); + if (context != null && context.type == OPENAL) { var alc = context.openal; @@ -120,4 +133,206 @@ class AudioManager } #end } + + private static function closeOpenALContext():Void + { + #if !lime_doc_gen + if (context == null || context.type != OPENAL) + { + return; + } + + var alc = context.openal; + var currentContext = alc.getCurrentContext(); + + if (currentContext != null) + { + var device = alc.getContextsDevice(currentContext); + alc.makeContextCurrent(null); + alc.destroyContext(currentContext); + + if (device != null) + { + alc.closeDevice(device); + } + } + #end + } + + private static function getCurrentOutputDeviceName():String + { + #if (lime_cffi && !macro && lime_openal) + var name = ALC.getString(null, ALC.DEFAULT_ALL_DEVICES_SPECIFIER); + + if (name == null || name.length == 0) + { + name = ALC.getString(null, ALC.DEFAULT_DEVICE_SPECIFIER); + } + + return name; + #else + return null; + #end + } + + private static function isOutputDeviceConnected():Bool + { + #if (lime_cffi && !macro && lime_openal) + if (outputDevice == null || !outputDeviceHasDisconnectExt) + { + return true; + } + + var connected = ALC.getIntegerv(outputDevice, ALC.CONNECTED, 1); + return connected == null || connected.length == 0 || connected[0] == ALC.TRUE; + #else + return true; + #end + } + + private static function openOpenALContext(deviceName:String = null):Bool + { + #if !lime_doc_gen + if (context == null || context.type != OPENAL) + { + return false; + } + + var alc = context.openal; + var device = alc.openDevice(deviceName); + + if (device == null && deviceName != null) + { + device = alc.openDevice(); + } + + if (device == null) + { + return false; + } + + var currentContext = alc.createContext(device); + + if (currentContext == null) + { + alc.closeDevice(device); + return false; + } + + alc.makeContextCurrent(currentContext); + alc.processContext(currentContext); + __contextGeneration++; + return true; + #else + return false; + #end + } + + private static function recoverOutputDevice(deviceName:String = null):Void + { + if (outputDeviceRecovering || context == null || context.type != OPENAL) + { + return; + } + + outputDeviceRecovering = true; + NativeAudioSource.prepareAudioContextRecovery(); + closeOpenALContext(); + + if (openOpenALContext(deviceName)) + { + refreshOutputDeviceRecovery(); + NativeAudioSource.restoreAudioContextRecovery(); + } + + outputDeviceRecovering = false; + } + + private static function refreshOutputDeviceRecovery():Void + { + #if (lime_cffi && !macro && lime_openal) + if (context == null || context.type != OPENAL) + { + outputDevice = null; + outputDeviceHasDisconnectExt = false; + outputDeviceName = null; + return; + } + + var alc = context.openal; + var currentContext = alc.getCurrentContext(); + outputDevice = currentContext != null ? alc.getContextsDevice(currentContext) : null; + outputDeviceHasDisconnectExt = outputDevice != null && ALC.isExtensionPresent(outputDevice, "ALC_EXT_disconnect"); + outputDeviceName = getCurrentOutputDeviceName(); + #end + } + + private static function setupOutputDeviceRecovery():Void + { + #if (lime_cffi && !macro && lime_openal) + stopOutputDeviceRecovery(); + + if (context == null || context.type != OPENAL) + { + return; + } + + refreshOutputDeviceRecovery(); + + if (!outputDeviceHasDisconnectExt) + { + return; + } + + outputDevicePreferredName = outputDeviceName; + // ALC_EXT_disconnect exposes disconnect state, but not device-change events. + // Polling is kept as the compatibility fallback for that older API. + outputDeviceTimer = new Timer(OUTPUT_DEVICE_POLL_TIME); + outputDeviceTimer.run = updateOutputDeviceRecovery; + #end + } + + private static function stopOutputDeviceRecovery():Void + { + if (outputDeviceTimer != null) + { + outputDeviceTimer.stop(); + outputDeviceTimer = null; + } + + outputDevice = null; + outputDeviceHasDisconnectExt = false; + outputDeviceName = null; + outputDevicePreferredName = null; + outputDeviceRecovering = false; + } + + private static function updateOutputDeviceRecovery():Void + { + #if (lime_cffi && !macro && lime_openal) + if (outputDeviceRecovering || context == null || context.type != OPENAL) + { + return; + } + + if (!isOutputDeviceConnected()) + { + recoverOutputDevice(); + return; + } + + if (outputDevicePreferredName != null && outputDeviceName != outputDevicePreferredName) + { + var currentName = getCurrentOutputDeviceName(); + + if (currentName == outputDevicePreferredName) + { + recoverOutputDevice(outputDevicePreferredName); + return; + } + + outputDeviceName = currentName; + } + #end + } } diff --git a/src/lime/media/openal/ALC.hx b/src/lime/media/openal/ALC.hx index 80194c9afa..a897a232a8 100644 --- a/src/lime/media/openal/ALC.hx +++ b/src/lime/media/openal/ALC.hx @@ -37,6 +37,7 @@ class ALC public static inline var CAPTURE_DEVICE_SPECIFIER:Int = 0x310; public static inline var CAPTURE_DEFAULT_DEVICE_SPECIFIER:Int = 0x311; public static inline var CAPTURE_SAMPLES:Int = 0x312; + public static inline var CONNECTED:Int = 0x313; public static function closeDevice(device:ALDevice):Bool { From 8d9a49e6955cc0c733fa62db9b1accbb15f56bb0 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Fri, 23 May 2025 13:57:51 +0200 Subject: [PATCH 52/76] AudioBuffer: Don't force HTML5 audio when using fromBytes()/fromBase64() --- src/lime/media/AudioBuffer.hx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/lime/media/AudioBuffer.hx b/src/lime/media/AudioBuffer.hx index 409739d212..1cf584c5d8 100644 --- a/src/lime/media/AudioBuffer.hx +++ b/src/lime/media/AudioBuffer.hx @@ -136,7 +136,13 @@ class AudioBuffer } var audioBuffer = new AudioBuffer(); - audioBuffer.src = new Howl({src: [base64String], html5: true, preload: false}); + + #if force_html5_audio + audioBuffer.src = new Howl({src: [base64String], html5: true, preload: true}); + #else + audioBuffer.src = new Howl({src: [base64String], preload: true}); + #end + return audioBuffer; #elseif (lime_cffi && !macro) #if !cs @@ -182,7 +188,12 @@ class AudioBuffer #if (js && html5 && lime_howlerjs) var audioBuffer = new AudioBuffer(); - audioBuffer.src = new Howl({src: ["data:" + __getCodec(bytes) + ";base64," + Base64.encode(bytes)], html5: true, preload: false}); + + #if force_html5_audio + audioBuffer.src = new Howl({src: ["data:" + __getCodec(bytes) + ";base64," + Base64.encode(bytes)], html5: true, preload: true}); + #else + audioBuffer.src = new Howl({src: ["data:" + __getCodec(bytes) + ";base64," + Base64.encode(bytes)], preload: true}); + #end return audioBuffer; #elseif (lime_cffi && !macro) From 01a9171aa1461cf000c634ff05dd951e7a7bced8 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 10:21:29 -0400 Subject: [PATCH 53/76] compilation checks --- src/lime/media/AudioManager.hx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lime/media/AudioManager.hx b/src/lime/media/AudioManager.hx index 023bf13696..5001f7ab72 100644 --- a/src/lime/media/AudioManager.hx +++ b/src/lime/media/AudioManager.hx @@ -1,12 +1,16 @@ package lime.media; import haxe.Timer; +#if (lime_cffi && !macro && lime_openal) import lime._internal.backend.native.NativeCFFI; import lime._internal.backend.native.NativeAudioSource; +#end +#if (!lime_doc_gen || lime_openal) import lime.media.openal.AL; import lime.media.openal.ALC; import lime.media.openal.ALContext; import lime.media.openal.ALDevice; +#end #if (js && html5) import js.Browser; #end @@ -19,9 +23,13 @@ import js.Browser; class AudioManager { public static var context:AudioContext; - @:noCompletion public static var __contextGeneration(default, null):Int; + @:noCompletion public static var __contextGeneration(default, null):Int = 0; private static inline var OUTPUT_DEVICE_POLL_TIME:Int = 1000; + #if (!lime_doc_gen || lime_openal) private static var outputDevice:ALDevice; + #else + private static var outputDevice:Dynamic; + #end private static var outputDeviceHasDisconnectExt:Bool; private static var outputDeviceName:String; private static var outputDevicePreferredName:String; @@ -230,6 +238,7 @@ class AudioManager private static function recoverOutputDevice(deviceName:String = null):Void { + #if (lime_cffi && !macro && lime_openal) if (outputDeviceRecovering || context == null || context.type != OPENAL) { return; @@ -246,6 +255,7 @@ class AudioManager } outputDeviceRecovering = false; + #end } private static function refreshOutputDeviceRecovery():Void From e090825667b3d2718e7b8ff4e59616f6f88471e5 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 3 Jun 2026 10:39:02 -0400 Subject: [PATCH 54/76] Fix HashLink layout mismatch --- project/include/media/AudioBuffer.h | 3 ++- project/src/ExternalInterface.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/project/include/media/AudioBuffer.h b/project/include/media/AudioBuffer.h index 5f9a8130e0..5cd3e476d9 100644 --- a/project/include/media/AudioBuffer.h +++ b/project/include/media/AudioBuffer.h @@ -40,6 +40,7 @@ namespace lime { vdynamic* __srcAudio; vdynamic* __srcBuffer; + int __srcBufferContext; vdynamic* __srcCustom; vdynamic* __srcHowl; bool __isDisposed; @@ -63,4 +64,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 0e52b3da2a..9e800f3772 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -13613,7 +13613,7 @@ namespace lime { #define _TARRAYBUFFER _TBYTES #define _TARRAYBUFFERVIEW _OBJ (_I32 _TARRAYBUFFER _I32 _I32 _I32 _I32) - #define _TAUDIOBUFFER _OBJ (_I32 _I32 _TARRAYBUFFERVIEW _I32 _DYN _DYN _DYN _DYN _BOOL _DYN _TBYTES _BOOL _I32 _STRING _TBYTES _STRING _TVORBISFILE) + #define _TAUDIOBUFFER _OBJ (_I32 _I32 _TARRAYBUFFERVIEW _I32 _DYN _DYN _I32 _DYN _DYN _BOOL _DYN _TBYTES _BOOL _I32 _STRING _TBYTES _STRING _TVORBISFILE) #define _TIMAGEBUFFER _OBJ (_I32 _TARRAYBUFFERVIEW _I32 _I32 _BOOL _BOOL _I32 _DYN _DYN _DYN _DYN _DYN _DYN) #define _TIMAGE _OBJ (_TIMAGEBUFFER _BOOL _I32 _I32 _I32 _TRECTANGLE _ENUM _I32 _I32 _F64 _F64) From bf2704d7216a1e1c37012001607bc1f30af38562 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 5 Jun 2026 05:54:53 -0400 Subject: [PATCH 55/76] Support inline stream looping and loop counts Add handling for inline looping audio streams by tracking per-buffer and per-stream loop counts. --- .../backend/native/NativeAudioSource.hx | 159 +++++++++++++++++- 1 file changed, 152 insertions(+), 7 deletions(-) diff --git a/src/lime/_internal/backend/native/NativeAudioSource.hx b/src/lime/_internal/backend/native/NativeAudioSource.hx index 1c19e1e757..e881c5166e 100644 --- a/src/lime/_internal/backend/native/NativeAudioSource.hx +++ b/src/lime/_internal/backend/native/NativeAudioSource.hx @@ -47,6 +47,8 @@ class NativeAudioSource private var playing:Bool; private var position:Vector4; private var queuedBufferCount:Int; + private var queuedBufferLoopCounts:Array; + private var queuedStreamLoopCount:Int; private var readArray:UInt8Array; private var readBuffer:Bytes; private var recoveryCompleted:Bool; @@ -131,6 +133,8 @@ class NativeAudioSource streamExhausted = false; streamPosition = 0; queuedBufferCount = 0; + queuedBufferLoopCounts = []; + queuedStreamLoopCount = 0; ownsVorbisStream = false; clearVorbisStream(); clearSDLSoundStream(); @@ -525,6 +529,79 @@ class NativeAudioSource return length - (length % frameSize); } + private function getStreamBytePosition(useSDLSound:Bool, vorbisFile:VorbisFile):Int + { + if (useSDLSound) + { + return Std.int(streamPosition * streamByteRate); + } + + #if lime_vorbis + return (vorbisFile != null) ? Int64.toInt(vorbisFile.pcmTell()) : 0; + #else + return 0; + #end + } + + private function shouldLoopStreamInline():Bool + { + return stream && loops > 0 && length == null; + } + + private function resetStreamForLoop(useSDLSound:Bool):Bool + { + if (!shouldLoopStreamInline() || loops <= queuedStreamLoopCount) + { + return false; + } + + var streamTime = parent.offset; + var reset = useSDLSound ? resetSDLSoundStream(streamTime) : resetVorbisStream(streamTime); + + if (!reset) + { + return false; + } + + queuedStreamLoopCount++; + streamExhausted = false; + return true; + } + + private function consumeProcessedStreamLoopCounts(processed:Int):Void + { + if (queuedBufferLoopCounts == null || processed <= 0) + { + return; + } + + var completedLoops = 0; + for (i in 0...processed) + { + if (queuedBufferLoopCounts.length == 0) + { + break; + } + + completedLoops += queuedBufferLoopCounts.shift(); + } + + if (completedLoops > 0) + { + loops -= completedLoops; + if (loops < 0) + { + loops = 0; + } + + queuedStreamLoopCount -= completedLoops; + if (queuedStreamLoopCount < 0) + { + queuedStreamLoopCount = 0; + } + } + } + private function clearQueuedBuffers():Void { if (handle == null) @@ -541,6 +618,8 @@ class NativeAudioSource } queuedBufferCount = 0; + queuedBufferLoopCounts = []; + queuedStreamLoopCount = 0; } private function prepareAudioContextRecoverySource():Void @@ -578,6 +657,8 @@ class NativeAudioSource buffers = null; bufferTimeBlocks = null; queuedBufferCount = 0; + queuedBufferLoopCounts = []; + queuedStreamLoopCount = 0; if (parent.buffer != null) { @@ -738,10 +819,12 @@ class NativeAudioSource if (buffers != null) { queuedBufferCount -= buffers.length; + consumeProcessedStreamLoopCounts(buffers.length); } else { queuedBufferCount -= buffersProcessed; + consumeProcessedStreamLoopCounts(buffersProcessed); } if (queuedBufferCount < 0) @@ -770,13 +853,30 @@ class NativeAudioSource var numBuffers = 0; var bytesRead = 0; + var newBufferLoopCounts = []; for (buffer in buffers) { + var bufferLoopCount = 0; + if (hasKnownStreamLength && position >= dataLength) { - streamExhausted = true; - break; + if (resetStreamForLoop(useSDLSound)) + { + if (!useSDLSound) + { + #if lime_vorbis + vorbisFile = vorbisStream; + #end + } + + position = getStreamBytePosition(useSDLSound, vorbisFile); + } + else + { + streamExhausted = true; + break; + } } var requestLength = hasKnownStreamLength ? (dataLength - position) : STREAM_BUFFER_SIZE; @@ -803,17 +903,57 @@ class NativeAudioSource if (bytesRead <= 0 || readArray == null) { - streamExhausted = true; - break; + if (resetStreamForLoop(useSDLSound)) + { + if (!useSDLSound) + { + #if lime_vorbis + vorbisFile = vorbisStream; + #end + } + + position = getStreamBytePosition(useSDLSound, vorbisFile); + continue; + } + else + { + streamExhausted = true; + break; + } } AL.bufferData(buffer, format, readArray, bytesRead, parent.buffer.sampleRate); position += bytesRead; numBuffers++; + var stopAfterBuffer = false; + if (bytesRead < requestLength || (hasKnownStreamLength && position >= dataLength)) { - streamExhausted = true; + if (resetStreamForLoop(useSDLSound)) + { + bufferLoopCount++; + + if (!useSDLSound) + { + #if lime_vorbis + vorbisFile = vorbisStream; + #end + } + + position = getStreamBytePosition(useSDLSound, vorbisFile); + } + else + { + streamExhausted = true; + stopAfterBuffer = true; + } + } + + newBufferLoopCounts.push(bufferLoopCount); + + if (stopAfterBuffer) + { break; } } @@ -823,6 +963,11 @@ class NativeAudioSource var buffersToQueue = (numBuffers == buffers.length) ? buffers : buffers.slice(0, numBuffers); AL.sourceQueueBuffers(handle, numBuffers, buffersToQueue); queuedBufferCount += numBuffers; + + for (i in 0...numBuffers) + { + queuedBufferLoopCounts.push(newBufferLoopCounts[i]); + } } // OpenAL can unexpectedly stop playback if the buffers run out @@ -1014,13 +1159,13 @@ class NativeAudioSource var totalLength = getLength(); var timeRemaining = Std.int((totalLength - value) / getPitch()); - if (timeRemaining > 0) + if (timeRemaining > 0 && !shouldLoopStreamInline()) { completed = false; timer = new Timer(timeRemaining); timer.run = timer_onRun; } - else if (stream && totalLength <= 0) + else if (stream && (totalLength <= 0 || shouldLoopStreamInline())) { completed = false; timer = null; From b8d06e088d60cbcf08cb4e311445194ea65145af Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 5 Jun 2026 06:50:45 -0400 Subject: [PATCH 56/76] Add transparent window support --- project/include/ui/Window.h | 3 +- project/src/ExternalInterface.cpp | 15 +++++- project/src/backend/sdl/SDLWindow.cpp | 53 ++++++++++++++++++- project/src/graphics/vulkan/VKRenderer.cpp | 15 +++++- .../_internal/backend/html5/HTML5Window.hx | 3 +- .../_internal/backend/native/NativeWindow.hx | 9 +++- src/lime/system/System.hx | 2 + src/lime/tools/WindowData.hx | 2 + src/lime/ui/Window.hx | 2 + src/lime/ui/WindowAttributes.hx | 1 + templates/haxe/ApplicationMain.hx | 1 + 11 files changed, 97 insertions(+), 9 deletions(-) diff --git a/project/include/ui/Window.h b/project/include/ui/Window.h index 8af2651c4a..81afa74fae 100644 --- a/project/include/ui/Window.h +++ b/project/include/ui/Window.h @@ -114,7 +114,8 @@ namespace lime { WINDOW_FLAG_MAXIMIZED = 0x00004000, WINDOW_FLAG_ALWAYS_ON_TOP = 0x00008000, WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000, - WINDOW_FLAG_VULKAN = 0x00020000 + WINDOW_FLAG_VULKAN = 0x00020000, + WINDOW_FLAG_TRANSPARENT = 0x00040000 }; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 9e800f3772..008dd4c5fb 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -1152,14 +1152,25 @@ namespace lime { } VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - const VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = { + const bool transparentWindow = targetWindow && ((targetWindow->flags & WINDOW_FLAG_TRANSPARENT) != 0); + const VkCompositeAlphaFlagBitsKHR opaqueCompositeAlphaFlags[] = { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR }; + const VkCompositeAlphaFlagBitsKHR transparentCompositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR + }; + const VkCompositeAlphaFlagBitsKHR* compositeAlphaFlags = transparentWindow ? transparentCompositeAlphaFlags : opaqueCompositeAlphaFlags; + const size_t compositeAlphaFlagCount = transparentWindow + ? sizeof (transparentCompositeAlphaFlags) / sizeof (transparentCompositeAlphaFlags[0]) + : sizeof (opaqueCompositeAlphaFlags) / sizeof (opaqueCompositeAlphaFlags[0]); - for (size_t i = 0; i < sizeof (compositeAlphaFlags) / sizeof (compositeAlphaFlags[0]); ++i) { + for (size_t i = 0; i < compositeAlphaFlagCount; ++i) { if (capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) { diff --git a/project/src/backend/sdl/SDLWindow.cpp b/project/src/backend/sdl/SDLWindow.cpp index 5d42c30bc3..d38ce8ae4a 100644 --- a/project/src/backend/sdl/SDLWindow.cpp +++ b/project/src/backend/sdl/SDLWindow.cpp @@ -189,6 +189,43 @@ namespace lime { RemovePropW (hwnd, LIME_SDL_LAST_RESIZE_TICK_PROP); } + + static bool EnableTransparentWindow (SDL_Window* sdlWindow) { + + if (!sdlWindow) return false; + + SDL_SysWMinfo wminfo; + SDL_VERSION (&wminfo.version); + if (SDL_GetWindowWMInfo (sdlWindow, &wminfo) != 1) return false; + + HWND hwnd = wminfo.info.win.window; + if (!hwnd) return false; + + typedef struct { + int leftWidth; + int rightWidth; + int topHeight; + int bottomHeight; + } DwmMargins; + typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaFunc) (HWND hwnd, const DwmMargins* margins); + + HMODULE dwmapi = LoadLibraryW (L"dwmapi.dll"); + if (!dwmapi) return false; + + DwmExtendFrameIntoClientAreaFunc extendFrame = (DwmExtendFrameIntoClientAreaFunc)GetProcAddress (dwmapi, "DwmExtendFrameIntoClientArea"); + bool enabled = false; + + if (extendFrame) { + + DwmMargins margins = { -1, -1, -1, -1 }; + enabled = SUCCEEDED (extendFrame (hwnd, &margins)); + + } + + FreeLibrary (dwmapi); + return enabled; + + } #endif @@ -241,6 +278,14 @@ namespace lime { SDL_SetHint (SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); #endif + if (flags & WINDOW_FLAG_TRANSPARENT) { + + #ifdef SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY + SDL_SetHint (SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, "1"); + #endif + + } + if (flags & WINDOW_FLAG_HARDWARE) { if (useVulkan) { @@ -304,7 +349,7 @@ namespace lime { } - if (flags & WINDOW_FLAG_COLOR_DEPTH_32_BIT) { + if (flags & (WINDOW_FLAG_COLOR_DEPTH_32_BIT | WINDOW_FLAG_TRANSPARENT)) { SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); @@ -345,6 +390,12 @@ namespace lime { #if defined (HX_WINDOWS) && !defined (HX_WINRT) InstallResizeEventHook (sdlWindow); + + if ((flags & WINDOW_FLAG_TRANSPARENT) && !useVulkan) { + + EnableTransparentWindow (sdlWindow); + + } #endif #if defined (HX_WINDOWS) && !defined (HX_WINRT) diff --git a/project/src/graphics/vulkan/VKRenderer.cpp b/project/src/graphics/vulkan/VKRenderer.cpp index dfe41d9553..a8b9069a0d 100644 --- a/project/src/graphics/vulkan/VKRenderer.cpp +++ b/project/src/graphics/vulkan/VKRenderer.cpp @@ -1031,14 +1031,25 @@ namespace lime { } VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - const VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = { + const bool transparentWindow = window && ((window->flags & WINDOW_FLAG_TRANSPARENT) != 0); + const VkCompositeAlphaFlagBitsKHR opaqueCompositeAlphaFlags[] = { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR }; + const VkCompositeAlphaFlagBitsKHR transparentCompositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR + }; + const VkCompositeAlphaFlagBitsKHR* compositeAlphaFlags = transparentWindow ? transparentCompositeAlphaFlags : opaqueCompositeAlphaFlags; + const size_t compositeAlphaFlagCount = transparentWindow + ? sizeof (transparentCompositeAlphaFlags) / sizeof (transparentCompositeAlphaFlags[0]) + : sizeof (opaqueCompositeAlphaFlags) / sizeof (opaqueCompositeAlphaFlags[0]); - for (size_t i = 0; i < sizeof (compositeAlphaFlags) / sizeof (compositeAlphaFlags[0]); ++i) { + for (size_t i = 0; i < compositeAlphaFlagCount; ++i) { if (capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) { diff --git a/src/lime/_internal/backend/html5/HTML5Window.hx b/src/lime/_internal/backend/html5/HTML5Window.hx index 8e7b662b08..2d30cb33e7 100644 --- a/src/lime/_internal/backend/html5/HTML5Window.hx +++ b/src/lime/_internal/backend/html5/HTML5Window.hx @@ -320,7 +320,8 @@ class HTML5Window if (forceWebGL || (!forceCanvas && (!Reflect.hasField(contextAttributes, "hardware") || contextAttributes.hardware))) { - var transparentBackground = Reflect.hasField(contextAttributes, "background") && contextAttributes.background == null; + var transparentBackground = (Reflect.hasField(contextAttributes, "background") && contextAttributes.background == null) + || (Reflect.hasField(attributes, "transparent") && attributes.transparent); var colorDepth = Reflect.hasField(contextAttributes, "colorDepth") ? contextAttributes.colorDepth : 16; var options = diff --git a/src/lime/_internal/backend/native/NativeWindow.hx b/src/lime/_internal/backend/native/NativeWindow.hx index ecadbb89c1..f548ae1c5f 100644 --- a/src/lime/_internal/backend/native/NativeWindow.hx +++ b/src/lime/_internal/backend/native/NativeWindow.hx @@ -68,9 +68,12 @@ class NativeWindow var resolvedVSyncMode = parent.application.__resolveVSyncMode(attributes); var title = Reflect.hasField(attributes, "title") ? attributes.title : "Lime Application"; var flags = 0; + var transparent = Reflect.hasField(attributes, "transparent") && attributes.transparent; if (!Reflect.hasField(contextAttributes, "antialiasing")) contextAttributes.antialiasing = 0; - if (!Reflect.hasField(contextAttributes, "background")) contextAttributes.background = 0; - if (!Reflect.hasField(contextAttributes, "colorDepth")) contextAttributes.colorDepth = 24; + if (transparent) contextAttributes.background = null; + else if (!Reflect.hasField(contextAttributes, "background")) contextAttributes.background = 0; + if (!Reflect.hasField(contextAttributes, "colorDepth")) contextAttributes.colorDepth = transparent ? 32 : 24; + else if (transparent && contextAttributes.colorDepth < 32) contextAttributes.colorDepth = 32; if (!Reflect.hasField(contextAttributes, "depth")) contextAttributes.depth = true; if (!Reflect.hasField(contextAttributes, "hardware")) contextAttributes.hardware = true; if (!Reflect.hasField(contextAttributes, "stencil")) contextAttributes.stencil = true; @@ -92,6 +95,7 @@ class NativeWindow if (Reflect.hasField(attributes, "alwaysOnTop") && attributes.alwaysOnTop) flags |= cast WindowFlags.WINDOW_FLAG_ALWAYS_ON_TOP; if (Reflect.hasField(attributes, "borderless") && attributes.borderless) flags |= cast WindowFlags.WINDOW_FLAG_BORDERLESS; if (Reflect.hasField(attributes, "fullscreen") && attributes.fullscreen) flags |= cast WindowFlags.WINDOW_FLAG_FULLSCREEN; + if (transparent) flags |= cast WindowFlags.WINDOW_FLAG_TRANSPARENT; if (Reflect.hasField(attributes, "hidden") && attributes.hidden) flags |= cast WindowFlags.WINDOW_FLAG_HIDDEN; if (Reflect.hasField(attributes, "maximized") && attributes.maximized) flags |= cast WindowFlags.WINDOW_FLAG_MAXIMIZED; @@ -757,4 +761,5 @@ class NativeWindow var WINDOW_FLAG_ALWAYS_ON_TOP = 0x00008000; var WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000; var WINDOW_FLAG_VULKAN = 0x00020000; + var WINDOW_FLAG_TRANSPARENT = 0x00040000; } diff --git a/src/lime/system/System.hx b/src/lime/system/System.hx index e3a5f7c15a..64dc264dc4 100644 --- a/src/lime/system/System.hx +++ b/src/lime/system/System.hx @@ -627,6 +627,8 @@ class System attributes.resizable = __parseBool(argValue); case "stencil", "stencil-buffer": attributes.context.stencil = __parseBool(argValue); + case "transparent": + attributes.transparent = __parseBool(argValue); // case "title": windowConfig.title = argValue; case "vsync", "vsync-mode": var vsyncMode = __parseVSyncMode(argValue); diff --git a/src/lime/tools/WindowData.hx b/src/lime/tools/WindowData.hx index 92f101feb1..1f74f090ad 100644 --- a/src/lime/tools/WindowData.hx +++ b/src/lime/tools/WindowData.hx @@ -26,6 +26,7 @@ abstract WindowData({ @:optional var depthBuffer:Bool; @:optional var stencilBuffer:Bool; @:optional var title:String; + @:optional var transparent:Bool; #if (js && html5) @:optional var element:js.html.Element; #end @@ -61,6 +62,7 @@ abstract WindowData({ depthBuffer: false, stencilBuffer: false, title: "", + transparent: false, #if (js && html5) element: null, #end diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index 7fe8d2a1c3..37e5f870b2 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -149,6 +149,7 @@ class Window #end public var textInputEnabled(get, set):Bool; public var title(get, set):String; + public var transparent(default, null):Bool; public var alwaysOnTop(get, set):Bool; public var visible(get, set):Bool; public var width(get, set):Int; @@ -236,6 +237,7 @@ class Window __resizable = Reflect.hasField(__attributes, "resizable") ? __attributes.resizable : false; __maximized = Reflect.hasField(__attributes, "maximized") ? __attributes.maximized : false; __minimized = Reflect.hasField(__attributes, "minimized") ? __attributes.minimized : false; + transparent = Reflect.hasField(__attributes, "transparent") ? __attributes.transparent : false; id = -1; __backend = new WindowBackend(this); if (id != -1 && application != null) application.__seedFrameConfiguration(__attributes); diff --git a/src/lime/ui/WindowAttributes.hx b/src/lime/ui/WindowAttributes.hx index 5568cd6448..fbf59dffe1 100644 --- a/src/lime/ui/WindowAttributes.hx +++ b/src/lime/ui/WindowAttributes.hx @@ -40,6 +40,7 @@ typedef WindowAttributes = @:optional public var parameters:Dynamic; @:optional public var resizable:Bool; @:optional public var skipTaskbar:Bool; + @:optional public var transparent:Bool; @:optional public var utility:Bool; @:optional public var popupMenu:Bool; @:optional public var tooltip:Bool; diff --git a/templates/haxe/ApplicationMain.hx b/templates/haxe/ApplicationMain.hx index 2fadafabb0..66c445d16f 100644 --- a/templates/haxe/ApplicationMain.hx +++ b/templates/haxe/ApplicationMain.hx @@ -49,6 +49,7 @@ import ::APP_MAIN::; parameters: ::parameters::, resizable: ::resizable::, title: "::title::", + transparent: ::transparent::, width: ::width::, x: ::x::, y: ::y::, From 6f124fcfa75b99b5fb6f08c9e949271a9e82a38c Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 5 Jun 2026 06:52:11 -0400 Subject: [PATCH 57/76] Fix HL Vulkan exports --- project/src/ExternalInterface.cpp | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 008dd4c5fb..2f6abcb4a8 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -13797,6 +13797,23 @@ namespace lime { DEFINE_HL_PRIM (_BOOL, hl_vk_wait_for_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_BOOL, hl_vk_reset_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_BOOL, hl_vk_queue_submit, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_allocate_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_free_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_upload_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_download_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_map_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_unmap_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_write_mapped_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_flush_mapped_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_invalidate_mapped_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_get_buffer_memory_requirements, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_bind_buffer_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_get_image_memory_requirements, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_bind_image_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_DYN, hl_vk_create_swapchain, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_VOID, hl_vk_destroy_swapchain, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_ARR, hl_vk_get_swapchain_images, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); @@ -13804,6 +13821,55 @@ namespace lime { DEFINE_HL_PRIM (_I32, hl_vk_queue_present, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_DYN, hl_vk_create_image_view, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); DEFINE_HL_PRIM (_VOID, hl_vk_destroy_image_view, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_image_view_ex, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_framebuffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _ARR _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_framebuffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_shader_module, _TCFFIPOINTER _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_shader_module, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_sampler, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _BOOL _F64 _I32 _F64 _F64); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_sampler, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_descriptor_set_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_descriptor_set_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_descriptor_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_descriptor_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_descriptor_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_allocate_descriptor_set, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_update_descriptor_set_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_update_descriptor_set_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_update_descriptor_sets, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_DYN, hl_vk_create_pipeline_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_pipeline_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_pipeline_cache, _TCFFIPOINTER _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_pipeline_cache, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_get_pipeline_cache_data, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES); + DEFINE_HL_PRIM (_DYN, hl_vk_create_graphics_pipeline, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_pipeline, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_queue_submit_synced, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_begin_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_end_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_pipeline, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_descriptor_set, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_descriptor_set_ex, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_descriptor_set_dynamic_offset, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_vertex_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_index_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_set_viewport, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _F64 _F64 _F64 _F64 _F64 _F64); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_set_scissor, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw_indexed, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw_indirect, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw_indexed_indirect, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_copy_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_copy_buffer_to_image_region, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_copy_image_to_buffer_region, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_pipeline_barrier_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_clear_color_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_clear_depth_stencil_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_clear_attachments, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _ARR _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_blit_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_push_constants, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR _TBYTES); DEFINE_HL_PRIM (_BYTES, hl_vk_get_last_error, _NO_ARG); DEFINE_HL_PRIM (_TCFFIPOINTER, hl_vulkan_renderer_create, _TCFFIPOINTER _STRING); DEFINE_HL_PRIM (_VOID, hl_vulkan_renderer_destroy, _TCFFIPOINTER); From f53e224096462121158ccf6ebe7037dd844bf290 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 5 Jun 2026 06:57:27 -0400 Subject: [PATCH 58/76] Fix HTML5 transparent docs build --- src/lime/_internal/backend/html5/HTML5Window.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lime/_internal/backend/html5/HTML5Window.hx b/src/lime/_internal/backend/html5/HTML5Window.hx index 2d30cb33e7..e36aa53e34 100644 --- a/src/lime/_internal/backend/html5/HTML5Window.hx +++ b/src/lime/_internal/backend/html5/HTML5Window.hx @@ -321,7 +321,7 @@ class HTML5Window if (forceWebGL || (!forceCanvas && (!Reflect.hasField(contextAttributes, "hardware") || contextAttributes.hardware))) { var transparentBackground = (Reflect.hasField(contextAttributes, "background") && contextAttributes.background == null) - || (Reflect.hasField(attributes, "transparent") && attributes.transparent); + || parent.transparent; var colorDepth = Reflect.hasField(contextAttributes, "colorDepth") ? contextAttributes.colorDepth : 16; var options = From 7c2d7e2e08823994a20fe56b0ecfa3abcf00600e Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Fri, 12 Jun 2026 17:55:35 -0400 Subject: [PATCH 59/76] Gate invisible window optimization --- src/lime/_internal/backend/native/NativeApplication.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lime/_internal/backend/native/NativeApplication.hx b/src/lime/_internal/backend/native/NativeApplication.hx index ba9ba37d72..ad45bbaba0 100644 --- a/src/lime/_internal/backend/native/NativeApplication.hx +++ b/src/lime/_internal/backend/native/NativeApplication.hx @@ -463,11 +463,13 @@ class NativeApplication for (window in parent.__windows) { if (window == null) continue; - if (!window.visible) continue; // parent.renderer = renderer; switch (renderEventInfo.type) { case RENDER: + #if lime_skip_invisible_windows + if (!window.visible) continue; + #end if (window.context != null) { window.__backend.render(); From dd530ba3f532d8b0743de56371a36c0cd3a2d7ac Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 12:59:14 -0400 Subject: [PATCH 60/76] prepare for 8.4.0 --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d456a168..f3ddcb60e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,38 @@ Changelog ========= +8.4.0 (06/18/2026) +------------------ + +- Added an experimental Vulkan renderer for native Windows, Linux, and Android targets. +- Added `VulkanRenderContext` and Haxe Vulkan bindings for instance, device, swapchain, command, descriptor, memory, and pipeline helpers. +- Added Vulkan bootstrap logging, error details, MSAA resolve support, mapped memory helpers, and descriptor helpers. +- Added configurable application frame timing with `FrameProfile`, `FrameOptions`, `VSyncMode`, busy-wait, time precision, and uncap controls. +- Added `AudioInput` and audio input device APIs with native OpenAL, HTML5, and Flash backends. +- Added SDL_sound decoding and streaming, including inline stream playback, streams with unknown length, and loop counts. +- Added `Window.alwaysOnTop` and transparent window support. +- Added input event timestamps without changing listener signatures. +- Added `Promise.completeAsync()`. +- Added explicit font rendering flags, DPI-aware glyph rendering, unhinted font decomposition, and HarfBuzz FT font change notifications. +- Added project.xml support for Android manifest tags and Gradle plugin entries. +- Added AIR options for Android App Bundles, Android Studio output, and shared runtime deployment. +- Added VAO support on macOS. +- Changed asset copying and embedding to behave consistently across targets. +- Changed OpenAL Soft HRTF to be disabled by default. +- Updated pixman and platform config for LLVM assembly fixes, ARM NEON, Android NDKs, and Apple platforms. +- Updated MojoAL and gamepad mappings. +- Fixed an asset embedding regression. +- Fixed Windows cpp icon resource handling when no icon is generated. +- Fixed GL cleanup and desktop GL object collection. +- Fixed native and HashLink `AudioBuffer` layout mismatches. +- Fixed `AudioBuffer.fromBytes()` and `AudioBuffer.fromBase64()` on HTML5 to avoid forcing HTML5 audio buffers. +- Fixed OpenAL output device recovery. +- Fixed perspective camera matrix calculation. +- Fixed Tizen `appinfo.json` templating. +- Fixed Android architecture parsing for `x86_64` and `x86_32`. +- Fixed SDL_sound ARM64 Linux detection outside Raspberry Pi OS. +- Fixed HTML5 transparent docs generation. + 8.3.2 (05/13/2026) ------------------ From e749e62e72b46e17319c0ca269d8852247b8e4c5 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 13:54:10 -0400 Subject: [PATCH 61/76] Stop copying embedded assets --- src/lime/tools/PlatformTarget.hx | 36 +++++++++++++++++++------- tools/platforms/AndroidPlatform.hx | 2 ++ tools/platforms/IOSPlatform.hx | 2 ++ tools/platforms/LinuxPlatform.hx | 2 ++ tools/platforms/MacPlatform.hx | 2 ++ tools/platforms/TVOSPlatform.hx | 2 ++ tools/platforms/TizenPlatform.hx | 2 ++ tools/platforms/WebAssemblyPlatform.hx | 2 ++ tools/platforms/WindowsPlatform.hx | 2 ++ 9 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/lime/tools/PlatformTarget.hx b/src/lime/tools/PlatformTarget.hx index fc5dc2a20f..11daa26e25 100644 --- a/src/lime/tools/PlatformTarget.hx +++ b/src/lime/tools/PlatformTarget.hx @@ -201,6 +201,22 @@ class PlatformTarget // Common functionality used by subclasses + private function prepareEmbeddedAssets():Void + { + var embedDirectory = Path.combine(targetDirectory, "obj/tmp"); + + for (asset in project.assets) + { + if (asset.type != AssetType.TEMPLATE && asset.embed == true && asset.sourcePath == "") + { + var path = Path.combine(embedDirectory, asset.targetPath); + System.mkdir(Path.directory(path)); + AssetHelper.copyAsset(asset, path); + asset.sourcePath = path; + } + } + } + private function copyProjectAssets(outputDirectory:String, assetDirectory:String = null) { if (assetDirectory == null) @@ -212,27 +228,27 @@ class PlatformTarget assetDirectory = Path.combine(outputDirectory, assetDirectory); } - var embedDirectory = Path.combine(targetDirectory, "obj/tmp"); + prepareEmbeddedAssets(); for (asset in project.assets) { + var path = Path.combine(assetDirectory, asset.targetPath); + if (asset.type == AssetType.TEMPLATE) { - var path = Path.combine(outputDirectory, asset.targetPath); + path = Path.combine(outputDirectory, asset.targetPath); System.mkdir(Path.directory(path)); AssetHelper.copyAsset(asset, path, project.templateContext); } - else + else if (asset.embed == true) { - if (asset.embed == true && asset.sourcePath == "") + if (FileSystem.exists(path) && !FileSystem.isDirectory(path)) { - var path = Path.combine(embedDirectory, asset.targetPath); - System.mkdir(Path.directory(path)); - AssetHelper.copyAsset(asset, path); - asset.sourcePath = path; + System.deleteFile(path); } - - var path = Path.combine(assetDirectory, asset.targetPath); + } + else + { System.mkdir(Path.directory(path)); AssetHelper.copyAssetIfNewer(asset, path); } diff --git a/tools/platforms/AndroidPlatform.hx b/tools/platforms/AndroidPlatform.hx index 91057bc452..5adcb94ceb 100644 --- a/tools/platforms/AndroidPlatform.hx +++ b/tools/platforms/AndroidPlatform.hx @@ -403,6 +403,8 @@ class AndroidPlatform extends PlatformTarget // initialize (project); + prepareEmbeddedAssets(); + var destination = targetDirectory + "/bin"; var sourceSet = destination + "/app/src/main"; System.mkdir(sourceSet); diff --git a/tools/platforms/IOSPlatform.hx b/tools/platforms/IOSPlatform.hx index dc9170417c..915463819f 100644 --- a/tools/platforms/IOSPlatform.hx +++ b/tools/platforms/IOSPlatform.hx @@ -523,6 +523,8 @@ class IOSPlatform extends PlatformTarget // manifest.type = AssetType.TEXT; // project.assets.push (manifest); + prepareEmbeddedAssets(); + var context = generateContext(); context.OUTPUT_DIR = targetDirectory; diff --git a/tools/platforms/LinuxPlatform.hx b/tools/platforms/LinuxPlatform.hx index b23644f544..094b0a9022 100644 --- a/tools/platforms/LinuxPlatform.hx +++ b/tools/platforms/LinuxPlatform.hx @@ -567,6 +567,8 @@ class LinuxPlatform extends PlatformTarget // project = project.clone (); // initialize (project); + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); diff --git a/tools/platforms/MacPlatform.hx b/tools/platforms/MacPlatform.hx index a90383a147..f2c0b3b6bd 100644 --- a/tools/platforms/MacPlatform.hx +++ b/tools/platforms/MacPlatform.hx @@ -520,6 +520,8 @@ class MacPlatform extends PlatformTarget // project = project.clone (); + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); diff --git a/tools/platforms/TVOSPlatform.hx b/tools/platforms/TVOSPlatform.hx index 159c531ebe..331805dd94 100644 --- a/tools/platforms/TVOSPlatform.hx +++ b/tools/platforms/TVOSPlatform.hx @@ -433,6 +433,8 @@ class TVOSPlatform extends PlatformTarget // manifest.type = AssetType.TEXT; // project.assets.push (manifest); + prepareEmbeddedAssets(); + var context = generateContext(); context.OUTPUT_DIR = targetDirectory; diff --git a/tools/platforms/TizenPlatform.hx b/tools/platforms/TizenPlatform.hx index 8ecb2d082f..5aff46f681 100644 --- a/tools/platforms/TizenPlatform.hx +++ b/tools/platforms/TizenPlatform.hx @@ -203,6 +203,8 @@ class TizenPlatform extends PlatformTarget asset.resourceName = "../res/" + asset.resourceName; } + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); diff --git a/tools/platforms/WebAssemblyPlatform.hx b/tools/platforms/WebAssemblyPlatform.hx index 420594e8bc..11281fb8de 100644 --- a/tools/platforms/WebAssemblyPlatform.hx +++ b/tools/platforms/WebAssemblyPlatform.hx @@ -375,6 +375,8 @@ class WebAssemblyPlatform extends PlatformTarget var destination = targetDirectory + "/bin/"; System.mkdir(destination); + prepareEmbeddedAssets(); + // for (asset in project.assets) { // // if (asset.type == AssetType.FONT) { diff --git a/tools/platforms/WindowsPlatform.hx b/tools/platforms/WindowsPlatform.hx index 3bc28d3110..de9f8ec17b 100644 --- a/tools/platforms/WindowsPlatform.hx +++ b/tools/platforms/WindowsPlatform.hx @@ -954,6 +954,8 @@ class WindowsPlatform extends PlatformTarget // project = project.clone (); + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); From 79e2cef701820fa6db8cdb2cbf3f103db4d6d946 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 14:39:10 -0400 Subject: [PATCH 62/76] Avoid duplicate embedded asset prep --- src/lime/tools/PlatformTarget.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lime/tools/PlatformTarget.hx b/src/lime/tools/PlatformTarget.hx index 11daa26e25..75768f0287 100644 --- a/src/lime/tools/PlatformTarget.hx +++ b/src/lime/tools/PlatformTarget.hx @@ -228,8 +228,6 @@ class PlatformTarget assetDirectory = Path.combine(outputDirectory, assetDirectory); } - prepareEmbeddedAssets(); - for (asset in project.assets) { var path = Path.combine(assetDirectory, asset.targetPath); From baaf478e60b294d9f499530857602c535cfd944a Mon Sep 17 00:00:00 2001 From: Joseph Cloutier Date: Thu, 18 Jun 2026 14:57:13 -0400 Subject: [PATCH 63/76] Document asset embedding functions. --- src/lime/tools/PlatformTarget.hx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lime/tools/PlatformTarget.hx b/src/lime/tools/PlatformTarget.hx index 75768f0287..49e5b17a95 100644 --- a/src/lime/tools/PlatformTarget.hx +++ b/src/lime/tools/PlatformTarget.hx @@ -201,6 +201,10 @@ class PlatformTarget // Common functionality used by subclasses + /** + Copies all embedded assets into a temporary directory and sets their + `sourcePath`. This must happen before generating template contexts. + **/ private function prepareEmbeddedAssets():Void { var embedDirectory = Path.combine(targetDirectory, "obj/tmp"); @@ -217,6 +221,13 @@ class PlatformTarget } } + /** + Copies all non-embedded assets into the given directories. + @param outputDirectory The root directory for template assets. + @param assetDirectory The root directory for non-template assets. If not + an absolute path, interpreted relative to `outputDirectory`. If null, + defaults to `outputDirectory`. + **/ private function copyProjectAssets(outputDirectory:String, assetDirectory:String = null) { if (assetDirectory == null) From ce2399729afd749e183b8435f9d297f203e42dc5 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 16:03:05 -0400 Subject: [PATCH 64/76] Reduce Bytes resize mutex scope Move Bytes resize allocation, copy, and free work outside the shared ownership mutex, leaving the lock only around usingValue bookkeeping and pointer/length updates. This reduces observed contention in threaded compression paths while preserving Haxe Bytes ownership. closes https://github.com/openfl/lime/issues/1943 --- project/src/utils/Bytes.cpp | 64 ++++++++++++------------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/project/src/utils/Bytes.cpp b/project/src/utils/Bytes.cpp index 83f028f2dd..e0136147f6 100644 --- a/project/src/utils/Bytes.cpp +++ b/project/src/utils/Bytes.cpp @@ -122,72 +122,50 @@ namespace lime { if (size != length || (length > 0 && !b)) { - mutex.Lock (); - - if (size <= 0) { - - if (b) { - - if (usingValue.find (this) != usingValue.end ()) { - - usingValue.erase (this); - - } else { + unsigned char* data = 0; + unsigned char* oldB = b; + bool freeOldB = false; - free (b); + if (size > 0) { - } - - } else if (usingValue.find (this) != usingValue.end ()) { - - usingValue.erase (this); - - } - - b = 0; - length = 0; - - } else { - - unsigned char* data = (unsigned char*)malloc (sizeof (char) * size); + data = (unsigned char*)malloc (sizeof (char) * size); if (!data) { - mutex.Unlock (); return false; } - if (b) { + if (b && length) { - if (length) { + memcpy (data, b, length < size ? length : size); - memcpy (data, b, length < size ? length : size); + } - } + } - if (usingValue.find (this) != usingValue.end ()) { + mutex.Lock (); - usingValue.erase (this); + if (usingValue.find (this) != usingValue.end ()) { - } else { + usingValue.erase (this); - free (b); + } else if (oldB) { - } + freeOldB = true; - } else if (usingValue.find (this) != usingValue.end ()) { + } - usingValue.erase (this); + b = data; + length = size > 0 ? size : 0; - } + mutex.Unlock (); - b = data; - length = size; + if (freeOldB) { - } + free (oldB); - mutex.Unlock (); + } } From aa6ce421236ee0856dac5c5d193fcbe97cbd238b Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 16:18:14 -0400 Subject: [PATCH 65/76] Fix FileDialog wildcard filter handling Normalize FileDialog filters so existing bare extensions like png still work while documented wildcard filters like *.png are accepted without becoming *.*.png. Also fixes save-dialog filter construction to use the full filter string with stable storage, and keeps save auto-extension from appending wildcard text into filenames. CLoses https://github.com/openfl/lime/issues/1945 --- project/src/ui/FileDialog.cpp | 90 +++++++++++++++++++++-------------- src/lime/ui/FileDialog.hx | 47 +++++++++++++++--- 2 files changed, 95 insertions(+), 42 deletions(-) diff --git a/project/src/ui/FileDialog.cpp b/project/src/ui/FileDialog.cpp index b740102696..ec561973b1 100644 --- a/project/src/ui/FileDialog.cpp +++ b/project/src/ui/FileDialog.cpp @@ -25,6 +25,45 @@ namespace lime { return str == nullptr || str[0] == 0; } + static string_t normalize_filter (const string_t& filter) { + + if (filter.empty () || filter.find (FD_STR('*')) != string_t::npos || filter.find (FD_STR('?')) != string_t::npos) { + + return filter; + + } + + if (filter[0] == FD_STR('.')) { + + return string_t (FD_STR("*")) + filter; + + } + + return string_t (FD_STR("*.")) + filter; + + } + + static std::vector normalize_filters (const char_t* filter) { + + std::vector filters; + + if (filter) { + + string_t line; + std::basic_stringstream ss (filter); + + while (std::getline (ss, line, FD_STR(','))) { + + filters.push_back (normalize_filter (line)); + + } + + } + + return filters; + + } + const char_t* FileDialog::OpenDirectory (const char_t* title, const char_t* filter, const char_t* defaultPath) { // TODO: Filter? @@ -44,27 +83,17 @@ namespace lime { const char_t* FileDialog::OpenFile (const char_t* title, const char_t* filter, const char_t* defaultPath) { - std::vector filters_vec; - if (filter) { - string_t temp(FD_STR("*.")); - string_t line; - std::basic_stringstream ss(filter); - while(std::getline(ss, line, FD_STR(','))) { - filters_vec.push_back(temp + line); - } - } + std::vector filters_vec = normalize_filters (filter); - const int numFilters = filter ? filters_vec.size() : 1; - const char_t **filters = new const char_t*[numFilters]; - if (filter && numFilters > 0) { + const int numFilters = filters_vec.size (); + const char_t **filters = numFilters > 0 ? new const char_t*[numFilters] : NULL; + if (numFilters > 0) { for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + filters[index] = filters_vec[index].c_str(); } - } else { - filters[0] = NULL; } - const char_t* path = tinyfd_openFileDialog (title, defaultPath, filter ? numFilters : 0, filter ? filters : NULL, NULL, 0); + const char_t* path = tinyfd_openFileDialog (title, defaultPath, numFilters, filters, NULL, 0); delete[] filters; @@ -82,27 +111,17 @@ namespace lime { std::vector FileDialog::OpenFiles (const char_t* title, const char_t* filter, const char_t* defaultPath) { std::vector files; - std::vector filters_vec; - if (filter) { - string_t temp(FD_STR("*.")); - string_t line; - std::basic_stringstream ss(filter); - while(std::getline(ss, line, FD_STR(','))) { - filters_vec.push_back(temp + line); - } - } + std::vector filters_vec = normalize_filters (filter); - const int numFilters = filter ? filters_vec.size() : 1; - const char_t **filters = new const char_t*[numFilters]; - if (filter && numFilters > 0) { + const int numFilters = filters_vec.size (); + const char_t **filters = numFilters > 0 ? new const char_t*[numFilters] : NULL; + if (numFilters > 0) { for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + filters[index] = filters_vec[index].c_str(); } - } else { - filters[0] = NULL; } - const char_t* paths = tinyfd_openFileDialog (title, defaultPath, filter ? numFilters : 0, filter ? filters : NULL, NULL, 1); + const char_t* paths = tinyfd_openFileDialog (title, defaultPath, numFilters, filters, NULL, 1); delete[] filters; @@ -133,10 +152,11 @@ namespace lime { const char_t* FileDialog::SaveFile (const char_t* title, const char_t* filter, const char_t* defaultPath) { - string_t temp(FD_STR("*.")); - const char_t* filters[] = { filter ? (temp + *filter).c_str () : NULL }; + std::vector filters_vec = normalize_filters (filter); + const int numFilters = filters_vec.size () > 0 ? 1 : 0; + const char_t* filters[] = { numFilters > 0 ? filters_vec[0].c_str () : NULL }; - const char_t* path = tinyfd_saveFileDialog (title, defaultPath, filter ? 1 : 0, filter ? filters : NULL, NULL); + const char_t* path = tinyfd_saveFileDialog (title, defaultPath, numFilters, numFilters > 0 ? filters : NULL, NULL); if (!is_null_or_empty(path)) { diff --git a/src/lime/ui/FileDialog.hx b/src/lime/ui/FileDialog.hx index 014c11b8b5..7004406412 100644 --- a/src/lime/ui/FileDialog.hx +++ b/src/lime/ui/FileDialog.hx @@ -82,14 +82,46 @@ class FileDialog public function new() {} + private static function __extensionFromFilter(filter:String):String + { + for (entry in filter.split(",")) + { + if (entry.length == 0) continue; + + var extension = entry; + + if (StringTools.startsWith(extension, "*.")) + { + extension = extension.substr(2); + } + else if (StringTools.startsWith(extension, ".")) + { + extension = extension.substr(1); + } + + if (extension.length == 0 + || extension.indexOf("*") != -1 + || extension.indexOf("?") != -1 + || extension.indexOf("/") != -1 + || extension.indexOf("\\") != -1) + { + continue; + } + + return extension; + } + + return null; + } + /** Opens a file selection dialog. If successful, either `onSelect` or `onSelectMultiple` will trigger with the result(s). This function only works on desktop targets, and will return `false` otherwise. @param type Type of the file dialog: `OPEN`, `SAVE`, `OPEN_DIRECTORY` or `OPEN_MULTIPLE`. - @param filter A filter to use when browsing. Asterisks are treated as wildcards. For example, - `"*.jpg"` will match any file ending in `.jpg`. + @param filter A filter to use when browsing. Use a bare extension such as `"jpg"` or + a wildcard pattern such as `"*.jpg"`. Multiple filters may be separated by commas. @param defaultPath The directory in which to start browsing and/or the default filename to suggest. Defaults to `Sys.getCwd()`, with no default filename. @param title The title to give the dialog window. @@ -137,7 +169,8 @@ class FileDialog // Makes sure the filename ends with extension if (type == SAVE && filter != null && path.indexOf(".") == -1) { - path += "." + filter; + var extension = __extensionFromFilter(filter); + if (extension != null) path += "." + extension; } onSelect.dispatch(path); @@ -239,8 +272,8 @@ class FileDialog Shows an open file dialog. If successful, `onOpen` will trigger with the file contents. This function only works on desktop targets, and will return `false` otherwise. - @param filter A filter to use when browsing. Asterisks are treated as wildcards. For example, - `"*.jpg"` will match any file ending in `.jpg`. + @param filter A filter to use when browsing. Use a bare extension such as `"jpg"` or + a wildcard pattern such as `"*.jpg"`. Multiple filters may be separated by commas. @param defaultPath The directory in which to start browsing and/or the default filename to suggest. Defaults to `Sys.getCwd()`, with no default filename. @param title The title to give the dialog window. @@ -293,8 +326,8 @@ class FileDialog This function only works on desktop and HMTL5 targets, and will return `false` otherwise. @param data The file contents, in `haxe.io.Bytes` format. (Implicit casting possible.) - @param filter A filter to use when browsing. Asterisks are treated as wildcards. For example, - `"*.jpg"` will match any file ending in `.jpg`. Used only if targeting deskop. + @param filter A filter to use when browsing. Use a bare extension such as `"jpg"` or + a wildcard pattern such as `"*.jpg"`. Multiple filters may be separated by commas. Used only if targeting deskop. @param defaultPath The directory in which to start browsing and/or the default filename to suggest. When targeting destkop, this defaults to `Sys.getCwd()` with no default filename. When targeting HTML5, this defaults to the browser's download directory, with a default filename based on the MIME type. From fcd53bd64a3d9569d2f9e77a71137fe341e796e1 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 16:31:55 -0400 Subject: [PATCH 66/76] Hide console for Windows HashLink app builds Patch the copied Windows HashLink launcher to use the GUI subsystem by default, matching Lime's other Windows app targets. The original bundled or user-provided hl.exe is left unchanged, and SHOW_CONSOLE keeps the old console behavior for users who need it. Closes https://github.com/openfl/lime/issues/1428 --- src/lime/tools/HashlinkHelper.hx | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/lime/tools/HashlinkHelper.hx b/src/lime/tools/HashlinkHelper.hx index 759f471493..efd1d29e5d 100644 --- a/src/lime/tools/HashlinkHelper.hx +++ b/src/lime/tools/HashlinkHelper.hx @@ -8,10 +8,52 @@ import lime.tools.HXProject; import lime.tools.Platform; import hxp.Path; import hxp.System; +import sys.io.File; class HashlinkHelper { public static inline var BUNDLED_HL_VER = "1.14.0"; + private static inline var IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; + + private static function readUInt32LE(bytes:haxe.io.Bytes, offset:Int):Int + { + return bytes.get(offset) | (bytes.get(offset + 1) << 8) | (bytes.get(offset + 2) << 16) | (bytes.get(offset + 3) << 24); + } + + private static function setWindowsGUISubsystem(executablePath:String):Void + { + try + { + var bytes = File.getBytes(executablePath); + + if (bytes.length < 0x100 || bytes.get(0) != 0x4D || bytes.get(1) != 0x5A) + { + Log.warn('Could not hide HashLink console: "$executablePath" is not a valid Windows executable'); + return; + } + + var peOffset = readUInt32LE(bytes, 0x3C); + var subsystemOffset = peOffset + 24 + 68; + + if (peOffset < 0 || subsystemOffset + 1 >= bytes.length + || bytes.get(peOffset) != 0x50 + || bytes.get(peOffset + 1) != 0x45 + || bytes.get(peOffset + 2) != 0 + || bytes.get(peOffset + 3) != 0) + { + Log.warn('Could not hide HashLink console: "$executablePath" has an unsupported PE header'); + return; + } + + bytes.set(subsystemOffset, IMAGE_SUBSYSTEM_WINDOWS_GUI); + bytes.set(subsystemOffset + 1, 0); + File.saveBytes(executablePath, bytes); + } + catch (e:Dynamic) + { + Log.warn('Could not hide HashLink console for "$executablePath": $e'); + } + } public static function copyHashlink(project:HXProject, targetDirectory:String, applicationDirectory:String, executablePath:String, ?is64 = true) { @@ -94,6 +136,11 @@ class HashlinkHelper } } + if (platform == WINDOWS && !project.targetFlags.exists("hlc") && !project.environment.exists("SHOW_CONSOLE")) + { + setWindowsGUISubsystem(executablePath); + } + // make sure no hxcpp hash files or MSVC build artifacts remain for (file in System.readDirectory(applicationDirectory)) From 70a41bff0bb15f3a6db8bd1edb9eec247a009fbb Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 17:11:37 -0400 Subject: [PATCH 67/76] CI fixes --- .github/workflows/main.yml | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b37d7d7c2a..3ea16a4a54 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -249,16 +249,27 @@ jobs: - name: Install HashLink dependencies run: | - arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - pushd project/lib/hashlink - arch -x86_64 /usr/local/bin/brew update - rm /usr/local/bin/2to3* - rm /usr/local/bin/idle3* - rm /usr/local/bin/pydoc3* - rm /usr/local/bin/python3* - rm /usr/local/bin/pip3* - arch -x86_64 /usr/local/bin/brew bundle - popd + set -euxo pipefail + + if [ ! -x /usr/local/bin/brew ]; then + NONINTERACTIVE=1 arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + fi + + rm -f /usr/local/bin/2to3* + rm -f /usr/local/bin/idle3* + rm -f /usr/local/bin/pydoc3* + rm -f /usr/local/bin/python3* + rm -f /usr/local/bin/pip3* + + for attempt in 1 2 3; do + if arch -x86_64 /usr/local/bin/brew update && arch -x86_64 /usr/local/bin/brew install jpeg-turbo libpng libuv libvorbis; then + break + fi + if [ "$attempt" -eq 3 ]; then + exit 1 + fi + sleep $((attempt * 30)) + done - name: Install Haxe dependencies run: | @@ -278,6 +289,9 @@ jobs: run: | lime rebuild macos -clean -release -64 -nocolor -verbose -nocffi lime rebuild macos -clean -release -arm64 -nocolor -verbose -nocffi + + - name: Rebuild Lime (HashLink macOS) + run: | lime rebuild hl -clean -release -nocolor -verbose -nocffi - uses: actions/upload-artifact@v7 From aec9d3f1e2e7e6f714fdbd33f730790e530bf98e Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 18 Jun 2026 20:06:36 -0400 Subject: [PATCH 68/76] Run formatter --- externs/air/flash/data/SQLCollationType.hx | 3 +- externs/air/flash/data/SQLColumnNameStyle.hx | 3 +- externs/air/flash/data/SQLMode.hx | 3 +- .../air/flash/data/SQLTransactionLockType.hx | 3 +- .../air/flash/desktop/InvokeEventReason.hx | 3 +- .../air/flash/desktop/NativeDragActions.hx | 3 +- externs/air/flash/desktop/NotificationType.hx | 3 +- externs/air/flash/desktop/SystemIdleMode.hx | 3 +- .../flash/display/NativeWindowDisplayState.hx | 3 +- .../flash/display/NativeWindowRenderMode.hx | 3 +- .../air/flash/display/NativeWindowResize.hx | 3 +- .../flash/display/NativeWindowSystemChrome.hx | 3 +- externs/air/flash/display/NativeWindowType.hx | 3 +- externs/air/flash/display/StageAspectRatio.hx | 3 +- externs/air/flash/display/StageOrientation.hx | 3 +- .../air/flash/display3D/Context3DProfile.hx | 3 +- externs/air/flash/errors/SQLErrorOperation.hx | 3 +- externs/air/flash/events/TouchEventIntent.hx | 3 +- externs/air/flash/filesystem/FileMode.hx | 3 +- externs/air/flash/media/AudioPlaybackMode.hx | 3 +- externs/air/flash/media/CameraPosition.hx | 3 +- externs/air/flash/media/MediaType.hx | 3 +- externs/air/flash/net/IPVersion.hx | 3 +- .../flash/notifications/NotificationStyle.hx | 3 +- externs/air/flash/printing/PaperSize.hx | 3 +- externs/air/flash/printing/PrintMethod.hx | 3 +- .../security/ReferencesValidationSetting.hx | 3 +- .../flash/security/RevocationCheckSettings.hx | 3 +- externs/air/flash/security/SignatureStatus.hx | 3 +- .../air/flash/security/SignerTrustSettings.hx | 3 +- externs/air/flash/text/AutoCapitalize.hx | 3 +- externs/air/flash/text/ReturnKeyLabel.hx | 3 +- externs/air/flash/text/SoftKeyboardType.hx | 3 +- .../flash/text/StageTextClearButtonMode.hx | 3 +- externs/air/sys/io/FileInput.hx | 4 +- externs/air/sys/io/FileOutput.hx | 4 +- src/lime/_internal/backend/air/AIRWindow.hx | 6 +- .../backend/emscripten/EmscriptenFetch.hx | 56 +- .../emscripten/EmscriptenHTTPRequest.hx | 447 ++++--- .../backend/flash/FlashHTTPRequest.hx | 2 +- .../_internal/backend/flash/FlashWindow.hx | 3 +- .../backend/html5/HTML5AudioSource.hx | 3 +- .../backend/html5/HTML5HTTPRequest.hx | 3 +- .../_internal/backend/html5/HTML5Thread.hx | 104 +- .../backend/native/NativeAudioSource.hx | 16 +- .../_internal/backend/native/NativeCFFI.hx | 1051 ++++++++--------- .../backend/native/NativeHTTPRequest.hx | 3 +- .../_internal/backend/native/NativeWindow.hx | 3 +- src/lime/_internal/graphics/ImageDataUtil.hx | 37 +- src/lime/_internal/macros/AssetsMacro.hx | 153 ++- src/lime/_internal/macros/CFFIMacro.hx | 16 +- src/lime/_internal/macros/EventMacro.hx | 11 +- src/lime/_internal/macros/HTTPRequestMacro.hx | 6 +- src/lime/app/Event.hx | 1 + src/lime/graphics/Image.hx | 4 +- src/lime/graphics/OpenGLES3RenderContext.hx | 1 - src/lime/graphics/VulkanRenderContext.hx | 1 - src/lime/graphics/WebGL2RenderContext.hx | 188 +-- src/lime/graphics/vulkan/VK.hx | 4 +- src/lime/graphics/vulkan/VKBuffer.hx | 1 - src/lime/graphics/vulkan/VKCommandBuffer.hx | 152 ++- src/lime/graphics/vulkan/VKCommandPool.hx | 1 - src/lime/graphics/vulkan/VKDescriptorPool.hx | 1 - src/lime/graphics/vulkan/VKDescriptorSet.hx | 16 +- .../graphics/vulkan/VKDescriptorSetLayout.hx | 5 +- src/lime/graphics/vulkan/VKDescriptorWrite.hx | 8 +- src/lime/graphics/vulkan/VKDevice.hx | 70 +- src/lime/graphics/vulkan/VKDeviceMemory.hx | 19 +- src/lime/graphics/vulkan/VKFence.hx | 1 - src/lime/graphics/vulkan/VKFramebuffer.hx | 1 - src/lime/graphics/vulkan/VKImage.hx | 14 +- src/lime/graphics/vulkan/VKImageView.hx | 1 - src/lime/graphics/vulkan/VKInstance.hx | 1 - src/lime/graphics/vulkan/VKPhysicalDevice.hx | 14 +- src/lime/graphics/vulkan/VKPipeline.hx | 1 - src/lime/graphics/vulkan/VKPipelineCache.hx | 5 +- src/lime/graphics/vulkan/VKPipelineLayout.hx | 1 - src/lime/graphics/vulkan/VKQueue.hx | 15 +- src/lime/graphics/vulkan/VKQueueFamilyInfo.hx | 3 +- src/lime/graphics/vulkan/VKRenderPass.hx | 1 - src/lime/graphics/vulkan/VKRenderer.hx | 1 - src/lime/graphics/vulkan/VKSampler.hx | 1 - src/lime/graphics/vulkan/VKSemaphore.hx | 1 - src/lime/graphics/vulkan/VKShaderModule.hx | 1 - src/lime/graphics/vulkan/VKSurface.hx | 1 - src/lime/graphics/vulkan/VKSwapchain.hx | 5 +- src/lime/math/Matrix3.hx | 30 +- src/lime/math/Matrix4.hx | 2 +- src/lime/media/AudioBuffer.hx | 30 +- src/lime/media/AudioInput.hx | 1 + src/lime/media/AudioInputDevice.hx | 1 + src/lime/media/AudioSource.hx | 6 +- src/lime/media/OpenALAudioContext.hx | 9 +- src/lime/net/HTTPRequest.hx | 7 +- src/lime/system/BackgroundWorker.hx | 7 +- src/lime/system/CFFI.hx | 5 +- src/lime/system/JNI.hx | 27 +- src/lime/system/Orientation.hx | 2 +- src/lime/system/System.hx | 23 +- src/lime/system/ThreadPool.hx | 74 +- src/lime/text/Font.hx | 210 ++-- .../text/harfbuzz/HBBufferSerializeFormat.hx | 1 + src/lime/tools/AIRHelper.hx | 15 +- src/lime/tools/ApplicationData.hx | 19 +- src/lime/tools/AssetHelper.hx | 66 +- src/lime/tools/CPPHelper.hx | 10 +- src/lime/tools/CSHelper.hx | 12 +- src/lime/tools/ConfigData.hx | 25 +- src/lime/tools/FlashHelper.hx | 17 +- src/lime/tools/HTML5Helper.hx | 20 +- src/lime/tools/HXProject.hx | 32 +- src/lime/tools/HashlinkHelper.hx | 21 +- src/lime/tools/IOSHelper.hx | 57 +- src/lime/tools/IconHelper.hx | 3 +- src/lime/tools/MetaData.hx | 23 +- src/lime/tools/PlatformTarget.hx | 11 +- src/lime/tools/ProjectXMLParser.hx | 2 - src/lime/tools/WindowData.hx | 69 +- src/lime/tools/XCodeHelper.hx | 5 +- src/lime/ui/FileDialog.hx | 9 +- src/lime/ui/Gamepad.hx | 15 +- src/lime/ui/KeyCode.hx | 3 +- src/lime/ui/ScanCode.hx | 3 +- src/lime/ui/Window.hx | 1 + src/lime/ui/WindowAttributes.hx | 1 + src/lime/utils/ArrayBufferView.hx | 10 +- src/lime/utils/AssetLibrary.hx | 10 +- src/lime/utils/Assets.hx | 2 +- src/lime/utils/ObjectPool.hx | 78 +- src/lime/utils/PackedAssetLibrary.hx | 17 +- src/lime/utils/Preloader.hx | 12 +- tests/unit/src/TestMain.hx | 6 +- tests/unit/src/utils/ArrayBufferTest.hx | 14 +- tests/unit/src/utils/DataViewTest.hx | 206 ++-- tests/unit/src/utils/UInt16ArrayTest.hx | 67 +- tests/unit/src/utils/UInt32ArrayTest.hx | 64 +- tests/unit/src/utils/UInt8ArrayTest.hx | 67 +- tests/vulkan-smoke/Source/Main.hx | 146 +-- tools/CommandLineTools.hx | 42 +- tools/RunScript.hx | 29 +- tools/SVGExport.hx | 2 +- tools/mpeg/audio/MpegAudioReader.hx | 4 +- tools/platforms/AndroidPlatform.hx | 81 +- tools/platforms/FlashPlatform.hx | 32 +- tools/platforms/HTML5Platform.hx | 3 +- tools/platforms/IOSPlatform.hx | 6 +- tools/platforms/LinuxPlatform.hx | 44 +- tools/platforms/MacPlatform.hx | 34 +- tools/platforms/TVOSPlatform.hx | 4 +- tools/platforms/WebAssemblyPlatform.hx | 68 +- tools/platforms/WindowsPlatform.hx | 60 +- tools/utils/PlatformSetup.hx | 37 +- 152 files changed, 2381 insertions(+), 2208 deletions(-) diff --git a/externs/air/flash/data/SQLCollationType.hx b/externs/air/flash/data/SQLCollationType.hx index fecbfc8382..0f93c36c1f 100644 --- a/externs/air/flash/data/SQLCollationType.hx +++ b/externs/air/flash/data/SQLCollationType.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLCollationType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLCollationType(String) +@:native("flash.data.SQLCollationType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLCollationType(String) { var BINARY = "binary"; var NO_CASE = "noCase"; diff --git a/externs/air/flash/data/SQLColumnNameStyle.hx b/externs/air/flash/data/SQLColumnNameStyle.hx index 03cb7a5adf..c25b13fc07 100644 --- a/externs/air/flash/data/SQLColumnNameStyle.hx +++ b/externs/air/flash/data/SQLColumnNameStyle.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLColumnNameStyle") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLColumnNameStyle(String) +@:native("flash.data.SQLColumnNameStyle") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLColumnNameStyle(String) { var DEFAULT = "default"; var LONG = "long"; diff --git a/externs/air/flash/data/SQLMode.hx b/externs/air/flash/data/SQLMode.hx index ebddf4c8c9..4b876d2d02 100644 --- a/externs/air/flash/data/SQLMode.hx +++ b/externs/air/flash/data/SQLMode.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLMode(String) +@:native("flash.data.SQLMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLMode(String) { var CREATE = "create"; var READ = "read"; diff --git a/externs/air/flash/data/SQLTransactionLockType.hx b/externs/air/flash/data/SQLTransactionLockType.hx index 36c24bc1a7..47a06a7a79 100644 --- a/externs/air/flash/data/SQLTransactionLockType.hx +++ b/externs/air/flash/data/SQLTransactionLockType.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLTransactionLockType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLTransactionLockType(String) +@:native("flash.data.SQLTransactionLockType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLTransactionLockType(String) { var DEFERRED = "deferred"; var EXCLUSIVE = "exclusive"; diff --git a/externs/air/flash/desktop/InvokeEventReason.hx b/externs/air/flash/desktop/InvokeEventReason.hx index d06e591c1b..1c053ad26c 100644 --- a/externs/air/flash/desktop/InvokeEventReason.hx +++ b/externs/air/flash/desktop/InvokeEventReason.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.InvokeEventReason") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract InvokeEventReason(String) +@:native("flash.desktop.InvokeEventReason") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract InvokeEventReason(String) { var LOGIN = "login"; var NOTIFICATION = "notification"; diff --git a/externs/air/flash/desktop/NativeDragActions.hx b/externs/air/flash/desktop/NativeDragActions.hx index fe67ff9db7..544ad2f1bf 100644 --- a/externs/air/flash/desktop/NativeDragActions.hx +++ b/externs/air/flash/desktop/NativeDragActions.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.NativeDragActions") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeDragActions(String) +@:native("flash.desktop.NativeDragActions") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeDragActions(String) { var COPY = "copy"; var LINK = "link"; diff --git a/externs/air/flash/desktop/NotificationType.hx b/externs/air/flash/desktop/NotificationType.hx index b2b3dcfb09..c9461c33cf 100644 --- a/externs/air/flash/desktop/NotificationType.hx +++ b/externs/air/flash/desktop/NotificationType.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.NotificationType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationType(String) +@:native("flash.desktop.NotificationType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationType(String) { var CRITICAL = "critical"; var INFORMATIONAL = "informational"; diff --git a/externs/air/flash/desktop/SystemIdleMode.hx b/externs/air/flash/desktop/SystemIdleMode.hx index 7fda8df044..c129940766 100644 --- a/externs/air/flash/desktop/SystemIdleMode.hx +++ b/externs/air/flash/desktop/SystemIdleMode.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.SystemIdleMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SystemIdleMode(String) +@:native("flash.desktop.SystemIdleMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SystemIdleMode(String) { var KEEP_AWAKE = "keepAwake"; var NORMAL = "normal"; diff --git a/externs/air/flash/display/NativeWindowDisplayState.hx b/externs/air/flash/display/NativeWindowDisplayState.hx index 4fb63f10d7..56a073a2e0 100644 --- a/externs/air/flash/display/NativeWindowDisplayState.hx +++ b/externs/air/flash/display/NativeWindowDisplayState.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowDisplayState") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowDisplayState(String) +@:native("flash.display.NativeWindowDisplayState") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowDisplayState(String) { var MAXIMIZED = "maximized"; var MINIMIZED = "minimized"; diff --git a/externs/air/flash/display/NativeWindowRenderMode.hx b/externs/air/flash/display/NativeWindowRenderMode.hx index e2d182c5bd..51a135f715 100644 --- a/externs/air/flash/display/NativeWindowRenderMode.hx +++ b/externs/air/flash/display/NativeWindowRenderMode.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowRenderMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowRenderMode(String) +@:native("flash.display.NativeWindowRenderMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowRenderMode(String) { var AUTO = "auto"; var CPU = "cpu"; diff --git a/externs/air/flash/display/NativeWindowResize.hx b/externs/air/flash/display/NativeWindowResize.hx index b3cd1a1f9f..5974784f0f 100644 --- a/externs/air/flash/display/NativeWindowResize.hx +++ b/externs/air/flash/display/NativeWindowResize.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowResize") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowResize(String) +@:native("flash.display.NativeWindowResize") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowResize(String) { var BOTTOM = "bottom"; var BOTTOM_LEFT = "bottomLeft"; diff --git a/externs/air/flash/display/NativeWindowSystemChrome.hx b/externs/air/flash/display/NativeWindowSystemChrome.hx index e271969831..367e6d9c22 100644 --- a/externs/air/flash/display/NativeWindowSystemChrome.hx +++ b/externs/air/flash/display/NativeWindowSystemChrome.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowSystemChrome") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowSystemChrome(String) +@:native("flash.display.NativeWindowSystemChrome") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowSystemChrome(String) { var ALTERNATE = "alternate"; var NONE = "none"; diff --git a/externs/air/flash/display/NativeWindowType.hx b/externs/air/flash/display/NativeWindowType.hx index 90ff5bb41f..0ffd8af4bc 100644 --- a/externs/air/flash/display/NativeWindowType.hx +++ b/externs/air/flash/display/NativeWindowType.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowType(String) +@:native("flash.display.NativeWindowType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowType(String) { var LIGHTWEIGHT = "lightweight"; var NORMAL = "normal"; diff --git a/externs/air/flash/display/StageAspectRatio.hx b/externs/air/flash/display/StageAspectRatio.hx index 70ede16512..8a308b07bf 100644 --- a/externs/air/flash/display/StageAspectRatio.hx +++ b/externs/air/flash/display/StageAspectRatio.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.StageAspectRatio") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageAspectRatio(String) +@:native("flash.display.StageAspectRatio") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageAspectRatio(String) { var ANY = "any"; var LANDSCAPE = "landscape"; diff --git a/externs/air/flash/display/StageOrientation.hx b/externs/air/flash/display/StageOrientation.hx index d55da84778..2f2a9b34a8 100644 --- a/externs/air/flash/display/StageOrientation.hx +++ b/externs/air/flash/display/StageOrientation.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.StageOrientation") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageOrientation(String) +@:native("flash.display.StageOrientation") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageOrientation(String) { var DEFAULT = "default"; var ROTATED_LEFT = "rotatedLeft"; diff --git a/externs/air/flash/display3D/Context3DProfile.hx b/externs/air/flash/display3D/Context3DProfile.hx index 2c29eea679..a7e697bc09 100644 --- a/externs/air/flash/display3D/Context3DProfile.hx +++ b/externs/air/flash/display3D/Context3DProfile.hx @@ -1,7 +1,6 @@ package flash.display3D; -@:native("flash.display3D.Context3DProfile") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract Context3DProfile(String) +@:native("flash.display3D.Context3DProfile") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract Context3DProfile(String) { var BASELINE = "baseline"; var BASELINE_CONSTRAINED = "baselineConstrained"; diff --git a/externs/air/flash/errors/SQLErrorOperation.hx b/externs/air/flash/errors/SQLErrorOperation.hx index 15e7a651c0..396ba8c237 100644 --- a/externs/air/flash/errors/SQLErrorOperation.hx +++ b/externs/air/flash/errors/SQLErrorOperation.hx @@ -1,7 +1,6 @@ package flash.errors; -@:native("flash.errors.SQLErrorOperation") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLErrorOperation(String) +@:native("flash.errors.SQLErrorOperation") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLErrorOperation(String) { var ANALYZE = "analyze"; var ATTACH = "attach"; diff --git a/externs/air/flash/events/TouchEventIntent.hx b/externs/air/flash/events/TouchEventIntent.hx index 19a3c6a0e6..0af83e0428 100644 --- a/externs/air/flash/events/TouchEventIntent.hx +++ b/externs/air/flash/events/TouchEventIntent.hx @@ -1,7 +1,6 @@ package flash.events; -@:native("flash.events.TouchEventIntent") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract TouchEventIntent(String) +@:native("flash.events.TouchEventIntent") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract TouchEventIntent(String) { var ERASER = "eraser"; var PEN = "pen"; diff --git a/externs/air/flash/filesystem/FileMode.hx b/externs/air/flash/filesystem/FileMode.hx index 3041db9b92..6644c1627b 100644 --- a/externs/air/flash/filesystem/FileMode.hx +++ b/externs/air/flash/filesystem/FileMode.hx @@ -1,7 +1,6 @@ package flash.filesystem; -@:native("flash.filesystem.FileMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract FileMode(String) +@:native("flash.filesystem.FileMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract FileMode(String) { var APPEND = "append"; var READ = "read"; diff --git a/externs/air/flash/media/AudioPlaybackMode.hx b/externs/air/flash/media/AudioPlaybackMode.hx index fdc31990c4..9757dadbe0 100644 --- a/externs/air/flash/media/AudioPlaybackMode.hx +++ b/externs/air/flash/media/AudioPlaybackMode.hx @@ -1,7 +1,6 @@ package flash.media; -@:native("flash.media.AudioPlaybackMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AudioPlaybackMode(String) +@:native("flash.media.AudioPlaybackMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AudioPlaybackMode(String) { var AMBIENT = "ambient"; var MEDIA = "media"; diff --git a/externs/air/flash/media/CameraPosition.hx b/externs/air/flash/media/CameraPosition.hx index 06184cc9ed..754d0051f9 100644 --- a/externs/air/flash/media/CameraPosition.hx +++ b/externs/air/flash/media/CameraPosition.hx @@ -1,7 +1,6 @@ package flash.media; -@:native("flash.media.CameraPosition") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract CameraPosition(String) +@:native("flash.media.CameraPosition") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract CameraPosition(String) { var BACK = "back"; var FRONT = "front"; diff --git a/externs/air/flash/media/MediaType.hx b/externs/air/flash/media/MediaType.hx index 41a10306fb..e925b08397 100644 --- a/externs/air/flash/media/MediaType.hx +++ b/externs/air/flash/media/MediaType.hx @@ -1,7 +1,6 @@ package flash.media; -@:native("flash.media.MediaType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract MediaType(String) +@:native("flash.media.MediaType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract MediaType(String) { var IMAGE = "image"; var VIDEO = "video"; diff --git a/externs/air/flash/net/IPVersion.hx b/externs/air/flash/net/IPVersion.hx index ef4a44fcf2..c9d8200955 100644 --- a/externs/air/flash/net/IPVersion.hx +++ b/externs/air/flash/net/IPVersion.hx @@ -1,7 +1,6 @@ package flash.net; -@:native("flash.net.IPVersion") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract IPVersion(String) +@:native("flash.net.IPVersion") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract IPVersion(String) { var IPV4 = "ipv4"; var IPV6 = "ipv6"; diff --git a/externs/air/flash/notifications/NotificationStyle.hx b/externs/air/flash/notifications/NotificationStyle.hx index a2a9f3fdd2..715052bf6d 100644 --- a/externs/air/flash/notifications/NotificationStyle.hx +++ b/externs/air/flash/notifications/NotificationStyle.hx @@ -1,7 +1,6 @@ package flash.notifications; -@:native("flash.notifications.NotificationStyle") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationStyle(String) +@:native("flash.notifications.NotificationStyle") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationStyle(String) { var ALERT = "alert"; var BADGE = "badge"; diff --git a/externs/air/flash/printing/PaperSize.hx b/externs/air/flash/printing/PaperSize.hx index fe607d1e2a..65e60bdbfa 100644 --- a/externs/air/flash/printing/PaperSize.hx +++ b/externs/air/flash/printing/PaperSize.hx @@ -1,7 +1,6 @@ package flash.printing; -@:native("flash.printing.PaperSize") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PaperSize(String) +@:native("flash.printing.PaperSize") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PaperSize(String) { var A4 = "a4"; var A5 = "a5"; diff --git a/externs/air/flash/printing/PrintMethod.hx b/externs/air/flash/printing/PrintMethod.hx index 070fcfcf1c..a6f7ac873a 100644 --- a/externs/air/flash/printing/PrintMethod.hx +++ b/externs/air/flash/printing/PrintMethod.hx @@ -1,7 +1,6 @@ package flash.printing; -@:native("flash.printing.PrintMethod") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PrintMethod(String) +@:native("flash.printing.PrintMethod") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PrintMethod(String) { var AUTO = "auto"; var BITMAP = "bitmap"; diff --git a/externs/air/flash/security/ReferencesValidationSetting.hx b/externs/air/flash/security/ReferencesValidationSetting.hx index 08fda5c8ca..b357c649d1 100644 --- a/externs/air/flash/security/ReferencesValidationSetting.hx +++ b/externs/air/flash/security/ReferencesValidationSetting.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.ReferencesValidationSetting") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReferencesValidationSetting(String) +@:native("flash.security.ReferencesValidationSetting") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReferencesValidationSetting(String) { var NEVER = "never"; var VALID_IDENTITY = "validIdentity"; diff --git a/externs/air/flash/security/RevocationCheckSettings.hx b/externs/air/flash/security/RevocationCheckSettings.hx index 09725cea85..11365b4a09 100644 --- a/externs/air/flash/security/RevocationCheckSettings.hx +++ b/externs/air/flash/security/RevocationCheckSettings.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.RevocationCheckSettings") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract RevocationCheckSettings(String) +@:native("flash.security.RevocationCheckSettings") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract RevocationCheckSettings(String) { var ALWAYS_REQUIRED = "alwaysRequired"; var BEST_EFFORT = "bestEffort"; diff --git a/externs/air/flash/security/SignatureStatus.hx b/externs/air/flash/security/SignatureStatus.hx index f8c632599e..68e03bcaf9 100644 --- a/externs/air/flash/security/SignatureStatus.hx +++ b/externs/air/flash/security/SignatureStatus.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.SignatureStatus") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignatureStatus(String) +@:native("flash.security.SignatureStatus") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignatureStatus(String) { var INVALID = "invalid"; var UNKNOWN = "unknown"; diff --git a/externs/air/flash/security/SignerTrustSettings.hx b/externs/air/flash/security/SignerTrustSettings.hx index 0164a3a253..0edf890a94 100644 --- a/externs/air/flash/security/SignerTrustSettings.hx +++ b/externs/air/flash/security/SignerTrustSettings.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.SignerTrustSettings") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignerTrustSettings(String) +@:native("flash.security.SignerTrustSettings") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignerTrustSettings(String) { var CODE_SIGNING = "codeSigning"; var PLAYLIST_SIGNING = "playlistSigning"; diff --git a/externs/air/flash/text/AutoCapitalize.hx b/externs/air/flash/text/AutoCapitalize.hx index e0bb0169df..472737f7cd 100644 --- a/externs/air/flash/text/AutoCapitalize.hx +++ b/externs/air/flash/text/AutoCapitalize.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.AutoCapitalize") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AutoCapitalize(String) +@:native("flash.text.AutoCapitalize") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AutoCapitalize(String) { var ALL = "all"; var NONE = "none"; diff --git a/externs/air/flash/text/ReturnKeyLabel.hx b/externs/air/flash/text/ReturnKeyLabel.hx index 3936c1722e..573d048ee3 100644 --- a/externs/air/flash/text/ReturnKeyLabel.hx +++ b/externs/air/flash/text/ReturnKeyLabel.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.ReturnKeyLabel") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReturnKeyLabel(String) +@:native("flash.text.ReturnKeyLabel") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReturnKeyLabel(String) { var DEFAULT = "default"; var DONE = "done"; diff --git a/externs/air/flash/text/SoftKeyboardType.hx b/externs/air/flash/text/SoftKeyboardType.hx index 3a9f747dc4..a6ff23fddb 100644 --- a/externs/air/flash/text/SoftKeyboardType.hx +++ b/externs/air/flash/text/SoftKeyboardType.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.SoftKeyboardType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SoftKeyboardType(String) +@:native("flash.text.SoftKeyboardType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SoftKeyboardType(String) { var CONTACT = "contact"; var DEFAULT = "default"; diff --git a/externs/air/flash/text/StageTextClearButtonMode.hx b/externs/air/flash/text/StageTextClearButtonMode.hx index 21f09ecb2b..ade3888cb0 100644 --- a/externs/air/flash/text/StageTextClearButtonMode.hx +++ b/externs/air/flash/text/StageTextClearButtonMode.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.StageTextClearButtonMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageTextClearButtonMode(String) +@:native("flash.text.StageTextClearButtonMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageTextClearButtonMode(String) { var ALWAYS = "always"; var NEVER = "never"; diff --git a/externs/air/sys/io/FileInput.hx b/externs/air/sys/io/FileInput.hx index 93e2f3b19d..7e3558ed28 100644 --- a/externs/air/sys/io/FileInput.hx +++ b/externs/air/sys/io/FileInput.hx @@ -34,9 +34,9 @@ class FileInput extends haxe.io.Input switch (pos) { case SeekBegin: - // this.pos = p; + // this.pos = p; case SeekEnd: - // this.pos = cast Fs.fstatSync(fd).size + p; + // this.pos = cast Fs.fstatSync(fd).size + p; case SeekCur: // this.pos += p; } diff --git a/externs/air/sys/io/FileOutput.hx b/externs/air/sys/io/FileOutput.hx index cdd3ba2414..e0e96e9d57 100644 --- a/externs/air/sys/io/FileOutput.hx +++ b/externs/air/sys/io/FileOutput.hx @@ -31,9 +31,9 @@ class FileOutput extends haxe.io.Output switch (pos) { case SeekBegin: - // this.pos = p; + // this.pos = p; case SeekEnd: - // this.pos = cast Fs.fstatSync(fd).size + p; + // this.pos = cast Fs.fstatSync(fd).size + p; case SeekCur: // this.pos += p; } diff --git a/src/lime/_internal/backend/air/AIRWindow.hx b/src/lime/_internal/backend/air/AIRWindow.hx index 0c5e022fda..195d78fbc4 100644 --- a/src/lime/_internal/backend/air/AIRWindow.hx +++ b/src/lime/_internal/backend/air/AIRWindow.hx @@ -187,7 +187,8 @@ class AIRWindow extends FlashWindow if (parent.application.window == parent) { var newDeviceOrientation:Orientation = UNKNOWN; - switch (parent.stage.deviceOrientation) { + switch (parent.stage.deviceOrientation) + { case DEFAULT: newDeviceOrientation = PORTRAIT; case UPSIDE_DOWN: @@ -202,7 +203,8 @@ class AIRWindow extends FlashWindow parent.application.onDeviceOrientationChange.dispatch(newDeviceOrientation); } var newDisplayOrientation:Orientation = UNKNOWN; - switch (event.afterOrientation) { + switch (event.afterOrientation) + { case DEFAULT: newDisplayOrientation = PORTRAIT; case UPSIDE_DOWN: diff --git a/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx b/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx index 91fc89814e..8777ae7134 100644 --- a/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx +++ b/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx @@ -7,44 +7,46 @@ import cpp.ConstCharStar; @:include("emscripten/fetch.h") @:native -extern class EmscriptenFetch { +extern class EmscriptenFetch +{ + @:native("emscripten_fetch_attr_init") + public static function emscripten_fetch_attr_init(attr:Pointer):Void; - @:native("emscripten_fetch_attr_init") - public static function emscripten_fetch_attr_init(attr:Pointer):Void; + @:native("emscripten_fetch") + public static function emscripten_fetch(attr:Pointer, url:ConstCharStar):Pointer; - @:native("emscripten_fetch") - public static function emscripten_fetch(attr:Pointer, url:ConstCharStar):Pointer; - - @:native("emscripten_fetch_close") - public static function emscripten_fetch_close(fetch:Pointer):Void; + @:native("emscripten_fetch_close") + public static function emscripten_fetch_close(fetch:Pointer):Void; } @:include("emscripten/fetch.h") @:native("emscripten_fetch_attr_t") @:structAccess @:unreflective -extern class EmscriptenFetchAttrType { - public var requestMethod:ConstCharStar; - public var onsuccess:Star->Void; - public var onprogress:Star->Void; - public var onerror:Star->Void; - public var attributes:Int; - public var userData:Star; +extern class EmscriptenFetchAttrType +{ + public var requestMethod:ConstCharStar; + public var onsuccess:Star->Void; + public var onprogress:Star->Void; + public var onerror:Star->Void; + public var attributes:Int; + public var userData:Star; } @:include("emscripten/fetch.h") @:native("emscripten_fetch_t") @:structAccess -extern class EmscriptenFetchType { - public var id:Int; - public var numBytes:Int; - public var dataOffset:Int; - public var totalBytes:Int; - public var url:ConstCharStar; - public var readyState:Int; - public var status:Int; - public var statusText:ConstCharStar; - public var data:Pointer; - public var userData:Star; +extern class EmscriptenFetchType +{ + public var id:Int; + public var numBytes:Int; + public var dataOffset:Int; + public var totalBytes:Int; + public var url:ConstCharStar; + public var readyState:Int; + public var status:Int; + public var statusText:ConstCharStar; + public var data:Pointer; + public var userData:Star; } -#end \ No newline at end of file +#end diff --git a/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx b/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx index 435afeff94..bb726fa0a8 100644 --- a/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx +++ b/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx @@ -16,238 +16,237 @@ import lime.net.HTTPRequest._HTTPRequestErrorResponse; @:access(lime.graphics.Image) class EmscriptenHTTPRequest { - private static var fetchId:Int = 0; - private static var activeFetches = new Map(); - - private var binary:Bool; - private var parent:_IHTTPRequest; - private var currentFetchId:Int = -1; - - public function new() - { - } - - public function cancel():Void - { - if (currentFetchId >= 0 && activeFetches.exists(currentFetchId)) - { - var context = activeFetches.get(currentFetchId); - if (context != null && context.fetchPtr != null) - { - EmscriptenFetch.emscripten_fetch_close(context.fetchPtr); - } - activeFetches.remove(currentFetchId); - currentFetchId = -1; - } - } - - public function init(parent:_IHTTPRequest):Void - { - this.parent = parent; - } - - public function loadData(uri:String):Future - { - var promise = new Promise(); - binary = true; - __load(uri, promise, LoadType.BINARY); - return promise.future; - } - - public function loadText(uri:String):Future - { - var promise = new Promise(); - binary = false; - __load(uri, promise, LoadType.TEXT); - return promise.future; - } - - private function __load(uri:String, promise:Dynamic, loadType:LoadType):Void - { - var id = fetchId++; - currentFetchId = id; - - var context:FetchContext = { - id: id, - promise: promise, - parent: parent, - loadType: loadType, - binary: binary, - fetchPtr: null - }; - - activeFetches.set(id, context); - - var attr:EmscriptenFetchAttrType = untyped __cpp__("{}"); - var attrPtr:Pointer = Pointer.addressOf(attr); - EmscriptenFetch.emscripten_fetch_attr_init(attrPtr); - - // Set request method - var method = parent.method != null ? Std.string(parent.method) : "GET"; - untyped __cpp__('strcpy({0}, {1})', attr.requestMethod, method); - - // Set callbacks - attr.onsuccess = untyped __cpp__("onFetchSuccess"); - attr.onprogress = untyped __cpp__("onFetchProgress"); - attr.onerror = untyped __cpp__("onFetchError"); - - // Store fetch ID in userData - var idPointer:Star = untyped __cpp__('(int*)malloc(sizeof(int))'); - untyped __cpp__('*{0} = {1}', idPointer, id); - attr.userData = cast idPointer; - - // Set EMSCRIPTEN_FETCH_LOAD_TO_MEMORY - attr.attributes = 1; - - // Start fetch - var fetchPtr = EmscriptenFetch.emscripten_fetch(attrPtr, uri); - context.fetchPtr = fetchPtr; - } - - @:keep - private static function onFetchSuccess(fetchPtr:Star):Void - { - var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; - var idPointer:Star = cast fetch.userData; - var id:Int = untyped __cpp__('*(int*){0}', idPointer); - - cpp.Native.free(idPointer); - fetch.userData = null; - - if (!activeFetches.exists(id)) - { - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - return; - } - - var context = activeFetches.get(id); - activeFetches.remove(id); - if(context == null) - trace("EmscriptenHTTPRequest.onFetchSuccess: context is null"); - - // Process response - if (context.parent.enableResponseHeaders) - { - context.parent.responseHeaders = []; - // Note: Emscripten Fetch API has limited header access - // You may need to parse headers from fetch.statusText if available - } - - context.parent.responseStatus = fetch.status; - - // Create bytes from fetch data - var bytes:Bytes = null; - if (fetch.numBytes > 0 && fetch.data != null) - { - bytes = Bytes.ofData(cast fetch.data.toUnmanagedArray(fetch.numBytes).copy()); - } - else - { - bytes = Bytes.alloc(0); - } - - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - - // Complete promise based on load type - if (fetch.status >= 200 && fetch.status < 400) - { - switch (context.loadType) - { - case LoadType.BINARY: - cast(context.promise, Promise).complete(bytes); - - case LoadType.TEXT: - var text = bytes.getString(0, bytes.length, UTF8); - cast(context.promise, Promise).complete(text); - - case LoadType.IMAGE: - // For images, we need to decode the bytes - var img = new Image(); - img.__fromBytes(bytes, function(image) - { - cast(context.promise, Promise).complete(image); - }); - } - } - else - { - var errorResponse:_HTTPRequestErrorResponse; - if(context.loadType == LoadType.BINARY) { - errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes); - cast(context.promise, Promise).error(errorResponse); - }else { - errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes.getString(0, bytes.length, UTF8)); - cast(context.promise, Promise).error(errorResponse); - } - } - } - - @:keep - private static function onFetchProgress(fetchPtr:Star):Void - { - var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; - var idPointer:Star = cast fetch.userData; - var id:Int = untyped __cpp__('*(int*){0}', idPointer); - - if (activeFetches.exists(id)) - { - var context = activeFetches.get(id); - if (fetch.totalBytes > 0) - { - if(context.loadType == LoadType.BINARY) - cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, fetch.totalBytes); - else if(context.loadType == LoadType.TEXT) - cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, fetch.totalBytes); - } - } - } - - @:keep - private static function onFetchError(fetchPtr:Star):Void - { - var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; - var idPointer:Star = cast fetch.userData; - var id:Int = untyped __cpp__('*(int*){0}', idPointer); - - cpp.Native.free(idPointer); - - if (!activeFetches.exists(id)) - { - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - return; - } - - var context = activeFetches.get(id); - activeFetches.remove(id); - - context.parent.responseStatus = fetch.status; - - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - - var errorResponse = new _HTTPRequestErrorResponse(fetch.status, null); - if(context.loadType == LoadType.BINARY) - cast(context.promise, Promise).error(errorResponse); - else - cast(context.promise, Promise).error(errorResponse); - } + private static var fetchId:Int = 0; + private static var activeFetches = new Map(); + + private var binary:Bool; + private var parent:_IHTTPRequest; + private var currentFetchId:Int = -1; + + public function new() {} + + public function cancel():Void + { + if (currentFetchId >= 0 && activeFetches.exists(currentFetchId)) + { + var context = activeFetches.get(currentFetchId); + if (context != null && context.fetchPtr != null) + { + EmscriptenFetch.emscripten_fetch_close(context.fetchPtr); + } + activeFetches.remove(currentFetchId); + currentFetchId = -1; + } + } + + public function init(parent:_IHTTPRequest):Void + { + this.parent = parent; + } + + public function loadData(uri:String):Future + { + var promise = new Promise(); + binary = true; + __load(uri, promise, LoadType.BINARY); + return promise.future; + } + + public function loadText(uri:String):Future + { + var promise = new Promise(); + binary = false; + __load(uri, promise, LoadType.TEXT); + return promise.future; + } + + private function __load(uri:String, promise:Dynamic, loadType:LoadType):Void + { + var id = fetchId++; + currentFetchId = id; + + var context:FetchContext = + { + id: id, + promise: promise, + parent: parent, + loadType: loadType, + binary: binary, + fetchPtr: null + }; + + activeFetches.set(id, context); + + var attr:EmscriptenFetchAttrType = untyped __cpp__("{}"); + var attrPtr:Pointer = Pointer.addressOf(attr); + EmscriptenFetch.emscripten_fetch_attr_init(attrPtr); + + // Set request method + var method = parent.method != null ? Std.string(parent.method) : "GET"; + untyped __cpp__('strcpy({0}, {1})', attr.requestMethod, method); + + // Set callbacks + attr.onsuccess = untyped __cpp__("onFetchSuccess"); + attr.onprogress = untyped __cpp__("onFetchProgress"); + attr.onerror = untyped __cpp__("onFetchError"); + + // Store fetch ID in userData + var idPointer:Star = untyped __cpp__('(int*)malloc(sizeof(int))'); + untyped __cpp__('*{0} = {1}', idPointer, id); + attr.userData = cast idPointer; + + // Set EMSCRIPTEN_FETCH_LOAD_TO_MEMORY + attr.attributes = 1; + + // Start fetch + var fetchPtr = EmscriptenFetch.emscripten_fetch(attrPtr, uri); + context.fetchPtr = fetchPtr; + } + + @:keep + private static function onFetchSuccess(fetchPtr:Star):Void + { + var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; + var idPointer:Star = cast fetch.userData; + var id:Int = untyped __cpp__('*(int*){0}', idPointer); + + cpp.Native.free(idPointer); + fetch.userData = null; + + if (!activeFetches.exists(id)) + { + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + return; + } + + var context = activeFetches.get(id); + activeFetches.remove(id); + if (context == null) trace("EmscriptenHTTPRequest.onFetchSuccess: context is null"); + + // Process response + if (context.parent.enableResponseHeaders) + { + context.parent.responseHeaders = []; + // Note: Emscripten Fetch API has limited header access + // You may need to parse headers from fetch.statusText if available + } + + context.parent.responseStatus = fetch.status; + + // Create bytes from fetch data + var bytes:Bytes = null; + if (fetch.numBytes > 0 && fetch.data != null) + { + bytes = Bytes.ofData(cast fetch.data.toUnmanagedArray(fetch.numBytes).copy()); + } + else + { + bytes = Bytes.alloc(0); + } + + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + + // Complete promise based on load type + if (fetch.status >= 200 && fetch.status < 400) + { + switch (context.loadType) + { + case LoadType.BINARY: + cast(context.promise, Promise).complete(bytes); + + case LoadType.TEXT: + var text = bytes.getString(0, bytes.length, UTF8); + cast(context.promise, Promise).complete(text); + + case LoadType.IMAGE: + // For images, we need to decode the bytes + var img = new Image(); + img.__fromBytes(bytes, function(image) + { + cast(context.promise, Promise).complete(image); + }); + } + } + else + { + var errorResponse:_HTTPRequestErrorResponse; + if (context.loadType == LoadType.BINARY) + { + errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes); + cast(context.promise, Promise).error(errorResponse); + } + else + { + errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes.getString(0, bytes.length, UTF8)); + cast(context.promise, Promise).error(errorResponse); + } + } + } + + @:keep + private static function onFetchProgress(fetchPtr:Star):Void + { + var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; + var idPointer:Star = cast fetch.userData; + var id:Int = untyped __cpp__('*(int*){0}', idPointer); + + if (activeFetches.exists(id)) + { + var context = activeFetches.get(id); + if (fetch.totalBytes > 0) + { + if (context.loadType == LoadType.BINARY) cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, fetch.totalBytes); + else if (context.loadType == LoadType.TEXT) cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, + fetch.totalBytes); + } + } + } + + @:keep + private static function onFetchError(fetchPtr:Star):Void + { + var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; + var idPointer:Star = cast fetch.userData; + var id:Int = untyped __cpp__('*(int*){0}', idPointer); + + cpp.Native.free(idPointer); + + if (!activeFetches.exists(id)) + { + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + return; + } + + var context = activeFetches.get(id); + activeFetches.remove(id); + + context.parent.responseStatus = fetch.status; + + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + + var errorResponse = new _HTTPRequestErrorResponse(fetch.status, null); + if (context.loadType == LoadType.BINARY) cast(context.promise, Promise).error(errorResponse); + else + cast(context.promise, Promise).error(errorResponse); + } } @:dox(hide) enum LoadType { - BINARY; - TEXT; - IMAGE; + BINARY; + TEXT; + IMAGE; } @:dox(hide) typedef FetchContext = { - var id:Int; - var promise:Dynamic; - var parent:_IHTTPRequest; - var loadType:LoadType; - var binary:Bool; - var fetchPtr:Pointer; + var id:Int; + var promise:Dynamic; + var parent:_IHTTPRequest; + var loadType:LoadType; + var binary:Bool; + var fetchPtr:Pointer; } -#end \ No newline at end of file +#end diff --git a/src/lime/_internal/backend/flash/FlashHTTPRequest.hx b/src/lime/_internal/backend/flash/FlashHTTPRequest.hx index 67861d810a..e44164755f 100644 --- a/src/lime/_internal/backend/flash/FlashHTTPRequest.hx +++ b/src/lime/_internal/backend/flash/FlashHTTPRequest.hx @@ -174,4 +174,4 @@ class FlashHTTPRequest urlLoader.load(urlRequest); return promise.future; } -} \ No newline at end of file +} diff --git a/src/lime/_internal/backend/flash/FlashWindow.hx b/src/lime/_internal/backend/flash/FlashWindow.hx index 1935a11208..ad9df272bd 100644 --- a/src/lime/_internal/backend/flash/FlashWindow.hx +++ b/src/lime/_internal/backend/flash/FlashWindow.hx @@ -225,8 +225,7 @@ class FlashWindow "middleMouseMove", "middleMouseUp" #if ((!openfl && !disable_flash_right_click) - || enable_flash_right_click), "rightMouseDown", "rightMouseMove", "rightMouseUp" - #end + || enable_flash_right_click), "rightMouseDown", "rightMouseMove", "rightMouseUp" #end ]; for (event in events) diff --git a/src/lime/_internal/backend/html5/HTML5AudioSource.hx b/src/lime/_internal/backend/html5/HTML5AudioSource.hx index f2b9fe80b2..a898c7ad16 100644 --- a/src/lime/_internal/backend/html5/HTML5AudioSource.hx +++ b/src/lime/_internal/backend/html5/HTML5AudioSource.hx @@ -261,7 +261,8 @@ class HTML5AudioSource position.w = value.w; #if lime_howlerjs - if (parent.buffer != null && parent.buffer.__srcHowl != null && parent.buffer.__srcHowl.pos != null) parent.buffer.__srcHowl.pos(position.x, position.y, position.z, id); + if (parent.buffer != null && parent.buffer.__srcHowl != null && parent.buffer.__srcHowl.pos != null) parent.buffer.__srcHowl.pos(position.x, + position.y, position.z, id); // There are more settings to the position of the sound on the "pannerAttr()" function of howler. Maybe somebody who understands sound should look into it? #end diff --git a/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx b/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx index 4b94560e66..547d2f348e 100644 --- a/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx +++ b/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx @@ -64,8 +64,7 @@ class HTML5HTTPRequest if (parent.method == POST) { - if(request.upload != null) - request.upload.addEventListener("progress", progress, false); + if (request.upload != null) request.upload.addEventListener("progress", progress, false); } else { diff --git a/src/lime/_internal/backend/html5/HTML5Thread.hx b/src/lime/_internal/backend/html5/HTML5Thread.hx index 9f744e59e1..02caf2ca0c 100644 --- a/src/lime/_internal/backend/html5/HTML5Thread.hx +++ b/src/lime/_internal/backend/html5/HTML5Thread.hx @@ -1,7 +1,6 @@ package lime._internal.backend.html5; import lime.app.Event; - #if macro import haxe.macro.Context; import haxe.macro.Expr; @@ -30,7 +29,8 @@ import lime.app.Application; /** Emulates much of the `sys.thread.Thread` API using web workers. **/ -class HTML5Thread { +class HTML5Thread +{ private static var __current:HTML5Thread = new HTML5Thread(Lib.global.location.href); private static var __isWorker:Bool #if !macro = #if !haxe4 untyped __js__ #else Syntax.code #end ('typeof window == "undefined"') #end; private static var __messages:List = new List(); @@ -80,8 +80,7 @@ class HTML5Thread { #if !macro // Find the URL of the primary JS file. var url:URL = new URL(__current.__href); - url.pathname = url.pathname.substr(0, url.pathname.lastIndexOf("/") + 1) - + Application.current.meta["file"] + ".js"; + url.pathname = url.pathname.substr(0, url.pathname.lastIndexOf("/") + 1) + Application.current.meta["file"] + ".js"; // Use the hash to distinguish workers. if (url.hash.length > 0) url.hash += "_"; @@ -108,9 +107,9 @@ class HTML5Thread { private static inline function zeroDelay():Promise { return new Promise(function(resolve, _):Void - { - js.Lib.global.setTimeout(resolve); - }); + { + js.Lib.global.setTimeout(resolve); + }); } #end @@ -128,8 +127,8 @@ class HTML5Thread { // suspended, so we must insert `await` even if `block` is false. // TODO: find a more efficient way to read messages. var zeroDelayExpr:Expr = macro @:privateAccess - $jsCode("await {0}", lime._internal.backend.html5.HTML5Thread.zeroDelay()) - .then(function(_) return lime._internal.backend.html5.HTML5Thread.__messages.pop()); + $jsCode("await {0}", lime._internal.backend.html5.HTML5Thread.zeroDelay()).then(function(_) return + lime._internal.backend.html5.HTML5Thread.__messages.pop()); switch (block.expr) { @@ -138,15 +137,18 @@ class HTML5Thread { default: return macro if ($block && @:privateAccess lime._internal.backend.html5.HTML5Thread.__messages.isEmpty()) { - $jsCode("await {0}", new #if haxe4 js.lib.Promise #else js.Promise #end + $jsCode("await {0}", new + #if haxe4 + js.lib.Promise + #else + js.Promise + #end (function(resolve, _):Void { @:privateAccess lime._internal.backend.html5.HTML5Thread.__resolveMethods.add(resolve); - } - )); + })); } - else - $zeroDelayExpr; + else $zeroDelayExpr; } } @@ -294,18 +296,18 @@ abstract WorkFunction(WorkFunctionData) from Wor as the `initialExpr`. For instance, `array[i].foo.bar` will result in `chain == ["foo", "bar"]` and `initialExpr == array[i]`. **/ - private static function parseFieldChain(chain:Expr):{ chain:Array, ?initialExpr:Expr } + private static function parseFieldChain(chain:Expr):{chain:Array, ?initialExpr:Expr} { - switch(chain.expr) + switch (chain.expr) { case EConst(CIdent(ident)): - return { chain: [ident] }; + return {chain: [ident]}; case EField(e, field): var out = parseFieldChain(e); out.chain.push(field); return out; default: - return { chain: [], initialExpr: chain }; + return {chain: [], initialExpr: chain}; } } #end @@ -314,9 +316,10 @@ abstract WorkFunction(WorkFunctionData) from Wor @:noCompletion @:dox(hide) #if !macro @:from #end public static #if !macro macro #end function fromFunction(func:ExprOf) { - var defaultOutput:Expr = macro { - func: $func - }; + var defaultOutput:Expr = macro + { + func: $func + }; if (!Context.defined("lime-threads")) { @@ -343,11 +346,12 @@ abstract WorkFunction(WorkFunctionData) from Wor var classPath:String = matcher.matched(1); var functionName:String = matcher.matched(2); - return macro { - func: $func, - classPath: $v{classPath}, - functionName: $v{functionName} - }; + return macro + { + func: $func, + classPath: $v{classPath}, + functionName: $v{functionName} + }; } } @@ -416,7 +420,7 @@ abstract WorkFunction(WorkFunctionData) from Wor else { #if !macro - this.sourceCode = (cast this.func #if haxe4 :Function #end).toString(); + this.sourceCode = (cast this.func #if haxe4 : Function #end).toString(); if (this.sourceCode.indexOf("[native code]") < 0) { // All set. @@ -456,7 +460,8 @@ abstract WorkFunction(WorkFunctionData) from Wor Stores the class path and function name of a function, so that it can be found again in the background thread. **/ -typedef WorkFunctionData = { +typedef WorkFunctionData = +{ @:optional var classPath:String; @:optional var functionName:String; @:optional var sourceCode:String; @@ -475,17 +480,15 @@ abstract Message(Dynamic) from Dynamic to Dynamic private static inline function skip(object:Dynamic):Bool { // Skip `null` for obvious reasons. - return object == null - // No need to preserve a primitive type. - || !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object, Object) - // Objects with this field have been deliberately excluded. - || Reflect.field(object, SKIP_FIELD) == true - // A `Uint8Array` (the type used by `haxe.io.Bytes`) can have - // thousands or millions of fields, which can take entire seconds to - // enumerate. This also applies to `Int8Array`, `Float64Array`, etc. - || object.byteLength != null && object.byteOffset != null - && object.buffer != null - && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object.buffer, #if haxe4 js.lib.ArrayBuffer #else js.html.ArrayBuffer #end); + return object == null // No need to preserve a primitive type. + || !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object, Object) // Objects with this field have been deliberately excluded. + || Reflect.field(object, SKIP_FIELD) == true // A `Uint8Array` (the type used by `haxe.io.Bytes`) can have + // thousands or millions of fields, which can take entire seconds to + // enumerate. This also applies to `Int8Array`, `Float64Array`, etc. + || object.byteLength != null + && object.byteOffset != null + && object.buffer != null + && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object.buffer, #if haxe4 js.lib.ArrayBuffer #else js.html.ArrayBuffer #end); } #end @@ -556,7 +559,7 @@ abstract Message(Dynamic) from Dynamic to Dynamic // Recurse. for (child in Object.values(this)) { - (child:Message).preserveClasses(); + (child : Message).preserveClasses(); } #end } @@ -600,9 +603,8 @@ abstract Message(Dynamic) from Dynamic to Dynamic { try { - Object.setPrototypeOf(this, - #if haxe4 Syntax.code #else untyped __js__ #end - ("$hxClasses[{0}].prototype", Reflect.field(this, PROTOTYPE_FIELD))); + Object.setPrototypeOf(this, #if haxe4 Syntax.code #else untyped __js__ #end ("$hxClasses[{0}].prototype", Reflect.field(this, + PROTOTYPE_FIELD))); } catch (e:Dynamic) {} } @@ -610,7 +612,7 @@ abstract Message(Dynamic) from Dynamic to Dynamic // Recurse. for (child in Object.values(this)) { - (child:Message).restoreClasses(flag); + (child : Message).restoreClasses(flag); } #end } @@ -620,13 +622,15 @@ abstract Message(Dynamic) from Dynamic to Dynamic typedef Worker = Dynamic; typedef URL = Dynamic; class Object {} + class Browser { public static var window:Dynamic; } + class Lib { - public static var global:Dynamic = { location: {} }; + public static var global:Dynamic = {location: {}}; } #end @@ -641,15 +645,15 @@ class Lib **/ // Mozilla uses "transferable" and "transferrable" interchangeably, but the HTML // specification only uses the former. + @:forward -abstract Transferable(Dynamic) #if macro from Dynamic - #else from lime.utils.ArrayBuffer from js.html.MessagePort from js.html.ImageBitmap #end -{ -} +abstract Transferable(Dynamic) #if macro from Dynamic #else from lime.utils.ArrayBuffer from js.html.MessagePort from js.html.ImageBitmap #end +{} #if (!haxe4 && !macro) @:native("Object") -extern class Object { +extern class Object +{ static function setPrototypeOf(obj:T, prototype:Null<{}>):T; @:pure static function values(obj:{}):Array; static var prototype(default, never):Dynamic; diff --git a/src/lime/_internal/backend/native/NativeAudioSource.hx b/src/lime/_internal/backend/native/NativeAudioSource.hx index e881c5166e..51c587d73b 100644 --- a/src/lime/_internal/backend/native/NativeAudioSource.hx +++ b/src/lime/_internal/backend/native/NativeAudioSource.hx @@ -253,7 +253,8 @@ class NativeAudioSource #if lime_openalsoft if (hasDirectChannelsExt == null) { - hasDirectChannelsExt = AL.isExtensionPresent("AL_SOFT_direct_channels") && AL.isExtensionPresent("AL_SOFT_direct_channels_remix"); + hasDirectChannelsExt = AL.isExtensionPresent("AL_SOFT_direct_channels") + && AL.isExtensionPresent("AL_SOFT_direct_channels_remix"); } if (hasDirectChannelsExt) @@ -1015,7 +1016,12 @@ class NativeAudioSource refillBuffers(); - if (playing && timer == null && streamExhausted && queuedBufferCount == 0 && handle != null && AL.getSourcei(handle, AL.SOURCE_STATE) != AL.PLAYING) + if (playing + && timer == null + && streamExhausted + && queuedBufferCount == 0 + && handle != null + && AL.getSourcei(handle, AL.SOURCE_STATE) != AL.PLAYING) { if (length == null && parent.buffer.__srcSDLSoundDuration <= 0) { @@ -1085,9 +1091,9 @@ class NativeAudioSource { // `setCurrentTime()` has side effects and is never safe to skip. /* if (value == getCurrentTime()) - { - return value; - } */ + { + return value; + }*/ if (handle != null) { diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index bbb081e3d8..906d38d1fe 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -400,14 +400,13 @@ class NativeCFFI @:cffi private static function lime_vk_destroy_semaphore(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, semaphoreHigh:Int, semaphoreLow:Int):Void; - @:cffi private static function lime_vk_create_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - flags:Int):Dynamic; + @:cffi private static function lime_vk_create_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, flags:Int):Dynamic; @:cffi private static function lime_vk_destroy_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Void; - @:cffi private static function lime_vk_wait_for_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - fenceHigh:Int, fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool; + @:cffi private static function lime_vk_wait_for_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, + fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool; @:cffi private static function lime_vk_reset_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Bool; @@ -415,23 +414,23 @@ class NativeCFFI @:cffi private static function lime_vk_queue_submit(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, fenceLow:Int):Bool; - @:cffi private static function lime_vk_allocate_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, - physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, memoryTypeBits:Int, properties:Int):Dynamic; + @:cffi private static function lime_vk_allocate_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, + deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, memoryTypeBits:Int, properties:Int):Dynamic; - @:cffi private static function lime_vk_free_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - memoryHigh:Int, memoryLow:Int):Void; + @:cffi private static function lime_vk_free_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int):Void; - @:cffi private static function lime_vk_upload_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + @:cffi private static function lime_vk_upload_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; - @:cffi private static function lime_vk_download_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + @:cffi private static function lime_vk_download_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; - @:cffi private static function lime_vk_map_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int, flags:Int):Bool; + @:cffi private static function lime_vk_map_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int, flags:Int):Bool; - @:cffi private static function lime_vk_unmap_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - memoryHigh:Int, memoryLow:Int):Void; + @:cffi private static function lime_vk_unmap_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int):Void; @:cffi private static function lime_vk_write_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; @@ -439,36 +438,36 @@ class NativeCFFI @:cffi private static function lime_vk_flush_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; - @:cffi private static function lime_vk_invalidate_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; + @:cffi private static function lime_vk_invalidate_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; - @:cffi private static function lime_vk_create_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic; + @:cffi private static function lime_vk_create_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, + sizeLow:Int, usage:Int):Dynamic; - @:cffi private static function lime_vk_destroy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - bufferHigh:Int, bufferLow:Int):Void; + @:cffi private static function lime_vk_destroy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, + bufferLow:Int):Void; - @:cffi private static function lime_vk_get_buffer_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, bufferHigh:Int, bufferLow:Int):Dynamic; + @:cffi private static function lime_vk_get_buffer_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bufferHigh:Int, bufferLow:Int):Dynamic; @:cffi private static function lime_vk_bind_buffer_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; - @:cffi private static function lime_vk_create_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - width:Int, height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, imageType:Int, tiling:Int, usage:Int, samples:Int):Dynamic; + @:cffi private static function lime_vk_create_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, width:Int, + height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, imageType:Int, tiling:Int, usage:Int, samples:Int):Dynamic; - @:cffi private static function lime_vk_destroy_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - imageHigh:Int, imageLow:Int):Void; + @:cffi private static function lime_vk_destroy_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, + imageLow:Int):Void; - @:cffi private static function lime_vk_get_image_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, imageHigh:Int, imageLow:Int):Dynamic; + @:cffi private static function lime_vk_get_image_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int):Dynamic; - @:cffi private static function lime_vk_bind_image_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - imageHigh:Int, imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; + @:cffi private static function lime_vk_bind_image_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, + imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; - @:cffi private static function lime_vk_create_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, - physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, queueFamilyIndex:Int, width:Int, height:Int, - presentMode:Int, oldSwapchainHigh:Int, oldSwapchainLow:Int):Dynamic; + @:cffi private static function lime_vk_create_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, + deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, queueFamilyIndex:Int, width:Int, height:Int, presentMode:Int, oldSwapchainHigh:Int, + oldSwapchainLow:Int):Dynamic; @:cffi private static function lime_vk_destroy_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):Void; @@ -482,15 +481,14 @@ class NativeCFFI @:cffi private static function lime_vk_queue_present(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, swapchainHigh:Int, swapchainLow:Int, imageIndex:Int, waitSemaphoreHigh:Int, waitSemaphoreLow:Int):Int; - @:cffi private static function lime_vk_create_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic; + @:cffi private static function lime_vk_create_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, + imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic; @:cffi private static function lime_vk_destroy_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageViewHigh:Int, imageViewLow:Int):Void; @:cffi private static function lime_vk_create_image_view_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int, baseMipLevel:Int, levelCount:Int, baseArrayLayer:Int, - layerCount:Int):Dynamic; + imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int, baseMipLevel:Int, levelCount:Int, baseArrayLayer:Int, layerCount:Int):Dynamic; @:cffi private static function lime_vk_create_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, state:Array):Dynamic; @@ -510,58 +508,57 @@ class NativeCFFI @:cffi private static function lime_vk_destroy_shader_module(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, shaderModuleHigh:Int, shaderModuleLow:Int):Void; - @:cffi private static function lime_vk_create_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - filter:Int, addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, maxAnisotropy:Float, compareOp:Int, minLod:Float, maxLod:Float):Dynamic; + @:cffi private static function lime_vk_create_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, filter:Int, + addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, maxAnisotropy:Float, compareOp:Int, minLod:Float, maxLod:Float):Dynamic; - @:cffi private static function lime_vk_destroy_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - samplerHigh:Int, samplerLow:Int):Void; + @:cffi private static function lime_vk_destroy_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, samplerHigh:Int, + samplerLow:Int):Void; - @:cffi private static function lime_vk_create_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, bindings:Array):Dynamic; + @:cffi private static function lime_vk_create_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bindings:Array):Dynamic; - @:cffi private static function lime_vk_destroy_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void; + @:cffi private static function lime_vk_destroy_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + layoutHigh:Int, layoutLow:Int):Void; - @:cffi private static function lime_vk_create_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, poolSizes:Array):Dynamic; + @:cffi private static function lime_vk_create_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolSizes:Array):Dynamic; - @:cffi private static function lime_vk_destroy_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, poolHigh:Int, poolLow:Int):Void; + @:cffi private static function lime_vk_destroy_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolHigh:Int, poolLow:Int):Void; - @:cffi private static function lime_vk_reset_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, poolHigh:Int, poolLow:Int, flags:Int):Bool; + @:cffi private static function lime_vk_reset_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolHigh:Int, poolLow:Int, flags:Int):Bool; - @:cffi private static function lime_vk_allocate_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic; + @:cffi private static function lime_vk_allocate_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic; - @:cffi private static function lime_vk_update_descriptor_set_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, imageViewHigh:Int, imageViewLow:Int, samplerHigh:Int, - samplerLow:Int, imageLayout:Int):Bool; + @:cffi private static function lime_vk_update_descriptor_set_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, imageViewHigh:Int, imageViewLow:Int, samplerHigh:Int, samplerLow:Int, imageLayout:Int):Bool; - @:cffi private static function lime_vk_update_descriptor_set_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool; + @:cffi private static function lime_vk_update_descriptor_set_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool; @:cffi private static function lime_vk_update_descriptor_sets(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, writes:Array):Bool; - @:cffi private static function lime_vk_create_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, setLayouts:Array, pushConstantStages:Int, pushConstantSize:Int):Dynamic; + @:cffi private static function lime_vk_create_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + setLayouts:Array, pushConstantStages:Int, pushConstantSize:Int):Dynamic; - @:cffi private static function lime_vk_destroy_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void; + @:cffi private static function lime_vk_destroy_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + layoutHigh:Int, layoutLow:Int):Void; - @:cffi private static function lime_vk_create_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Dynamic; + @:cffi private static function lime_vk_create_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bytes:Dynamic, byteOffset:Int, byteLength:Int):Dynamic; - @:cffi private static function lime_vk_destroy_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void; + @:cffi private static function lime_vk_destroy_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + cacheHigh:Int, cacheLow:Int):Void; - @:cffi private static function lime_vk_get_pipeline_cache_data(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, cacheHigh:Int, cacheLow:Int, bytes:Dynamic):Bool; + @:cffi private static function lime_vk_get_pipeline_cache_data(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + cacheHigh:Int, cacheLow:Int, bytes:Dynamic):Bool; - @:cffi private static function lime_vk_create_graphics_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, - fragmentShaderHigh:Int, fragmentShaderLow:Int, state:Array):Dynamic; + @:cffi private static function lime_vk_create_graphics_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, fragmentShaderHigh:Int, + fragmentShaderLow:Int, state:Array):Dynamic; @:cffi private static function lime_vk_destroy_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, pipelineHigh:Int, pipelineLow:Int):Void; @@ -570,8 +567,8 @@ class NativeCFFI queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:Array):Bool; @:cffi private static function lime_vk_cmd_begin_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, renderPassLow:Int, framebufferHigh:Int, framebufferLow:Int, - state:Array, clear:Array):Bool; + commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, renderPassLow:Int, framebufferHigh:Int, framebufferLow:Int, state:Array, + clear:Array):Bool; @:cffi private static function lime_vk_cmd_end_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool; @@ -579,16 +576,15 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_bind_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, bindPoint:Int):Bool; - @:cffi private static function lime_vk_cmd_bind_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, - firstSet:Int):Bool; + @:cffi private static function lime_vk_cmd_bind_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, firstSet:Int):Bool; - @:cffi private static function lime_vk_cmd_bind_descriptor_set_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, state:Array):Bool; + @:cffi private static function lime_vk_cmd_bind_descriptor_set_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, state:Array):Bool; - @:cffi private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset(handle:Dynamic, instanceHigh:Int, instanceLow:Int, - deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, - dynamicOffset:Int, firstSet:Int, bindPoint:Int):Bool; + @:cffi private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, dynamicOffset:Int, firstSet:Int, + bindPoint:Int):Bool; @:cffi private static function lime_vk_cmd_bind_vertex_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool; @@ -602,8 +598,8 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_set_scissor(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, height:Int):Bool; - @:cffi private static function lime_vk_cmd_draw(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, - commandBufferHigh:Int, commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, firstInstance:Int):Bool; + @:cffi private static function lime_vk_cmd_draw(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, + commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, firstInstance:Int):Bool; @:cffi private static function lime_vk_cmd_draw_indexed(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, firstIndex:Int, vertexOffset:Int, firstInstance:Int):Bool; @@ -611,29 +607,26 @@ class NativeCFFI @:cffi private static function lime_vk_cmd_draw_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool; - @:cffi private static function lime_vk_cmd_draw_indexed_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, - stride:Int):Bool; + @:cffi private static function lime_vk_cmd_draw_indexed_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool; @:cffi private static function lime_vk_cmd_copy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; - @:cffi private static function lime_vk_cmd_copy_buffer_to_image_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, - state:Array):Bool; + @:cffi private static function lime_vk_cmd_copy_buffer_to_image_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; - @:cffi private static function lime_vk_cmd_copy_image_to_buffer_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, bufferHigh:Int, bufferLow:Int, - state:Array):Bool; + @:cffi private static function lime_vk_cmd_copy_image_to_buffer_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, bufferHigh:Int, bufferLow:Int, state:Array):Bool; - @:cffi private static function lime_vk_cmd_pipeline_barrier_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; + @:cffi private static function lime_vk_cmd_pipeline_barrier_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; @:cffi private static function lime_vk_cmd_clear_color_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, layout:Int, aspectMask:Int, clear:Array):Bool; - @:cffi private static function lime_vk_cmd_clear_depth_stencil_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, - deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array, clear:Array):Bool; + @:cffi private static function lime_vk_cmd_clear_depth_stencil_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array, clear:Array):Bool; @:cffi private static function lime_vk_cmd_clear_attachments(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:Array, clear:Array):Bool; @@ -741,16 +734,16 @@ class NativeCFFI "lime_sdl_sound_get_info_from_file", "so", false)); private static var lime_sdl_sound_stream_from_bytes = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_from_bytes", "oo", false)); - private static var lime_sdl_sound_stream_from_file = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_from_file", "so", false)); + private static var lime_sdl_sound_stream_from_file = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_from_file", + "so", false)); private static var lime_sdl_sound_stream_read = new cpp.Callablecpp.Object->Int->Int>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_read", "ooii", false)); - private static var lime_sdl_sound_stream_rewind = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_rewind", "ob", false)); - private static var lime_sdl_sound_stream_seek = new cpp.CallableInt->Bool>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_seek", "oib", false)); - private static var lime_sdl_sound_stream_clear = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_clear", "ov", false)); + private static var lime_sdl_sound_stream_rewind = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_rewind", "ob", + false)); + private static var lime_sdl_sound_stream_seek = new cpp.CallableInt->Bool>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_seek", "oib", + false)); + private static var lime_sdl_sound_stream_clear = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_clear", "ov", + false)); private static var lime_bytes_from_data_pointer = new cpp.CallableInt->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_bytes_from_data_pointer", "dioo", false)); private static var lime_bytes_get_data_pointer = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_bytes_get_data_pointer", "od", @@ -787,8 +780,7 @@ class NativeCFFI "lime_file_watcher_add_directory", "oobo", false)); private static var lime_file_watcher_remove_directory = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_file_watcher_remove_directory", "oov", false)); - private static var lime_file_watcher_update = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_file_watcher_update", "ov", - false)); + private static var lime_file_watcher_update = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_file_watcher_update", "ov", false)); private static var lime_font_get_ascender = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_ascender", "oi", false)); private static var lime_font_get_descender = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_descender", "oi", false)); private static var lime_font_get_family_name = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_font_get_family_name", "oo", @@ -805,10 +797,10 @@ class NativeCFFI "oi", false)); private static var lime_font_get_underline_thickness = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_underline_thickness", "oi", false)); - private static var lime_font_get_strikethrough_position = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_strikethrough_position", - "oi", false)); - private static var lime_font_get_strikethrough_thickness = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_strikethrough_thickness", - "oi", false)); + private static var lime_font_get_strikethrough_position = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", + "lime_font_get_strikethrough_position", "oi", false)); + private static var lime_font_get_strikethrough_thickness = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", + "lime_font_get_strikethrough_thickness", "oi", false)); private static var lime_font_get_units_per_em = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_units_per_em", "oi", false)); private static var lime_font_load = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_font_load", "oo", false)); private static var lime_font_load_bytes = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_font_load_bytes", "oo", false)); @@ -885,10 +877,8 @@ class NativeCFFI "lime_jpeg_decode_bytes", "oboo", false)); private static var lime_jpeg_decode_file = new cpp.CallableBool->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_jpeg_decode_file", "sboo", false)); - private static var lime_key_code_from_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_from_scan_code", - "ii", false)); - private static var lime_key_code_to_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_to_scan_code", - "ii", false)); + private static var lime_key_code_from_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_from_scan_code", "ii", false)); + private static var lime_key_code_to_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_to_scan_code", "ii", false)); private static var lime_key_event_manager_register = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_key_event_manager_register", "oov", false)); private static var lime_lzma_compress = new cpp.Callablecpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_lzma_compress", "ooo", @@ -921,7 +911,8 @@ class NativeCFFI private static var lime_system_get_display = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_system_get_display", "io", false)); private static var lime_system_get_ios_tablet = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_system_get_ios_tablet", "b", false)); private static var lime_system_get_num_displays = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_system_get_num_displays", "i", false)); - private static var lime_system_get_device_orientation = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_system_get_device_orientation", "i", false)); + private static var lime_system_get_device_orientation = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_system_get_device_orientation", + "i", false)); private static var lime_system_get_platform_label = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_system_get_platform_label", "o", false)); private static var lime_system_get_platform_name = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_system_get_platform_name", "o", @@ -938,8 +929,7 @@ class NativeCFFI private static var lime_window_alert = new cpp.CallableString->String->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_alert", "ossv", false)); private static var lime_window_close = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_close", "ov", false)); - private static var lime_window_context_flip = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_context_flip", "ov", - false)); + private static var lime_window_context_flip = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_context_flip", "ov", false)); private static var lime_window_context_lock = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_context_lock", "oo", false)); private static var lime_window_context_make_current = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", @@ -959,8 +949,7 @@ class NativeCFFI "oo", false)); private static var lime_window_get_height = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_height", "oi", false)); private static var lime_window_get_id = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_id", "oi", false)); - private static var lime_window_get_mouse_lock = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_window_get_mouse_lock", "ob", - false)); + private static var lime_window_get_mouse_lock = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_window_get_mouse_lock", "ob", false)); private static var lime_window_get_opacity = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_opacity", "od", false)); private static var lime_window_get_scale = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_scale", "od", false)); private static var lime_window_get_text_input_enabled = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", @@ -971,10 +960,10 @@ class NativeCFFI "lime_window_get_vulkan_instance_extensions", "oo", false)); private static var lime_window_get_vulkan_instance_proc_addr = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_get_vulkan_instance_proc_addr", "oo", false)); - private static var lime_vk_create_instance = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_instance", "oso", false)); - private static var lime_vk_destroy_instance = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", - "lime_vk_destroy_instance", "oiiv", false)); + private static var lime_vk_create_instance = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_instance", + "oso", false)); + private static var lime_vk_destroy_instance = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_instance", + "oiiv", false)); private static var lime_vk_destroy_surface = new cpp.CallableInt->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_surface", "oiiiiv", false)); private static var lime_vk_get_physical_devices = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", @@ -994,10 +983,10 @@ class NativeCFFI "lime_vk_destroy_command_pool", "oiiiiiiv", false)); private static var lime_vk_reset_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_reset_command_pool", "oiiiiiiib", false)); - private static var lime_vk_allocate_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_allocate_command_buffer", "oiiiiiiio", false)); - private static var lime_vk_free_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", - "lime_vk_free_command_buffer", "oiiiiiiiiv", false)); + private static var lime_vk_allocate_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_command_buffer", "oiiiiiiio", false)); + private static var lime_vk_free_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int-> + cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_free_command_buffer", "oiiiiiiiiv", false)); private static var lime_vk_begin_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_begin_command_buffer", "oiiiiiiib", false)); private static var lime_vk_end_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", @@ -1018,40 +1007,40 @@ class NativeCFFI "lime_vk_reset_fence", "oiiiiiib", false)); private static var lime_vk_queue_submit = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_queue_submit", "oiiiiiiiiiib", false)); - private static var lime_vk_allocate_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime( - "lime", "lime_vk_allocate_memory", "oiiiiiiiiiio", false)); + private static var lime_vk_allocate_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_memory", "oiiiiiiiiiio", false)); private static var lime_vk_free_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_free_memory", "oiiiiiiv", false)); - private static var lime_vk_upload_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_upload_memory", "oiiiiiiiioiib", false)); - private static var lime_vk_download_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_download_memory", "oiiiiiiiioiib", false)); - private static var lime_vk_map_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_map_memory", "oiiiiiiiiiiib", false)); + private static var lime_vk_upload_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_upload_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_download_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_download_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_map_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_map_memory", "oiiiiiiiiiiib", false)); private static var lime_vk_unmap_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_unmap_memory", "oiiiiiiv", false)); - private static var lime_vk_write_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_write_mapped_memory", "oiiiiiiiioiib", false)); - private static var lime_vk_flush_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_flush_mapped_memory", "oiiiiiiiiiib", false)); - private static var lime_vk_invalidate_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_invalidate_mapped_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_write_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_write_mapped_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_flush_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_flush_mapped_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_invalidate_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_invalidate_mapped_memory", "oiiiiiiiiiib", false)); private static var lime_vk_create_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_buffer", "oiiiiiiio", false)); private static var lime_vk_destroy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_buffer", "oiiiiiiv", false)); - private static var lime_vk_get_buffer_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_get_buffer_memory_requirements", "oiiiiiio", false)); - private static var lime_vk_bind_buffer_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_bind_buffer_memory", "oiiiiiiiiiib", false)); - private static var lime_vk_create_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( - cpp.Prime._loadPrime("lime", "lime_vk_create_image", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_get_buffer_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_buffer_memory_requirements", "oiiiiiio", false)); + private static var lime_vk_bind_buffer_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_bind_buffer_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_create_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_image", "oiiiiiiiiiiiiiio", false)); private static var lime_vk_destroy_image = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_image", "oiiiiiiv", false)); - private static var lime_vk_get_image_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_get_image_memory_requirements", "oiiiiiio", false)); - private static var lime_vk_bind_image_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_bind_image_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_get_image_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_image_memory_requirements", "oiiiiiio", false)); + private static var lime_vk_bind_image_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_bind_image_memory", "oiiiiiiiiiib", false)); private static var lime_vk_create_swapchain = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_swapchain", "oiiiiiiiiiiiiiio", false)); private static var lime_vk_destroy_swapchain = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1060,119 +1049,118 @@ class NativeCFFI "lime_vk_get_swapchain_images", "oiiiiiio", false)); private static var lime_vk_acquire_next_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_acquire_next_image", "oiiiiiiiiiiiio", false)); - private static var lime_vk_queue_present = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int>(cpp.Prime._loadPrime("lime", - "lime_vk_queue_present", "oiiiiiiiiiiii", false)); - private static var lime_vk_create_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_image_view", "oiiiiiiiiio", false)); + private static var lime_vk_queue_present = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Int>(cpp.Prime._loadPrime("lime", "lime_vk_queue_present", "oiiiiiiiiiiii", false)); + private static var lime_vk_create_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_image_view", "oiiiiiiiiio", false)); private static var lime_vk_destroy_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_image_view", "oiiiiiiv", false)); - private static var lime_vk_create_image_view_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object>( - cpp.Prime._loadPrime("lime", "lime_vk_create_image_view_ex", "oiiiiiiiiiiiiio", false)); - private static var lime_vk_create_render_pass = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>( - cpp.Prime._loadPrime("lime", "lime_vk_create_render_pass", "oiiiioo", false)); + private static var lime_vk_create_image_view_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_image_view_ex", "oiiiiiiiiiiiiio", false)); + private static var lime_vk_create_render_pass = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_render_pass", "oiiiioo", false)); private static var lime_vk_destroy_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_render_pass", "oiiiiiiv", false)); - private static var lime_vk_create_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Int->cpp.Object>( - cpp.Prime._loadPrime("lime", "lime_vk_create_framebuffer", "oiiiiiioiiio", false)); + private static var lime_vk_create_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_framebuffer", "oiiiiiioiiio", false)); private static var lime_vk_destroy_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_framebuffer", "oiiiiiiv", false)); - private static var lime_vk_create_shader_module = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_shader_module", "oiiiioiio", false)); + private static var lime_vk_create_shader_module = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_shader_module", "oiiiioiio", false)); private static var lime_vk_destroy_shader_module = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_shader_module", "oiiiiiiv", false)); - private static var lime_vk_create_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool->Float->Int->Float->Float->cpp.Object>( - cpp.Prime._loadPrime("lime", "lime_vk_create_sampler", "oiiiiiiibdiddo", false)); + private static var lime_vk_create_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool->Float->Int->Float->Float-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_sampler", "oiiiiiiibdiddo", false)); private static var lime_vk_destroy_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_sampler", "oiiiiiiv", false)); - private static var lime_vk_create_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_descriptor_set_layout", "oiiiioo", false)); - private static var lime_vk_destroy_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", - "lime_vk_destroy_descriptor_set_layout", "oiiiiiiv", false)); + private static var lime_vk_create_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_descriptor_set_layout", "oiiiioo", false)); + private static var lime_vk_destroy_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->Int->Int-> + cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_descriptor_set_layout", "oiiiiiiv", false)); private static var lime_vk_create_descriptor_pool = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_descriptor_pool", "oiiiioo", false)); private static var lime_vk_destroy_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_descriptor_pool", "oiiiiiiv", false)); private static var lime_vk_reset_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_reset_descriptor_pool", "oiiiiiiib", false)); - private static var lime_vk_allocate_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_allocate_descriptor_set", "oiiiiiiiio", false)); - private static var lime_vk_update_descriptor_set_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_image", "oiiiiiiiiiiiiib", false)); - private static var lime_vk_update_descriptor_set_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_buffer", "oiiiiiiiiiiiib", false)); + private static var lime_vk_allocate_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_descriptor_set", "oiiiiiiiio", false)); + private static var lime_vk_update_descriptor_set_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_image", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_update_descriptor_set_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_buffer", "oiiiiiiiiiiiib", false)); private static var lime_vk_update_descriptor_sets = new cpp.CallableInt->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_sets", "oiiiiob", false)); - private static var lime_vk_create_pipeline_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_pipeline_layout", "oiiiioiio", false)); + private static var lime_vk_create_pipeline_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_pipeline_layout", "oiiiioiio", false)); private static var lime_vk_destroy_pipeline_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_pipeline_layout", "oiiiiiiv", false)); - private static var lime_vk_create_pipeline_cache = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_create_pipeline_cache", "oiiiioiio", false)); + private static var lime_vk_create_pipeline_cache = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_pipeline_cache", "oiiiioiio", false)); private static var lime_vk_destroy_pipeline_cache = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_pipeline_cache", "oiiiiiiv", false)); - private static var lime_vk_get_pipeline_cache_data = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_get_pipeline_cache_data", "oiiiiiiob", false)); + private static var lime_vk_get_pipeline_cache_data = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_get_pipeline_cache_data", "oiiiiiiob", false)); private static var lime_vk_create_graphics_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_graphics_pipeline", "oiiiiiiiiiiiioo", false)); private static var lime_vk_destroy_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_pipeline", "oiiiiiiv", false)); - private static var lime_vk_queue_submit_synced = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_queue_submit_synced", "oiiiiiiiiob", false)); - private static var lime_vk_cmd_begin_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_begin_render_pass", "oiiiiiiiiiioob", false)); + private static var lime_vk_queue_submit_synced = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_queue_submit_synced", "oiiiiiiiiob", false)); + private static var lime_vk_cmd_begin_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_begin_render_pass", "oiiiiiiiiiioob", false)); private static var lime_vk_cmd_end_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_end_render_pass", "oiiiiiib", false)); private static var lime_vk_cmd_bind_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_pipeline", "oiiiiiiiiib", false)); - private static var lime_vk_cmd_bind_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set", "oiiiiiiiiiiiib", false)); - private static var lime_vk_cmd_bind_descriptor_set_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_ex", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_bind_descriptor_set_dynamic_offset = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_dynamic_offset", "oiiiiiiiiiiiiib", false)); - private static var lime_vk_cmd_bind_vertex_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_vertex_buffer", "oiiiiiiiiiiib", false)); - private static var lime_vk_cmd_bind_index_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_index_buffer", "oiiiiiiiiiiib", false)); - private static var lime_vk_cmd_set_viewport = new cpp.CallableInt->Int->Int->Int->Int->Int->Float->Float->Float->Float->Float->Float->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_set_viewport", "oiiiiiiddddddb", false)); - private static var lime_vk_cmd_set_scissor = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_cmd_set_scissor", "oiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_descriptor_set_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_ex", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_bind_descriptor_set_dynamic_offset = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_dynamic_offset", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_vertex_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_vertex_buffer", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_index_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_index_buffer", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_set_viewport = new cpp.CallableInt->Int->Int->Int->Int->Int->Float->Float->Float->Float->Float->Float-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_set_viewport", "oiiiiiiddddddb", false)); + private static var lime_vk_cmd_set_scissor = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_set_scissor", "oiiiiiiiiiib", false)); private static var lime_vk_cmd_draw = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw", "oiiiiiiiiiib", false)); - private static var lime_vk_cmd_draw_indexed = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_cmd_draw_indexed", "oiiiiiiiiiiib", false)); - private static var lime_vk_cmd_draw_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", - "lime_vk_cmd_draw_indirect", "oiiiiiiiiiiiib", false)); - private static var lime_vk_cmd_draw_indexed_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime( - "lime", "lime_vk_cmd_draw_indexed_indirect", "oiiiiiiiiiiiib", false)); - private static var lime_vk_cmd_copy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_copy_buffer_to_image_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image_region", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_copy_image_to_buffer_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_image_to_buffer_region", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_pipeline_barrier_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_pipeline_barrier_image", "oiiiiiiiiob", false)); - private static var lime_vk_cmd_clear_color_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_color_image", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_clear_depth_stencil_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_depth_stencil_image", "oiiiiiiiioob", false)); - private static var lime_vk_cmd_clear_attachments = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_attachments", "oiiiiiioob", false)); - private static var lime_vk_cmd_blit_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_blit_image", "oiiiiiiiiiiob", false)); - private static var lime_vk_cmd_push_constants = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object->Bool>( - cpp.Prime._loadPrime("lime", "lime_vk_cmd_push_constants", "oiiiiiiiioob", false)); + private static var lime_vk_cmd_draw_indexed = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indexed", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indirect", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indexed_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indexed_indirect", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_copy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_copy_buffer_to_image_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image_region", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_copy_image_to_buffer_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_image_to_buffer_region", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_pipeline_barrier_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_pipeline_barrier_image", "oiiiiiiiiob", false)); + private static var lime_vk_cmd_clear_color_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_color_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_clear_depth_stencil_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_depth_stencil_image", "oiiiiiiiioob", false)); + private static var lime_vk_cmd_clear_attachments = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_attachments", "oiiiiiioob", false)); + private static var lime_vk_cmd_blit_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_blit_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_push_constants = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_push_constants", "oiiiiiiiioob", false)); #end - private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vk_get_last_error", "o", false)); + private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_last_error", "o", false)); private static var lime_vulkan_renderer_create = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_create", "oso", false)); - private static var lime_vulkan_renderer_destroy = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", - "lime_vulkan_renderer_destroy", "ov", false)); - private static var lime_vulkan_renderer_get_info = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", - "lime_vulkan_renderer_get_info", "oo", false)); + private static var lime_vulkan_renderer_destroy = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_destroy", + "ov", false)); + private static var lime_vulkan_renderer_get_info = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_get_info", + "oo", false)); private static var lime_vulkan_renderer_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_get_last_error", "o", false)); private static var lime_vulkan_renderer_set_overlay = new cpp.Callablecpp.Object->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", @@ -1181,20 +1169,19 @@ class NativeCFFI "lime_vulkan_renderer_clear_overlay", "ob", false)); private static var lime_vulkan_renderer_render = new cpp.CallableFloat->Float->Float->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_render", "oddddb", false)); - private static var lime_vulkan_renderer_resize = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", - "lime_vulkan_renderer_resize", "ob", false)); + private static var lime_vulkan_renderer_resize = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_resize", "ob", + false)); private static var lime_window_get_width = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_width", "oi", false)); private static var lime_window_get_x = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_x", "oi", false)); private static var lime_window_get_y = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_y", "oi", false)); private static var lime_window_move = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_move", "oiiv", false)); private static var lime_window_read_pixels = new cpp.Callablecpp.Object->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_read_pixels", "oooo", false)); - private static var lime_window_resize = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_resize", "oiiv", - false)); - private static var lime_window_set_minimum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_set_minimum_size", "oiiv", - false)); - private static var lime_window_set_maximum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_set_maximum_size", "oiiv", - false)); + private static var lime_window_resize = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_resize", "oiiv", false)); + private static var lime_window_set_minimum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_window_set_minimum_size", "oiiv", false)); + private static var lime_window_set_maximum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_window_set_maximum_size", "oiiv", false)); private static var lime_window_set_borderless = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_borderless", "obb", false)); private static var lime_window_set_cursor = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_set_cursor", "oiv", @@ -1223,8 +1210,8 @@ class NativeCFFI false)); private static var lime_window_set_visible = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_visible", "obb", false)); - private static var lime_window_set_always_on_top = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_always_on_top", "obb", - false)); + private static var lime_window_set_always_on_top = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_always_on_top", + "obb", false)); private static var lime_window_warp_mouse = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_warp_mouse", "oiiv", false)); private static var lime_window_event_manager_register = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1658,8 +1645,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_file_dialog_open_file") private static function lime_file_dialog_open_file(title:String, filter:String, - defaultPath:String):hl.Bytes + @:hlNative("lime", "hl_file_dialog_open_file") private static function lime_file_dialog_open_file(title:String, filter:String, defaultPath:String):hl.Bytes { return null; } @@ -1670,8 +1656,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_file_dialog_save_file") private static function lime_file_dialog_save_file(title:String, filter:String, - defaultPath:String):hl.Bytes + @:hlNative("lime", "hl_file_dialog_save_file") private static function lime_file_dialog_save_file(title:String, filter:String, defaultPath:String):hl.Bytes { return null; } @@ -1687,8 +1672,7 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_file_watcher_remove_directory") private static function lime_file_watcher_remove_directory(handle:CFFIPointer, - watchID:Int):Void {} + @:hlNative("lime", "hl_file_watcher_remove_directory") private static function lime_file_watcher_remove_directory(handle:CFFIPointer, watchID:Int):Void {} @:hlNative("lime", "hl_file_watcher_update") private static function lime_file_watcher_update(handle:CFFIPointer):Void {} @@ -1810,7 +1794,8 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_gamepad_rumble") private static function lime_gamepad_rumble(id:Int, lowFrequencyRumble:Float, highFrequencyRumble:Float, duration:Int):Void {} + @:hlNative("lime", "hl_gamepad_rumble") private static function lime_gamepad_rumble(id:Int, lowFrequencyRumble:Float, highFrequencyRumble:Float, + duration:Int):Void {} @:hlNative("lime", "hl_gamepad_event_manager_register") private static function lime_gamepad_event_manager_register(callback:Void->Void, eventObject:GamepadEventInfo):Void {} @@ -2081,8 +2066,8 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_window_create_vulkan_surface") private static function lime_window_create_vulkan_surface(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int):Dynamic + @:hlNative("lime", "hl_window_create_vulkan_surface") private static function lime_window_create_vulkan_surface(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int):Dynamic { return null; } @@ -2124,8 +2109,8 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_window_get_vulkan_instance_extensions") private static function lime_window_get_vulkan_instance_extensions( - handle:CFFIPointer):hl.NativeArray + @:hlNative("lime", + "hl_window_get_vulkan_instance_extensions") private static function lime_window_get_vulkan_instance_extensions(handle:CFFIPointer):hl.NativeArray { return null; } @@ -2140,11 +2125,10 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vk_destroy_instance") private static function lime_vk_destroy_instance(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_instance") private static function lime_vk_destroy_instance(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int):Void {} - @:hlNative("lime", "hl_vk_destroy_surface") private static function lime_vk_destroy_surface(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_surface") private static function lime_vk_destroy_surface(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + surfaceHigh:Int, surfaceLow:Int):Void {} @:hlNative("lime", "hl_vk_get_physical_devices") private static function lime_vk_get_physical_devices(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):hl.NativeArray @@ -2159,44 +2143,44 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vk_destroy_device") private static function lime_vk_destroy_device(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_device") private static function lime_vk_destroy_device(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int):Void {} - @:hlNative("lime", "hl_vk_device_wait_idle") private static function lime_vk_device_wait_idle(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int):Bool + @:hlNative("lime", "hl_vk_device_wait_idle") private static function lime_vk_device_wait_idle(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_queue_wait_idle") private static function lime_vk_queue_wait_idle(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int):Bool + @:hlNative("lime", "hl_vk_queue_wait_idle") private static function lime_vk_queue_wait_idle(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_create_command_pool") private static function lime_vk_create_command_pool(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueFamilyIndex:Int, flags:Int):Dynamic + @:hlNative("lime", "hl_vk_create_command_pool") private static function lime_vk_create_command_pool(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueFamilyIndex:Int, flags:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_command_pool") private static function lime_vk_destroy_command_pool(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_command_pool") private static function lime_vk_destroy_command_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int):Void {} - @:hlNative("lime", "hl_vk_reset_command_pool") private static function lime_vk_reset_command_pool(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, flags:Int):Bool + @:hlNative("lime", "hl_vk_reset_command_pool") private static function lime_vk_reset_command_pool(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, flags:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_allocate_command_buffer") private static function lime_vk_allocate_command_buffer(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, level:Int):Dynamic + @:hlNative("lime", "hl_vk_allocate_command_buffer") private static function lime_vk_allocate_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, level:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_free_command_buffer") private static function lime_vk_free_command_buffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Void {} + @:hlNative("lime", "hl_vk_free_command_buffer") private static function lime_vk_free_command_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Void {} @:hlNative("lime", "hl_vk_begin_command_buffer") private static function lime_vk_begin_command_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool @@ -2204,8 +2188,8 @@ class NativeCFFI return false; } - @:hlNative("lime", "hl_vk_end_command_buffer") private static function lime_vk_end_command_buffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool + @:hlNative("lime", "hl_vk_end_command_buffer") private static function lime_vk_end_command_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool { return false; } @@ -2216,106 +2200,98 @@ class NativeCFFI return false; } - @:hlNative("lime", "hl_vk_create_semaphore") private static function lime_vk_create_semaphore(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int):Dynamic + @:hlNative("lime", "hl_vk_create_semaphore") private static function lime_vk_create_semaphore(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_semaphore") private static function lime_vk_destroy_semaphore(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, semaphoreHigh:Int, semaphoreLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_semaphore") private static function lime_vk_destroy_semaphore(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, semaphoreHigh:Int, semaphoreLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_fence") private static function lime_vk_create_fence(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, flags:Int):Dynamic + @:hlNative("lime", "hl_vk_create_fence") private static function lime_vk_create_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, flags:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_fence") private static function lime_vk_destroy_fence(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_fence") private static function lime_vk_destroy_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Void {} - @:hlNative("lime", "hl_vk_wait_for_fence") private static function lime_vk_wait_for_fence(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool + @:hlNative("lime", "hl_vk_wait_for_fence") private static function lime_vk_wait_for_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_reset_fence") private static function lime_vk_reset_fence(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Bool + @:hlNative("lime", "hl_vk_reset_fence") private static function lime_vk_reset_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, fenceHigh:Int, fenceLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_queue_submit") private static function lime_vk_queue_submit(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, - fenceLow:Int):Bool + @:hlNative("lime", "hl_vk_queue_submit") private static function lime_vk_queue_submit(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, fenceLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_allocate_memory") private static function lime_vk_allocate_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, - memoryTypeBits:Int, properties:Int):Dynamic + @:hlNative("lime", "hl_vk_allocate_memory") private static function lime_vk_allocate_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, memoryTypeBits:Int, properties:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_free_memory") private static function lime_vk_free_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} + @:hlNative("lime", "hl_vk_free_memory") private static function lime_vk_free_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} - @:hlNative("lime", "hl_vk_upload_memory") private static function lime_vk_upload_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, - byteOffset:Int, byteLength:Int):Bool + @:hlNative("lime", "hl_vk_upload_memory") private static function lime_vk_upload_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_download_memory") private static function lime_vk_download_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, - byteOffset:Int, byteLength:Int):Bool + @:hlNative("lime", "hl_vk_download_memory") private static function lime_vk_download_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_map_memory") private static function lime_vk_map_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, - sizeLow:Int, flags:Int):Bool + @:hlNative("lime", "hl_vk_map_memory") private static function lime_vk_map_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int, flags:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_unmap_memory") private static function lime_vk_unmap_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} + @:hlNative("lime", "hl_vk_unmap_memory") private static function lime_vk_unmap_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} - @:hlNative("lime", "hl_vk_write_mapped_memory") private static function lime_vk_write_mapped_memory(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, - bytes:Bytes, byteOffset:Int, byteLength:Int):Bool + @:hlNative("lime", "hl_vk_write_mapped_memory") private static function lime_vk_write_mapped_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_flush_mapped_memory") private static function lime_vk_flush_mapped_memory(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, - sizeHigh:Int, sizeLow:Int):Bool + @:hlNative("lime", "hl_vk_flush_mapped_memory") private static function lime_vk_flush_mapped_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_invalidate_mapped_memory") private static function lime_vk_invalidate_mapped_memory(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, - sizeHigh:Int, sizeLow:Int):Bool + @:hlNative("lime", "hl_vk_invalidate_mapped_memory") private static function lime_vk_invalidate_mapped_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_create_buffer") private static function lime_vk_create_buffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic + @:hlNative("lime", "hl_vk_create_buffer") private static function lime_vk_create_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_buffer") private static function lime_vk_destroy_buffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_buffer") private static function lime_vk_destroy_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Void {} @:hlNative("lime", "hl_vk_get_buffer_memory_requirements") private static function lime_vk_get_buffer_memory_requirements(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Dynamic @@ -2323,22 +2299,21 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vk_bind_buffer_memory") private static function lime_vk_bind_buffer_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, - offsetLow:Int):Bool + @:hlNative("lime", "hl_vk_bind_buffer_memory") private static function lime_vk_bind_buffer_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_create_image") private static function lime_vk_create_image(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, width:Int, height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, - imageType:Int, tiling:Int, usage:Int, samples:Int):Dynamic + @:hlNative("lime", "hl_vk_create_image") private static function lime_vk_create_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, width:Int, height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, imageType:Int, tiling:Int, usage:Int, + samples:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_image") private static function lime_vk_destroy_image(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_image") private static function lime_vk_destroy_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Void {} @:hlNative("lime", "hl_vk_get_image_memory_requirements") private static function lime_vk_get_image_memory_requirements(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Dynamic @@ -2346,22 +2321,21 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vk_bind_image_memory") private static function lime_vk_bind_image_memory(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, - offsetLow:Int):Bool + @:hlNative("lime", "hl_vk_bind_image_memory") private static function lime_vk_bind_image_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_create_swapchain") private static function lime_vk_create_swapchain(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, - queueFamilyIndex:Int, width:Int, height:Int, presentMode:Int, oldSwapchainHigh:Int, oldSwapchainLow:Int):Dynamic + @:hlNative("lime", "hl_vk_create_swapchain") private static function lime_vk_create_swapchain(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, queueFamilyIndex:Int, width:Int, + height:Int, presentMode:Int, oldSwapchainHigh:Int, oldSwapchainLow:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_swapchain") private static function lime_vk_destroy_swapchain(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_swapchain") private static function lime_vk_destroy_swapchain(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):Void {} @:hlNative("lime", "hl_vk_get_swapchain_images") private static function lime_vk_get_swapchain_images(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):hl.NativeArray @@ -2369,9 +2343,9 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vk_acquire_next_image") private static function lime_vk_acquire_next_image(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int, timeoutHigh:Int, timeoutLow:Int, semaphoreHigh:Int, - semaphoreLow:Int, fenceHigh:Int, fenceLow:Int):Dynamic + @:hlNative("lime", "hl_vk_acquire_next_image") private static function lime_vk_acquire_next_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int, timeoutHigh:Int, timeoutLow:Int, semaphoreHigh:Int, semaphoreLow:Int, + fenceHigh:Int, fenceLow:Int):Dynamic { return null; } @@ -2383,59 +2357,58 @@ class NativeCFFI return -3; } - @:hlNative("lime", "hl_vk_create_image_view") private static function lime_vk_create_image_view(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic + @:hlNative("lime", "hl_vk_create_image_view") private static function lime_vk_create_image_view(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_image_view") private static function lime_vk_destroy_image_view(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageViewHigh:Int, imageViewLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_image_view") private static function lime_vk_destroy_image_view(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageViewHigh:Int, imageViewLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_image_view_ex") private static function lime_vk_create_image_view_ex(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, - viewType:Int, baseMipLevel:Int, levelCount:Int, baseArrayLayer:Int, layerCount:Int):Dynamic + @:hlNative("lime", "hl_vk_create_image_view_ex") private static function lime_vk_create_image_view_ex(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int, baseMipLevel:Int, + levelCount:Int, baseArrayLayer:Int, layerCount:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_create_render_pass") private static function lime_vk_create_render_pass(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, state:hl.NativeArray):Dynamic + @:hlNative("lime", "hl_vk_create_render_pass") private static function lime_vk_create_render_pass(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, state:hl.NativeArray):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_render_pass") private static function lime_vk_destroy_render_pass(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_render_pass") private static function lime_vk_destroy_render_pass(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_framebuffer") private static function lime_vk_create_framebuffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, attachments:hl.NativeArray, - width:Int, height:Int, layers:Int):Dynamic + @:hlNative("lime", "hl_vk_create_framebuffer") private static function lime_vk_create_framebuffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, attachments:hl.NativeArray, width:Int, height:Int, layers:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_framebuffer") private static function lime_vk_destroy_framebuffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, framebufferHigh:Int, framebufferLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_framebuffer") private static function lime_vk_destroy_framebuffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, framebufferHigh:Int, framebufferLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_shader_module") private static function lime_vk_create_shader_module(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic + @:hlNative("lime", "hl_vk_create_shader_module") private static function lime_vk_create_shader_module(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_shader_module") private static function lime_vk_destroy_shader_module(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, shaderModuleHigh:Int, shaderModuleLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_shader_module") private static function lime_vk_destroy_shader_module(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, shaderModuleHigh:Int, shaderModuleLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_sampler") private static function lime_vk_create_sampler(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, filter:Int, addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, - maxAnisotropy:Float, compareOp:Int, minLod:Float, maxLod:Float):Dynamic + @:hlNative("lime", "hl_vk_create_sampler") private static function lime_vk_create_sampler(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, filter:Int, addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, maxAnisotropy:Float, compareOp:Int, + minLod:Float, maxLod:Float):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_sampler") private static function lime_vk_destroy_sampler(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, samplerHigh:Int, samplerLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_sampler") private static function lime_vk_destroy_sampler(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, samplerHigh:Int, samplerLow:Int):Void {} @:hlNative("lime", "hl_vk_create_descriptor_set_layout") private static function lime_vk_create_descriptor_set_layout(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bindings:hl.NativeArray):Dynamic @@ -2444,248 +2417,243 @@ class NativeCFFI } @:hlNative("lime", "hl_vk_destroy_descriptor_set_layout") private static function lime_vk_destroy_descriptor_set_layout(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_descriptor_pool") private static function lime_vk_create_descriptor_pool(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolSizes:hl.NativeArray):Dynamic + @:hlNative("lime", "hl_vk_create_descriptor_pool") private static function lime_vk_create_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolSizes:hl.NativeArray):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_descriptor_pool") private static function lime_vk_destroy_descriptor_pool(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_descriptor_pool") private static function lime_vk_destroy_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int):Void {} - @:hlNative("lime", "hl_vk_reset_descriptor_pool") private static function lime_vk_reset_descriptor_pool(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, flags:Int):Bool + @:hlNative("lime", "hl_vk_reset_descriptor_pool") private static function lime_vk_reset_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, flags:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_allocate_descriptor_set") private static function lime_vk_allocate_descriptor_set(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic + @:hlNative("lime", "hl_vk_allocate_descriptor_set") private static function lime_vk_allocate_descriptor_set(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_update_descriptor_set_image") private static function lime_vk_update_descriptor_set_image(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, - imageViewHigh:Int, imageViewLow:Int, samplerHigh:Int, samplerLow:Int, imageLayout:Int):Bool + @:hlNative("lime", "hl_vk_update_descriptor_set_image") private static function lime_vk_update_descriptor_set_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, imageViewHigh:Int, imageViewLow:Int, + samplerHigh:Int, samplerLow:Int, imageLayout:Int):Bool { return false; } @:hlNative("lime", "hl_vk_update_descriptor_set_buffer") private static function lime_vk_update_descriptor_set_buffer(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, - bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, + bufferLow:Int, offset:Int, range:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_update_descriptor_sets") private static function lime_vk_update_descriptor_sets(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, writes:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_update_descriptor_sets") private static function lime_vk_update_descriptor_sets(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, writes:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_create_pipeline_layout") private static function lime_vk_create_pipeline_layout(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setLayouts:hl.NativeArray, pushConstantStages:Int, - pushConstantSize:Int):Dynamic + @:hlNative("lime", "hl_vk_create_pipeline_layout") private static function lime_vk_create_pipeline_layout(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, setLayouts:hl.NativeArray, pushConstantStages:Int, pushConstantSize:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_pipeline_layout") private static function lime_vk_destroy_pipeline_layout(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_pipeline_layout") private static function lime_vk_destroy_pipeline_layout(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} - @:hlNative("lime", "hl_vk_create_pipeline_cache") private static function lime_vk_create_pipeline_cache(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic + @:hlNative("lime", "hl_vk_create_pipeline_cache") private static function lime_vk_create_pipeline_cache(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_pipeline_cache") private static function lime_vk_destroy_pipeline_cache(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_pipeline_cache") private static function lime_vk_destroy_pipeline_cache(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void {} - @:hlNative("lime", "hl_vk_get_pipeline_cache_data") private static function lime_vk_get_pipeline_cache_data(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int, bytes:Bytes):Bool + @:hlNative("lime", "hl_vk_get_pipeline_cache_data") private static function lime_vk_get_pipeline_cache_data(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int, bytes:Bytes):Bool { return false; } - @:hlNative("lime", "hl_vk_create_graphics_pipeline") private static function lime_vk_create_graphics_pipeline(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, - layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, fragmentShaderHigh:Int, fragmentShaderLow:Int, - state:hl.NativeArray):Dynamic + @:hlNative("lime", "hl_vk_create_graphics_pipeline") private static function lime_vk_create_graphics_pipeline(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, + vertexShaderLow:Int, fragmentShaderHigh:Int, fragmentShaderLow:Int, state:hl.NativeArray):Dynamic { return null; } - @:hlNative("lime", "hl_vk_destroy_pipeline") private static function lime_vk_destroy_pipeline(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, pipelineHigh:Int, pipelineLow:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_pipeline") private static function lime_vk_destroy_pipeline(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, pipelineHigh:Int, pipelineLow:Int):Void {} - @:hlNative("lime", "hl_vk_queue_submit_synced") private static function lime_vk_queue_submit_synced(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, - commandBufferLow:Int, state:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_queue_submit_synced") private static function lime_vk_queue_submit_synced(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_begin_render_pass") private static function lime_vk_cmd_begin_render_pass(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, - renderPassLow:Int, framebufferHigh:Int, framebufferLow:Int, state:hl.NativeArray, clear:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_begin_render_pass") private static function lime_vk_cmd_begin_render_pass(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, renderPassLow:Int, + framebufferHigh:Int, framebufferLow:Int, state:hl.NativeArray, clear:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_end_render_pass") private static function lime_vk_cmd_end_render_pass(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool + @:hlNative("lime", "hl_vk_cmd_end_render_pass") private static function lime_vk_cmd_end_render_pass(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_bind_pipeline") private static function lime_vk_cmd_bind_pipeline(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, - bindPoint:Int):Bool + @:hlNative("lime", "hl_vk_cmd_bind_pipeline") private static function lime_vk_cmd_bind_pipeline(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, bindPoint:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set") private static function lime_vk_cmd_bind_descriptor_set(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, - layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, firstSet:Int):Bool + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set") private static function lime_vk_cmd_bind_descriptor_set(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, + setLow:Int, bindPoint:Int, firstSet:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set_ex") private static function lime_vk_cmd_bind_descriptor_set_ex(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, - layoutLow:Int, setHigh:Int, setLow:Int, state:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set_ex") private static function lime_vk_cmd_bind_descriptor_set_ex(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, + setLow:Int, state:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set_dynamic_offset") private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset( - handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, - layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, dynamicOffset:Int, firstSet:Int, bindPoint:Int):Bool + @:hlNative("lime", + "hl_vk_cmd_bind_descriptor_set_dynamic_offset") private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, + layoutLow:Int, setHigh:Int, setLow:Int, dynamicOffset:Int, firstSet:Int, bindPoint:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_bind_vertex_buffer") private static function lime_vk_cmd_bind_vertex_buffer(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, - bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool + @:hlNative("lime", "hl_vk_cmd_bind_vertex_buffer") private static function lime_vk_cmd_bind_vertex_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, + offsetHigh:Int, offsetLow:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_bind_index_buffer") private static function lime_vk_cmd_bind_index_buffer(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, - bufferLow:Int, offsetHigh:Int, offsetLow:Int, indexType:Int):Bool + @:hlNative("lime", "hl_vk_cmd_bind_index_buffer") private static function lime_vk_cmd_bind_index_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, + offsetLow:Int, indexType:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_set_viewport") private static function lime_vk_cmd_set_viewport(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Float, y:Float, width:Float, - height:Float, minDepth:Float, maxDepth:Float):Bool + @:hlNative("lime", "hl_vk_cmd_set_viewport") private static function lime_vk_cmd_set_viewport(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Float, y:Float, width:Float, height:Float, minDepth:Float, + maxDepth:Float):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_set_scissor") private static function lime_vk_cmd_set_scissor(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, - height:Int):Bool + @:hlNative("lime", "hl_vk_cmd_set_scissor") private static function lime_vk_cmd_set_scissor(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, height:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_draw") private static function lime_vk_cmd_draw(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, - deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, - firstInstance:Int):Bool + @:hlNative("lime", "hl_vk_cmd_draw") private static function lime_vk_cmd_draw(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, firstInstance:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_draw_indexed") private static function lime_vk_cmd_draw_indexed(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, - firstIndex:Int, vertexOffset:Int, firstInstance:Int):Bool + @:hlNative("lime", "hl_vk_cmd_draw_indexed") private static function lime_vk_cmd_draw_indexed(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, firstIndex:Int, vertexOffset:Int, + firstInstance:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_draw_indirect") private static function lime_vk_cmd_draw_indirect(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, - offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool + @:hlNative("lime", "hl_vk_cmd_draw_indirect") private static function lime_vk_cmd_draw_indirect(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, + drawCount:Int, stride:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_draw_indexed_indirect") private static function lime_vk_cmd_draw_indexed_indirect(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, - bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool + @:hlNative("lime", "hl_vk_cmd_draw_indexed_indirect") private static function lime_vk_cmd_draw_indexed_indirect(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, + offsetLow:Int, drawCount:Int, stride:Int):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_copy_buffer") private static function lime_vk_cmd_copy_buffer(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, - destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_copy_buffer") private static function lime_vk_cmd_copy_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, + destinationLow:Int, state:hl.NativeArray):Bool { return false; } @:hlNative("lime", "hl_vk_cmd_copy_buffer_to_image_region") private static function lime_vk_cmd_copy_buffer_to_image_region(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, - bufferLow:Int, imageHigh:Int, imageLow:Int, state:hl.NativeArray):Bool + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, + imageHigh:Int, imageLow:Int, state:hl.NativeArray):Bool { return false; } @:hlNative("lime", "hl_vk_cmd_copy_image_to_buffer_region") private static function lime_vk_cmd_copy_image_to_buffer_region(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, - imageLow:Int, bufferHigh:Int, bufferLow:Int, state:hl.NativeArray):Bool + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, + bufferHigh:Int, bufferLow:Int, state:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_pipeline_barrier_image") private static function lime_vk_cmd_pipeline_barrier_image(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, - imageLow:Int, state:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_pipeline_barrier_image") private static function lime_vk_cmd_pipeline_barrier_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, + state:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_clear_color_image") private static function lime_vk_cmd_clear_color_image(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, - imageLow:Int, layout:Int, aspectMask:Int, clear:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_clear_color_image") private static function lime_vk_cmd_clear_color_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, layout:Int, + aspectMask:Int, clear:hl.NativeArray):Bool { return false; } @:hlNative("lime", "hl_vk_cmd_clear_depth_stencil_image") private static function lime_vk_cmd_clear_depth_stencil_image(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, - imageLow:Int, state:hl.NativeArray, clear:hl.NativeArray):Bool + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, + state:hl.NativeArray, clear:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_clear_attachments") private static function lime_vk_cmd_clear_attachments(handle:CFFIPointer, - instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, - state:hl.NativeArray, clear:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_clear_attachments") private static function lime_vk_cmd_clear_attachments(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:hl.NativeArray, + clear:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_blit_image") private static function lime_vk_cmd_blit_image(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, - destinationHigh:Int, destinationLow:Int, state:hl.NativeArray):Bool + @:hlNative("lime", "hl_vk_cmd_blit_image") private static function lime_vk_cmd_blit_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, + destinationLow:Int, state:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_vk_cmd_push_constants") private static function lime_vk_cmd_push_constants(handle:CFFIPointer, instanceHigh:Int, - instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, - state:hl.NativeArray, bytes:Bytes):Bool + @:hlNative("lime", "hl_vk_cmd_push_constants") private static function lime_vk_cmd_push_constants(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, state:hl.NativeArray, + bytes:Bytes):Bool { return false; } @@ -2696,8 +2664,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vulkan_renderer_create") private static function lime_vulkan_renderer_create(handle:CFFIPointer, - applicationName:String):CFFIPointer + @:hlNative("lime", "hl_vulkan_renderer_create") private static function lime_vulkan_renderer_create(handle:CFFIPointer, applicationName:String):CFFIPointer { return null; } @@ -2714,8 +2681,8 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_vulkan_renderer_set_overlay") private static function lime_vulkan_renderer_set_overlay(handle:CFFIPointer, - bytes:Bytes, width:Int, height:Int, x:Int, y:Int):Bool + @:hlNative("lime", "hl_vulkan_renderer_set_overlay") private static function lime_vulkan_renderer_set_overlay(handle:CFFIPointer, bytes:Bytes, width:Int, + height:Int, x:Int, y:Int):Bool { return false; } @@ -2799,11 +2766,9 @@ class NativeCFFI return false; } - @:hlNative("lime", "hl_window_set_text_input_enabled") private static function lime_window_set_text_input_enabled(handle:CFFIPointer, - enabled:Bool):Void {} + @:hlNative("lime", "hl_window_set_text_input_enabled") private static function lime_window_set_text_input_enabled(handle:CFFIPointer, enabled:Bool):Void {} - @:hlNative("lime", "hl_window_set_text_input_rect") private static function lime_window_set_text_input_rect(handle:CFFIPointer, - rect:Rectangle):Void {} + @:hlNative("lime", "hl_window_set_text_input_rect") private static function lime_window_set_text_input_rect(handle:CFFIPointer, rect:Rectangle):Void {} @:hlNative("lime", "hl_window_set_title") private static function lime_window_set_title(handle:CFFIPointer, title:String):String { @@ -2822,7 +2787,10 @@ class NativeCFFI @:hlNative("lime", "hl_window_warp_mouse") private static function lime_window_warp_mouse(handle:CFFIPointer, x:Int, y:Int):Void {} - @:hlNative("lime", "hl_window_get_opacity") private static function lime_window_get_opacity(handle:CFFIPointer):Float { return 0.0; } + @:hlNative("lime", "hl_window_get_opacity") private static function lime_window_get_opacity(handle:CFFIPointer):Float + { + return 0.0; + } @:hlNative("lime", "hl_window_set_opacity") private static function lime_window_set_opacity(handle:CFFIPointer, value:Float):Void {} @@ -3174,10 +3142,8 @@ class NativeCFFI private static var lime_al_get_booleanv = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_booleanv", "iio", false)); private static var lime_al_gen_buffer = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_buffer", "o", false)); private static var lime_al_gen_buffers = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_buffers", "io", false)); - private static var lime_al_get_buffer3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3f", "oio", - false)); - private static var lime_al_get_buffer3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3i", "oio", - false)); + private static var lime_al_get_buffer3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3f", "oio", false)); + private static var lime_al_get_buffer3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3i", "oio", false)); private static var lime_al_get_bufferf = new cpp.CallableInt->cpp.Float32>(cpp.Prime._loadPrime("lime", "lime_al_get_bufferf", "oif", false)); private static var lime_al_get_bufferfv = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_bufferfv", "oiio", false)); @@ -3199,10 +3165,8 @@ class NativeCFFI private static var lime_al_get_listeneri = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_al_get_listeneri", "ii", false)); private static var lime_al_get_listeneriv = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_listeneriv", "iio", false)); private static var lime_al_get_proc_address = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_al_get_proc_address", "sd", false)); - private static var lime_al_get_source3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3f", "oio", - false)); - private static var lime_al_get_source3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3i", "oio", - false)); + private static var lime_al_get_source3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3f", "oio", false)); + private static var lime_al_get_source3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3i", "oio", false)); private static var lime_al_get_sourcef = new cpp.CallableInt->cpp.Float32>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcef", "oif", false)); private static var lime_al_get_sourcefv = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcefv", "oiio", false)); @@ -3212,10 +3176,9 @@ class NativeCFFI private static var lime_al_get_string = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_string", "io", false)); private static var lime_al_is_buffer = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_buffer", "ob", false)); private static var lime_al_is_enabled = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_enabled", "ib", false)); - private static var lime_al_is_extension_present = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_extension_present", "sb", - false)); - private static var lime_alc_is_extension_present = new cpp.CallableString->Bool>(cpp.Prime._loadPrime("lime", "lime_alc_is_extension_present", - "osb", false)); + private static var lime_al_is_extension_present = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_extension_present", "sb", false)); + private static var lime_alc_is_extension_present = new cpp.CallableString->Bool>(cpp.Prime._loadPrime("lime", + "lime_alc_is_extension_present", "osb", false)); private static var lime_al_is_source = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_source", "ob", false)); private static var lime_al_listener3f = new cpp.Callablecpp.Float32->cpp.Float32->cpp.Float32->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listener3f", "ifffv", false)); @@ -3225,8 +3188,7 @@ class NativeCFFI private static var lime_al_listeneri = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listeneri", "iiv", false)); private static var lime_al_listeneriv = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listeneriv", "iov", false)); private static var lime_al_source_pause = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_pause", "ov", false)); - private static var lime_al_source_pausev = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_pausev", "iov", - false)); + private static var lime_al_source_pausev = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_pausev", "iov", false)); private static var lime_al_source_play = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_play", "ov", false)); private static var lime_al_source_playv = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_playv", "iov", false)); private static var lime_al_source_queue_buffers = new cpp.CallableInt->cpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -3254,8 +3216,7 @@ class NativeCFFI private static var lime_alc_close_device = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_alc_close_device", "ob", false)); private static var lime_alc_create_context = new cpp.Callablecpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_create_context", "ooo", false)); - private static var lime_alc_destroy_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_destroy_context", "ov", - false)); + private static var lime_alc_destroy_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_destroy_context", "ov", false)); private static var lime_alc_get_contexts_device = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_get_contexts_device", "oo", false)); private static var lime_alc_get_current_context = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_get_current_context", "o", @@ -3268,21 +3229,17 @@ class NativeCFFI false)); private static var lime_alc_open_device = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_open_device", "so", false)); private static var lime_alc_pause_device = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_pause_device", "ov", false)); - private static var lime_alc_process_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_process_context", "ov", - false)); + private static var lime_alc_process_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_process_context", "ov", false)); private static var lime_alc_resume_device = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_resume_device", "ov", false)); - private static var lime_alc_suspend_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_suspend_context", "ov", - false)); - private static var lime_alc_capture_open_device = new cpp.CallableInt->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_capture_open_device", - "siiio", false)); + private static var lime_alc_suspend_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_suspend_context", "ov", false)); + private static var lime_alc_capture_open_device = new cpp.CallableInt->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_alc_capture_open_device", "siiio", false)); private static var lime_alc_capture_close_device = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_alc_capture_close_device", "ob", false)); - private static var lime_alc_capture_start = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_start", "ov", - false)); - private static var lime_alc_capture_stop = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_stop", "ov", - false)); - private static var lime_alc_capture_samples = new cpp.Callablecpp.Object->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_samples", - "ooiv", false)); + private static var lime_alc_capture_start = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_start", "ov", false)); + private static var lime_alc_capture_stop = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_stop", "ov", false)); + private static var lime_alc_capture_samples = new cpp.Callablecpp.Object->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_alc_capture_samples", "ooiv", false)); private static var lime_al_gen_filter = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_filter", "o", false)); private static var lime_al_filteri = new cpp.CallableInt->cpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_filteri", "oiov", false)); @@ -3702,8 +3659,7 @@ class NativeCFFI @:hlNative("lime", "hl_al_source3f") private static function lime_al_source3f(source:CFFIPointer, param:Int, value1:hl.F32, value2:hl.F32, value3:hl.F32):Void {} - @:hlNative("lime", "hl_al_source3i") private static function lime_al_source3i(source:CFFIPointer, param:Int, value1:Dynamic, value2:Int, - value3:Int):Void {} + @:hlNative("lime", "hl_al_source3i") private static function lime_al_source3i(source:CFFIPointer, param:Int, value1:Dynamic, value2:Int, value3:Int):Void {} @:hlNative("lime", "hl_al_sourcef") private static function lime_al_sourcef(source:CFFIPointer, param:Int, value:hl.F32):Void {} @@ -3770,7 +3726,8 @@ class NativeCFFI @:hlNative("lime", "hl_alc_suspend_context") private static function lime_alc_suspend_context(context:ALContext):Void {} - @:hlNative("lime", "hl_alc_capture_open_device") private static function lime_alc_capture_open_device(devicename:String, frequency:Int, format:Int, buffersize:Int):CFFIPointer + @:hlNative("lime", "hl_alc_capture_open_device") private static function lime_alc_capture_open_device(devicename:String, frequency:Int, format:Int, + buffersize:Int):CFFIPointer { return null; } @@ -4088,8 +4045,7 @@ class NativeCFFI private static var lime_cairo_arc_negative = new cpp.CallableFloat->Float->Float->Float->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_arc_negative", "odddddv", false)); private static var lime_cairo_clip = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip", "ov", false)); - private static var lime_cairo_clip_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip_preserve", "ov", - false)); + private static var lime_cairo_clip_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip_preserve", "ov", false)); private static var lime_cairo_clip_extents = new cpp.CallableFloat->Float->Float->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip_extents", "oddddv", false)); private static var lime_cairo_close_path = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_close_path", "ov", false)); @@ -4100,8 +4056,7 @@ class NativeCFFI private static var lime_cairo_fill = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill", "ov", false)); private static var lime_cairo_fill_extents = new cpp.CallableFloat->Float->Float->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill_extents", "oddddv", false)); - private static var lime_cairo_fill_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill_preserve", "ov", - false)); + private static var lime_cairo_fill_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill_preserve", "ov", false)); private static var lime_cairo_get_antialias = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_cairo_get_antialias", "oi", false)); private static var lime_cairo_get_current_point = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_cairo_get_current_point", "oo", false)); @@ -4128,10 +4083,8 @@ class NativeCFFI false)); private static var lime_cairo_identity_matrix = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_identity_matrix", "ov", false)); - private static var lime_cairo_in_clip = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_clip", "oddb", - false)); - private static var lime_cairo_in_fill = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_fill", "oddb", - false)); + private static var lime_cairo_in_clip = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_clip", "oddb", false)); + private static var lime_cairo_in_fill = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_fill", "oddb", false)); private static var lime_cairo_in_stroke = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_stroke", "oddb", false)); private static var lime_cairo_line_to = new cpp.CallableFloat->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_line_to", "oddv", @@ -4163,8 +4116,7 @@ class NativeCFFI private static var lime_cairo_restore = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_restore", "ov", false)); private static var lime_cairo_rotate = new cpp.CallableFloat->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_rotate", "odv", false)); private static var lime_cairo_save = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_save", "ov", false)); - private static var lime_cairo_scale = new cpp.CallableFloat->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_scale", "oddv", - false)); + private static var lime_cairo_scale = new cpp.CallableFloat->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_scale", "oddv", false)); private static var lime_cairo_set_antialias = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_set_antialias", "oiv", false)); private static var lime_cairo_set_dash = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_set_dash", "oov", @@ -4282,8 +4234,7 @@ class NativeCFFI "lime_cairo_pattern_set_filter", "oiv", false)); private static var lime_cairo_pattern_set_matrix = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_pattern_set_matrix", "oov", false)); - private static var lime_cairo_surface_flush = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_surface_flush", "ov", - false)); + private static var lime_cairo_surface_flush = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_surface_flush", "ov", false)); #end #end #if (neko || cppia) @@ -4428,8 +4379,8 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_cairo_curve_to") private static function lime_cairo_curve_to(handle:CFFIPointer, x1:Float, y1:Float, x2:Float, y2:Float, - x3:Float, y3:Float):Void {} + @:hlNative("lime", "hl_cairo_curve_to") private static function lime_cairo_curve_to(handle:CFFIPointer, x1:Float, y1:Float, x2:Float, y2:Float, x3:Float, + y3:Float):Void {} @:hlNative("lime", "hl_cairo_fill") private static function lime_cairo_fill(handle:CFFIPointer):Void {} @@ -4569,8 +4520,7 @@ class NativeCFFI @:hlNative("lime", "hl_cairo_push_group") private static function lime_cairo_push_group(handle:CFFIPointer):Void {} - @:hlNative("lime", "hl_cairo_push_group_with_content") private static function lime_cairo_push_group_with_content(handle:CFFIPointer, - content:Int):Void {} + @:hlNative("lime", "hl_cairo_push_group_with_content") private static function lime_cairo_push_group_with_content(handle:CFFIPointer, content:Int):Void {} @:hlNative("lime", "hl_cairo_rectangle") private static function lime_cairo_rectangle(handle:CFFIPointer, x:Float, y:Float, width:Float, height:Float):Void {} @@ -4623,8 +4573,8 @@ class NativeCFFI @:hlNative("lime", "hl_cairo_set_source_rgba") private static function lime_cairo_set_source_rgba(handle:CFFIPointer, r:Float, g:Float, b:Float, a:Float):Void {} - @:hlNative("lime", "hl_cairo_set_source_surface") private static function lime_cairo_set_source_surface(handle:CFFIPointer, surface:CFFIPointer, - x:Float, y:Float):Void {} + @:hlNative("lime", "hl_cairo_set_source_surface") private static function lime_cairo_set_source_surface(handle:CFFIPointer, surface:CFFIPointer, x:Float, + y:Float):Void {} @:hlNative("lime", "hl_cairo_set_tolerance") private static function lime_cairo_set_tolerance(handle:CFFIPointer, tolerance:Float):Void {} @@ -4692,14 +4642,12 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_cairo_font_options_set_antialias") private static function lime_cairo_font_options_set_antialias(handle:CFFIPointer, - v:Int):Void {} + @:hlNative("lime", "hl_cairo_font_options_set_antialias") private static function lime_cairo_font_options_set_antialias(handle:CFFIPointer, v:Int):Void {} @:hlNative("lime", "hl_cairo_font_options_set_hint_metrics") private static function lime_cairo_font_options_set_hint_metrics(handle:CFFIPointer, v:Int):Void {} - @:hlNative("lime", "hl_cairo_font_options_set_hint_style") private static function lime_cairo_font_options_set_hint_style(handle:CFFIPointer, - v:Int):Void {} + @:hlNative("lime", "hl_cairo_font_options_set_hint_style") private static function lime_cairo_font_options_set_hint_style(handle:CFFIPointer, v:Int):Void {} @:hlNative("lime", "hl_cairo_font_options_set_subpixel_order") private static function lime_cairo_font_options_set_subpixel_order(handle:CFFIPointer, v:Int):Void {} @@ -4709,8 +4657,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_cairo_image_surface_create") private static function lime_cairo_image_surface_create(format:Int, width:Int, - height:Int):CFFIPointer + @:hlNative("lime", "hl_cairo_image_surface_create") private static function lime_cairo_image_surface_create(format:Int, width:Int, height:Int):CFFIPointer { return null; } @@ -4746,8 +4693,8 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_cairo_pattern_add_color_stop_rgb") private static function lime_cairo_pattern_add_color_stop_rgb(handle:CFFIPointer, - offset:Float, red:Float, green:Float, blue:Float):Void {} + @:hlNative("lime", "hl_cairo_pattern_add_color_stop_rgb") private static function lime_cairo_pattern_add_color_stop_rgb(handle:CFFIPointer, offset:Float, + red:Float, green:Float, blue:Float):Void {} @:hlNative("lime", "hl_cairo_pattern_add_color_stop_rgba") private static function lime_cairo_pattern_add_color_stop_rgba(handle:CFFIPointer, offset:Float, red:Float, green:Float, blue:Float, alpha:Float):Void {} @@ -5867,8 +5814,7 @@ class NativeCFFI private static var lime_gl_get_vertex_attribi = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribi", "iii", false)); private static var lime_gl_get_vertex_attribiv = new cpp.CallableInt->lime.utils.DataPointer->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribiv", "iidv", false)); - private static var lime_gl_get_vertex_attribii = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribii", "iii", - false)); + private static var lime_gl_get_vertex_attribii = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribii", "iii", false)); private static var lime_gl_get_vertex_attribiiv = new cpp.CallableInt->lime.utils.DataPointer->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribiiv", "iidv", false)); private static var lime_gl_get_vertex_attribiui = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribiui", "iii", @@ -6377,8 +6323,7 @@ class NativeCFFI @:hlNative("lime", "hl_gl_buffer_data") private static function lime_gl_buffer_data(target:Int, size:Int, srcData:DataPointer, usage:Int):Void {} - @:hlNative("lime", "hl_gl_buffer_sub_data") private static function lime_gl_buffer_sub_data(target:Int, offset:Int, size:Int, - srcData:DataPointer):Void {} + @:hlNative("lime", "hl_gl_buffer_sub_data") private static function lime_gl_buffer_sub_data(target:Int, offset:Int, size:Int, srcData:DataPointer):Void {} @:hlNative("lime", "hl_gl_check_framebuffer_status") private static function lime_gl_check_framebuffer_status(target:Int):Int { @@ -6395,8 +6340,7 @@ class NativeCFFI @:hlNative("lime", "hl_gl_clear_bufferuiv") private static function lime_gl_clear_bufferuiv(buffer:Int, drawBuffer:Int, data:DataPointer):Void {} - @:hlNative("lime", "hl_gl_client_wait_sync") private static function lime_gl_client_wait_sync(sync:CFFIPointer, flags:Int, timeoutA:Int, - timeoutB:Int):Int + @:hlNative("lime", "hl_gl_client_wait_sync") private static function lime_gl_client_wait_sync(sync:CFFIPointer, flags:Int, timeoutA:Int, timeoutB:Int):Int { return 0; } @@ -6619,8 +6563,7 @@ class NativeCFFI @:hlNative("lime", "hl_gl_get_buffer_parameteri64v") private static function lime_gl_get_buffer_parameteri64v(target:Int, index:Int, params:DataPointer):Void {} - @:hlNative("lime", "hl_gl_get_buffer_parameteriv") private static function lime_gl_get_buffer_parameteriv(target:Int, pname:Int, - params:DataPointer):Void {} + @:hlNative("lime", "hl_gl_get_buffer_parameteriv") private static function lime_gl_get_buffer_parameteriv(target:Int, pname:Int, params:DataPointer):Void {} @:hlNative("lime", "hl_gl_get_buffer_pointerv") private static function lime_gl_get_buffer_pointerv(target:Int, pname:Int):DataPointer { @@ -6982,8 +6925,8 @@ class NativeCFFI @:hlNative("lime", "hl_gl_scissor") private static function lime_gl_scissor(x:Int, y:Int, width:Int, height:Int):Void {} - @:hlNative("lime", "hl_gl_shader_binary") private static function lime_gl_shader_binary(shaders:hl.NativeArray, binaryformat:Int, - binary:DataPointer, length:Int):Void {} + @:hlNative("lime", "hl_gl_shader_binary") private static function lime_gl_shader_binary(shaders:hl.NativeArray, binaryformat:Int, binary:DataPointer, + length:Int):Void {} @:hlNative("lime", "hl_gl_shader_source") private static function lime_gl_shader_source(shader:Int, source:String):Void {} @@ -7015,8 +6958,8 @@ class NativeCFFI @:hlNative("lime", "hl_gl_tex_storage_3d") private static function lime_gl_tex_storage_3d(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int):Void {} - @:hlNative("lime", "hl_gl_tex_sub_image_2d") private static function lime_gl_tex_sub_image_2d(target:Int, level:Int, xoffset:Int, yoffset:Int, - width:Int, height:Int, format:Int, type:Int, data:DataPointer):Void {} + @:hlNative("lime", "hl_gl_tex_sub_image_2d") private static function lime_gl_tex_sub_image_2d(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, + height:Int, format:Int, type:Int, data:DataPointer):Void {} @:hlNative("lime", "hl_gl_tex_sub_image_3d") private static function lime_gl_tex_sub_image_3d(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, depth:Int, format:Int, type:Int, data:DataPointer):Void {} @@ -7387,8 +7330,7 @@ class NativeCFFI private static var lime_hb_blob_is_immutable = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_hb_blob_is_immutable", "ob", false)); private static var lime_hb_blob_make_immutable = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_blob_make_immutable", "ov", false)); - private static var lime_hb_buffer_add = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_buffer_add", "oiiv", - false)); + private static var lime_hb_buffer_add = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_buffer_add", "oiiv", false)); private static var lime_hb_buffer_add_hxstring = new cpp.CallableString->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_buffer_add_hxstring", "osiiv", false)); private static var lime_hb_buffer_add_codepoints = new cpp.Callablelime.utils.DataPointer->Int->Int->Int-> @@ -7475,8 +7417,7 @@ class NativeCFFI "oiv", false)); private static var lime_hb_face_set_index = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_face_set_index", "oiv", false)); - private static var lime_hb_face_set_upem = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_face_set_upem", "oiv", - false)); + private static var lime_hb_face_set_upem = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_face_set_upem", "oiv", false)); private static var lime_hb_feature_from_string = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_feature_from_string", "so", false)); private static var lime_hb_feature_to_string = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_feature_to_string", "oo", @@ -7494,8 +7435,7 @@ class NativeCFFI "lime_hb_font_get_glyph_kerning_for_direction", "oiiio", false)); private static var lime_hb_font_get_glyph_origin_for_direction = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_glyph_origin_for_direction", "oiio", false)); - private static var lime_hb_font_get_parent = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_parent", "oo", - false)); + private static var lime_hb_font_get_parent = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_parent", "oo", false)); private static var lime_hb_font_get_ppem = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_ppem", "oo", false)); private static var lime_hb_font_get_scale = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_scale", "oo", false)); private static var lime_hb_font_glyph_from_string = new cpp.CallableString->Int>(cpp.Prime._loadPrime("lime", @@ -7839,8 +7779,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_hb_buffer_set_cluster_level") private static function lime_hb_buffer_set_cluster_level(buffer:CFFIPointer, - clusterLevel:Int):Void {} + @:hlNative("lime", "hl_hb_buffer_set_cluster_level") private static function lime_hb_buffer_set_cluster_level(buffer:CFFIPointer, clusterLevel:Int):Void {} @:hlNative("lime", "hl_hb_buffer_set_content_type") private static function lime_hb_buffer_set_content_type(buffer:CFFIPointer, contentType:Int):Void {} @@ -7999,8 +7938,8 @@ class NativeCFFI @:hlNative("lime", "hl_hb_font_set_scale") private static function lime_hb_font_set_scale(font:CFFIPointer, xScale:Int, yScale:Int):Void {} @:hlNative("lime", - "hl_hb_font_subtract_glyph_origin_for_direction") private static function lime_hb_font_subtract_glyph_origin_for_direction(font:CFFIPointer, - glyph:Int, direction:Int, x:Int, y:Int):Void {} + "hl_hb_font_subtract_glyph_origin_for_direction") private static function lime_hb_font_subtract_glyph_origin_for_direction(font:CFFIPointer, glyph:Int, + direction:Int, x:Int, y:Int):Void {} @:hlNative("lime", "hl_hb_ft_font_create") private static function lime_hb_ft_font_create(font:CFFIPointer):CFFIPointer { @@ -8123,8 +8062,7 @@ class NativeCFFI @:hlNative("lime", "hl_hb_set_union") private static function lime_hb_set_union(set:CFFIPointer, other:CFFIPointer):Void {} - @:hlNative("lime", "hl_hb_shape") private static function lime_hb_shape(font:CFFIPointer, buffer:CFFIPointer, - features:hl.NativeArray):Void {} + @:hlNative("lime", "hl_hb_shape") private static function lime_hb_shape(font:CFFIPointer, buffer:CFFIPointer, features:hl.NativeArray):Void {} #end #end #if (lime_cffi && !macro && lime_vorbis) @@ -8321,8 +8259,7 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_vorbis_file_pcm_seek_lap") private static function lime_vorbis_file_pcm_seek_lap(vorbisFile:CFFIPointer, posLow:Int, - posHigh:Int):Int + @:hlNative("lime", "hl_vorbis_file_pcm_seek_lap") private static function lime_vorbis_file_pcm_seek_lap(vorbisFile:CFFIPointer, posLow:Int, posHigh:Int):Int { return 0; } @@ -8344,8 +8281,7 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_vorbis_file_raw_seek_lap") private static function lime_vorbis_file_raw_seek_lap(vorbisFile:CFFIPointer, posLow:Int, - posHigh:Int):Int + @:hlNative("lime", "hl_vorbis_file_raw_seek_lap") private static function lime_vorbis_file_raw_seek_lap(vorbisFile:CFFIPointer, posLow:Int, posHigh:Int):Int { return 0; } @@ -8429,4 +8365,3 @@ class NativeCFFI #end #end } - diff --git a/src/lime/_internal/backend/native/NativeHTTPRequest.hx b/src/lime/_internal/backend/native/NativeHTTPRequest.hx index 026d23f963..c09d041288 100644 --- a/src/lime/_internal/backend/native/NativeHTTPRequest.hx +++ b/src/lime/_internal/backend/native/NativeHTTPRequest.hx @@ -361,7 +361,8 @@ class NativeHTTPRequest return promise.future; } - private function buildBuffer() { + private function buildBuffer() + { bytes = buffer.getBytes(); return bytes; } diff --git a/src/lime/_internal/backend/native/NativeWindow.hx b/src/lime/_internal/backend/native/NativeWindow.hx index f548ae1c5f..6fc4344a59 100644 --- a/src/lime/_internal/backend/native/NativeWindow.hx +++ b/src/lime/_internal/backend/native/NativeWindow.hx @@ -173,7 +173,8 @@ class NativeWindow contextAttributes.hardware = true; context.vulkan = new VulkanRenderContext(handle); context.type = VULKAN; - context.version = Reflect.hasField(contextAttributes, "version") && contextAttributes.version != null ? contextAttributes.version : ""; + context.version = Reflect.hasField(contextAttributes, "version") + && contextAttributes.version != null ? contextAttributes.version : ""; default: useHardware = false; diff --git a/src/lime/_internal/graphics/ImageDataUtil.hx b/src/lime/_internal/graphics/ImageDataUtil.hx index 5837151cc5..6cf41a857f 100644 --- a/src/lime/_internal/graphics/ImageDataUtil.hx +++ b/src/lime/_internal/graphics/ImageDataUtil.hx @@ -238,11 +238,7 @@ class ImageDataUtil var srcPremultiplied = sourceImage.buffer.premultiplied; var destPremultiplied = image.buffer.premultiplied; - var srcPosition, - destPosition, - srcPixel:RGBA = 0, - destPixel:RGBA = 0, - value = 0; + var srcPosition, destPosition, srcPixel:RGBA = 0, destPixel:RGBA = 0, value = 0; for (y in 0...destView.height) { @@ -601,12 +597,7 @@ class ImageDataUtil queue.push(x); queue.push(y); - var curPointX, - curPointY, - nextPointX, - nextPointY, - nextPointOffset, - readColor:RGBA = 0; + var curPointX, curPointY, nextPointX, nextPointY, nextPointOffset, readColor:RGBA = 0; while (queue.length > 0) { @@ -1000,18 +991,9 @@ class ImageDataUtil var data = image.data; var newData = newBuffer.data; - var sourceIndex:Int, - sourceIndexX:Int, - sourceIndexY:Int, - sourceIndexXY:Int, - index:Int; + var sourceIndex:Int, sourceIndexX:Int, sourceIndexY:Int, sourceIndexXY:Int, index:Int; var sourceX:Int, sourceY:Int; - var u:Float, - v:Float, - uRatio:Float, - vRatio:Float, - uOpposite:Float, - vOpposite:Float; + var u:Float, v:Float, uRatio:Float, vRatio:Float, uOpposite:Float, vOpposite:Float; for (y in 0...newHeight) { @@ -1361,13 +1343,7 @@ class ImageDataUtil var srcPremultiplied = sourceImage.buffer.premultiplied; var destPremultiplied = image.buffer.premultiplied; - var srcPosition, - destPosition, - srcPixel:RGBA = 0, - destPixel:RGBA = 0, - pixelMask:UInt, - test:Bool, - value:Int; + var srcPosition, destPosition, srcPixel:RGBA = 0, destPixel:RGBA = 0, pixelMask:UInt, test:Bool, value:Int; for (y in 0...destView.height) { @@ -1774,8 +1750,7 @@ private class ImageDataView } } -@:noCompletion @:dox(hide) -#if (haxe_ver >= 4.0) private enum #else @:enum private #end abstract ThresholdOperation(Int) from Int to Int +@:noCompletion @:dox(hide) #if (haxe_ver >= 4.0) private enum #else @:enum private #end abstract ThresholdOperation(Int) from Int to Int { var NOT_EQUALS = 0; var EQUALS = 1; diff --git a/src/lime/_internal/macros/AssetsMacro.hx b/src/lime/_internal/macros/AssetsMacro.hx index a5b403ee86..390cc4c209 100644 --- a/src/lime/_internal/macros/AssetsMacro.hx +++ b/src/lime/_internal/macros/AssetsMacro.hx @@ -41,18 +41,17 @@ class AssetsMacro } } - var superCall = Context.defined("html5") ? macro super(bytes.b.buffer) - : Context.defined("hl") ? macro super(bytes.b, bytes.length) - : macro super(bytes.length, bytes.b); + var superCall = Context.defined("html5") ? macro super(bytes.b.buffer) : Context.defined("hl") ? macro super(bytes.b, + bytes.length) : macro super(bytes.length, bytes.b); var definition = macro class Temp - { - public function new(?length:Int, ?bytesData:haxe.io.BytesData) { - var bytes = haxe.Resource.getBytes(resourceName); - $superCall; - } - }; + public function new(?length:Int, ?bytesData:haxe.io.BytesData) + { + var bytes = haxe.Resource.getBytes(resourceName); + $superCall; + } + }; fields.push(definition.fields[0]); @@ -65,15 +64,15 @@ class AssetsMacro if (fields == null) return null; var definition = macro class Temp - { - public function new(?length:Int = 0) { - super(); + public function new(?length:Int = 0) + { + super(); - var bytes = haxe.Resource.getBytes(resourceName); - __fromBytes(bytes); - } - }; + var bytes = haxe.Resource.getBytes(resourceName); + __fromBytes(bytes); + } + }; fields.push(definition.fields[0]); @@ -112,11 +111,7 @@ class AssetsMacro } var bytes = File.getBytes(path); - var resourceName = "__ASSET__" - + metaName - + "_" - + (classType.pack.length > 0 ? classType.pack.join("_") + "_" : "") - + classType.name; + var resourceName = "__ASSET__" + metaName + "_" + (classType.pack.length > 0 ? classType.pack.join("_") + "_" : "") + classType.name; if (Context.getResources().exists(resourceName)) { @@ -137,9 +132,9 @@ class AssetsMacro } var definition = macro class Temp - { - private static inline var resourceType:String = $v{ resourceType }; - }; + { + private static inline var resourceType:String = $v{resourceType}; + }; fields.push(definition.fields[0]); @@ -152,9 +147,9 @@ class AssetsMacro } var definition = macro class Temp - { - private static inline var resourceName:String = $v{ resourceName }; - }; + { + private static inline var resourceName:String = $v{resourceName}; + }; fields.push(definition.fields[0]); @@ -226,16 +221,16 @@ class AssetsMacro } var definition = macro class Temp - { - private static var resourceName:String = $v{ resourceName }; - - public function new() { - super(); + private static var resourceName:String = $v{resourceName}; - __fromBytes(haxe.Resource.getBytes(resourceName)); - } - }; + public function new() + { + super(); + + __fromBytes(haxe.Resource.getBytes(resourceName)); + } + }; fields.push(definition.fields[0]); fields.push(definition.fields[1]); @@ -255,56 +250,53 @@ class AssetsMacro if (Context.defined("html5")) { definition = macro class Temp - { - public static var preload:js.html.Image; - - public function new(?buffer:lime.graphics.ImageBuffer, - ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, - ?color:Null, ?type:lime.graphics.ImageType, - ?onload:Dynamic = true) { - super(); + public static var preload:js.html.Image; - if (preload != null) + public function new(?buffer:lime.graphics.ImageBuffer, ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, ?color:Null, + ?type:lime.graphics.ImageType, ?onload:Dynamic = true) { - var buffer = new lime.graphics.ImageBuffer(); - buffer.__srcImage = preload; - buffer.width = preload.width; - buffer.width = preload.height; + super(); - __fromImageBuffer(buffer); - } - else - { - __fromBase64(haxe.Resource.getString(resourceName), resourceType, function(image) + if (preload != null) { - if (preload == null) - { - preload = image.buffer.__srcImage; - } + var buffer = new lime.graphics.ImageBuffer(); + buffer.__srcImage = preload; + buffer.width = preload.width; + buffer.width = preload.height; - if (onload != null) + __fromImageBuffer(buffer); + } + else + { + __fromBase64(haxe.Resource.getString(resourceName), resourceType, function(image) { - onload(image); - } - }); + if (preload == null) + { + preload = image.buffer.__srcImage; + } + + if (onload != null) + { + onload(image); + } + }); + } } - } - }; + }; } else { definition = macro class Temp - { - public function new(?buffer:lime.graphics.ImageBuffer, - ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, - ?color:Null, ?type:lime.graphics.ImageType) { - super(); + public function new(?buffer:lime.graphics.ImageBuffer, ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, ?color:Null, + ?type:lime.graphics.ImageType) + { + super(); - __fromBytes(haxe.Resource.getBytes(resourceName), null); - } - }; + __fromBytes(haxe.Resource.getBytes(resourceName), null); + } + }; } for (field in definition.fields) @@ -319,21 +311,18 @@ class AssetsMacro { var fields = embedData(":sound"); // CFFILoader.h(248) : NOT Implemented:api_buffer_data - if (fields == null || Context.defined("html5") || !Context.defined("openfl")) - return null; + if (fields == null || Context.defined("html5") || !Context.defined("openfl")) return null; var definition = macro class Temp - { - public function new(?stream:openfl.net.URLRequest, - ?context:openfl.media.SoundLoaderContext, - ?forcePlayAsMusic:Bool = false) { - super(); + public function new(?stream:openfl.net.URLRequest, ?context:openfl.media.SoundLoaderContext, ?forcePlayAsMusic:Bool = false) + { + super(); - var byteArray = openfl.utils.ByteArray.fromBytes(haxe.Resource.getBytes(resourceName)); - loadCompressedDataFromByteArray(byteArray, byteArray.length, forcePlayAsMusic); - } - }; + var byteArray = openfl.utils.ByteArray.fromBytes(haxe.Resource.getBytes(resourceName)); + loadCompressedDataFromByteArray(byteArray, byteArray.length, forcePlayAsMusic); + } + }; fields.push(definition.fields[0]); diff --git a/src/lime/_internal/macros/CFFIMacro.hx b/src/lime/_internal/macros/CFFIMacro.hx index 5b65675863..51430f550d 100644 --- a/src/lime/_internal/macros/CFFIMacro.hx +++ b/src/lime/_internal/macros/CFFIMacro.hx @@ -183,7 +183,7 @@ class CFFIMacro case "cpp.Float32": if (useCPPTypes) { - typeArgs.push({name: arg.name, opt: false, t: (macro:cpp.Float32).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :cpp.Float32).toType()}); } else { @@ -207,7 +207,7 @@ class CFFIMacro case "Void", "cpp.Void": if (useCPPTypes) { - typeArgs.push({name: arg.name, opt: false, t: (macro:cpp.Void).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :cpp.Void).toType()}); } else { @@ -219,11 +219,11 @@ class CFFIMacro default: if (useCPPTypes) { - typeArgs.push({name: arg.name, opt: false, t: (macro:cpp.Object).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :cpp.Object).toType()}); } else { - typeArgs.push({name: arg.name, opt: false, t: (macro:Dynamic).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :Dynamic).toType()}); } typeSignature += "o"; @@ -243,7 +243,7 @@ class CFFIMacro case "cpp.Float32": if (useCPPTypes) { - typeResult = (macro:cpp.Float32).toType(); + typeResult = (macro :cpp.Float32).toType(); } else { @@ -267,7 +267,7 @@ class CFFIMacro case "Void", "cpp.Void": if (useCPPTypes) { - typeResult = (macro:cpp.Void).toType(); + typeResult = (macro :cpp.Void).toType(); } else { @@ -279,11 +279,11 @@ class CFFIMacro default: if (useCPPTypes) { - typeResult = (macro:cpp.Object).toType(); + typeResult = (macro :cpp.Object).toType(); } else { - typeResult = (macro:Dynamic).toType(); + typeResult = (macro :Dynamic).toType(); } typeSignature += "o"; diff --git a/src/lime/_internal/macros/EventMacro.hx b/src/lime/_internal/macros/EventMacro.hx index 4071ce5841..eae7aad1b2 100644 --- a/src/lime/_internal/macros/EventMacro.hx +++ b/src/lime/_internal/macros/EventMacro.hx @@ -29,8 +29,8 @@ class EventMacro return null; case TInst(_, paramTypes): - Context.fatalError("Expected only one type parameter. Did you mean Event<" - + paramTypes.map(haxe.macro.TypeTools.toString).join(" -> ") + ">?", Context.currentPos()); + Context.fatalError("Expected only one type parameter. Did you mean Event<" + paramTypes.map(haxe.macro.TypeTools.toString).join(" -> ") + ">?", + Context.currentPos()); return null; default: @@ -200,7 +200,7 @@ class EventMacro args: args, expr: dispatch, params: [], - ret: macro:Void + ret: macro :Void }), pos: pos }); @@ -210,10 +210,11 @@ class EventMacro access: [APublic], kind: FFun( { - args: [{name: "timestamp", type: macro:Int}].concat(args), + args: [ + {name: "timestamp", type: macro :Int}].concat(args), expr: timestampDispatch, params: [], - ret: macro:Void + ret: macro :Void }), meta: [ {name: ":dox", params: [macro hide], pos: pos}, diff --git a/src/lime/_internal/macros/HTTPRequestMacro.hx b/src/lime/_internal/macros/HTTPRequestMacro.hx index f862fe6ead..e4532738e7 100644 --- a/src/lime/_internal/macros/HTTPRequestMacro.hx +++ b/src/lime/_internal/macros/HTTPRequestMacro.hx @@ -129,11 +129,11 @@ class HTTPRequestMacro kind: FFun( { args: [ - {name: "uri", type: macro:String, opt: true}], + {name: "uri", type: macro :String, opt: true}], expr: macro {super(uri);}, params: [], - ret: macro:Void + ret: macro :Void }), pos: Context.currentPos() }, @@ -143,7 +143,7 @@ class HTTPRequestMacro kind: FFun( { args: [ - {name: "bytes", type: macro:haxe.io.Bytes}], + {name: "bytes", type: macro :haxe.io.Bytes}], expr: Context.parse("return " + typeString + ".fromBytes (bytes)", pos), params: [], ret: paramType.toComplexType() diff --git a/src/lime/app/Event.hx b/src/lime/app/Event.hx index 5c4b0a9daa..bdca9898f0 100644 --- a/src/lime/app/Event.hx +++ b/src/lime/app/Event.hx @@ -97,6 +97,7 @@ class Event takes two `Int` arguments, like `dispatch (1, 2);` **/ public var dispatch:Dynamic; + @:noCompletion @:dox(hide) public var __dispatchWithTimestamp:Dynamic; // macro public function dispatch (ethis:Expr, args:Array):Void { diff --git a/src/lime/graphics/Image.hx b/src/lime/graphics/Image.hx index 79c79ac326..5bfd568619 100644 --- a/src/lime/graphics/Image.hx +++ b/src/lime/graphics/Image.hx @@ -59,7 +59,6 @@ import format.tools.Deflate; import sys.io.File; #end #end - /** `Image` is a convenience class for working with bitmap images in Lime. @@ -395,8 +394,7 @@ class Image sourceRect.offset(sourceImage.offsetX, sourceImage.offsetY); destPoint.offset(offsetX, offsetY); - buffer.__srcBitmapData.copyChannel(sourceImage.buffer.src, sourceRect.__toFlashRectangle(), destPoint.__toFlashPoint(), srcChannel, - dstChannel); + buffer.__srcBitmapData.copyChannel(sourceImage.buffer.src, sourceRect.__toFlashRectangle(), destPoint.__toFlashPoint(), srcChannel, dstChannel); default: } diff --git a/src/lime/graphics/OpenGLES3RenderContext.hx b/src/lime/graphics/OpenGLES3RenderContext.hx index 8c0c21ae7d..2ab458e81c 100644 --- a/src/lime/graphics/OpenGLES3RenderContext.hx +++ b/src/lime/graphics/OpenGLES3RenderContext.hx @@ -9,7 +9,6 @@ import lime.graphics.opengl.*; import lime.utils.DataPointer; import lime.utils.Float32Array; import lime.utils.Int32Array; - /** The `OpenGLES3RenderContext` allows access to OpenGL ES 3.0 features when OpenGL or OpenGL ES is the render context type of the `Window`, and the current context supports diff --git a/src/lime/graphics/VulkanRenderContext.hx b/src/lime/graphics/VulkanRenderContext.hx index 39e2e3c1b6..b9b6412056 100644 --- a/src/lime/graphics/VulkanRenderContext.hx +++ b/src/lime/graphics/VulkanRenderContext.hx @@ -9,7 +9,6 @@ import lime.system.CFFI; #if (!lime_doc_gen || lime_cffi) import lime.system.CFFIPointer; #end - #if hl import hl.Bytes as HLBytes; import hl.NativeArray; diff --git a/src/lime/graphics/WebGL2RenderContext.hx b/src/lime/graphics/WebGL2RenderContext.hx index 3fdc913647..802b3fa5f0 100644 --- a/src/lime/graphics/WebGL2RenderContext.hx +++ b/src/lime/graphics/WebGL2RenderContext.hx @@ -301,15 +301,14 @@ import lime.utils.UInt32Array; **/ @:access(lime.graphics.RenderContext) #if !doc_gen -@:transitive -abstract WebGL2RenderContext(OpenGLRenderContext) from OpenGLRenderContext to OpenGLRenderContext +@:transitive abstract WebGL2RenderContext(OpenGLRenderContext) from OpenGLRenderContext to OpenGLRenderContext { #else abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic { #end - private static var __tempPointer = new BytePointer(); + public var DEPTH_BUFFER_BIT(get, never):Int; public var STENCIL_BUFFER_BIT(get, never):Int; public var COLOR_BUFFER_BIT(get, never):Int; @@ -3766,10 +3765,9 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #end { var size = (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.bufferData(target, size, __tempPointer, usage); - } + } #if !lime_webgl public inline function bufferSubData(target:Int, offset:Int, srcData:ArrayBufferView, srcOffset:Int = 0, ?length:Int):Void @@ -3778,7 +3776,6 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #end { var size = (length != null) ? length : (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.bufferSubData(target, offset, size, __tempPointer); } @@ -3849,21 +3846,18 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #if !lime_webgl public function compressedTexImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, srcData:ArrayBufferView, srcOffset:Int = 0, - ?srcLengthOverride:Int):Void + ?srcLengthOverride:Int):Void #else - public inline function compressedTexImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, srcData:Dynamic, - ?srcOffset:Int, - ?srcLengthOverride:Int):Void + public inline function compressedTexImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, srcData:Dynamic, ?srcOffset:Int, + ?srcLengthOverride:Int):Void #end { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, __tempPointer); } - public function compressedTexImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, - srcData:ArrayBufferView, + public function compressedTexImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, srcData:ArrayBufferView, srcOffset:Int = 0, ?srcLengthOverride:Int):Void { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; @@ -3872,23 +3866,19 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, - srcData:ArrayBufferView, - srcOffset:Int = 0, ?srcLengthOverride:Int):Void + public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, srcData:ArrayBufferView, + srcOffset:Int = 0, ?srcLengthOverride:Int):Void #else - public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, - srcData:Dynamic, - ?srcOffset:Int, ?srcLengthOverride:Int):Void + public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, srcData:Dynamic, + ?srcOffset:Int, ?srcLengthOverride:Int):Void #end { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, __tempPointer); } - public inline function compressedTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, - depth:Int, format:Int, + public inline function compressedTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, depth:Int, format:Int, srcData:ArrayBufferView, srcOffset:Int = 0, ?srcLengthOverride:Int):Void { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; @@ -3911,8 +3901,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); } - public inline function copyTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, x:Int, y:Int, width:Int, - height:Int):Void + public inline function copyTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, x:Int, y:Int, width:Int, height:Int):Void { this.copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); } @@ -4195,7 +4184,6 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic { #if !js var size = (length != null) ? length : (dstData != null) ? dstData.length : 0; - this.getBufferSubData(target, srcByteOffset + srcOffset, size, dstData); #end } @@ -4451,8 +4439,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function readPixels(x:Int, y:Int, width:Int, height:Int, format:Int, type:Int, pixels:ArrayBufferView, - dstOffset:Int = 0):Void + public inline function readPixels(x:Int, y:Int, width:Int, height:Int, format:Int, type:Int, pixels:ArrayBufferView, dstOffset:Int = 0):Void #else public inline function readPixels(x:Int, y:Int, width:Int, height:Int, format:Int, type:Int, pixels:Dynamic, ?dstOffset:Int):Void #end @@ -4532,13 +4519,13 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, format:Int, - type:Int, srcData:ArrayBufferView, - srcOffset:Int = 0):Void + public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, format:Int, type:Int, + srcData:ArrayBufferView, + srcOffset:Int = 0):Void #else - public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Dynamic, ?format:Int, - ?type:Int, ?srcData:Dynamic, - ?srcOffset:Int):Void + public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Dynamic, ?format:Int, ?type:Int, + ?srcData:Dynamic, + ?srcOffset:Int):Void #end { #if !lime_webgl @@ -4547,8 +4534,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #end } - public inline function texImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, - format:Int, type:Int, + public inline function texImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, format:Int, type:Int, srcData:ArrayBufferView, srcOffset:Int = 0):Void { __tempPointer.set(srcData, srcOffset); @@ -4576,21 +4562,18 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, - type:Int, srcData:ArrayBufferView, - srcOffset:Int = 0):Void + public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, type:Int, srcData:ArrayBufferView, + srcOffset:Int = 0):Void #else - public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Dynamic, - ?type:Int, ?srcData:Dynamic, - ?srcOffset:Int):Void + public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Dynamic, ?type:Int, ?srcData:Dynamic, + ?srcOffset:Int):Void #end { __tempPointer.set(srcData, srcOffset); this.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, __tempPointer); } - public inline function texSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, - depth:Int, format:Int, type:Int, + public inline function texSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, depth:Int, format:Int, type:Int, srcData:ArrayBufferView, srcOffset:Int = 0):Void { __tempPointer.set(srcData, srcOffset); @@ -4673,8 +4656,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniform2ui(location, v0, v1); } - public inline function uniform2uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform2uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, ?srcLength:Int):Void { this.uniform2uiv(location, v != null ? v.length >> 1 : 0, v); } @@ -4685,11 +4667,9 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function uniform3fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform3fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform3fv(location, v != null ? Std.int(v.length / 3) : 0, v); @@ -4701,11 +4681,9 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function uniform3iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform3iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform3iv(location, v != null ? Std.int(v.length / 3) : 0, v); @@ -4716,82 +4694,68 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniform3ui(location, v0, v1, v2); } - public inline function uniform3uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, ?srcLength:Int):Void { this.uniform3uiv(location, v != null ? Std.int(v.length / 3) : 0, v); } - public inline function uniform4f(location:GLUniformLocation, v0:Float, v1:Float, v2:Float, - v3:Float):Void + public inline function uniform4f(location:GLUniformLocation, v0:Float, v1:Float, v2:Float, v3:Float):Void { this.uniform4f(location, v0, v1, v2, v3); } #if !lime_webgl - public inline function uniform4fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform4fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform4fv(location, v != null ? v.length >> 2 : 0, v); } - public inline function uniform4i(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, - v3:Int):Void + public inline function uniform4i(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, v3:Int):Void { this.uniform4i(location, v0, v1, v2, v3); } #if !lime_webgl - public inline function uniform4iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform4iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform4iv(location, v != null ? v.length >> 2 : 0, v); } - public inline function uniform4ui(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, - v3:Int):Void + public inline function uniform4ui(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, v3:Int):Void { this.uniform4ui(location, v0, v1, v2, v3); } - public inline function uniform4uiv(location:GLUniformLocation, v:UInt32Array, - ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniform4uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, ?srcLength:Int):Void { this.uniform4uiv(location, v != null ? v.length >> 2 : 0, v); } - public inline function uniformBlockBinding(program:GLProgram, uniformBlockIndex:Int, - uniformBlockBinding:Int):Void + public inline function uniformBlockBinding(program:GLProgram, uniformBlockIndex:Int, uniformBlockBinding:Int):Void { this.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); } #if !lime_webgl - public function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void #else - public inline function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, - v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { var count = 0; - if (srcLength != null) count = srcLength; else if (v != null) count = v.length >> 2; __tempPointer.set(v, srcOffset); this.uniformMatrix2fv(location, count, transpose, __tempPointer); } - public function uniformMatrix2x3fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix2x3fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4802,8 +4766,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniformMatrix2x3fv(location, count, transpose, __tempPointer); } - public function uniformMatrix2x4fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix2x4fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4815,23 +4778,19 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void #else - public inline function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, - v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { var count = 0; - if (srcLength != null) count = srcLength; else if (v != null) count = Std.int(v.length / 9); __tempPointer.set(v, srcOffset); this.uniformMatrix3fv(location, count, transpose, __tempPointer); } - public function uniformMatrix3x2fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix3x2fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4842,8 +4801,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniformMatrix3x2fv(location, count, transpose, __tempPointer); } - public function uniformMatrix3x4fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix3x4fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4855,23 +4813,19 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void #else - public inline function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, - v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { var count = 0; - if (srcLength != null) count = srcLength; else if (v != null) count = v.length >> 4; __tempPointer.set(v, srcOffset); this.uniformMatrix4fv(location, count, transpose, __tempPointer); } - public function uniformMatrix4x2fv(location:GLUniformLocation, - transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix4x2fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4882,8 +4836,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniformMatrix4x2fv(location, count, transpose, __tempPointer); } - public function uniformMatrix4x3fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix4x3fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4909,8 +4862,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttrib1f(indx, x); } - public inline function vertexAttrib1fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib1fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib1fv(indx, values); } @@ -4920,8 +4872,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttrib2f(indx, x, y); } - public inline function vertexAttrib2fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib2fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib2fv(indx, values); } @@ -4931,20 +4882,17 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttrib3f(indx, x, y, z); } - public inline function vertexAttrib3fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib3fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib3fv(indx, values); } - public inline function vertexAttrib4f(indx:Int, x:Float, y:Float, z:Float, - w:Float):Void + public inline function vertexAttrib4f(indx:Int, x:Float, y:Float, z:Float, w:Float):Void { this.vertexAttrib4f(indx, x, y, z, w); } - public inline function vertexAttrib4fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib4fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib4fv(indx, values); } @@ -4954,38 +4902,32 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttribDivisor(index, divisor); } - public inline function vertexAttribI4i(indx:Int, x:Int, y:Int, z:Int, - w:Int):Void + public inline function vertexAttribI4i(indx:Int, x:Int, y:Int, z:Int, w:Int):Void { this.vertexAttribI4i(indx, x, y, z, w); } - public inline function vertexAttribI4iv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttribI4iv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttribI4iv(indx, values); } - public inline function vertexAttribI4ui(indx:Int, x:Int, y:Int, z:Int, - w:Int):Void + public inline function vertexAttribI4ui(indx:Int, x:Int, y:Int, z:Int, w:Int):Void { this.vertexAttribI4ui(indx, x, y, z, w); } - public inline function vertexAttribI4uiv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttribI4uiv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttribI4uiv(indx, values); } - public inline function vertexAttribIPointer(index:Int, size:Int, type:Int, - stride:Int, offset:DataPointer):Void + public inline function vertexAttribIPointer(index:Int, size:Int, type:Int, stride:Int, offset:DataPointer):Void { this.vertexAttribIPointer(index, size, type, stride, offset); } - public inline function vertexAttribPointer(indx:Int, size:Int, type:Int, - normalized:Bool, stride:Int, offset:DataPointer):Void + public inline function vertexAttribPointer(indx:Int, size:Int, type:Int, normalized:Bool, stride:Int, offset:DataPointer):Void { this.vertexAttribPointer(indx, size, type, normalized, stride, offset); } @@ -5016,5 +4958,5 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic { return cast GL.context; } -} + } #end diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx index 93e9a0137b..35f47c8f1d 100644 --- a/src/lime/graphics/vulkan/VK.hx +++ b/src/lime/graphics/vulkan/VK.hx @@ -5,7 +5,6 @@ import lime.graphics.VulkanRenderContext; #if (!lime_doc_gen || lime_cffi) import lime.system.CFFI; #end - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -352,8 +351,7 @@ class VK This currently prefers graphics-capable devices, optionally requiring present support, and favors discrete GPUs by default. **/ - public static function pickPhysicalDevice(devices:Array, requirePresent:Bool = false, - preferDiscrete:Bool = true):VKPhysicalDevice + public static function pickPhysicalDevice(devices:Array, requirePresent:Bool = false, preferDiscrete:Bool = true):VKPhysicalDevice { if (devices == null || devices.length == 0) { diff --git a/src/lime/graphics/vulkan/VKBuffer.hx b/src/lime/graphics/vulkan/VKBuffer.hx index de31962199..c87157323e 100644 --- a/src/lime/graphics/vulkan/VKBuffer.hx +++ b/src/lime/graphics/vulkan/VKBuffer.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import haxe.io.Bytes; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKCommandBuffer.hx b/src/lime/graphics/vulkan/VKCommandBuffer.hx index 12638f2e2a..01ba3250ca 100644 --- a/src/lime/graphics/vulkan/VKCommandBuffer.hx +++ b/src/lime/graphics/vulkan/VKCommandBuffer.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -47,21 +46,19 @@ class VKCommandBuffer } } - public function beginRenderPass(renderPass:VKRenderPass, framebuffer:VKFramebuffer, width:Int, height:Int, - clearRed:Float = 0, clearGreen:Float = 0, clearBlue:Float = 0, clearAlpha:Float = 1, - clearDepth:Float = 1, clearStencil:Int = 0, x:Int = 0, y:Int = 0):Bool + public function beginRenderPass(renderPass:VKRenderPass, framebuffer:VKFramebuffer, width:Int, height:Int, clearRed:Float = 0, clearGreen:Float = 0, + clearBlue:Float = 0, clearAlpha:Float = 1, clearDepth:Float = 1, clearStencil:Int = 0, x:Int = 0, y:Int = 0):Bool { var clearValueCount = renderPass != null && renderPass.depthStencilFormat != VK.FORMAT_UNDEFINED ? 2 : 1; var state = [x, y, width, height, clearStencil, clearValueCount]; var clear = [clearRed, clearGreen, clearBlue, clearAlpha, clearDepth]; #if (!macro && lime_cffi && lime_vulkan) - if (isValid() && device != null && device.isValid() && renderPass != null && renderPass.isValid() && framebuffer != null - && framebuffer.isValid()) + if (isValid() && device != null && device.isValid() && renderPass != null && renderPass.isValid() && framebuffer != null && framebuffer.isValid()) { - return NativeCFFI.lime_vk_cmd_begin_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, renderPass.handle.high, - renderPass.handle.low, framebuffer.handle.high, framebuffer.handle.low, state, clear); + return NativeCFFI.lime_vk_cmd_begin_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, framebuffer.handle.high, + framebuffer.handle.low, state, clear); } #end @@ -86,9 +83,9 @@ class VKCommandBuffer descriptorSet.handle.high, descriptorSet.handle.low, state); } - return NativeCFFI.lime_vk_cmd_bind_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, - descriptorSet.handle.high, descriptorSet.handle.low, bindPoint, firstSet); + return NativeCFFI.lime_vk_cmd_bind_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, descriptorSet.handle.high, + descriptorSet.handle.low, bindPoint, firstSet); } #end @@ -120,9 +117,8 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) { - return NativeCFFI.lime_vk_cmd_bind_index_buffer(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, - offset.high, offset.low, indexType); + return NativeCFFI.lime_vk_cmd_bind_index_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, offset.high, offset.low, indexType); } #end @@ -134,9 +130,8 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && pipeline != null && pipeline.isValid()) { - return NativeCFFI.lime_vk_cmd_bind_pipeline(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, pipeline.handle.high, pipeline.handle.low, - bindPoint); + return NativeCFFI.lime_vk_cmd_bind_pipeline(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, pipeline.handle.high, pipeline.handle.low, bindPoint); } #end @@ -153,9 +148,8 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) { - return NativeCFFI.lime_vk_cmd_bind_vertex_buffer(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, - binding, offset.high, offset.low); + return NativeCFFI.lime_vk_cmd_bind_vertex_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, binding, offset.high, offset.low); } #end @@ -170,9 +164,9 @@ class VKCommandBuffer public function blitImageRegion(source:VKImage, destination:VKImage, sourceWidth:Int, sourceHeight:Int, sourceLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destinationLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - filter:Int = VK.FILTER_LINEAR, destinationWidth:Int = -1, destinationHeight:Int = -1, sourceX:Int = 0, sourceY:Int = 0, - sourceZ:Int = 0, destinationX:Int = 0, destinationY:Int = 0, destinationZ:Int = 0, sourceDepth:Int = 1, destinationDepth:Int = 1, - sourceMipLevel:Int = 0, destinationMipLevel:Int = 0, sourceBaseArrayLayer:Int = 0, destinationBaseArrayLayer:Int = 0, layerCount:Int = 1, + filter:Int = VK.FILTER_LINEAR, destinationWidth:Int = -1, destinationHeight:Int = -1, sourceX:Int = 0, sourceY:Int = 0, sourceZ:Int = 0, + destinationX:Int = 0, destinationY:Int = 0, destinationZ:Int = 0, sourceDepth:Int = 1, destinationDepth:Int = 1, sourceMipLevel:Int = 0, + destinationMipLevel:Int = 0, sourceBaseArrayLayer:Int = 0, destinationBaseArrayLayer:Int = 0, layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool { if (destinationWidth < 0) destinationWidth = sourceWidth; @@ -213,15 +207,14 @@ class VKCommandBuffer return false; } - public function clearColorImage(image:VKImage, layout:Int, red:Float, green:Float, blue:Float, alpha:Float, - aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + public function clearColorImage(image:VKImage, layout:Int, red:Float, green:Float, blue:Float, alpha:Float, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool { #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && image != null && image.isValid()) { - return NativeCFFI.lime_vk_cmd_clear_color_image(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, - layout, aspectMask, [red, green, blue, alpha]); + return NativeCFFI.lime_vk_cmd_clear_color_image(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, layout, aspectMask, + [red, green, blue, alpha]); } #end @@ -229,25 +222,33 @@ class VKCommandBuffer } public function clearDepthStencilImage(image:VKImage, layout:Int, depth:Float = 1, stencil:Int = 0, - aspectMask:Int = VK.IMAGE_ASPECT_DEPTH_BIT | VK.IMAGE_ASPECT_STENCIL_BIT, baseMipLevel:Int = 0, levelCount:Int = 1, - baseArrayLayer:Int = 0, layerCount:Int = 1):Bool + aspectMask:Int = VK.IMAGE_ASPECT_DEPTH_BIT | VK.IMAGE_ASPECT_STENCIL_BIT, baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, + layerCount:Int = 1):Bool { - var state = [layout, stencil, aspectMask, baseMipLevel, levelCount, baseArrayLayer, layerCount]; + var state = [ + layout, + stencil, + aspectMask, + baseMipLevel, + levelCount, + baseArrayLayer, + layerCount + ]; #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && image != null && image.isValid()) { return NativeCFFI.lime_vk_cmd_clear_depth_stencil_image(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, - state, [depth]); + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, state, + [depth]); } #end return false; } - public function clearAttachments(color:Bool, depth:Bool, stencil:Bool, x:Int, y:Int, width:Int, height:Int, red:Float = 0, - green:Float = 0, blue:Float = 0, alpha:Float = 0, depthValue:Float = 1, stencilValue:Int = 0):Bool + public function clearAttachments(color:Bool, depth:Bool, stencil:Bool, x:Int, y:Int, width:Int, height:Int, red:Float = 0, green:Float = 0, + blue:Float = 0, alpha:Float = 0, depthValue:Float = 1, stencilValue:Int = 0):Bool { var state = [color ? 1 : 0, depth ? 1 : 0, stencil ? 1 : 0, x, y, width, height, stencilValue]; var clear = [red, green, blue, alpha, depthValue]; @@ -255,8 +256,8 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { - return NativeCFFI.lime_vk_cmd_clear_attachments(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, state, clear); + return NativeCFFI.lime_vk_cmd_clear_attachments(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, state, clear); } #end @@ -267,7 +268,14 @@ class VKCommandBuffer { if (sourceOffset == null) sourceOffset = Int64.ofInt(0); if (destinationOffset == null) destinationOffset = Int64.ofInt(0); - var state = [size.high, size.low, sourceOffset.high, sourceOffset.low, destinationOffset.high, destinationOffset.low]; + var state = [ + size.high, + size.low, + sourceOffset.high, + sourceOffset.low, + destinationOffset.high, + destinationOffset.low + ]; #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && source != null && source.isValid() && destination != null && destination.isValid()) @@ -281,16 +289,14 @@ class VKCommandBuffer return false; } - public function copyBufferToImage(buffer:VKBuffer, image:VKImage, width:Int, height:Int, - layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL):Bool + public function copyBufferToImage(buffer:VKBuffer, image:VKImage, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL):Bool { return copyBufferToImageRegion(buffer, image, width, height, layout); } - public function copyBufferToImageRegion(buffer:VKBuffer, image:VKImage, width:Int, height:Int, - layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, - bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, mipLevel:Int = 0, baseArrayLayer:Int = 0, - layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + public function copyBufferToImageRegion(buffer:VKBuffer, image:VKImage, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, + mipLevel:Int = 0, baseArrayLayer:Int = 0, layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool { if (bufferOffset == null) bufferOffset = Int64.ofInt(0); var state = [ @@ -312,7 +318,13 @@ class VKCommandBuffer ]; #if (!macro && lime_cffi && lime_vulkan) - if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid() && image != null && image.isValid()) + if (isValid() + && device != null + && device.isValid() + && buffer != null + && buffer.isValid() + && image != null + && image.isValid()) { return NativeCFFI.lime_vk_cmd_copy_buffer_to_image_region(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, @@ -323,10 +335,9 @@ class VKCommandBuffer return false; } - public function copyImageToBufferRegion(image:VKImage, buffer:VKBuffer, width:Int, height:Int, - layout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, - bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, mipLevel:Int = 0, baseArrayLayer:Int = 0, - layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + public function copyImageToBufferRegion(image:VKImage, buffer:VKBuffer, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, + mipLevel:Int = 0, baseArrayLayer:Int = 0, layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool { if (bufferOffset == null) bufferOffset = Int64.ofInt(0); var state = [ @@ -348,7 +359,13 @@ class VKCommandBuffer ]; #if (!macro && lime_cffi && lime_vulkan) - if (isValid() && device != null && device.isValid() && image != null && image.isValid() && buffer != null && buffer.isValid()) + if (isValid() + && device != null + && device.isValid() + && image != null + && image.isValid() + && buffer != null + && buffer.isValid()) { return NativeCFFI.lime_vk_cmd_copy_image_to_buffer_region(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, @@ -390,9 +407,9 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) { - return NativeCFFI.lime_vk_cmd_draw_indirect(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, - offset.high, offset.low, drawCount, stride); + return NativeCFFI.lime_vk_cmd_draw_indirect(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, offset.high, offset.low, drawCount, + stride); } #end @@ -431,8 +448,8 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { - return NativeCFFI.lime_vk_cmd_end_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + return NativeCFFI.lime_vk_cmd_end_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); } #end @@ -465,8 +482,19 @@ class VKCommandBuffer public function pipelineBarrierImage(image:VKImage, oldLayout:Int, newLayout:Int, srcStageMask:Int, dstStageMask:Int, srcAccessMask:Int, dstAccessMask:Int, aspectMask:Int, baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):Bool { - var state = [oldLayout, newLayout, srcStageMask, dstStageMask, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount, - baseArrayLayer, layerCount]; + var state = [ + oldLayout, + newLayout, + srcStageMask, + dstStageMask, + srcAccessMask, + dstAccessMask, + aspectMask, + baseMipLevel, + levelCount, + baseArrayLayer, + layerCount + ]; #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && image != null && image.isValid()) @@ -479,8 +507,7 @@ class VKCommandBuffer return false; } - public function pushConstants(layout:VKPipelineLayout, stageFlags:Int, bytes:haxe.io.Bytes, offset:Int = 0, byteOffset:Int = 0, - byteLength:Int = -1):Bool + public function pushConstants(layout:VKPipelineLayout, stageFlags:Int, bytes:haxe.io.Bytes, offset:Int = 0, byteOffset:Int = 0, byteLength:Int = -1):Bool { if (bytes == null || layout == null) { @@ -495,9 +522,8 @@ class VKCommandBuffer #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && layout.isValid()) { - return NativeCFFI.lime_vk_cmd_push_constants(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, state, - bytes); + return NativeCFFI.lime_vk_cmd_push_constants(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, state, bytes); } #end diff --git a/src/lime/graphics/vulkan/VKCommandPool.hx b/src/lime/graphics/vulkan/VKCommandPool.hx index a95be9ee2e..f01e0c3a71 100644 --- a/src/lime/graphics/vulkan/VKCommandPool.hx +++ b/src/lime/graphics/vulkan/VKCommandPool.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKDescriptorPool.hx b/src/lime/graphics/vulkan/VKDescriptorPool.hx index e754efbb31..8763407d72 100644 --- a/src/lime/graphics/vulkan/VKDescriptorPool.hx +++ b/src/lime/graphics/vulkan/VKDescriptorPool.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKDescriptorSet.hx b/src/lime/graphics/vulkan/VKDescriptorSet.hx index 26c7d806c6..8fe7110a9f 100644 --- a/src/lime/graphics/vulkan/VKDescriptorSet.hx +++ b/src/lime/graphics/vulkan/VKDescriptorSet.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -33,24 +32,23 @@ class VKDescriptorSet return !VK.__isZero(handle); } - public function updateBuffer(binding:Int, buffer:VKBuffer, range:Int, offset:Int = 0, - descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER):Bool + public function updateBuffer(binding:Int, buffer:VKBuffer, range:Int, offset:Int = 0, descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER):Bool { #if (!macro && lime_cffi && lime_vulkan) var device = get_device(); if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) { return NativeCFFI.lime_vk_update_descriptor_set_buffer(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, - buffer.handle.high, buffer.handle.low, offset, range); + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, buffer.handle.high, + buffer.handle.low, offset, range); } #end return false; } - public function updateImage(binding:Int, imageView:VKImageView, sampler:VKSampler = null, - layout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER):Bool + public function updateImage(binding:Int, imageView:VKImageView, sampler:VKSampler = null, layout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER):Bool { #if (!macro && lime_cffi && lime_vulkan) var device = get_device(); @@ -58,8 +56,8 @@ class VKDescriptorSet { var samplerHandle = (sampler != null && sampler.isValid()) ? sampler.handle : Int64.ofInt(0); return NativeCFFI.lime_vk_update_descriptor_set_image(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, - imageView.handle.high, imageView.handle.low, samplerHandle.high, samplerHandle.low, layout); + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, imageView.handle.high, + imageView.handle.low, samplerHandle.high, samplerHandle.low, layout); } #end diff --git a/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx b/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx index d14fb572ba..fd6a04d14c 100644 --- a/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx +++ b/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -25,8 +24,8 @@ class VKDescriptorSetLayout #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { - NativeCFFI.lime_vk_destroy_descriptor_set_layout(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + NativeCFFI.lime_vk_destroy_descriptor_set_layout(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); handle = Int64.ofInt(0); } #end diff --git a/src/lime/graphics/vulkan/VKDescriptorWrite.hx b/src/lime/graphics/vulkan/VKDescriptorWrite.hx index 5768a76244..b06c522d7e 100644 --- a/src/lime/graphics/vulkan/VKDescriptorWrite.hx +++ b/src/lime/graphics/vulkan/VKDescriptorWrite.hx @@ -34,8 +34,8 @@ class VKDescriptorWrite range = Int64.ofInt(0); } - public static function forBuffer(descriptorSet:VKDescriptorSet, binding:Int, buffer:VKBuffer, range:Int64 = null, - offset:Int64 = null, descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, arrayElement:Int = 0):VKDescriptorWrite + public static function forBuffer(descriptorSet:VKDescriptorSet, binding:Int, buffer:VKBuffer, range:Int64 = null, offset:Int64 = null, + descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, arrayElement:Int = 0):VKDescriptorWrite { var write = new VKDescriptorWrite(); write.kind = KIND_BUFFER; @@ -50,8 +50,8 @@ class VKDescriptorWrite } public static function forImage(descriptorSet:VKDescriptorSet, binding:Int, imageView:VKImageView, sampler:VKSampler = null, - imageLayout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arrayElement:Int = 0):VKDescriptorWrite + imageLayout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + arrayElement:Int = 0):VKDescriptorWrite { var write = new VKDescriptorWrite(); write.kind = KIND_IMAGE; diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx index 28e375114e..50bd192581 100644 --- a/src/lime/graphics/vulkan/VKDevice.hx +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import haxe.io.Bytes; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -42,8 +41,8 @@ class VKDevice #if (!macro && lime_cffi && lime_vulkan) if (isValid() && queueFamily != null) { - var data:Dynamic = NativeCFFI.lime_vk_create_command_pool(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, queueFamily.index, flags); + var data:Dynamic = NativeCFFI.lime_vk_create_command_pool(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, queueFamily.index, flags); var commandPoolHandle = VK.__makeHandle(data); if (!VK.__isZero(commandPoolHandle)) { @@ -103,8 +102,8 @@ class VKDevice #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { - var data:Dynamic = NativeCFFI.lime_vk_create_buffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, size.high, size.low, usage); + var data:Dynamic = NativeCFFI.lime_vk_create_buffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, size.high, size.low, usage); var bufferHandle = VK.__makeHandle(data); if (!VK.__isZero(bufferHandle)) { @@ -147,8 +146,8 @@ class VKDevice public inline function createStagingBuffer(size:Int64, bytes:Bytes = null):VKBuffer { - return createBufferWithMemory(size, VK.BUFFER_USAGE_TRANSFER_SRC_BIT, - VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, bytes); + return createBufferWithMemory(size, VK.BUFFER_USAGE_TRANSFER_SRC_BIT, VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + bytes); } public inline function createUploadRing(byteCapacity:Int, usage:Int = VK.BUFFER_USAGE_TRANSFER_SRC_BIT, @@ -217,8 +216,8 @@ class VKDevice #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { - var data:Dynamic = NativeCFFI.lime_vk_create_descriptor_set_layout(instance.context.__windowHandle, instance.handle.high, - instance.handle.low, handle.high, handle.low, packed); + var data:Dynamic = NativeCFFI.lime_vk_create_descriptor_set_layout(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, packed); var descriptorSetLayoutHandle = VK.__makeHandle(data); if (!VK.__isZero(descriptorSetLayoutHandle)) { @@ -278,8 +277,8 @@ class VKDevice #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { - var data:Dynamic = NativeCFFI.lime_vk_create_framebuffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, packed, width, height, layers); + var data:Dynamic = NativeCFFI.lime_vk_create_framebuffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, renderPass.handle.high, renderPass.handle.low, packed, width, height, layers); var framebufferHandle = VK.__makeHandle(data); if (!VK.__isZero(framebufferHandle)) { @@ -291,8 +290,8 @@ class VKDevice return null; } - public function createGraphicsPipeline(renderPass:VKRenderPass, layout:VKPipelineLayout, vertexShader:VKShaderModule, - fragmentShader:VKShaderModule, info:VKGraphicsPipelineInfo, cache:VKPipelineCache = null):VKPipeline + public function createGraphicsPipeline(renderPass:VKRenderPass, layout:VKPipelineLayout, vertexShader:VKShaderModule, fragmentShader:VKShaderModule, + info:VKGraphicsPipelineInfo, cache:VKPipelineCache = null):VKPipeline { if (renderPass == null || layout == null || vertexShader == null || fragmentShader == null) { @@ -309,8 +308,8 @@ class VKDevice if (isValid() && renderPass.isValid() && layout.isValid() && vertexShader.isValid() && fragmentShader.isValid()) { var data:Dynamic = NativeCFFI.lime_vk_create_graphics_pipeline(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, layout.handle.high, layout.handle.low, - vertexShader.handle.high, vertexShader.handle.low, fragmentShader.handle.high, fragmentShader.handle.low, info.pack(cacheHandle)); + handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, layout.handle.high, layout.handle.low, vertexShader.handle.high, + vertexShader.handle.low, fragmentShader.handle.high, fragmentShader.handle.low, info.pack(cacheHandle)); var pipelineHandle = VK.__makeHandle(data); if (!VK.__isZero(pipelineHandle)) { @@ -328,8 +327,8 @@ class VKDevice #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { - var data:Dynamic = NativeCFFI.lime_vk_create_image(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, width, height, depth, mipLevels, arrayLayers, format, imageType, tiling, usage, samples); + var data:Dynamic = NativeCFFI.lime_vk_create_image(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, width, height, depth, mipLevels, arrayLayers, format, imageType, tiling, usage, samples); var imageHandle = VK.__makeHandle(data); if (!VK.__isZero(imageHandle)) { @@ -397,16 +396,13 @@ class VKDevice return null; } - public function createRenderPass(colorFormat:Int, depthStencilFormat:Int = VK.FORMAT_UNDEFINED, - samples:Int = VK.SAMPLE_COUNT_1_BIT, colorLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, - colorStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, colorInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, - colorFinalLayout:Int = VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - depthInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, - depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE, - resolveFormat:Int = VK.FORMAT_UNDEFINED, resolveLoadOp:Int = VK.ATTACHMENT_LOAD_OP_DONT_CARE, - resolveStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, resolveInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, - resolveFinalLayout:Int = VK.IMAGE_LAYOUT_PRESENT_SRC_KHR):VKRenderPass + public function createRenderPass(colorFormat:Int, depthStencilFormat:Int = VK.FORMAT_UNDEFINED, samples:Int = VK.SAMPLE_COUNT_1_BIT, + colorLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, colorStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, + colorInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, colorFinalLayout:Int = VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + depthInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE, resolveFormat:Int = VK.FORMAT_UNDEFINED, + resolveLoadOp:Int = VK.ATTACHMENT_LOAD_OP_DONT_CARE, resolveStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, + resolveInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, resolveFinalLayout:Int = VK.IMAGE_LAYOUT_PRESENT_SRC_KHR):VKRenderPass { #if (!macro && lime_cffi && lime_vulkan) if (isValid()) @@ -429,8 +425,8 @@ class VKDevice resolveInitialLayout, resolveFinalLayout ]; - var data:Dynamic = NativeCFFI.lime_vk_create_render_pass(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, state); + var data:Dynamic = NativeCFFI.lime_vk_create_render_pass(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, state); var renderPassHandle = VK.__makeHandle(data); if (!VK.__isZero(renderPassHandle)) { @@ -443,14 +439,14 @@ class VKDevice } public function createSampler(filter:Int = VK.FILTER_LINEAR, addressMode:Int = VK.SAMPLER_ADDRESS_MODE_REPEAT, - mipmapMode:Int = VK.SAMPLER_MIPMAP_MODE_LINEAR, anisotropyEnable:Bool = false, maxAnisotropy:Float = 1, - compareOp:Int = -1, minLod:Float = 0, maxLod:Float = 0):VKSampler + mipmapMode:Int = VK.SAMPLER_MIPMAP_MODE_LINEAR, anisotropyEnable:Bool = false, maxAnisotropy:Float = 1, compareOp:Int = -1, minLod:Float = 0, + maxLod:Float = 0):VKSampler { #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { - var data:Dynamic = NativeCFFI.lime_vk_create_sampler(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low, filter, addressMode, mipmapMode, anisotropyEnable, maxAnisotropy, compareOp, minLod, maxLod); + var data:Dynamic = NativeCFFI.lime_vk_create_sampler(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, filter, addressMode, mipmapMode, anisotropyEnable, maxAnisotropy, compareOp, minLod, maxLod); var samplerHandle = VK.__makeHandle(data); if (!VK.__isZero(samplerHandle)) { @@ -467,8 +463,8 @@ class VKDevice #if (!macro && lime_cffi && lime_vulkan) if (isValid()) { - var data:Dynamic = NativeCFFI.lime_vk_create_semaphore(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - handle.high, handle.low); + var data:Dynamic = NativeCFFI.lime_vk_create_semaphore(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low); var semaphoreHandle = VK.__makeHandle(data); if (!VK.__isZero(semaphoreHandle)) { @@ -519,8 +515,8 @@ class VKDevice { var oldSwapchainHandle = (oldSwapchain != null && oldSwapchain.isValid()) ? oldSwapchain.handle : Int64.ofInt(0); var data:Dynamic = NativeCFFI.lime_vk_create_swapchain(instance.context.__windowHandle, instance.handle.high, instance.handle.low, - physicalDevice.handle.high, physicalDevice.handle.low, handle.high, handle.low, surface.high, surface.low, queueFamily.index, width, - height, presentMode, oldSwapchainHandle.high, oldSwapchainHandle.low); + physicalDevice.handle.high, physicalDevice.handle.low, handle.high, handle.low, surface.high, surface.low, queueFamily.index, width, height, + presentMode, oldSwapchainHandle.high, oldSwapchainHandle.low); var swapchainHandle = VK.__makeHandle(data != null ? data.handle : null); if (!VK.__isZero(swapchainHandle)) { diff --git a/src/lime/graphics/vulkan/VKDeviceMemory.hx b/src/lime/graphics/vulkan/VKDeviceMemory.hx index 39dc6ad5ee..ef742ebffc 100644 --- a/src/lime/graphics/vulkan/VKDeviceMemory.hx +++ b/src/lime/graphics/vulkan/VKDeviceMemory.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import haxe.io.Bytes; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -78,9 +77,8 @@ class VKDeviceMemory #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { - var result = NativeCFFI.lime_vk_map_memory(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, - size.low, flags); + var result = NativeCFFI.lime_vk_map_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, size.low, flags); if (result) { mapped = true; @@ -131,9 +129,8 @@ class VKDeviceMemory #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { - return NativeCFFI.lime_vk_write_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, dstOffset.high, dstOffset.low, bytes, - srcOffset, length); + return NativeCFFI.lime_vk_write_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, dstOffset.high, dstOffset.low, bytes, srcOffset, length); } #end @@ -158,9 +155,8 @@ class VKDeviceMemory #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid()) { - return NativeCFFI.lime_vk_flush_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, - size.low); + return NativeCFFI.lime_vk_flush_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, size.low); } #end @@ -186,8 +182,7 @@ class VKDeviceMemory if (isValid() && device != null && device.isValid()) { return NativeCFFI.lime_vk_invalidate_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, - size.low); + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, size.low); } #end diff --git a/src/lime/graphics/vulkan/VKFence.hx b/src/lime/graphics/vulkan/VKFence.hx index 6fd009ac1f..9fc7d1779a 100644 --- a/src/lime/graphics/vulkan/VKFence.hx +++ b/src/lime/graphics/vulkan/VKFence.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKFramebuffer.hx b/src/lime/graphics/vulkan/VKFramebuffer.hx index be12eaf8b9..d2298a2f09 100644 --- a/src/lime/graphics/vulkan/VKFramebuffer.hx +++ b/src/lime/graphics/vulkan/VKFramebuffer.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKImage.hx b/src/lime/graphics/vulkan/VKImage.hx index 491f40350a..fd5a556a81 100644 --- a/src/lime/graphics/vulkan/VKImage.hx +++ b/src/lime/graphics/vulkan/VKImage.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -82,9 +81,8 @@ class VKImage #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && memory != null && memory.isValid()) { - var result = NativeCFFI.lime_vk_bind_image_memory(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, memory.handle.high, memory.handle.low, - offset.high, offset.low); + var result = NativeCFFI.lime_vk_bind_image_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, memory.handle.high, memory.handle.low, offset.high, offset.low); if (result) { this.memory = memory; @@ -96,8 +94,8 @@ class VKImage return false; } - public function createView(format:Int = 0, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT, viewType:Int = VK.IMAGE_VIEW_TYPE_2D, - baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):VKImageView + public function createView(format:Int = 0, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT, viewType:Int = VK.IMAGE_VIEW_TYPE_2D, baseMipLevel:Int = 0, + levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):VKImageView { if (format == 0) { @@ -108,8 +106,8 @@ class VKImage if (isValid() && device != null && device.isValid()) { var data:Dynamic = NativeCFFI.lime_vk_create_image_view_ex(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, format, aspectMask, viewType, - baseMipLevel, levelCount, baseArrayLayer, layerCount); + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, format, aspectMask, viewType, baseMipLevel, + levelCount, baseArrayLayer, layerCount); var imageViewHandle = VK.__makeHandle(data); if (!VK.__isZero(imageViewHandle)) { diff --git a/src/lime/graphics/vulkan/VKImageView.hx b/src/lime/graphics/vulkan/VKImageView.hx index 5cf888f93a..6f911c1b60 100644 --- a/src/lime/graphics/vulkan/VKImageView.hx +++ b/src/lime/graphics/vulkan/VKImageView.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKInstance.hx b/src/lime/graphics/vulkan/VKInstance.hx index 71d4e079a3..42601584fc 100644 --- a/src/lime/graphics/vulkan/VKInstance.hx +++ b/src/lime/graphics/vulkan/VKInstance.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import lime.graphics.VulkanRenderContext; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx index c05a23fc4f..f21d0e9d0b 100644 --- a/src/lime/graphics/vulkan/VKPhysicalDevice.hx +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -121,7 +121,7 @@ class VKPhysicalDevice Returns the first queue family that matches the requested capabilities. **/ public function getQueueFamily(requireGraphics:Bool = true, requirePresent:Bool = false, requireCompute:Bool = false, - requireTransfer:Bool = false):VKQueueFamilyInfo + requireTransfer:Bool = false):VKQueueFamilyInfo { for (queueFamily in queueFamilies) { @@ -135,7 +135,7 @@ class VKPhysicalDevice } public inline function hasQueueFamily(requireGraphics:Bool = true, requirePresent:Bool = false, requireCompute:Bool = false, - requireTransfer:Bool = false):Bool + requireTransfer:Bool = false):Bool { return getQueueFamily(requireGraphics, requirePresent, requireCompute, requireTransfer) != null; } @@ -152,8 +152,14 @@ class VKPhysicalDevice counts &= framebufferStencilSampleCounts; } - for (sampleCount in [VK.SAMPLE_COUNT_64_BIT, VK.SAMPLE_COUNT_32_BIT, VK.SAMPLE_COUNT_16_BIT, VK.SAMPLE_COUNT_8_BIT, - VK.SAMPLE_COUNT_4_BIT, VK.SAMPLE_COUNT_2_BIT]) + for (sampleCount in [ + VK.SAMPLE_COUNT_64_BIT, + VK.SAMPLE_COUNT_32_BIT, + VK.SAMPLE_COUNT_16_BIT, + VK.SAMPLE_COUNT_8_BIT, + VK.SAMPLE_COUNT_4_BIT, + VK.SAMPLE_COUNT_2_BIT + ]) { if ((counts & sampleCount) != 0) { diff --git a/src/lime/graphics/vulkan/VKPipeline.hx b/src/lime/graphics/vulkan/VKPipeline.hx index 20b377ec44..6baa424b04 100644 --- a/src/lime/graphics/vulkan/VKPipeline.hx +++ b/src/lime/graphics/vulkan/VKPipeline.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKPipelineCache.hx b/src/lime/graphics/vulkan/VKPipelineCache.hx index e690940e26..9214294458 100644 --- a/src/lime/graphics/vulkan/VKPipelineCache.hx +++ b/src/lime/graphics/vulkan/VKPipelineCache.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import haxe.io.Bytes; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -49,8 +48,8 @@ class VKPipelineCache if (isValid() && device != null && device.isValid()) { var bytes = Bytes.alloc(0); - if (NativeCFFI.lime_vk_get_pipeline_cache_data(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, bytes)) + if (NativeCFFI.lime_vk_get_pipeline_cache_data(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, bytes)) { return bytes; } diff --git a/src/lime/graphics/vulkan/VKPipelineLayout.hx b/src/lime/graphics/vulkan/VKPipelineLayout.hx index 83c3b77ed2..958a77c519 100644 --- a/src/lime/graphics/vulkan/VKPipelineLayout.hx +++ b/src/lime/graphics/vulkan/VKPipelineLayout.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKQueue.hx b/src/lime/graphics/vulkan/VKQueue.hx index a372e78d26..6e563c193a 100644 --- a/src/lime/graphics/vulkan/VKQueue.hx +++ b/src/lime/graphics/vulkan/VKQueue.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -80,8 +79,8 @@ class VKQueue This preserves the simple `submit(commandBuffer, fence)` path while exposing the explicit wait/signal pieces renderers need per frame. **/ - public function submitSynced(commandBuffer:VKCommandBuffer, waitSemaphore:VKSemaphore = null, signalSemaphore:VKSemaphore = null, - fence:VKFence = null, waitStageMask:Int = VK.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT):Bool + public function submitSynced(commandBuffer:VKCommandBuffer, waitSemaphore:VKSemaphore = null, signalSemaphore:VKSemaphore = null, fence:VKFence = null, + waitStageMask:Int = VK.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT):Bool { #if (!macro && lime_cffi && lime_vulkan) if (isValid() && device != null && device.isValid() && commandBuffer != null && commandBuffer.isValid()) @@ -89,7 +88,15 @@ class VKQueue var waitHandle = waitSemaphore != null && waitSemaphore.isValid() ? waitSemaphore.handle : Int64.ofInt(0); var signalHandle = signalSemaphore != null && signalSemaphore.isValid() ? signalSemaphore.handle : Int64.ofInt(0); var fenceHandle = fence != null && fence.isValid() ? fence.handle : Int64.ofInt(0); - var state = [waitHandle.high, waitHandle.low, waitStageMask, signalHandle.high, signalHandle.low, fenceHandle.high, fenceHandle.low]; + var state = [ + waitHandle.high, + waitHandle.low, + waitStageMask, + signalHandle.high, + signalHandle.low, + fenceHandle.high, + fenceHandle.low + ]; return NativeCFFI.lime_vk_queue_submit_synced(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low, state); diff --git a/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx b/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx index d8df278384..d80c4ed39c 100644 --- a/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx +++ b/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx @@ -30,8 +30,7 @@ class VKQueueFamilyInfo /** Checks whether this queue family satisfies a requested capability set. **/ - public inline function matches(requireGraphics:Bool = false, requirePresent:Bool = false, requireCompute:Bool = false, - requireTransfer:Bool = false):Bool + public inline function matches(requireGraphics:Bool = false, requirePresent:Bool = false, requireCompute:Bool = false, requireTransfer:Bool = false):Bool { if (requireGraphics && !supportsGraphics) return false; if (requirePresent && !supportsPresent) return false; diff --git a/src/lime/graphics/vulkan/VKRenderPass.hx b/src/lime/graphics/vulkan/VKRenderPass.hx index 8a7ddfe95c..fa0f580e70 100644 --- a/src/lime/graphics/vulkan/VKRenderPass.hx +++ b/src/lime/graphics/vulkan/VKRenderPass.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKRenderer.hx b/src/lime/graphics/vulkan/VKRenderer.hx index d3b70e3023..25ca3651b6 100644 --- a/src/lime/graphics/vulkan/VKRenderer.hx +++ b/src/lime/graphics/vulkan/VKRenderer.hx @@ -7,7 +7,6 @@ import lime.system.CFFI; #if (!lime_doc_gen || lime_cffi) import lime.system.CFFIPointer; #end - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKSampler.hx b/src/lime/graphics/vulkan/VKSampler.hx index 69504203a1..7c3cbafd67 100644 --- a/src/lime/graphics/vulkan/VKSampler.hx +++ b/src/lime/graphics/vulkan/VKSampler.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKSemaphore.hx b/src/lime/graphics/vulkan/VKSemaphore.hx index 4128be555b..9301dfc3c6 100644 --- a/src/lime/graphics/vulkan/VKSemaphore.hx +++ b/src/lime/graphics/vulkan/VKSemaphore.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKShaderModule.hx b/src/lime/graphics/vulkan/VKShaderModule.hx index 4204a32c3a..09edfc1411 100644 --- a/src/lime/graphics/vulkan/VKShaderModule.hx +++ b/src/lime/graphics/vulkan/VKShaderModule.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKSurface.hx b/src/lime/graphics/vulkan/VKSurface.hx index 6abd8988fb..f6166a3e41 100644 --- a/src/lime/graphics/vulkan/VKSurface.hx +++ b/src/lime/graphics/vulkan/VKSurface.hx @@ -2,7 +2,6 @@ package lime.graphics.vulkan; import haxe.Int64; import lime.graphics.VulkanRenderContext; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end diff --git a/src/lime/graphics/vulkan/VKSwapchain.hx b/src/lime/graphics/vulkan/VKSwapchain.hx index 389c36e58e..089f38adcd 100644 --- a/src/lime/graphics/vulkan/VKSwapchain.hx +++ b/src/lime/graphics/vulkan/VKSwapchain.hx @@ -1,7 +1,6 @@ package lime.graphics.vulkan; import haxe.Int64; - #if (!lime_doc_gen || lime_cffi) import lime._internal.backend.native.NativeCFFI; #end @@ -56,8 +55,8 @@ class VKSwapchain var semaphoreHandle = (semaphore != null && semaphore.isValid()) ? semaphore.handle : Int64.ofInt(0); var fenceHandle = (fence != null && fence.isValid()) ? fence.handle : Int64.ofInt(0); var data:Dynamic = NativeCFFI.lime_vk_acquire_next_image(device.instance.context.__windowHandle, device.instance.handle.high, - device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, timeout.high, timeout.low, - semaphoreHandle.high, semaphoreHandle.low, fenceHandle.high, fenceHandle.low); + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, timeout.high, timeout.low, semaphoreHandle.high, + semaphoreHandle.low, fenceHandle.high, fenceHandle.low); if (data != null) { diff --git a/src/lime/math/Matrix3.hx b/src/lime/math/Matrix3.hx index 330cad97c9..15aedcbdd1 100644 --- a/src/lime/math/Matrix3.hx +++ b/src/lime/math/Matrix3.hx @@ -70,9 +70,15 @@ abstract Matrix3(Float32Array) to Float32Array { // Column-major order means adjacent values form a column, not a row. this = new Float32Array([ - a, b, 0, // column 0 - c, d, 0, // column 1 - tx, ty, 1 // column 2 + a, + b, + 0, // column 0 + c, + d, + 0, // column 1 + tx, + ty, + 1 // column 2 ]); } @@ -561,7 +567,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[0]; } - inline function set_a(value: Float):Float + + inline function set_a(value:Float):Float { return this[0] = value; } @@ -570,7 +577,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[1]; } - inline function set_b(value: Float):Float + + inline function set_b(value:Float):Float { return this[1] = value; } @@ -579,7 +587,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[3]; } - inline function set_c(value: Float):Float + + inline function set_c(value:Float):Float { return this[3] = value; } @@ -588,7 +597,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[4]; } - inline function set_d(value: Float):Float + + inline function set_d(value:Float):Float { return this[4] = value; } @@ -597,7 +607,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[6]; } - inline function set_tx(value: Float):Float + + inline function set_tx(value:Float):Float { return this[6] = value; } @@ -606,7 +617,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[7]; } - inline function set_ty(value: Float):Float + + inline function set_ty(value:Float):Float { return this[7] = value; } diff --git a/src/lime/math/Matrix4.hx b/src/lime/math/Matrix4.hx index ee479fbb78..65807d478b 100644 --- a/src/lime/math/Matrix4.hx +++ b/src/lime/math/Matrix4.hx @@ -378,7 +378,7 @@ abstract Matrix4(Float32Array) from Float32Array to Float32Array this[14] = -(zNear + zFar) * sz; this[15] = 1; } - + /** Initializes this matrix with values for a perspective projection @param fov The field of view diff --git a/src/lime/media/AudioBuffer.hx b/src/lime/media/AudioBuffer.hx index 1cf584c5d8..b3cfa7e1d3 100644 --- a/src/lime/media/AudioBuffer.hx +++ b/src/lime/media/AudioBuffer.hx @@ -396,7 +396,6 @@ class AudioBuffer @return An `AudioBuffer` instance with the decoded audio data. **/ #if lime_vorbis - public static function fromVorbisFile(vorbisFile:VorbisFile):AudioBuffer { if (vorbisFile == null) return null; @@ -509,22 +508,19 @@ class AudioBuffer var promise = new Promise(); var request = new HTTPRequest(); - request.load(path) - .onProgress(promise.progress) - .onComplete(function(bytes) + request.load(path).onProgress(promise.progress).onComplete(function(bytes) + { + var buffer = fromBytesStream(bytes); + + if (buffer != null) { - var buffer = fromBytesStream(bytes); - - if (buffer != null) - { - promise.complete(buffer); - } - else - { - promise.error(""); - } - }) - .onError(promise.error); + promise.complete(buffer); + } + else + { + promise.error(""); + } + }).onError(promise.error); return promise.future; } @@ -694,7 +690,7 @@ class AudioBuffer } }).onError(function(_) { - __loadFromFilesStream(paths, promise, index + 1); + __loadFromFilesStream(paths, promise, index + 1); }); } diff --git a/src/lime/media/AudioInput.hx b/src/lime/media/AudioInput.hx index 17446ff888..7fc3919d97 100644 --- a/src/lime/media/AudioInput.hx +++ b/src/lime/media/AudioInput.hx @@ -7,6 +7,7 @@ import lime.app.Event; @:fileXml('tags="haxe,release"') @:noDebug #end + /** The `AudioInput` class provides polling-based access to microphone or other audio capture input. diff --git a/src/lime/media/AudioInputDevice.hx b/src/lime/media/AudioInputDevice.hx index 948fe799a9..cfcf4a6ced 100644 --- a/src/lime/media/AudioInputDevice.hx +++ b/src/lime/media/AudioInputDevice.hx @@ -4,6 +4,7 @@ package lime.media; @:fileXml('tags="haxe,release"') @:noDebug #end + /** The `AudioInputDevice` class describes an audio capture device that can be used with `AudioInput`. diff --git a/src/lime/media/AudioSource.hx b/src/lime/media/AudioSource.hx index 2ccc9b1465..5e883167ad 100644 --- a/src/lime/media/AudioSource.hx +++ b/src/lime/media/AudioSource.hx @@ -9,6 +9,7 @@ import lime.math.Vector4; @:fileXml('tags="haxe,release"') @:noDebug #end + /** The `AudioSource` class provides a way to control audio playback in a Lime application. It allows for playing, pausing, and stopping audio, as well as controlling various @@ -24,7 +25,7 @@ class AudioSource An event that is dispatched when the audio playback is complete. **/ public var onComplete = new EventVoid>(); - + /** The `AudioBuffer` associated with this `AudioSource`. **/ @@ -78,16 +79,13 @@ class AudioSource { this.buffer = buffer; this.offset = offset; - __backend = new AudioSourceBackend(this); if (length != null && length != 0) { this.length = length; } - this.loops = loops; - if (buffer != null) { init(); diff --git a/src/lime/media/OpenALAudioContext.hx b/src/lime/media/OpenALAudioContext.hx index 9d7b7d21a7..b7d0cc90e6 100644 --- a/src/lime/media/OpenALAudioContext.hx +++ b/src/lime/media/OpenALAudioContext.hx @@ -412,8 +412,13 @@ class OpenALAudioContext return ALC.getString(device, param); } - if (param == DEFAULT_DEVICE_SPECIFIER || param == DEVICE_SPECIFIER || param == ALC.EXTENSIONS || param == DEFAULT_ALL_DEVICES_SPECIFIER - || param == ALL_DEVICES_SPECIFIER || param == CAPTURE_DEVICE_SPECIFIER || param == CAPTURE_DEFAULT_DEVICE_SPECIFIER) + if (param == DEFAULT_DEVICE_SPECIFIER + || param == DEVICE_SPECIFIER + || param == ALC.EXTENSIONS + || param == DEFAULT_ALL_DEVICES_SPECIFIER + || param == ALL_DEVICES_SPECIFIER + || param == CAPTURE_DEVICE_SPECIFIER + || param == CAPTURE_DEFAULT_DEVICE_SPECIFIER) { return ALC.getString(cast null, param); } diff --git a/src/lime/net/HTTPRequest.hx b/src/lime/net/HTTPRequest.hx index 70c0ac8fe8..6703673b52 100644 --- a/src/lime/net/HTTPRequest.hx +++ b/src/lime/net/HTTPRequest.hx @@ -160,10 +160,13 @@ public function load(uri:String = null):Future } } -@:noCompletion class _HTTPRequestErrorResponse { +@:noCompletion class _HTTPRequestErrorResponse +{ public var error:Dynamic; public var responseData:T; - public function new(error:Dynamic, responseData:T) { + + public function new(error:Dynamic, responseData:T) + { this.error = error; this.responseData = responseData; } diff --git a/src/lime/system/BackgroundWorker.hx b/src/lime/system/BackgroundWorker.hx index 30d69d1ed8..df72812a36 100644 --- a/src/lime/system/BackgroundWorker.hx +++ b/src/lime/system/BackgroundWorker.hx @@ -14,7 +14,6 @@ import neko.vm.Deque; import neko.vm.Thread; #end #end - /** A `BackgroundWorker` allows the execution of a function on a background thread, avoiding the blocking of the main thread. This is particularly useful for long-running @@ -24,7 +23,7 @@ import neko.vm.Thread; - **Thread Support:** Only system targets (such as C++, Neko) support threading. - **Events:** The class uses the `Event` class to dispatch completion, error, and progress notifications. - + @see `ThreadPool` for more advanced threading capabilities, including thread safety, HTML5 threads, and more robust handling of tasks. **/ @@ -62,7 +61,7 @@ class BackgroundWorker Dispatched if an error occurs during the execution of the worker's task. **/ public var onError = new EventVoid>(); - + /** Dispatched periodically during the worker's task to provide progress updates. **/ @@ -154,7 +153,7 @@ class BackgroundWorker } #end } - + /** Sends a progress update message. @param message An optional message to pass to the `onProgress` event. diff --git a/src/lime/system/CFFI.hx b/src/lime/system/CFFI.hx index add385db32..20fb07e438 100644 --- a/src/lime/system/CFFI.hx +++ b/src/lime/system/CFFI.hx @@ -315,7 +315,10 @@ class CFFI var ndllFolder = __findNDLLFolder() + __sysName(); throw "Could not load lime.ndll. This file is provided with Lime's Haxelib releases, but not via Git. " + "Please copy it from Lime's latest Haxelib release into either " - + ndllFolder + " or " + ndllFolder + "64, as appropriate for your system. " + + ndllFolder + + " or " + + ndllFolder + + "64, as appropriate for your system. " + "Advanced users may run `lime rebuild cpp` instead." + (error != null ? '\nInternal error: $error' : ""); } diff --git a/src/lime/system/JNI.hx b/src/lime/system/JNI.hx index 8c1c4ad5bd..ed2007028b 100644 --- a/src/lime/system/JNI.hx +++ b/src/lime/system/JNI.hx @@ -17,7 +17,6 @@ import cpp.vm.Thread; import neko.vm.Thread; #end #end - using StringTools; /** @@ -51,12 +50,10 @@ class JNI private static function transformClassName(className:String):String { var parts:Array = className.split("."); - if (parts.length <= 1) - return className; + if (parts.length <= 1) return className; var nestedClassName:String = ""; - if (~/^[A-Z]/.match(parts[parts.length - 2])) - nestedClassName = "$" + parts.pop(); + if (~/^[A-Z]/.match(parts[parts.length - 2])) nestedClassName = "$" + parts.pop(); return parts.join("/") + nestedClassName; } @@ -430,8 +427,7 @@ class JNISafetyTools } // Don't modify functions lacking `@:runOnMainThread`. - if (field.meta == null || !Lambda.exists(field.meta, - function(meta) return meta.name == ":runOnMainThread")) + if (field.meta == null || !Lambda.exists(field.meta, function(meta) return meta.name == ":runOnMainThread")) { continue; } @@ -445,13 +441,12 @@ class JNISafetyTools // Make sure there's no return value. switch (f.ret) { - case macro:Void: + case macro :Void: // Good to go. case null: - f.ret = macro:Void; + f.ret = macro :Void; default: - Context.error("Expected return type Void, got " - + new haxe.macro.Printer().printComplexType(f.ret) + ".", field.pos); + Context.error("Expected return type Void, got " + new haxe.macro.Printer().printComplexType(f.ret) + ".", field.pos); } var args:Array = []; @@ -460,16 +455,12 @@ class JNISafetyTools args.push(macro $i{arg.name}); // Account for an unlikely edge case. - if (arg.name == field.name) - Context.error('${field.name}() should not take an argument named ${field.name}.', field.pos); + if (arg.name == field.name) Context.error('${field.name}() should not take an argument named ${field.name}.', field.pos); } // Check the thread before running the function. - f.expr = macro - if (!lime.system.JNI.JNISafetyTools.onMainThread()) - haxe.MainLoop.runInMainThread($i{field.name}.bind($a{args})) - else - ${f.expr}; + f.expr = macro if (!lime.system.JNI.JNISafetyTools.onMainThread()) haxe.MainLoop.runInMainThread($i{field.name}.bind($a{args})) else + ${f.expr}; default: } } diff --git a/src/lime/system/Orientation.hx b/src/lime/system/Orientation.hx index b3d076b908..34e5bfb95a 100644 --- a/src/lime/system/Orientation.hx +++ b/src/lime/system/Orientation.hx @@ -7,4 +7,4 @@ package lime.system; var LANDSCAPE_FLIPPED = 2; var PORTRAIT = 3; var PORTRAIT_FLIPPED = 4; -} \ No newline at end of file +} diff --git a/src/lime/system/System.hx b/src/lime/system/System.hx index 64dc264dc4..25c1fca04a 100644 --- a/src/lime/system/System.hx +++ b/src/lime/system/System.hx @@ -252,17 +252,16 @@ class System #if android var getDisplaySafeArea = JNI.createStaticMethod("org/haxe/lime/GameActivity", "getDisplaySafeAreaInsets", "()[I"); var result = getDisplaySafeArea(); - display.safeArea = new Rectangle( - display.bounds.x + result[0], - display.bounds.y + result[1], - display.bounds.width - result[0] - result[2], - display.bounds.height - result[1] - result[3]); + display.safeArea = new Rectangle(display.bounds.x + + result[0], display.bounds.y + + result[1], display.bounds.width + - result[0] + - result[2], + display.bounds.height + - result[1] + - result[3]); #else - display.safeArea = new Rectangle( - displayInfo.safeArea.x, - displayInfo.safeArea.y, - displayInfo.safeArea.width, - displayInfo.safeArea.height); + display.safeArea = new Rectangle(displayInfo.safeArea.x, displayInfo.safeArea.y, displayInfo.safeArea.width, displayInfo.safeArea.height); #end #if ios @@ -328,7 +327,8 @@ class System display.dpi = Capabilities.screenDPI; display.currentMode = new DisplayMode(Std.int(Capabilities.screenResolutionX), Std.int(Capabilities.screenResolutionY), 60, ARGB32); #if air - switch (flash.Lib.current.stage.orientation) { + switch (flash.Lib.current.stage.orientation) + { case DEFAULT: display.orientation = PORTRAIT; case UPSIDE_DOWN: @@ -340,7 +340,6 @@ class System default: display.orientation = UNKNOWN; } - #else display.orientation = UNKNOWN; #end diff --git a/src/lime/system/ThreadPool.hx b/src/lime/system/ThreadPool.hx index 6e0150341f..8cb6a874f7 100644 --- a/src/lime/system/ThreadPool.hx +++ b/src/lime/system/ThreadPool.hx @@ -16,7 +16,6 @@ import neko.vm.Thread; #elseif html5 import lime._internal.backend.html5.HTML5Thread as Thread; import lime._internal.backend.html5.HTML5Thread.Transferable; - #if lime_threads_deque #error "lime_threads_deque is not yet supported in HTML5" #end @@ -474,21 +473,21 @@ class ThreadPool extends WorkOutput } } #end - else if (event.jobID != null) + else if (event.jobID != null) + { + #if (lime_threads && lime_threads_deque) + // `cancelJob()` can't remove the job from the queue, so instead it + // marks it to be canceled later. (And "later" is now.) + if (event.event == WORK && event.threadID != null) { - #if (lime_threads && lime_threads_deque) - // `cancelJob()` can't remove the job from the queue, so instead it - // marks it to be canceled later. (And "later" is now.) - if (event.event == WORK && event.threadID != null) - { - __threads[event.threadID].thread.sendMessage({event: IDLE}); - __queuedWorkEvents--; - } - #end - - activeJob = oldActiveJob; - return; + __threads[event.threadID].thread.sendMessage({event: IDLE}); + __queuedWorkEvents--; } + #end + + activeJob = oldActiveJob; + return; + } switch (event.event) { @@ -514,7 +513,7 @@ class ThreadPool extends WorkOutput } else { - message = (event.message:Exception).details(); + message = (event.message : Exception).details(); } } else @@ -553,8 +552,7 @@ class ThreadPool extends WorkOutput case EXIT: var threadData:ThreadData = __threads[event.threadID]; - if (threadData.jobID != null) - activeThreads--; + if (threadData.jobID != null) activeThreads--; else __idleThreads--; @@ -834,7 +832,6 @@ class ThreadPool extends WorkOutput } #if lime_threads - /** Handles a thread that just became idle. Depending on the circumstances, this may do one of three things: @@ -897,12 +894,13 @@ class ThreadPool extends WorkOutput job.doWork.makePortable(); #end - var threadEvent:ThreadEvent = { - event: WORK, - jobID: job.id, - doWork: job.doWork, - state: job.state - }; + var threadEvent:ThreadEvent = + { + event: WORK, + jobID: job.id, + doWork: job.doWork, + state: job.state + }; #if lime_threads_deque __multiThreadedQueue.add(threadEvent); @@ -991,19 +989,19 @@ class ThreadPool extends WorkOutput __threads[index] = {thread: thread, jobID: null}; __idleThreads++; - thread.sendMessage({ - #if !html5 - output: this, - #end - #if lime_threads_deque - queue: __multiThreadedQueue, - #end - threadID: index - }); + thread.sendMessage( + { + #if !html5 + output: this, + #end + #if lime_threads_deque + queue: __multiThreadedQueue, + #end + threadID: index + }); return thread; } - #end // Getters & Setters @@ -1026,7 +1024,7 @@ class ThreadPool extends WorkOutput private inline function get_idleThreads():Int { return __idleThreads - #if lime_threads - __queuedExitEvents #end; + #if lime_threads - __queuedExitEvents #end; } private inline function set___singleThreadedJobRunning(value:Bool):Bool @@ -1255,7 +1253,8 @@ private abstract JobQueue(Deque) from Deque } #end -private typedef ThreadArguments = { +private typedef ThreadArguments = +{ #if !html5 var output:WorkOutput; #end @@ -1268,7 +1267,8 @@ private typedef ThreadArguments = { }; #if lime_threads -private typedef ThreadData = { +private typedef ThreadData = +{ var thread:Thread; @:optional var jobID:Int; }; diff --git a/src/lime/text/Font.hx b/src/lime/text/Font.hx index 586a75d25a..090499423f 100644 --- a/src/lime/text/Font.hx +++ b/src/lime/text/Font.hx @@ -35,56 +35,55 @@ import haxe.io.Path; class Font { /** - * The ascender value of the font. - */ + * The ascender value of the font. + */ public var ascender:Int; - /** - * The descender value of the font. - */ + /** + * The descender value of the font. + */ public var descender:Int; /** - * The height of the font. - */ + * The height of the font. + */ public var height:Int; /** - * The name of the font. - */ + * The name of the font. + */ public var name(default, null):String; /** - * The number of glyphs in the font. - */ + * The number of glyphs in the font. + */ public var numGlyphs:Int; - public var src:Dynamic; /** - * The underline position of the font. - */ + * The underline position of the font. + */ public var underlinePosition:Int; /** - * The underline thickness of the font. - */ + * The underline thickness of the font. + */ public var underlineThickness:Int; /** - * The underline position of the font. - */ + * The underline position of the font. + */ public var strikethroughPosition:Int; /** - * The underline thickness of the font. - */ + * The underline thickness of the font. + */ public var strikethroughThickness:Int; /** - * The units per EM of the font. - */ + * The units per EM of the font. + */ public var unitsPerEM:Int; @:noCompletion private var __fontID:String; @@ -95,10 +94,10 @@ class Font @:noCompletion private var __init:Bool; /** - * Creates a new instance of a Font object. - * - * @param name Optional name of the font. - */ + * Creates a new instance of a Font object. + * + * @param name Optional name of the font. + */ public function new(name:String = null) { if (name != null) @@ -149,19 +148,18 @@ class Font } /** - * Decomposes the font into outline data. - * - * @param forceAutoHint When `true`, force auto-hinting for outline decomposition. - * When `false`, preserve the unhinted glyph outlines. - * @return An instance of `NativeFontData` that contains decomposed font outline information. - */ + * Decomposes the font into outline data. + * + * @param forceAutoHint When `true`, force auto-hinting for outline decomposition. + * When `false`, preserve the unhinted glyph outlines. + * @return An instance of `NativeFontData` that contains decomposed font outline information. + */ public function decompose(forceAutoHint:Bool = true):NativeFontData { #if (lime_cffi && !macro) if (src == null) throw "Uninitialized font handle."; - var data:Dynamic = forceAutoHint - ? NativeCFFI.lime_font_outline_decompose(src, 1024 * 20) - : NativeCFFI.lime_font_outline_decompose_no_hint(src, 1024 * 20); + var data:Dynamic = forceAutoHint ? NativeCFFI.lime_font_outline_decompose(src, + 1024 * 20) : NativeCFFI.lime_font_outline_decompose_no_hint(src, 1024 * 20); #if hl if (data != null) { @@ -176,11 +174,11 @@ class Font } /** - * Creates a Font instance from byte data. - * - * @param bytes The byte data containing the font. - * @return A `Font` instance. - */ + * Creates a Font instance from byte data. + * + * @param bytes The byte data containing the font. + * @return A `Font` instance. + */ public static function fromBytes(bytes:Bytes):Font { if (bytes == null) return null; @@ -196,11 +194,11 @@ class Font } /** - * Creates a Font instance from a file path. - * - * @param path The file path of the font. - * @return A `Font` instance. - */ + * Creates a Font instance from a file path. + * + * @param path The file path of the font. + * @return A `Font` instance. + */ public static function fromFile(path:String):Font { if (path == null) return null; @@ -216,22 +214,22 @@ class Font } /** - * Loads a Font from byte data asynchronously. - * - * @param bytes The byte data containing the font. - * @return A `Future` containing a `Font` instance. - */ + * Loads a Font from byte data asynchronously. + * + * @param bytes The byte data containing the font. + * @return A `Future` containing a `Font` instance. + */ public static function loadFromBytes(bytes:Bytes):Future { return Future.withValue(fromBytes(bytes)); } /** - * Loads a Font from a file path asynchronously. - * - * @param path The file path of the font. - * @return A `Future` containing a `Font` instance. - */ + * Loads a Font from a file path asynchronously. + * + * @param path The file path of the font. + * @return A `Future` containing a `Font` instance. + */ public static function loadFromFile(path:String):Future { var request = new HTTPRequest(); @@ -249,11 +247,11 @@ class Font } /** - * Loads a Font by its name asynchronously. - * - * @param path The name of the font. - * @return A `Future` containing a `Font` instance. - */ + * Loads a Font by its name asynchronously. + * + * @param path The name of the font. + * @return A `Future` containing a `Font` instance. + */ public static function loadFromName(path:String):Future { #if (js && html5) @@ -265,11 +263,11 @@ class Font } /** - * Retrieves a glyph from the font by a character. - * - * @param character The character whose glyph to retrieve. - * @return A `Glyph` instance representing the glyph of the character. - */ + * Retrieves a glyph from the font by a character. + * + * @param character The character whose glyph to retrieve. + * @return A `Glyph` instance representing the glyph of the character. + */ public function getGlyph(character:String):Glyph { #if (lime_cffi && !macro) @@ -280,16 +278,18 @@ class Font } /** - * Retrieves an array of glyphs for a set of characters. - * - * @param characters The string containing characters to retrieve glyphs for. - * @return An array of `Glyph` instances representing the glyphs of the characters. - */ + * Retrieves an array of glyphs for a set of characters. + * + * @param characters The string containing characters to retrieve glyphs for. + * @return An array of `Glyph` instances representing the glyphs of the characters. + */ public function getGlyphs(characters:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. "):Array { #if (lime_cffi && !macro) #if hl - return [for (index in NativeCFFI.lime_font_get_glyph_indices(src, characters)) new Glyph(index)]; + return [ + for (index in NativeCFFI.lime_font_get_glyph_indices(src, characters)) new Glyph(index) + ]; #else return NativeCFFI.lime_font_get_glyph_indices(src, characters); #end @@ -299,11 +299,11 @@ class Font } /** - * Retrieves metrics for a given glyph. - * - * @param glyph The glyph whose metrics to retrieve. - * @return A `GlyphMetrics` instance containing the metrics of the glyph. - */ + * Retrieves metrics for a given glyph. + * + * @param glyph The glyph whose metrics to retrieve. + * @return A `GlyphMetrics` instance containing the metrics of the glyph. + */ public function getGlyphMetrics(glyph:Glyph):GlyphMetrics { #if (lime_cffi && !macro) @@ -322,26 +322,26 @@ class Font } /** - * Renders a specific glyph to an image. - * - * @param glyph The glyph to render. - * @param fontSize The size to render the glyph at. - * @return An `Image` instance representing the rendered glyph. - */ + * Renders a specific glyph to an image. + * + * @param glyph The glyph to render. + * @param fontSize The size to render the glyph at. + * @return An `Image` instance representing the rendered glyph. + */ public function renderGlyph(glyph:Glyph, fontSize:Int, dpi:Int = 96):Image { return renderGlyphWithLoadFlags(glyph, fontSize, dpi); } /** - * Renders a specific glyph to an image using explicit FreeType load flags. - * - * @param glyph The glyph to render. - * @param fontSize The size to render the glyph at. - * @param dpi The DPI used to size the glyph before rasterization. - * @param loadFlags Additional FreeType load flags to apply when rasterizing. - * @return An `Image` instance representing the rendered glyph. - */ + * Renders a specific glyph to an image using explicit FreeType load flags. + * + * @param glyph The glyph to render. + * @param fontSize The size to render the glyph at. + * @param dpi The DPI used to size the glyph before rasterization. + * @param loadFlags Additional FreeType load flags to apply when rasterizing. + * @return An `Image` instance representing the rendered glyph. + */ public function renderGlyphWithLoadFlags(glyph:Glyph, fontSize:Int, dpi:Int = 96, ?loadFlags:Int):Image { #if (lime_cffi && !macro) @@ -351,9 +351,8 @@ class Font var bytes:Bytes = Bytes.alloc(0); // Allocate some reasonable initial size // Call native function to render glyph and get byte data - bytes = loadFlags == null - ? NativeCFFI.lime_font_render_glyph(src, glyph, bytes) - : NativeCFFI.lime_font_render_glyph_with_flags(src, glyph, loadFlags, bytes); + bytes = loadFlags == null ? NativeCFFI.lime_font_render_glyph(src, glyph, + bytes) : NativeCFFI.lime_font_render_glyph_with_flags(src, glyph, loadFlags, bytes); if (bytes != null && bytes.length > 0) { @@ -405,13 +404,14 @@ class Font return null; } + /** - * Renders a set of glyphs to images. - * - * @param glyphs The glyphs to render. - * @param fontSize The size to render the glyphs at. - * @return A `Map` containing glyphs mapped to their corresponding images. - */ + * Renders a set of glyphs to images. + * + * @param glyphs The glyphs to render. + * @param fontSize The size to render the glyphs at. + * @return A `Map` containing glyphs mapped to their corresponding images. + */ public function renderGlyphs(glyphs:Array, fontSize:Int):Map { #if (lime_cffi && !macro) @@ -760,8 +760,8 @@ class Font } /** -* Represents decomposed font data, containing kerning information, glyphs, and other properties. -*/ + * Represents decomposed font data, containing kerning information, glyphs, and other properties. + */ typedef NativeFontData = { var has_kerning:Bool; @@ -781,8 +781,8 @@ typedef NativeFontData = } /** -* Represents data for an individual glyph, including dimensions and control points. -*/ + * Represents data for an individual glyph, including dimensions and control points. + */ typedef NativeGlyphData = { var char_code:Int; @@ -795,8 +795,8 @@ typedef NativeGlyphData = } /** -* Represents kerning information between two glyphs. -*/ + * Represents kerning information between two glyphs. + */ typedef NativeKerningData = { var left_glyph:Int; diff --git a/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx b/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx index 92f60090e3..b932134305 100644 --- a/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx +++ b/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx @@ -12,6 +12,7 @@ package lime.text.harfbuzz; // // } } + // @:cffi private static function lime_hb_buffer_serialize_format_from_string (str:String, len:Int):Int; // @:cffi private static function lime_hb_buffer_serialize_format_to_string (format:Int):CFFIPointer; // @:cffi private static function lime_hb_buffer_serialize_list_formats ():CFFIPointer; diff --git a/src/lime/tools/AIRHelper.hx b/src/lime/tools/AIRHelper.hx index d3837bba5c..5495fc39cc 100644 --- a/src/lime/tools/AIRHelper.hx +++ b/src/lime/tools/AIRHelper.hx @@ -5,22 +5,20 @@ import sys.FileSystem; class AIRHelper { - public static function build(project:HXProject, workingDirectory:String, targetPlatform:Platform, targetPathWithoutExtension:String, applicationXML:String, - files:Array, fileDirectory:String = null):String + public static function build(project:HXProject, workingDirectory:String, targetPlatform:Platform, targetPathWithoutExtension:String, + applicationXML:String, files:Array, fileDirectory:String = null):String { var airTarget = "bundle"; - switch(targetPlatform) + switch (targetPlatform) { case WINDOWS: - if (project.targetFlags.exists("shared")) { airTarget = "air"; } case MAC: - if (project.targetFlags.exists("shared")) { airTarget = "air"; @@ -53,7 +51,8 @@ class AIRHelper exportMethod = m; } } - if (exportMethod == null && project.targetFlags.exists("final")) { + if (exportMethod == null && project.targetFlags.exists("final")) + { exportMethod = "appstore"; } @@ -122,14 +121,12 @@ class AIRHelper switch (targetPlatform) { case WINDOWS: - if (airTarget == "air") { extension = ".air"; } case MAC: - if (airTarget == "bundle") { extension = ".app"; @@ -140,7 +137,6 @@ class AIRHelper } case ANDROID: - if (StringTools.startsWith(airTarget, "aab")) { extension = ".aab"; @@ -155,7 +151,6 @@ class AIRHelper } case IOS: - extension = ".ipa"; default: diff --git a/src/lime/tools/ApplicationData.hx b/src/lime/tools/ApplicationData.hx index 301917209d..a81d4688c2 100644 --- a/src/lime/tools/ApplicationData.hx +++ b/src/lime/tools/ApplicationData.hx @@ -12,13 +12,14 @@ abstract ApplicationData({ }) from Dynamic { @:noCompletion - public static var expectedFields:ApplicationData = { - file: "", - init: "", - main: "", - path: "", - preloader: "", - swfVersion: 0.0, - url: "" - }; + public static var expectedFields:ApplicationData = + { + file: "", + init: "", + main: "", + path: "", + preloader: "", + swfVersion: 0.0, + url: "" + }; } diff --git a/src/lime/tools/AssetHelper.hx b/src/lime/tools/AssetHelper.hx index f0ab371c82..ed4bb6bdbb 100644 --- a/src/lime/tools/AssetHelper.hx +++ b/src/lime/tools/AssetHelper.hx @@ -25,13 +25,65 @@ class AssetHelper { knownExtensions = [ - "jpg" => IMAGE, "jpeg" => IMAGE, "png" => IMAGE, "gif" => IMAGE, "webp" => IMAGE, "bmp" => IMAGE, "tiff" => IMAGE, "jfif" => IMAGE, "otf" => FONT, - "ttf" => FONT, "wav" => SOUND, "wave" => SOUND, "flac" => SOUND, "mid" => SOUND, "midi" => SOUND, "ogg" => SOUND, "spx" => SOUND, "au" => SOUND, - "aiff" => SOUND, "oga" => SOUND, "mp3" => MUSIC, "mp2" => MUSIC, "exe" => BINARY, "bin" => BINARY, "so" => BINARY, "pch" => BINARY, - "dll" => BINARY, "zip" => BINARY, "tar" => BINARY, "gz" => BINARY, "fla" => BINARY, "swf" => BINARY, "atf" => BINARY, "psd" => BINARY, - "awd" => BINARY, "txt" => TEXT, "text" => TEXT, "xml" => TEXT, "java" => TEXT, "hx" => TEXT, "cpp" => TEXT, "c" => TEXT, "h" => TEXT, - "cs" => TEXT, "js" => TEXT, "mm" => TEXT, "hxml" => TEXT, "html" => TEXT, "json" => TEXT, "css" => TEXT, "gpe" => TEXT, "pbxproj" => TEXT, - "plist" => TEXT, "properties" => TEXT, "ini" => TEXT, "hxproj" => TEXT, "nmml" => TEXT, "lime" => TEXT, "svg" => TEXT, + "jpg" => IMAGE, + "jpeg" => IMAGE, + "png" => IMAGE, + "gif" => IMAGE, + "webp" => IMAGE, + "bmp" => IMAGE, + "tiff" => IMAGE, + "jfif" => IMAGE, + "otf" => FONT, + "ttf" => FONT, + "wav" => SOUND, + "wave" => SOUND, + "flac" => SOUND, + "mid" => SOUND, + "midi" => SOUND, + "ogg" => SOUND, + "spx" => SOUND, + "au" => SOUND, + "aiff" => SOUND, + "oga" => SOUND, + "mp3" => MUSIC, + "mp2" => MUSIC, + "exe" => BINARY, + "bin" => BINARY, + "so" => BINARY, + "pch" => BINARY, + "dll" => BINARY, + "zip" => BINARY, + "tar" => BINARY, + "gz" => BINARY, + "fla" => BINARY, + "swf" => BINARY, + "atf" => BINARY, + "psd" => BINARY, + "awd" => BINARY, + "txt" => TEXT, + "text" => TEXT, + "xml" => TEXT, + "java" => TEXT, + "hx" => TEXT, + "cpp" => TEXT, + "c" => TEXT, + "h" => TEXT, + "cs" => TEXT, + "js" => TEXT, + "mm" => TEXT, + "hxml" => TEXT, + "html" => TEXT, + "json" => TEXT, + "css" => TEXT, + "gpe" => TEXT, + "pbxproj" => TEXT, + "plist" => TEXT, + "properties" => TEXT, + "ini" => TEXT, + "hxproj" => TEXT, + "nmml" => TEXT, + "lime" => TEXT, + "svg" => TEXT, ]; } diff --git a/src/lime/tools/CPPHelper.hx b/src/lime/tools/CPPHelper.hx index e2877c9205..66d2dc71bc 100644 --- a/src/lime/tools/CPPHelper.hx +++ b/src/lime/tools/CPPHelper.hx @@ -208,7 +208,10 @@ class CPPHelper if (!FileSystem.exists(path)) { - Log.warn("Skipping rebuild. Path not found: " + path + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); + Log.warn("Skipping rebuild. Path not found: " + + path + + + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); return; } @@ -221,7 +224,10 @@ class CPPHelper if (!FileSystem.exists(Path.combine(path, buildFile))) { - Log.warn("Skipping rebuild. Path not found: " + path + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); + Log.warn("Skipping rebuild. Path not found: " + + path + + + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); return; } diff --git a/src/lime/tools/CSHelper.hx b/src/lime/tools/CSHelper.hx index 2aa3a391d1..e92149248c 100644 --- a/src/lime/tools/CSHelper.hx +++ b/src/lime/tools/CSHelper.hx @@ -11,8 +11,16 @@ using StringTools; class CSHelper { public static var ndllSourceFiles:Array = [ - "cs.ndll.NDLLFunction", "cs.ndll.CFFICSLoader", "cs.ndll.CSAbstract", "cs.ndll.CSHandleContainer", "cs.ndll.CSHandleScope", "cs.ndll.CSPersistent", - "cs.ndll.DelegateConverter", "cs.ndll.HandleUtils", "cs.ndll.NativeMethods", "cs.ndll.NDLLFunction", + "cs.ndll.NDLLFunction", + "cs.ndll.CFFICSLoader", + "cs.ndll.CSAbstract", + "cs.ndll.CSHandleContainer", + "cs.ndll.CSHandleScope", + "cs.ndll.CSPersistent", + "cs.ndll.DelegateConverter", + "cs.ndll.HandleUtils", + "cs.ndll.NativeMethods", + "cs.ndll.NDLLFunction", ]; private static function getAndroidABIName(arch:Architecture):String diff --git a/src/lime/tools/ConfigData.hx b/src/lime/tools/ConfigData.hx index 96b3928505..1ae3c54c2e 100644 --- a/src/lime/tools/ConfigData.hx +++ b/src/lime/tools/ConfigData.hx @@ -175,7 +175,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic return defaultValue; } - public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{ key:String, value:Dynamic }> + public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{key:String, value:Dynamic}> { var values = {}; if (defaultValues != null) @@ -192,10 +192,10 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic } } - var pairs:Array<{ key:String, value:Dynamic }> = []; + var pairs:Array<{key:String, value:Dynamic}> = []; for (key in Reflect.fields(values)) { - pairs.push({ key: key, value: Reflect.field(values, key) }); + pairs.push({key: key, value: Reflect.field(values, key)}); } return pairs; @@ -237,7 +237,10 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic continue; } - if (valueSource != valueDest && valueDest != null && typeSource != "TObject" && !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueSource, Array)) + if (valueSource != valueDest + && valueDest != null + && typeSource != "TObject" + && !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array)) { if (!Reflect.hasField(destination, ARRAY + field)) { @@ -264,11 +267,13 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic { mergeValues(valueSource, valueDest); } - else if (typeDest == "TClass" && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array) && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueDest, Array)) + else if (typeDest == "TClass" + && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array) + && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueDest, Array)) { - for (item in (cast valueSource:Array)) + for (item in (cast valueSource : Array)) { - (cast valueDest:Array).push(item); + (cast valueDest : Array).push(item); } } else @@ -529,11 +534,13 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic // Getters & Setters - private inline function get_xmlChildren():Array { + private inline function get_xmlChildren():Array + { return Reflect.field(this, "config:xml_children"); } - private inline function set_xmlChildren(value:Array):Array { + private inline function set_xmlChildren(value:Array):Array + { Reflect.setField(this, "config:xml_children", value); return value; } diff --git a/src/lime/tools/FlashHelper.hx b/src/lime/tools/FlashHelper.hx index 07b68201f5..0b4f840432 100644 --- a/src/lime/tools/FlashHelper.hx +++ b/src/lime/tools/FlashHelper.hx @@ -623,7 +623,22 @@ class FlashHelper var label = (id > 0 ? Std.string(id + 1) : ""); var swfVersions = [ - 9, 10, /*10.1,*/ 10.2, 10.3, 11, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 12, 13, 14 + 9, + 10, /*10.1,*/ + 10.2, + 10.3, + 11, + 11.1, + 11.2, + 11.3, + 11.4, + 11.5, + 11.6, + 11.7, + 11.8, + 12, + 13, + 14 ]; var flashVersion = 9; diff --git a/src/lime/tools/HTML5Helper.hx b/src/lime/tools/HTML5Helper.hx index d7550381f1..f895a46295 100644 --- a/src/lime/tools/HTML5Helper.hx +++ b/src/lime/tools/HTML5Helper.hx @@ -107,11 +107,11 @@ class HTML5Helper { suffix += "32"; } - else if( System.hostArchitecture == ARMV7) + else if (System.hostArchitecture == ARMV7) { suffix += "Arm"; } - else if( System.hostArchitecture == ARM64) + else if (System.hostArchitecture == ARM64) { suffix += "Arm64"; } @@ -174,7 +174,8 @@ class HTML5Helper { var executable = "npx"; var terser = "terser"; - if (!project.targetFlags.exists("npx")) { + if (!project.targetFlags.exists("npx")) + { var suffix = switch (System.hostPlatform) { case WINDOWS: "-windows.exe"; @@ -207,14 +208,7 @@ class HTML5Helper } } - var args = [ - terser, - sourceFile, - "-c", - "-m", - "-o", - tempFile - ]; + var args = [terser, sourceFile, "-c", "-m", "-o", tempFile]; if (FileSystem.exists(sourceFile + ".map")) { @@ -245,9 +239,7 @@ class HTML5Helper if (project.targetFlags.exists("npx")) { executable = "npx"; - args = [ - "google-closure-compiler" - ]; + args = ["google-closure-compiler"]; } else { diff --git a/src/lime/tools/HXProject.hx b/src/lime/tools/HXProject.hx index 164a3e0fee..c87cf3dc06 100644 --- a/src/lime/tools/HXProject.hx +++ b/src/lime/tools/HXProject.hx @@ -107,7 +107,7 @@ class HXProject extends Script var classRef = Type.resolveClass(inputData.name); if (classRef == null) { - Log.error('Unable to find class ${ inputData.name } in ${ inputData.projectFile }'); + Log.error('Unable to find class ${inputData.name} in ${inputData.projectFile}'); return; } var instance = Type.createInstance(classRef, []); @@ -189,7 +189,20 @@ class HXProject extends Script else { environment = Sys.environment(); - for (conflict in ["air", "android", "cpp", "flash", "hl", "html5", "ios", "linux", "mac", "neko", "webassembly", "windows"]) + for (conflict in [ + "air", + "android", + "cpp", + "flash", + "hl", + "html5", + "ios", + "linux", + "mac", + "neko", + "webassembly", + "windows" + ]) { environment.remove(conflict); } @@ -212,7 +225,7 @@ class HXProject extends Script splashScreens = new Array(); targetHandlers = new Map(); - config.set("android", { manifest:{}, application:{}, activity:{} }); + config.set("android", {manifest: {}, application: {}, activity: {}}); config.get("android.manifest").xmlChildren = []; config.get("android.application").xmlChildren = []; config.get("android.activity").xmlChildren = []; @@ -403,11 +416,12 @@ class HXProject extends Script var args = [ name, #if lime - "-lib", "lime", - "-lib", "hxp", + "-lib", "lime", "-lib", "hxp", #end - "-cp", tempDirectory, - "-cp", Path.combine(Haxelib.getPath(new Haxelib("hxp")), "src") + "-cp", + tempDirectory, + "-cp", + Path.combine(Haxelib.getPath(new Haxelib("hxp")), "src") ]; var input = File.read(classFile, false); var tag = "@:compiler("; @@ -682,6 +696,7 @@ class HXProject extends Script @:privateAccess projectXML.parseXML(new Access(Xml.parse(xml).firstElement()), ""); merge(projectXML); } + // #end private function initializeDefines():Void @@ -793,8 +808,7 @@ class HXProject extends Script defines.set("native", "1"); defines.set("cpp", "1"); } - else if (targetFlags.exists("cpp") - || ((platformType != PlatformType.WEB) && !targetFlags.exists("html5"))) + else if (targetFlags.exists("cpp") || ((platformType != PlatformType.WEB) && !targetFlags.exists("html5"))) { defines.set("targetType", "cpp"); defines.set("native", "1"); diff --git a/src/lime/tools/HashlinkHelper.hx b/src/lime/tools/HashlinkHelper.hx index efd1d29e5d..879f180bcc 100644 --- a/src/lime/tools/HashlinkHelper.hx +++ b/src/lime/tools/HashlinkHelper.hx @@ -35,11 +35,8 @@ class HashlinkHelper var peOffset = readUInt32LE(bytes, 0x3C); var subsystemOffset = peOffset + 24 + 68; - if (peOffset < 0 || subsystemOffset + 1 >= bytes.length - || bytes.get(peOffset) != 0x50 - || bytes.get(peOffset + 1) != 0x45 - || bytes.get(peOffset + 2) != 0 - || bytes.get(peOffset + 3) != 0) + if (peOffset < 0 || subsystemOffset + 1 >= bytes.length || bytes.get(peOffset) != 0x50 || bytes.get(peOffset + 1) != 0x45 + || bytes.get(peOffset + 2) != 0 || bytes.get(peOffset + 3) != 0) { Log.warn('Could not hide HashLink console: "$executablePath" has an unsupported PE header'); return; @@ -68,7 +65,8 @@ class HashlinkHelper Sys.exit(1); ""; }; - if(is64) { + if (is64) + { bindir += "64"; } @@ -81,9 +79,8 @@ class HashlinkHelper if (project.targetFlags.exists("hlc")) { var limeDirectory = Haxelib.getPath(new Haxelib("lime"), true); - var includeDirectory = sys.FileSystem.exists(Path.combine(limeDirectory, "project")) - ? Path.combine(limeDirectory, "project/lib/hashlink/src") - : Path.combine(limeDirectory, "templates/bin/hl/include"); + var includeDirectory = sys.FileSystem.exists(Path.combine(limeDirectory, + "project")) ? Path.combine(limeDirectory, "project/lib/hashlink/src") : Path.combine(limeDirectory, "templates/bin/hl/include"); System.copyFile(Path.combine(includeDirectory, "hlc.h"), Path.combine(targetDirectory, "obj/hlc.h"), null, false); System.copyFile(Path.combine(includeDirectory, "hl.h"), Path.combine(targetDirectory, "obj/hl.h"), null, false); @@ -167,7 +164,8 @@ class HashlinkHelper var appMainCPath = Path.combine(targetDirectory, "obj/ApplicationMain.c"); var appMainCText = System.readText(appMainCPath); var index = appMainCText.indexOf("#ifndef HL_MAKE"); - appMainCText = appMainCText.substr(0, index) + " + appMainCText = appMainCText.substr(0, index) + + " // --------- START LIME HL/C INJECTED CODE --------- // // undefine things to avoid Haxe field name conflicts #undef BIG_ENDIAN @@ -197,7 +195,8 @@ class HashlinkHelper #undef __valid #undef WAIT_FAILED // ---------- END LIME HL/C INJECTED CODE ---------- // -" + appMainCText.substr(index); +" + + appMainCText.substr(index); System.writeText(appMainCText, appMainCPath); } else diff --git a/src/lime/tools/IOSHelper.hx b/src/lime/tools/IOSHelper.hx index c4202c2faf..431312f13a 100644 --- a/src/lime/tools/IOSHelper.hx +++ b/src/lime/tools/IOSHelper.hx @@ -364,7 +364,8 @@ class IOSHelper var requireIPhone = project.config.getString("ios.device", "universal") == "iphone"; var xcodeVersion = Std.parseFloat(getXcodeVersion()); - if (!Math.isNaN(xcodeVersion) && xcodeVersion >= 16) { + if (!Math.isNaN(xcodeVersion) && xcodeVersion >= 16) + { // ios-deploy doesn't work with newer iOS SDKs where it can't // find DeveloperDiskImage.dmg. however, Xcode 16 adds new // commands for installing and launching apps on connected @@ -389,10 +390,7 @@ class IOSHelper // 1. the platform must always be iOS (which includes iPadOS). // 2. the device must be in developer mode. // 3. if required by the project config, limit to iPhone or iPad only - var baseFilters = [ - filterPlatformIOS, - filterDeveloperModeEnabled, - ]; + var baseFilters = [filterPlatformIOS, filterDeveloperModeEnabled,]; if (requireIPad) { baseFilters.push(filterDeviceTypeIPad); @@ -411,10 +409,7 @@ class IOSHelper { for (transportTypeFilter in transportTypeFilters) { - deviceUUID = findDeviceUUIDWithFilters(baseFilters.concat([ - stateFilter, - transportTypeFilter - ])); + deviceUUID = findDeviceUUIDWithFilters(baseFilters.concat([stateFilter, transportTypeFilter])); if (deviceUUID != null && deviceUUID.length > 0) { break; @@ -426,7 +421,8 @@ class IOSHelper } } - if (deviceUUID == null || deviceUUID.length == 0) { + if (deviceUUID == null || deviceUUID.length == 0) + { // devices running iOS 16 and older don't support // xcrun devicectl, so if no device was found, try falling // back to ios-deploy @@ -440,9 +436,28 @@ class IOSHelper Log.info("Detected iOS device UUID: " + deviceUUID); } - System.runCommand("", "xcrun", ["devicectl", "device", "install", "app", "--device", deviceUUID, FileSystem.fullPath(applicationPath)]); - System.runCommand("", "xcrun", ["devicectl", "device", "process", "launch", "--console", "--device", deviceUUID, project.meta.packageName]); - } else { + System.runCommand("", "xcrun", [ + "devicectl", + "device", + "install", + "app", + "--device", + deviceUUID, + FileSystem.fullPath(applicationPath) + ]); + System.runCommand("", "xcrun", [ + "devicectl", + "device", + "process", + "launch", + "--console", + "--device", + deviceUUID, + project.meta.packageName + ]); + } + else + { // continue using ios-deploy if Xcode version is 15 or older fallbackLaunch(project, applicationPath); } @@ -451,12 +466,16 @@ class IOSHelper private static function findDeviceUUIDWithFilters(filters:Array):String { - var listDevicesOutput = System.runProcess("", "xcrun", - [ - "devicectl", "list", "devices", - "--hide-default-columns", "--columns", "Identifier", - "--filter", filters.join(" AND ") - ]); + var listDevicesOutput = System.runProcess("", "xcrun", [ + "devicectl", + "list", + "devices", + "--hide-default-columns", + "--columns", + "Identifier", + "--filter", + filters.join(" AND ") + ]); var ready = false; for (line in listDevicesOutput.split("\n")) { diff --git a/src/lime/tools/IconHelper.hx b/src/lime/tools/IconHelper.hx index 95b1a7d6c0..694c18af4f 100644 --- a/src/lime/tools/IconHelper.hx +++ b/src/lime/tools/IconHelper.hx @@ -311,7 +311,8 @@ class IconHelper } if (Math.abs(iconDifference) < Math.abs(matchDifference) - || iconDifference == matchDifference && icon.priority >= match.priority) + || iconDifference == matchDifference + && icon.priority >= match.priority) { match = icon; matchDifference = iconDifference; diff --git a/src/lime/tools/MetaData.hx b/src/lime/tools/MetaData.hx index f06a76b20d..8680a18dc8 100644 --- a/src/lime/tools/MetaData.hx +++ b/src/lime/tools/MetaData.hx @@ -14,15 +14,16 @@ abstract MetaData({ }) from Dynamic { @:noCompletion - public static var expectedFields:MetaData = { - buildNumber: "", - company: "", - companyId: "", - companyUrl: "", - description: "", - packageName: "", - title: "", - version: "", - copyrightYears: "" - }; + public static var expectedFields:MetaData = + { + buildNumber: "", + company: "", + companyId: "", + companyUrl: "", + description: "", + packageName: "", + title: "", + version: "", + copyrightYears: "" + }; } diff --git a/src/lime/tools/PlatformTarget.hx b/src/lime/tools/PlatformTarget.hx index 49e5b17a95..b752ac16f9 100644 --- a/src/lime/tools/PlatformTarget.hx +++ b/src/lime/tools/PlatformTarget.hx @@ -57,8 +57,7 @@ class PlatformTarget // known issue: this may not log in `-eval` mode on Linux inline function logCommand(command:String):Void { - if (!Reflect.hasField(metaFields, command) - || !Reflect.hasField(Reflect.field(metaFields, command), "ignore")) + if (!Reflect.hasField(metaFields, command) || !Reflect.hasField(Reflect.field(metaFields, command), "ignore")) { Log.info("", "\n" + Log.accentColor + "Running command: " + command.toUpperCase() + Log.resetColor); } @@ -137,8 +136,7 @@ class PlatformTarget run(); } - if ((command == "test" || command == "trace" || command == "run" || command == "rerun") - && (traceEnabled || command == "trace")) + if ((command == "test" || command == "trace" || command == "run" || command == "rerun") && (traceEnabled || command == "trace")) { logCommand("trace"); this.trace(); @@ -264,7 +262,10 @@ class PlatformTarget } } - private function getDisplayHXML():HXML { return null; } + private function getDisplayHXML():HXML + { + return null; + } // Functions to track and delete stale files diff --git a/src/lime/tools/ProjectXMLParser.hx b/src/lime/tools/ProjectXMLParser.hx index e535b37f5e..83b5ec4ef8 100644 --- a/src/lime/tools/ProjectXMLParser.hx +++ b/src/lime/tools/ProjectXMLParser.hx @@ -1434,7 +1434,6 @@ class ProjectXMLParser extends HXProject sources.push(path); case "extension": - // deprecated case "haxedef": @@ -1536,7 +1535,6 @@ class ProjectXMLParser extends HXProject parseModuleElement(element, extensionPath); case "ssl": - // if (wantSslCertificate()) // parseSsl (element); diff --git a/src/lime/tools/WindowData.hx b/src/lime/tools/WindowData.hx index 1f74f090ad..712cb44b7e 100644 --- a/src/lime/tools/WindowData.hx +++ b/src/lime/tools/WindowData.hx @@ -37,38 +37,39 @@ abstract WindowData({ }) from Dynamic { @:noCompletion - public static var expectedFields:WindowData = { - width: 0, - height: 0, - x: 0.0, - y: 0.0, - background: 0, - parameters: "", - fps: 0, - hardware: false, - display: 0, - resizable: false, - borderless: false, - vsync: false, - vsyncMode: null, - fullscreen: false, - allowHighDPI: false, - alwaysOnTop: false, - antialiasing: 0, - renderType: null, - orientation: Orientation.AUTO, - allowShaders: false, - requireShaders: false, - depthBuffer: false, - stencilBuffer: false, - title: "", - transparent: false, - #if (js && html5) - element: null, - #end - colorDepth: 0, - minimized: false, - maximized: false, - hidden: false - }; + public static var expectedFields:WindowData = + { + width: 0, + height: 0, + x: 0.0, + y: 0.0, + background: 0, + parameters: "", + fps: 0, + hardware: false, + display: 0, + resizable: false, + borderless: false, + vsync: false, + vsyncMode: null, + fullscreen: false, + allowHighDPI: false, + alwaysOnTop: false, + antialiasing: 0, + renderType: null, + orientation: Orientation.AUTO, + allowShaders: false, + requireShaders: false, + depthBuffer: false, + stencilBuffer: false, + title: "", + transparent: false, + #if (js && html5) + element: null, + #end + colorDepth: 0, + minimized: false, + maximized: false, + hidden: false + }; } diff --git a/src/lime/tools/XCodeHelper.hx b/src/lime/tools/XCodeHelper.hx index 7abd0c08dd..1121a79090 100644 --- a/src/lime/tools/XCodeHelper.hx +++ b/src/lime/tools/XCodeHelper.hx @@ -7,10 +7,7 @@ class XCodeHelper { // different computers may have different sets of simulators installed // so there isn't necessarily a reasonable default for ipads - private static var DEFAULT_IPAD_SIMULATOR_NAMES = [ - "ipad", - "ipad-air" - ]; + private static var DEFAULT_IPAD_SIMULATOR_NAMES = ["ipad", "ipad-air"]; private static var DEFAULT_IPAD_AIR_SIMULATOR_FALLBACK_REGEX = ~/ipad-air-.+/g; private static var DEFAULT_IPAD_SIMULATOR_FALLBACK_REGEX = ~/ipad-.+/g; // this should be a standard iPhone of a particular generation diff --git a/src/lime/ui/FileDialog.hx b/src/lime/ui/FileDialog.hx index 7004406412..31a1a349b2 100644 --- a/src/lime/ui/FileDialog.hx +++ b/src/lime/ui/FileDialog.hx @@ -99,10 +99,7 @@ class FileDialog extension = extension.substr(1); } - if (extension.length == 0 - || extension.indexOf("*") != -1 - || extension.indexOf("?") != -1 - || extension.indexOf("/") != -1 + if (extension.length == 0 || extension.indexOf("*") != -1 || extension.indexOf("?") != -1 || extension.indexOf("/") != -1 || extension.indexOf("\\") != -1) { continue; @@ -132,9 +129,7 @@ class FileDialog if (type == null) type = FileDialogType.OPEN; #if sys - if (defaultPath != null && defaultPath.length > 0 - && FileSystem.exists(defaultPath) - && FileSystem.isDirectory(defaultPath)) + if (defaultPath != null && defaultPath.length > 0 && FileSystem.exists(defaultPath) && FileSystem.isDirectory(defaultPath)) { // if the default path is a directory, and the default path doesn't // end with a separator, tiny file dialogs may open its parent diff --git a/src/lime/ui/Gamepad.hx b/src/lime/ui/Gamepad.hx index 19017ead14..3c7ab47f74 100644 --- a/src/lime/ui/Gamepad.hx +++ b/src/lime/ui/Gamepad.hx @@ -65,18 +65,17 @@ class Gamepad #if (lime_cffi && !macro) NativeCFFI.lime_gamepad_rumble(this.id, lowFrequencyRumble, highFrequencyRumble, duration); #elseif (js && html5) - var actuator:Dynamic = (untyped __jsGamepad.vibrationActuator) ? untyped __jsGamepad.vibrationActuator - : (untyped __jsGamepad.hapticActuators) ? untyped __jsGamepad.hapticActuators[0] - : null; + var actuator:Dynamic = (untyped __jsGamepad.vibrationActuator) ? untyped __jsGamepad.vibrationActuator : (untyped __jsGamepad.hapticActuators) ? untyped __jsGamepad.hapticActuators[0] : null; if (actuator == null) return; if (untyped actuator.playEffect) { - untyped actuator.playEffect("dual-rumble", { - duration: duration, - strongMagnitude: lowFrequencyRumble, - weakMagnitude: highFrequencyRumble - }); + untyped actuator.playEffect("dual-rumble", + { + duration: duration, + strongMagnitude: lowFrequencyRumble, + weakMagnitude: highFrequencyRumble + }); } else if (untyped actuator.pulse) { diff --git a/src/lime/ui/KeyCode.hx b/src/lime/ui/KeyCode.hx index 36bdedf7de..7772aaa710 100644 --- a/src/lime/ui/KeyCode.hx +++ b/src/lime/ui/KeyCode.hx @@ -10,8 +10,7 @@ import lime._internal.backend.native.NativeCFFI; @see `lime.ui.Window.onKeyUp` @see `lime.ui.ScanCode` **/ -@:access(lime._internal.backend.native.NativeCFFI) -#if (haxe_ver >= 4.0) enum #else @:enum #end abstract KeyCode(Int) from Int to Int from UInt to UInt +@:access(lime._internal.backend.native.NativeCFFI) #if (haxe_ver >= 4.0) enum #else @:enum #end abstract KeyCode(Int) from Int to Int from UInt to UInt { var UNKNOWN = 0x00; var BACKSPACE = 0x08; diff --git a/src/lime/ui/ScanCode.hx b/src/lime/ui/ScanCode.hx index 1d115499ed..c6a9eab247 100644 --- a/src/lime/ui/ScanCode.hx +++ b/src/lime/ui/ScanCode.hx @@ -11,8 +11,7 @@ import lime._internal.backend.native.NativeCFFI; @see `lime.ui.KeyCode` **/ @:access(lime._internal.backend.native.NativeCFFI) -@:access(lime.ui.KeyCode) -#if (haxe_ver >= 4.0) enum #else @:enum #end abstract ScanCode(Int) from Int to Int from UInt to UInt +@:access(lime.ui.KeyCode) #if (haxe_ver >= 4.0) enum #else @:enum #end abstract ScanCode(Int) from Int to Int from UInt to UInt { var UNKNOWN = 0; var BACKSPACE = 42; diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index 37e5f870b2..eb364c4bcd 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -56,6 +56,7 @@ class Window * vertical-sync setting. **/ public var vsyncMode(get, set):VSyncMode; + public var fullscreen(get, set):Bool; public var height(get, set):Int; public var hidden(get, null):Bool; diff --git a/src/lime/ui/WindowAttributes.hx b/src/lime/ui/WindowAttributes.hx index fbf59dffe1..96d5fbe6e7 100644 --- a/src/lime/ui/WindowAttributes.hx +++ b/src/lime/ui/WindowAttributes.hx @@ -32,6 +32,7 @@ typedef WindowAttributes = shared application frame profile. **/ @:optional public var frameProfile:FrameProfile; + @:optional public var fullscreen:Bool; @:optional public var height:Int; @:optional public var hidden:Bool; diff --git a/src/lime/utils/ArrayBufferView.hx b/src/lime/utils/ArrayBufferView.hx index 8b25a82c79..aa429a1277 100644 --- a/src/lime/utils/ArrayBufferView.hx +++ b/src/lime/utils/ArrayBufferView.hx @@ -46,6 +46,7 @@ class ArrayBufferView } // new // Constructor helpers + @:allow(lime.utils) #if !no_typedarray_inline inline @@ -138,7 +139,8 @@ class ArrayBufferView { if (view != null && array == null) { - if (offset + view.length > this.length) { + if (offset + view.length > this.length) + { throw TAError.RangeError; } if (bytesPerElement == view.bytesPerElement) @@ -296,12 +298,13 @@ class ArrayBufferView // Non-spec #if !no_typedarray_inline #end - function copyFromArray(array:Array<#if hl Dynamic #else Float #end>, offset:Int = 0) + function copyFromArray(array:Array< #if hl Dynamic #else Float #end>, offset:Int = 0) { // Ideally, native semantics could be used, like cpp.NativeArray.blit var i = 0, len = array.length; - if (offset + len > this.length) { + if (offset + len > this.length) + { throw TAError.RangeError; } @@ -471,7 +474,6 @@ class ArrayBufferView throw "transferElement on a base type ArrayBuffer"; } } - } // ArrayBufferView #end // !js diff --git a/src/lime/utils/AssetLibrary.hx b/src/lime/utils/AssetLibrary.hx index 146d9a7191..ea3c287098 100644 --- a/src/lime/utils/AssetLibrary.hx +++ b/src/lime/utils/AssetLibrary.hx @@ -381,8 +381,11 @@ class AssetLibrary return switch (cast(type, AssetType)) { case null: - cachedBytes.exists(id) || cachedText.exists(id) || cachedImages.exists(id) - || cachedAudioBuffers.exists(id) || cachedFonts.exists(id); + cachedBytes.exists(id) + || cachedText.exists(id) + || cachedImages.exists(id) + || cachedAudioBuffers.exists(id) + || cachedFonts.exists(id); case IMAGE: cachedImages.exists(id); @@ -393,8 +396,7 @@ class AssetLibrary case FONT: cachedFonts.exists(id); - default: - cachedBytes.exists(id) || cachedText.exists(id); + default: cachedBytes.exists(id) || cachedText.exists(id); } #end } diff --git a/src/lime/utils/Assets.hx b/src/lime/utils/Assets.hx index 2f43d1327f..8ddeceb16b 100644 --- a/src/lime/utils/Assets.hx +++ b/src/lime/utils/Assets.hx @@ -15,8 +15,8 @@ import lime.utils.Log; #if !macro import haxe.Json; #end -@:access(lime.media.AudioBuffer) +@:access(lime.media.AudioBuffer) /** *

The Assets class provides a cross-platform interface to access * embedded images, fonts, sounds and other resource files.

diff --git a/src/lime/utils/ObjectPool.hx b/src/lime/utils/ObjectPool.hx index a023128f02..0b10868c89 100644 --- a/src/lime/utils/ObjectPool.hx +++ b/src/lime/utils/ObjectPool.hx @@ -2,10 +2,9 @@ package lime.utils; import haxe.ds.ObjectMap; - /** - A generic object pool for reusing objects. - **/ + A generic object pool for reusing objects. +**/ #if !lime_debug @:fileXml('tags="haxe,release"') @:noDebug @@ -13,18 +12,18 @@ import haxe.ds.ObjectMap; #if !js @:generic #end class ObjectPool { /** - The number of active objects in the pool. - **/ + The number of active objects in the pool. + **/ public var activeObjects(default, null):Int; /** - The number of inactive objects in the pool. - **/ + The number of inactive objects in the pool. + **/ public var inactiveObjects(default, null):Int; /** - The total size of the object pool (both active and inactive objects). - **/ + The total size of the object pool (both active and inactive objects). + **/ public var size(get, set):Null; @:noCompletion private var __inactiveObject0:T; @@ -34,12 +33,12 @@ import haxe.ds.ObjectMap; @:noCompletion private var __size:Null; /** - Creates a new ObjectPool instance. - - @param create A function that creates a new instance of type T. - @param clean A function that cleans up an instance of type T before it is reused. - @param size The maximum size of the object pool. - **/ + Creates a new ObjectPool instance. + + @param create A function that creates a new instance of type T. + @param clean A function that cleans up an instance of type T before it is reused. + @param size The maximum size of the object pool. + **/ public function new(create:Void->T = null, clean:T->Void = null, size:Null = null) { __pool = cast new ObjectMap(); @@ -64,11 +63,12 @@ import haxe.ds.ObjectMap; this.size = size; } } + /** - Adds an object to the object pool. - - @param object The object to add to the pool. - **/ + Adds an object to the object pool. + + @param object The object to add to the pool. + **/ public function add(object:T):Void { if (object != null && !__pool.exists(object)) @@ -82,15 +82,15 @@ import haxe.ds.ObjectMap; /** Dynamic function. - Cleans up an object before returning it to the pool. - - @param object The object to clean up. - **/ + Cleans up an object before returning it to the pool. + + @param object The object to clean up. + **/ public dynamic function clean(object:T):Void {} /** - Clears the object pool, removing all objects. - **/ + Clears the object pool, removing all objects. + **/ public function clear():Void { __pool = cast new ObjectMap(); @@ -106,18 +106,18 @@ import haxe.ds.ObjectMap; /** Dynamic function. - Creates a new Object. - **/ + Creates a new Object. + **/ public dynamic function create():T { return null; } /** - Creates a new object and adds it to the pool, or returns an existing inactive object from the pool. - - @return The object retrieved from the pool, or null if the pool is full and no new objects can be created. - **/ + Creates a new object and adds it to the pool, or returns an existing inactive object from the pool. + + @return The object retrieved from the pool, or null if the pool is full and no new objects can be created. + **/ public function get():T { var object = null; @@ -141,10 +141,10 @@ import haxe.ds.ObjectMap; } /** - Releases an active object back into the pool. - - @param object The object to release. - **/ + Releases an active object back into the pool. + + @param object The object to release. + **/ public function release(object:T):Void { #if debug @@ -172,10 +172,10 @@ import haxe.ds.ObjectMap; } /** - Removes an object from the pool. - - @param object The object to remove from the pool. - **/ + Removes an object from the pool. + + @param object The object to remove from the pool. + **/ public function remove(object:T):Void { if (object != null && __pool.exists(object)) diff --git a/src/lime/utils/PackedAssetLibrary.hx b/src/lime/utils/PackedAssetLibrary.hx index 5a7a98f10a..42021c954d 100644 --- a/src/lime/utils/PackedAssetLibrary.hx +++ b/src/lime/utils/PackedAssetLibrary.hx @@ -174,7 +174,7 @@ import flash.media.Sound; // TODO: Do not preload bytes on native, if we can read from it instead (all non-Android targets?) assetsLoaded = 0; - assetsTotal = 2; //for our initial __assetLoaded(null) call and __assetLoaded(this.id) + assetsTotal = 2; // for our initial __assetLoaded(null) call and __assetLoaded(this.id) for (id in preload.keys()) { @@ -252,7 +252,7 @@ import flash.media.Sound; } else { - var basePath = rootPath == null || rootPath == "" ? "" : Path.addTrailingSlash(rootPath); + var basePath = rootPath == null || rootPath == "" ? "" : Path.addTrailingSlash(rootPath); var libPath = getPath(id); if (libPath == null) libPath = id; @@ -261,7 +261,10 @@ import flash.media.Sound; var packedData_onProgress = load_onProgress.bind(this.id); - Bytes.loadFromFile(path).onProgress(packedData_onProgress).onError(promise.error).onComplete(packedData_onComplete); + Bytes.loadFromFile(path) + .onProgress(packedData_onProgress) + .onError(promise.error) + .onComplete(packedData_onComplete); } } @@ -431,9 +434,9 @@ import flash.media.Sound; var length = Reflect.field(asset, "length"); lengths.set(id, length); - //for individual packed assets, the size represents the work done unpacking them - //since this is likely to be much faster than downloading, set it to something - //small like the packed length / 10. + // for individual packed assets, the size represents the work done unpacking them + // since this is likely to be much faster than downloading, set it to something + // small like the packed length / 10. sizes.set(id, Math.floor(length / 10)); packedBytesTotal += length; @@ -444,7 +447,7 @@ import flash.media.Sound; bytesTotal += sizes.get(id); } } - + sizes.set(this.id, packedBytesTotal); bytesTotal += packedBytesTotal; } diff --git a/src/lime/utils/Preloader.hx b/src/lime/utils/Preloader.hx index d9f309aeff..f74c35c25d 100644 --- a/src/lime/utils/Preloader.hx +++ b/src/lime/utils/Preloader.hx @@ -26,8 +26,7 @@ import flash.Lib; @:access(lime.utils.AssetLibrary) #if !lime_debug -@:fileXml('tags="haxe,release"') -@:noDebug +@:fileXml('tags="haxe,release"') @:noDebug #end class Preloader #if flash extends Sprite #end { @@ -36,12 +35,12 @@ class Preloader #if flash extends Sprite #end public var onProgress = new EventInt->Void>(); @:noCompletion private var bytesLoaded:Int; - @:noCompletion private var bytesLoadedCache = new ObjectMap<#if !disable_preloader_assets AssetLibrary #else Dynamic #end, Int>(); + @:noCompletion private var bytesLoadedCache = new ObjectMap< #if !disable_preloader_assets AssetLibrary #else Dynamic #end, Int>(); @:noCompletion private var bytesLoadedCache2 = new Map(); @:noCompletion private var bytesTotal:Int; @:noCompletion private var bytesTotalCache = new Map(); @:noCompletion private var initLibraryNames:Bool; - @:noCompletion private var libraries:Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>; + @:noCompletion private var libraries:Array< #if !disable_preloader_assets AssetLibrary #else Dynamic #end>; @:noCompletion private var libraryNames:Array; @:noCompletion private var loadedLibraries:Int; @:noCompletion private var loadedStage:Bool; @@ -60,7 +59,7 @@ class Preloader #if flash extends Sprite #end bytesLoaded = 0; bytesTotal = 0; - libraries = new Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>(); + libraries = new Array< #if !disable_preloader_assets AssetLibrary #else Dynamic #end>(); libraryNames = new Array(); onProgress.add(update); @@ -296,8 +295,7 @@ class Preloader #if flash extends Sprite #end } #end - if (!simulateProgress #if flash && loadedStage #end - && loadedLibraries == (libraries.length + libraryNames.length)) + if (!simulateProgress #if flash && loadedStage #end && loadedLibraries == (libraries.length + libraryNames.length)) { if (!preloadComplete) { diff --git a/tests/unit/src/TestMain.hx b/tests/unit/src/TestMain.hx index e5f15d054e..dae8fda9c3 100644 --- a/tests/unit/src/TestMain.hx +++ b/tests/unit/src/TestMain.hx @@ -2,8 +2,10 @@ import utest.Runner; import utest.ui.Report; import lime.app.Application; -class TestMain extends Application { - public function new() { +class TestMain extends Application +{ + public function new() + { super(); var runner = new Runner(); diff --git a/tests/unit/src/utils/ArrayBufferTest.hx b/tests/unit/src/utils/ArrayBufferTest.hx index 32dda5e2cf..8981b1b080 100644 --- a/tests/unit/src/utils/ArrayBufferTest.hx +++ b/tests/unit/src/utils/ArrayBufferTest.hx @@ -6,17 +6,21 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class ArrayBufferTest extends Test { - public function new() { +class ArrayBufferTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(4); Assert.equals(4, buffer.byteLength); } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); array[0] = 0xca; @@ -66,4 +70,4 @@ class ArrayBufferTest extends Test { Assert.equals(0xba, beyondLengthArray[2]); Assert.equals(0xbe, beyondLengthArray[3]); } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/DataViewTest.hx b/tests/unit/src/utils/DataViewTest.hx index 3fb397dfa2..ad2fcfa8bb 100644 --- a/tests/unit/src/utils/DataViewTest.hx +++ b/tests/unit/src/utils/DataViewTest.hx @@ -6,62 +6,61 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class DataViewTest extends Test { - public function new() { +class DataViewTest extends Test +{ + public function new() + { super(); } - public function testInt8():Void { - var values:Array = [0, 1, 2, 127, 128, 255, -1, -2, -128, -129]; - var result:Array = [0, 1, 2, 127, -128, -1, -1, -2, -128, 127]; + public function testInt8():Void + { + var values:Array = [0, 1, 2, 127, 128, 255, -1, -2, -128, -129]; + var result:Array = [0, 1, 2, 127, -128, -1, -1, -2, -128, 127]; Assert.equals(values.length, result.length); var count = values.length; var buffer = new ArrayBuffer(count); var dataView = new DataView(buffer); - for (i in 0...count) { + for (i in 0...count) + { var value = values[i]; dataView.setInt8(i, value); } - for (i in 0...count) { + for (i in 0...count) + { var value = dataView.getInt8(i); var expected = result[i]; Assert.equals(expected, value, 'Int8: expected $expected but got $value at index $i'); } } - public function testUint8():Void { - var values:Array = [0, 1, 2, 255, 256, -1, -2, -255]; - var result:Array = [0, 1, 2, 255, 0, 255, 254, 1]; + public function testUint8():Void + { + var values:Array = [0, 1, 2, 255, 256, -1, -2, -255]; + var result:Array = [0, 1, 2, 255, 0, 255, 254, 1]; Assert.equals(values.length, result.length); var count = values.length; var buffer = new ArrayBuffer(count); var dataView = new DataView(buffer); - for (i in 0...count) { + for (i in 0...count) + { var value = values[i]; dataView.setUint8(i, value); } - for (i in 0...count) { + for (i in 0...count) + { var value = dataView.getUint8(i); var expected = result[i]; Assert.equals(expected, value, 'Uint8: expected $expected but got $value at index $i'); } } - public function testInt16():Void { - var values:Array = [0, 1, 2, 32767, 32768, 65535, -1, -2, -32768, -32769]; - var result:Array = [0, 1, 2, 32767, -32768, -1, -1, -2, -32768, 32767]; + public function testInt16():Void + { + var values:Array = [0, 1, 2, 32767, 32768, 65535, -1, -2, -32768, -32769]; + var result:Array = [0, 1, 2, 32767, -32768, -1, -1, -2, -32768, 32767]; var resultBytesLE:Array> = [ - [0x00, 0x00], - [0x01, 0x00], - [0x02, 0x00], - [0xff, 0x7f], - [0x00, 0x80], - [0xff, 0xff], - [0xff, 0xff], - [0xfe, 0xff], - [0x00, 0x80], - [0xff, 0x7f] - ]; + [0x00, 0x00], [0x01, 0x00], [0x02, 0x00], [0xff, 0x7f], [0x00, 0x80], [0xff, 0xff], [0xff, 0xff], [0xfe, 0xff], [0x00, 0x80], [0xff, 0x7f]]; Assert.equals(values.length, result.length); Assert.equals(values.length, resultBytesLE.length); var count = values.length; @@ -69,52 +68,55 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setInt16(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getInt16(byteIndex); var expected = result[i]; Assert.equals(expected, value, 'Int16 little endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(2, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Int16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Int16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Int16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Int16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setInt16(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getInt16(byteIndex, false); var expected = result[i]; Assert.equals(expected, value, 'Int16 big endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(2, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Int16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Int16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Int16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Int16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } } - public function testUint16():Void { - var values:Array = [0, 1, 2, 65535, 65536, -1, -2, -65535]; - var result:Array = [0, 1, 2, 65535, 0, 65535, 65534, 1]; + public function testUint16():Void + { + var values:Array = [0, 1, 2, 65535, 65536, -1, -2, -65535]; + var result:Array = [0, 1, 2, 65535, 0, 65535, 65534, 1]; var resultBytesLE:Array> = [ [0x00, 0x00], [0x01, 0x00], @@ -132,50 +134,53 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setUint16(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getUint16(byteIndex); var expected = result[i]; Assert.equals(expected, value, 'Uint16 little endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(2, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Uint16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Uint16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Uint16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Uint16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setUint16(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getUint16(byteIndex, false); var expected = result[i]; Assert.equals(expected, value, 'Uint16 big endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(2, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Uint16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Uint16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Uint16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Uint16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } } - public function testInt32():Void { + public function testInt32():Void + { var values:Array = [0, 1, 2, 2147483647, -1, -2, -2147483648]; var result:Array = [0, 1, 2, 2147483647, -1, -2, -2147483648]; var resultBytesLE:Array> = [ @@ -194,12 +199,14 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setInt32(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = dataView.getInt32(byteIndex); var expected = result[i]; @@ -213,19 +220,25 @@ class DataViewTest extends Test { ]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(4, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Int32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Int32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesLE[2], valueBytes[2], 'Int32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesLE[3], valueBytes[3], 'Int32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Int32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Int32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[2], valueBytes[2], + 'Int32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesLE[3], valueBytes[3], + 'Int32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setInt32(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = dataView.getInt32(byteIndex, false); var expected = result[i]; @@ -240,14 +253,19 @@ class DataViewTest extends Test { var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(4, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Int32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Int32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesBE[2], valueBytes[2], 'Int32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesBE[3], valueBytes[3], 'Int32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Int32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Int32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[2], valueBytes[2], + 'Int32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesBE[3], valueBytes[3], + 'Int32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } } - public function testUint32():Void { + public function testUint32():Void + { var values:Array = [0, 1, 2, 0xffffffff, 0xdeadbeef, 0xcafebabe, 0xdecafbad]; var resultBytesLE:Array> = [ [0x00, 0x00, 0x00, 0x00], @@ -264,12 +282,14 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setUint32(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var valueBytes = [ dataView.getUint8(byteIndex), @@ -279,19 +299,25 @@ class DataViewTest extends Test { ]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(4, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Uint32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Uint32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesLE[2], valueBytes[2], 'Uint32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesLE[3], valueBytes[3], 'Uint32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Uint32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Uint32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[2], valueBytes[2], + 'Uint32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesLE[3], valueBytes[3], + 'Uint32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setUint32(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var valueBytes = [ dataView.getUint8(byteIndex), @@ -302,10 +328,14 @@ class DataViewTest extends Test { var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(4, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Uint32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Uint32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesBE[2], valueBytes[2], 'Uint32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesBE[3], valueBytes[3], 'Uint32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Uint32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Uint32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[2], valueBytes[2], + 'Uint32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesBE[3], valueBytes[3], + 'Uint32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/UInt16ArrayTest.hx b/tests/unit/src/utils/UInt16ArrayTest.hx index 84200f99f4..6f3d1ae8cf 100644 --- a/tests/unit/src/utils/UInt16ArrayTest.hx +++ b/tests/unit/src/utils/UInt16ArrayTest.hx @@ -7,19 +7,23 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class UInt16ArrayTest extends Test { - public function new() { +class UInt16ArrayTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(8); var array = new UInt16Array(buffer); Assert.equals(4, array.length); Assert.equals(8, array.byteLength); } - public function testValues():Void { + public function testValues():Void + { var buffer = new ArrayBuffer(8); var array = new UInt16Array(buffer); Assert.equals(0x0, array[0]); @@ -36,7 +40,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0xfbad, array[3]); } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(8); var array = new UInt16Array(buffer); array[0] = 0xcafe; @@ -81,12 +86,13 @@ class UInt16ArrayTest extends Test { Assert.equals(0xfbad, beyondLength[3]); } - public function testSetArrayOfInts():Void { + public function testSetArrayOfInts():Void + { var array1:Array = [0xcafe, 0xbabe, 0xdeca, 0xfbad]; var buffer2 = new ArrayBuffer(16); var array2 = new UInt16Array(buffer2); - + array2.set(array1); Assert.equals(0xcafe, array2[0]); Assert.equals(0xbabe, array2[1]); @@ -97,7 +103,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -111,11 +118,13 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); Assert.equals(0x0, array2[0]); @@ -128,7 +137,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8Array():Void { + public function testSetUInt8Array():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -150,7 +160,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -164,12 +175,14 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -183,7 +196,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16Array():Void { + public function testSetUInt16Array():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -205,7 +219,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -219,12 +234,14 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -238,7 +255,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32Array():Void { + public function testSetUInt32Array():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -260,7 +278,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -274,12 +293,14 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -292,4 +313,4 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/UInt32ArrayTest.hx b/tests/unit/src/utils/UInt32ArrayTest.hx index 5e3c88a42a..882ff52efb 100644 --- a/tests/unit/src/utils/UInt32ArrayTest.hx +++ b/tests/unit/src/utils/UInt32ArrayTest.hx @@ -7,19 +7,23 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class UInt32ArrayTest extends Test { - public function new() { +class UInt32ArrayTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(16); var array = new UInt32Array(buffer); Assert.equals(4, array.length); Assert.equals(16, array.byteLength); } - public function testValues():Void { + public function testValues():Void + { var buffer = new ArrayBuffer(16); var array = new UInt32Array(buffer); Assert.equals(0x0, array[0]); @@ -44,7 +48,8 @@ class UInt32ArrayTest extends Test { #end } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(16); var array = new UInt32Array(buffer); array[0] = 0xcafebabe; @@ -113,12 +118,13 @@ class UInt32ArrayTest extends Test { #end } - public function testSetArrayOfInts():Void { + public function testSetArrayOfInts():Void + { var array1:Array = [0xcafebabe, 0xdecafbad, 0xffffffff, 0xdeadbeef]; var buffer2 = new ArrayBuffer(32); var array2 = new UInt32Array(buffer2); - + array2.set(array1); #if js Assert.equals(untyped #if haxe4 js.Syntax.code #else __js__ #end ('0xcafebabe'), array2[0]); @@ -136,7 +142,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -165,7 +172,8 @@ class UInt32ArrayTest extends Test { var buffer2 = new ArrayBuffer(32); var array2 = new UInt32Array(buffer2); - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); Assert.equals(0x0, array2[0]); @@ -178,7 +186,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8Array():Void { + public function testSetUInt8Array():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -200,7 +209,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -215,7 +225,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8ArrayRangeError():Void { + public function testSetUInt8ArrayRangeError():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -227,7 +238,8 @@ class UInt32ArrayTest extends Test { var array2 = new UInt32Array(buffer2); // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -241,7 +253,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16Array():Void { + public function testSetUInt16Array():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -263,7 +276,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -278,7 +292,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16ArrayRangeError():Void { + public function testSetUInt16ArrayRangeError():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -290,7 +305,8 @@ class UInt32ArrayTest extends Test { var array2 = new UInt32Array(buffer2); // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -304,7 +320,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32Array():Void { + public function testSetUInt32Array():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -333,7 +350,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -355,7 +373,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32ArrayRangeError():Void { + public function testSetUInt32ArrayRangeError():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -367,7 +386,8 @@ class UInt32ArrayTest extends Test { var array2 = new UInt32Array(buffer2); // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -380,4 +400,4 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/UInt8ArrayTest.hx b/tests/unit/src/utils/UInt8ArrayTest.hx index 04a87afd8c..9503481fc9 100644 --- a/tests/unit/src/utils/UInt8ArrayTest.hx +++ b/tests/unit/src/utils/UInt8ArrayTest.hx @@ -7,19 +7,23 @@ import lime.utils.UInt8Array; import utest.Assert; import utest.Test; -class UInt8ArrayTest extends Test { - public function new() { +class UInt8ArrayTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); Assert.equals(4, array.length); Assert.equals(4, array.byteLength); } - public function testValues():Void { + public function testValues():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); Assert.equals(0x0, array[0]); @@ -36,7 +40,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0xbe, array[3]); } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); array[0] = 0xca; @@ -81,12 +86,13 @@ class UInt8ArrayTest extends Test { Assert.equals(0xbe, beyondLength[3]); } - public function testSetArrayOfInts():Void { + public function testSetArrayOfInts():Void + { var array1:Array = [0xca, 0xfe, 0xba, 0xbe]; var buffer2 = new ArrayBuffer(8); var array2 = new UInt8Array(buffer2); - + array2.set(array1); Assert.equals(0xca, array2[0]); Assert.equals(0xfe, array2[1]); @@ -97,7 +103,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -111,11 +118,13 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); Assert.equals(0x0, array2[0]); @@ -128,7 +137,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8Array():Void { + public function testSetUInt8Array():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -150,7 +160,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -164,12 +175,14 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -183,7 +196,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16Array():Void { + public function testSetUInt16Array():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -205,7 +219,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -219,12 +234,14 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -238,7 +255,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32Array():Void { + public function testSetUInt32Array():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -260,7 +278,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -274,12 +293,14 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -292,4 +313,4 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); } -} \ No newline at end of file +} diff --git a/tests/vulkan-smoke/Source/Main.hx b/tests/vulkan-smoke/Source/Main.hx index fd63e61ba6..d0ca0048ac 100644 --- a/tests/vulkan-smoke/Source/Main.hx +++ b/tests/vulkan-smoke/Source/Main.hx @@ -220,7 +220,11 @@ class Main extends Application return; } - if (!createSourceTexture() || !createGeometry() || !createDescriptorLayouts() || !createOffscreenPass() || !createOnscreenPass()) + if (!createSourceTexture() + || !createGeometry() + || !createDescriptorLayouts() + || !createOffscreenPass() + || !createOnscreenPass()) { return; } @@ -264,7 +268,8 @@ class Main extends Application return false; } - if (!commandBuffer.reset() || !commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) + if (!commandBuffer.reset() + || !commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) || !commandBuffer.pipelineBarrierImage(sourceTextureImage, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK.PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK.PIPELINE_STAGE_TRANSFER_BIT, 0, VK.ACCESS_TRANSFER_WRITE_BIT, VK.IMAGE_ASPECT_COLOR_BIT) || !commandBuffer.copyBufferToImage(staging, sourceTextureImage, 2, 2) @@ -306,8 +311,7 @@ class Main extends Application return false; } - uniformBuffer = device.createUniformBuffer(Int64.ofInt(64), - VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT); + uniformBuffer = device.createUniformBuffer(Int64.ofInt(64), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT); if (uniformBuffer == null) { fail("Failed to create Vulkan uniform buffer: " + VK.getLastError()); @@ -322,9 +326,9 @@ class Main extends Application var vertices = Bytes.alloc(4 * 32); var data = [ -0.72, -0.72, 0.0, 1.0, 1.0, 1.0, 1.0, 0.86, - 0.72, -0.72, 1.0, 1.0, 1.0, 1.0, 1.0, 0.86, - 0.72, 0.72, 1.0, 0.0, 1.0, 1.0, 1.0, 0.86, - -0.72, 0.72, 0.0, 0.0, 1.0, 1.0, 1.0, 0.86 + 0.72, -0.72, 1.0, 1.0, 1.0, 1.0, 1.0, 0.86, + 0.72, 0.72, 1.0, 0.0, 1.0, 1.0, 1.0, 0.86, + -0.72, 0.72, 0.0, 0.0, 1.0, 1.0, 1.0, 0.86 ]; for (i in 0...data.length) { @@ -338,10 +342,10 @@ class Main extends Application indices.setUInt16(i * 2, indexData[i]); } - quadVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), - VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, vertices); - quadIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), - VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, indices); + quadVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + vertices); + quadIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + indices); if (quadVertexBuffer == null || quadIndexBuffer == null) { @@ -355,36 +359,36 @@ class Main extends Application private function createCubeGeometry():Bool { var vertexData = [ - -1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.85, 0.55, 1.0, - 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0.85, 0.55, 1.0, - 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.85, 0.55, 1.0, - -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.85, 0.55, 1.0, - 1.0, -1.0, -1.0, 0.0, 1.0, 0.55, 0.8, 1.0, 1.0, - -1.0, -1.0, -1.0, 1.0, 1.0, 0.55, 0.8, 1.0, 1.0, - -1.0, 1.0, -1.0, 1.0, 0.0, 0.55, 0.8, 1.0, 1.0, - 1.0, 1.0, -1.0, 0.0, 0.0, 0.55, 0.8, 1.0, 1.0, - -1.0, -1.0, -1.0, 0.0, 1.0, 0.75, 1.0, 0.65, 1.0, - -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 1.0, 0.65, 1.0, - -1.0, 1.0, 1.0, 1.0, 0.0, 0.75, 1.0, 0.65, 1.0, - -1.0, 1.0, -1.0, 0.0, 0.0, 0.75, 1.0, 0.65, 1.0, - 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.75, 0.6, 1.0, - 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 0.6, 1.0, - 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 0.75, 0.6, 1.0, - 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.75, 0.6, 1.0, - -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.95, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 0.65, 0.95, 1.0, 1.0, - 1.0, 1.0, -1.0, 1.0, 0.0, 0.65, 0.95, 1.0, 1.0, - -1.0, 1.0, -1.0, 0.0, 0.0, 0.65, 0.95, 1.0, 1.0, - -1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.65, 0.75, 1.0, - 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.65, 0.75, 1.0, - 1.0, -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.75, 1.0, - -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.65, 0.75, 1.0 + -1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.85, 0.55, 1.0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0.85, 0.55, 1.0, + 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.85, 0.55, 1.0, + -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.85, 0.55, 1.0, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.55, 0.8, 1.0, 1.0, + -1.0, -1.0, -1.0, 1.0, 1.0, 0.55, 0.8, 1.0, 1.0, + -1.0, 1.0, -1.0, 1.0, 0.0, 0.55, 0.8, 1.0, 1.0, + 1.0, 1.0, -1.0, 0.0, 0.0, 0.55, 0.8, 1.0, 1.0, + -1.0, -1.0, -1.0, 0.0, 1.0, 0.75, 1.0, 0.65, 1.0, + -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 1.0, 0.65, 1.0, + -1.0, 1.0, 1.0, 1.0, 0.0, 0.75, 1.0, 0.65, 1.0, + -1.0, 1.0, -1.0, 0.0, 0.0, 0.75, 1.0, 0.65, 1.0, + 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.75, 0.6, 1.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 0.6, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 0.75, 0.6, 1.0, + 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.75, 0.6, 1.0, + -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.95, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 0.65, 0.95, 1.0, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 0.65, 0.95, 1.0, 1.0, + -1.0, 1.0, -1.0, 0.0, 0.0, 0.65, 0.95, 1.0, 1.0, + -1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.65, 0.75, 1.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.65, 0.75, 1.0, + 1.0, -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.75, 1.0, + -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.65, 0.75, 1.0 ]; var indexData = [ - 0, 1, 2, 2, 3, 0, - 4, 5, 6, 6, 7, 4, - 8, 9, 10, 10, 11, 8, + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4, + 8, 9, 10, 10, 11, 8, 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 20, 21, 22, 22, 23, 20 @@ -402,10 +406,10 @@ class Main extends Application indices.setUInt16(i * 2, indexData[i]); } - cubeVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), - VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, vertices); - cubeIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), - VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, indices); + cubeVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + vertices); + cubeIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + indices); if (cubeVertexBuffer == null || cubeIndexBuffer == null) { @@ -441,13 +445,14 @@ class Main extends Application private function createOffscreenPass():Bool { - offscreenRenderPass = device.createRenderPass(OFFSCREEN_FORMAT, VK.FORMAT_UNDEFINED, VK.SAMPLE_COUNT_1_BIT, - VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, - VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + offscreenRenderPass = device.createRenderPass(OFFSCREEN_FORMAT, VK.FORMAT_UNDEFINED, VK.SAMPLE_COUNT_1_BIT, VK.ATTACHMENT_LOAD_OP_CLEAR, + VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); offscreenImage = device.createImage(OFFSCREEN_SIZE, OFFSCREEN_SIZE, OFFSCREEN_FORMAT, VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_SAMPLED_BIT | VK.IMAGE_USAGE_TRANSFER_SRC_BIT); - if (offscreenRenderPass == null || offscreenImage == null || offscreenImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + if (offscreenRenderPass == null + || offscreenImage == null + || offscreenImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) { fail("Failed to create Vulkan offscreen render target: " + VK.getLastError()); return false; @@ -462,8 +467,13 @@ class Main extends Application quadVertexShader = device.createShaderModule(Assets.getBytes("Assets/shaders/quad.vert.spv")); quadFragmentShader = device.createShaderModule(Assets.getBytes("Assets/shaders/quad.frag.spv")); - if (offscreenView == null || offscreenSampler == null || offscreenFramebuffer == null || offscreenDescriptorSet == null - || offscreenPipelineLayout == null || quadVertexShader == null || quadFragmentShader == null + if (offscreenView == null + || offscreenSampler == null + || offscreenFramebuffer == null + || offscreenDescriptorSet == null + || offscreenPipelineLayout == null + || quadVertexShader == null + || quadFragmentShader == null || !offscreenDescriptorSet.updateImage(0, sourceTextureView, sourceTextureSampler)) { fail("Failed to create Vulkan offscreen pipeline resources: " + VK.getLastError()); @@ -492,17 +502,15 @@ class Main extends Application { if (msaaSamples != VK.SAMPLE_COUNT_1_BIT) { - renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, msaaSamples, - VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_DONT_CARE, VK.IMAGE_LAYOUT_UNDEFINED, - VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK.IMAGE_LAYOUT_UNDEFINED, - VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK.ATTACHMENT_LOAD_OP_CLEAR, - VK.ATTACHMENT_STORE_OP_DONT_CARE, swapchain.format, VK.ATTACHMENT_LOAD_OP_DONT_CARE, - VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, msaaSamples, VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_DONT_CARE, + VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK.IMAGE_LAYOUT_UNDEFINED, + VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_DONT_CARE, swapchain.format, + VK.ATTACHMENT_LOAD_OP_DONT_CARE, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); } else { - renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, VK.SAMPLE_COUNT_1_BIT, - VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, VK.SAMPLE_COUNT_1_BIT, VK.ATTACHMENT_LOAD_OP_CLEAR, + VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); } if (renderPass == null || !createColorResources() || !createDepthResources() || !createFramebuffers()) @@ -516,8 +524,12 @@ class Main extends Application cubeVertexShader = device.createShaderModule(Assets.getBytes("Assets/shaders/cube.vert.spv")); cubeFragmentShader = device.createShaderModule(Assets.getBytes("Assets/shaders/cube.frag.spv")); - if (cubeDescriptorSet == null || cubePipelineLayout == null || cubeVertexShader == null || cubeFragmentShader == null - || !cubeDescriptorSet.updateBuffer(0, uniformBuffer, 64) || !cubeDescriptorSet.updateImage(1, offscreenView, offscreenSampler)) + if (cubeDescriptorSet == null + || cubePipelineLayout == null + || cubeVertexShader == null + || cubeFragmentShader == null + || !cubeDescriptorSet.updateBuffer(0, uniformBuffer, 64) + || !cubeDescriptorSet.updateImage(1, offscreenView, offscreenSampler)) { fail("Failed to create Vulkan cube descriptor resources: " + VK.getLastError()); return false; @@ -555,8 +567,7 @@ class Main extends Application } colorImage = device.createImage(swapchain.width, swapchain.height, swapchain.format, - VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, 1, 1, 1, VK.IMAGE_TYPE_2D, - VK.IMAGE_TILING_OPTIMAL, msaaSamples); + VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, 1, 1, 1, VK.IMAGE_TYPE_2D, VK.IMAGE_TILING_OPTIMAL, msaaSamples); if (colorImage == null || colorImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) { return false; @@ -570,8 +581,8 @@ class Main extends Application { disposeDepthResources(); - depthImage = device.createImage(swapchain.width, swapchain.height, DEPTH_FORMAT, VK.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - 1, 1, 1, VK.IMAGE_TYPE_2D, VK.IMAGE_TILING_OPTIMAL, msaaSamples); + depthImage = device.createImage(swapchain.width, swapchain.height, DEPTH_FORMAT, VK.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1, 1, 1, + VK.IMAGE_TYPE_2D, VK.IMAGE_TILING_OPTIMAL, msaaSamples); if (depthImage == null || depthImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) { return false; @@ -671,7 +682,8 @@ class Main extends Application return false; } - if (!fence.reset() || !device.graphicsQueue.submitSynced(commandBuffer, imageAvailable, renderFinished, fence) + if (!fence.reset() + || !device.graphicsQueue.submitSynced(commandBuffer, imageAvailable, renderFinished, fence) || !fence.waitForever()) { fail("Failed to submit Vulkan draw commands: " + VK.getLastError()); @@ -933,10 +945,10 @@ class Main extends Application { var f = 1.0 / Math.tan(fovY * 0.5); var result = [ - f / aspect, 0.0, 0.0, 0.0, - 0.0, -f, 0.0, 0.0, - 0.0, 0.0, far / (near - far), -1.0, - 0.0, 0.0, (far * near) / (near - far), 0.0 + f / aspect, 0.0, 0.0, 0.0, + 0.0, -f, 0.0, 0.0, + 0.0, 0.0, far / (near - far), -1.0, + 0.0, 0.0, (far * near) / (near - far), 0.0 ]; return result; } diff --git a/tools/CommandLineTools.hx b/tools/CommandLineTools.hx index 0d3e63f448..67f27f7920 100644 --- a/tools/CommandLineTools.hx +++ b/tools/CommandLineTools.hx @@ -420,8 +420,7 @@ class CommandLineTools publishProject(); case "installer", "copy-if-newer": - - // deprecated? + // deprecated? default: Log.error("'" + command + "' is not a valid command"); @@ -511,7 +510,7 @@ class CommandLineTools case LINUX: var arguments = Sys.args(); - if (System.hostArchitecture == ARMV7 ) + if (System.hostArchitecture == ARMV7) { untyped $loader.path = $array(path + "LinuxArm/", $loader.path); } @@ -600,19 +599,16 @@ class CommandLineTools platform = new AndroidPlatform(command, project, targetFlags); case BLACKBERRY: - - // platform = new BlackBerryPlatform (command, project, targetFlags); + // platform = new BlackBerryPlatform (command, project, targetFlags); case IOS: platform = new IOSPlatform(command, project, targetFlags); case TIZEN: - - // platform = new TizenPlatform (command, project, targetFlags); + // platform = new TizenPlatform (command, project, targetFlags); case WEBOS: - - // platform = new WebOSPlatform (command, project, targetFlags); + // platform = new WebOSPlatform (command, project, targetFlags); case WINDOWS: platform = new WindowsPlatform(command, project, targetFlags); @@ -788,14 +784,22 @@ class CommandLineTools { var commands = [ - "config" => "Display or set command-line configuration values", "create" => "Create a new project or extension using templates", - "clean" => "Clean the specified project and target", "update" => "Copy assets for the specified project and target", - "build" => "Compile and package for the specified project and target", "run" => "Install and run for the specified project and target", - "test" => "Update, build and run in one command", "help" => "Show this information", - "trace" => "Trace output for the specifed project and target", "deploy" => "Archive and upload builds", - "display" => "Display information for the specified project and target", "rebuild" => "Recompile native binaries for libraries", - "install" => "Install a library from haxelib, plus dependencies", "remove" => "Remove a library from haxelib", - "upgrade" => "Upgrade a library from haxelib", "setup" => "Setup " + defaultLibraryName + " or a specific platform" + "config" => "Display or set command-line configuration values", + "create" => "Create a new project or extension using templates", + "clean" => "Clean the specified project and target", + "update" => "Copy assets for the specified project and target", + "build" => "Compile and package for the specified project and target", + "run" => "Install and run for the specified project and target", + "test" => "Update, build and run in one command", + "help" => "Show this information", + "trace" => "Trace output for the specifed project and target", + "deploy" => "Archive and upload builds", + "display" => "Display information for the specified project and target", + "rebuild" => "Recompile native binaries for libraries", + "install" => "Install a library from haxelib, plus dependencies", + "remove" => "Remove a library from haxelib", + "upgrade" => "Upgrade a library from haxelib", + "setup" => "Setup " + defaultLibraryName + " or a specific platform" ]; @@ -1841,7 +1845,9 @@ class CommandLineTools var projectDirectory = Path.directory(projectFile); var localRepository = Path.combine(projectDirectory, ".haxelib"); - if (FileSystem.exists(localRepository) && FileSystem.isDirectory(localRepository) && StringTools.startsWith(path, localRepository)) + if (FileSystem.exists(localRepository) + && FileSystem.isDirectory(localRepository) + && StringTools.startsWith(path, localRepository)) { args.push("-nolocalrepocheck"); } diff --git a/tools/RunScript.hx b/tools/RunScript.hx index 8b6060829e..4dcd97b71f 100644 --- a/tools/RunScript.hx +++ b/tools/RunScript.hx @@ -27,7 +27,16 @@ class RunScript if (!rebuildBinaries) return; - var platforms = ["Windows", "Mac", "Mac64", "MacArm64", "Linux", "Linux64", "LinuxArm", "LinuxArm64"]; + var platforms = [ + "Windows", + "Mac", + "Mac64", + "MacArm64", + "Linux", + "Linux64", + "LinuxArm", + "LinuxArm64" + ]; for (platform in platforms) { @@ -208,17 +217,17 @@ class RunScript if (args.indexOf("-eval") >= 0) { args.remove("-eval"); - Log.info("Experimental: executing `lime " + args.slice(0, args.length - 1).join(" ") - + "` using Eval (https://haxe.org/blog/eval/)"); + Log.info("Experimental: executing `lime " + args.slice(0, args.length - 1).join(" ") + "` using Eval (https://haxe.org/blog/eval/)"); var args = [ - "-D", "lime", - "-cp", toolsDirectory, - "-cp", Path.combine(toolsDirectory, "platforms"), - "-cp", Path.combine(limeDirectory, "src"), - "-lib", "format", - "-lib", "hxp", - "--run", "CommandLineTools"].concat(args); + "-D", "lime", + "-cp", toolsDirectory, + "-cp", Path.combine(toolsDirectory, "platforms"), + "-cp", Path.combine(limeDirectory, "src"), + "-lib", "format", + "-lib", "hxp", + "--run", "CommandLineTools" + ].concat(args); Sys.exit(runCommand("", "haxe", args)); } diff --git a/tools/SVGExport.hx b/tools/SVGExport.hx index 4bb62d0bdf..f83d2e23e9 100644 --- a/tools/SVGExport.hx +++ b/tools/SVGExport.hx @@ -79,7 +79,7 @@ class SVGExport case LINUX: var arguments = Sys.args(); - if ( System.hostArchitecture == ARMV7 ) + if (System.hostArchitecture == ARMV7) { untyped $loader.path = $array(path + "LinuxArm/", $loader.path); } diff --git a/tools/mpeg/audio/MpegAudioReader.hx b/tools/mpeg/audio/MpegAudioReader.hx index 91ba3f830b..81a0279828 100644 --- a/tools/mpeg/audio/MpegAudioReader.hx +++ b/tools/mpeg/audio/MpegAudioReader.hx @@ -102,14 +102,14 @@ class MpegAudioReader frames.push(frame); case Info(_): - // Discard info tag. + // Discard info tag. case GaplessInfo(giEncoderDelay, giEndPadding): encoderDelay = giEncoderDelay; endPadding = giEndPadding; case Unknown(_): - // Discard unknown bytes + // Discard unknown bytes case End: break; diff --git a/tools/platforms/AndroidPlatform.hx b/tools/platforms/AndroidPlatform.hx index 5adcb94ceb..2887c6a23c 100644 --- a/tools/platforms/AndroidPlatform.hx +++ b/tools/platforms/AndroidPlatform.hx @@ -162,8 +162,16 @@ class AndroidPlatform extends PlatformTarget for (architecture in architectures) { var minSDKVer = project.config.getInt("android.minimum-sdk-version", 21); - //PLATFORM define needed for older ndk and gcc toolchain - var haxeParams = [hxml, "-D", "android", "-D", 'PLATFORM_NUMBER=$minSDKVer', "-D", 'PLATFORM=android-$minSDKVer']; + // PLATFORM define needed for older ndk and gcc toolchain + var haxeParams = [ + hxml, + "-D", + "android", + "-D", + 'PLATFORM_NUMBER=$minSDKVer', + "-D", + 'PLATFORM=android-$minSDKVer' + ]; var cppParams = ["-Dandroid", '-DPLATFORM_NUMBER=$minSDKVer', '-DPLATFORM=android-$minSDKVer']; var path = sourceSet + "/jniLibs/armeabi"; var suffix = ".so"; @@ -301,7 +309,8 @@ class AndroidPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -357,8 +366,7 @@ class AndroidPlatform extends PlatformTarget public override function rebuild():Void { - var armv5 = (/*command == "rebuild" ||*/ - ArrayTools.containsValue(project.architectures, Architecture.ARMV5) + var armv5 = (/*command == "rebuild" ||*/ ArrayTools.containsValue(project.architectures, Architecture.ARMV5) || ArrayTools.containsValue(project.architectures, Architecture.ARMV6)); var armv7 = (command == "rebuild" || ArrayTools.containsValue(project.architectures, Architecture.ARMV7)); var arm64 = (command == "rebuild" || ArrayTools.containsValue(project.architectures, Architecture.ARM64)); @@ -447,30 +455,43 @@ class AndroidPlatform extends PlatformTarget context.ANDROID_VULKAN_REQUIRED = project.config.getBool("android.vulkan-required", true); context.ANDROID_VULKAN_VERSION = project.config.getString("android.vulkan-version", "0x400003"); - context.ANDROID_MANIFEST = project.config.getKeyValueArray("android.manifest", { - "android:versionCode": project.meta.buildNumber, - "android:versionName": project.meta.version, - "android:installLocation": project.config.getString("android.install-location", "auto") - }); + context.ANDROID_MANIFEST = project.config.getKeyValueArray("android.manifest", + { + "android:versionCode": project.meta.buildNumber, + "android:versionName": project.meta.version, + "android:installLocation": project.config.getString("android.install-location", "auto") + }); context.ANDROID_MANIFEST_CHILDREN = project.config.get("android.manifest").xmlChildren; - context.ANDROID_APPLICATION = project.config.getKeyValueArray("android.application", { - "android:label": project.meta.title, - "android:allowBackup": "true", - "android:theme": "@android:style/Theme.NoTitleBar" + (project.window.fullscreen ? ".Fullscreen" : ""), - "android:hardwareAccelerated": "true", - "android:allowNativeHeapPointerTagging": context.ANDROID_TARGET_SDK_VERSION >= 30 ? "false" : null - }); + context.ANDROID_APPLICATION = project.config.getKeyValueArray("android.application", + { + "android:label": project.meta.title, + "android:allowBackup": "true", + "android:theme": "@android:style/Theme.NoTitleBar" + (project.window.fullscreen ? ".Fullscreen" : ""), + "android:hardwareAccelerated": "true", + "android:allowNativeHeapPointerTagging": context.ANDROID_TARGET_SDK_VERSION >= 30 ? "false" : null + }); context.ANDROID_APPLICATION_CHILDREN = project.config.get("android.application").xmlChildren; - context.ANDROID_ACTIVITY = project.config.getKeyValueArray("android.activity", { - "android:name": "MainActivity", - "android:exported": "true", - "android:launchMode": "singleTask", - "android:label": project.meta.title, - "android:configChanges": project.config.getArrayString("android.configChanges", - ["layoutDirection", "locale", "orientation", "uiMode", "screenLayout", "screenSize", "smallestScreenSize", "keyboard", "keyboardHidden", "navigation"]) - .join("|"), - "android:screenOrientation": project.window.orientation == PORTRAIT ? "sensorPortrait" : (project.window.orientation == LANDSCAPE ? "sensorLandscape" : null) - }); + context.ANDROID_ACTIVITY = project.config.getKeyValueArray("android.activity", + { + "android:name": "MainActivity", + "android:exported": "true", + "android:launchMode": "singleTask", + "android:label": project.meta.title, + "android:configChanges": project.config.getArrayString("android.configChanges", + [ + "layoutDirection", + "locale", + "orientation", + "uiMode", + "screenLayout", + "screenSize", + "smallestScreenSize", + "keyboard", + "keyboardHidden", + "navigation" + ]).join("|"), + "android:screenOrientation": project.window.orientation == PORTRAIT ? "sensorPortrait" : (project.window.orientation == LANDSCAPE ? "sensorLandscape" : null) + }); context.ANDROID_ACTIVITY_CHILDREN = project.config.get("android.activity").xmlChildren; context.ANDROID_ACCEPT_FILE_INTENT = project.config.getArrayString("android.accept-file-intent", []); @@ -544,9 +565,7 @@ class AndroidPlatform extends PlatformTarget } } } - catch (e:Dynamic) - { - } + catch (e:Dynamic) {} } if (Reflect.hasField(context, "KEY_STORE")) context.KEY_STORE = StringTools.replace(context.KEY_STORE, "\\", "\\\\"); @@ -606,7 +625,7 @@ class AndroidPlatform extends PlatformTarget && !context.HAS_ICON) { context.HAS_ICON = true; - context.ANDROID_APPLICATION.push({ key: "android:icon", value: "@drawable/icon" }); + context.ANDROID_APPLICATION.push({key: "android:icon", value: "@drawable/icon"}); } } diff --git a/tools/platforms/FlashPlatform.hx b/tools/platforms/FlashPlatform.hx index 7fd57cd39e..e2fa792214 100644 --- a/tools/platforms/FlashPlatform.hx +++ b/tools/platforms/FlashPlatform.hx @@ -173,7 +173,8 @@ class FlashPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -312,21 +313,20 @@ class FlashPlatform extends PlatformTarget } /*private function getIcon (size:Int, targetPath:String):Void { - - var icon = icons.findIcon (size, size); - - if (icon != "") { - - System.copyIfNewer (icon, targetPath); - - } else { - - icons.updateIcon (size, size, targetPath); - - } - - }*/ - + + var icon = icons.findIcon (size, size); + + if (icon != "") { + + System.copyIfNewer (icon, targetPath); + + } else { + + icons.updateIcon (size, size, targetPath); + + } + + }*/ @ignore public override function install():Void {} @ignore public override function rebuild():Void {} diff --git a/tools/platforms/HTML5Platform.hx b/tools/platforms/HTML5Platform.hx index e998836661..498b7cb8b8 100644 --- a/tools/platforms/HTML5Platform.hx +++ b/tools/platforms/HTML5Platform.hx @@ -209,7 +209,8 @@ class HTML5Platform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); diff --git a/tools/platforms/IOSPlatform.hx b/tools/platforms/IOSPlatform.hx index 915463819f..b5e5931a44 100644 --- a/tools/platforms/IOSPlatform.hx +++ b/tools/platforms/IOSPlatform.hx @@ -409,7 +409,7 @@ class IOSPlatform extends PlatformTarget if (allowInsecureHTTP != "*" && allowInsecureHTTP != "true") { - var sites:Array<{domain: String}> = []; + var sites:Array<{domain:String}> = []; if (allowInsecureHTTP != "false") { @@ -446,7 +446,8 @@ class IOSPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -867,7 +868,6 @@ class IOSPlatform extends PlatformTarget context.HAS_LAUNCH_IMAGE = has_launch_image; }*/ - @ignore public override function install():Void {} @ignore public override function trace():Void {} diff --git a/tools/platforms/LinuxPlatform.hx b/tools/platforms/LinuxPlatform.hx index 094b0a9022..0bccbbc624 100644 --- a/tools/platforms/LinuxPlatform.hx +++ b/tools/platforms/LinuxPlatform.hx @@ -122,7 +122,9 @@ class LinuxPlatform extends PlatformTarget for (architecture in project.architectures) { - if (!targetFlags.exists("32") && !targetFlags.exists("x86_32") && (architecture == Architecture.X64 || architecture == Architecture.ARM64)) + if (!targetFlags.exists("32") + && !targetFlags.exists("x86_32") + && (architecture == Architecture.X64 || architecture == Architecture.ARM64)) { is64 = true; } @@ -198,7 +200,8 @@ class LinuxPlatform extends PlatformTarget } else { - ProjectHelper.copyLibrary(project, ndll, "Linux" + (( System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64)?"Arm":"") + (is64 ? "64" : ""), "", + ProjectHelper.copyLibrary(project, ndll, + "Linux" + ((System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + (is64 ? "64" : ""), "", (ndll.haxelib != null && (ndll.haxelib.name == "hxcpp" || ndll.haxelib.name == "hxlibc")) ? ".dll" : ".ndll", applicationDirectory, project.debug, targetSuffix); @@ -212,9 +215,13 @@ class LinuxPlatform extends PlatformTarget if (noOutput) return; - NekoHelper.createExecutable(project.templatePaths, "linux" + (( System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64)?"Arm":"") + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath); + NekoHelper.createExecutable(project.templatePaths, + "linux" + + ((System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + + (is64 ? "64" : ""), + targetDirectory + + "/obj/ApplicationMain.n", executablePath); NekoHelper.copyLibraries(project.templatePaths, "linux" + (is64 ? "64" : ""), applicationDirectory); - } else if (targetType == "hl") { @@ -230,12 +237,15 @@ class LinuxPlatform extends PlatformTarget var command = [ compiler, "-O3", - "-o", executablePath, + "-o", + executablePath, "-std=c11", "-Wl,-rpath,$ORIGIN", - "-I", Path.combine(targetDirectory, "obj"), + "-I", + Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c"), - "-L", applicationDirectory, + "-L", + applicationDirectory, // gcc 14 and clang 22 made incompatible-pointer-types an // error instead of a warning, but it's required for // assignment to Dynamic in Haxe @@ -416,7 +426,7 @@ class LinuxPlatform extends PlatformTarget { // var project = project.clone (); - if(targetFlags.exists('rpi')) + if (targetFlags.exists('rpi')) { project.haxedefs.set("rpi", 1); } @@ -441,7 +451,8 @@ class LinuxPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -473,7 +484,7 @@ class LinuxPlatform extends PlatformTarget { var commands:Array> = []; - if (targetFlags.exists('rpi') && System.hostArchitecture == ARM64 ) + if (targetFlags.exists('rpi') && System.hostArchitecture == ARM64) { commands.push([ "-Dlinux", @@ -506,14 +517,9 @@ class LinuxPlatform extends PlatformTarget // TODO: Support single binary commands.push(["-Dlinux", "-DHXCPP_M64", "-Dhashlink"]); } - else if (System.hostArchitecture == ARM64 ) + else if (System.hostArchitecture == ARM64) { - commands.push([ - "-Dlinux", - "-Dtoolchain=linux", - "-DBINDIR=LinuxArm64", - "-DHXCPP_ARM64", - ]); + commands.push(["-Dlinux", "-Dtoolchain=linux", "-DBINDIR=LinuxArm64", "-DHXCPP_ARM64",]); } else { @@ -590,7 +596,9 @@ class LinuxPlatform extends PlatformTarget if (ndll.path == null || ndll.path == "") { - context.ndlls[i].path = NDLL.getLibraryPath(ndll, "Linux" + (( System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + (is64 ? "64" : ""), "lib", ".a", project.debug); + context.ndlls[i].path = NDLL.getLibraryPath(ndll, + "Linux" + ((System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + (is64 ? "64" : ""), "lib", ".a", + project.debug); } } } diff --git a/tools/platforms/MacPlatform.hx b/tools/platforms/MacPlatform.hx index f2c0b3b6bd..c883bbf68b 100644 --- a/tools/platforms/MacPlatform.hx +++ b/tools/platforms/MacPlatform.hx @@ -231,13 +231,16 @@ class MacPlatform extends PlatformTarget // if we ever support ARM or Universal binaries, this will // need to be handled differently. var command = [ - "arch", "-x86_64", + "arch", + "-x86_64", compiler, "-O3", - "-o", executablePath, + "-o", + executablePath, "-std=c11", "-Wl,-rpath,@executable_path", - "-I", Path.combine(targetDirectory, "obj"), + "-I", + Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c"), // gcc 14 and clang 22 made incompatible-pointer-types an // error instead of a warning, but it's required for @@ -264,7 +267,12 @@ class MacPlatform extends PlatformTarget // when launched inside an .app file, the executable // can't find the library files unless we tell // it to search specifically from @executable_path - System.runCommand("", "install_name_tool", ["-change", Path.withoutDirectory(file), "@executable_path/" + Path.withoutDirectory(file), executablePath]); + System.runCommand("", "install_name_tool", [ + "-change", + Path.withoutDirectory(file), + "@executable_path/" + Path.withoutDirectory(file), + executablePath + ]); default: } } @@ -367,7 +375,10 @@ class MacPlatform extends PlatformTarget } } - if (System.hostPlatform != WINDOWS && targetType != "nodejs" && targetType != "java" && sys.FileSystem.exists(executablePath)) + if (System.hostPlatform != WINDOWS + && targetType != "nodejs" + && targetType != "java" + && sys.FileSystem.exists(executablePath)) { System.runCommand("", "chmod", ["755", executablePath]); } @@ -410,7 +421,8 @@ class MacPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -632,10 +644,7 @@ class MacPlatform extends PlatformTarget // these are the known directories where Homebrew installs its dependencies // we may need to add more in the future, but this seems to be enough for now - var homebrewDirs = [ - "/usr/local/opt/", - "/usr/local/Cellar/" - ]; + var homebrewDirs = ["/usr/local/opt/", "/usr/local/Cellar/"]; // first, collect all executables, hdlls, and dylibs that were built // by BuildHashlink.xml @@ -700,7 +709,10 @@ class MacPlatform extends PlatformTarget continue; } } - if (Lambda.exists(homebrewDirs, function(dirPath:String):Bool { return StringTools.startsWith(resolvedLibPath, dirPath); })) + if (Lambda.exists(homebrewDirs, function(dirPath:String):Bool + { + return StringTools.startsWith(resolvedLibPath, dirPath); + })) { homebrewDependencyPaths.push(libPath); pathsToSearchForHomebrewDependencies.push(resolvedLibPath); diff --git a/tools/platforms/TVOSPlatform.hx b/tools/platforms/TVOSPlatform.hx index 331805dd94..39e0b629d0 100644 --- a/tools/platforms/TVOSPlatform.hx +++ b/tools/platforms/TVOSPlatform.hx @@ -357,7 +357,8 @@ class TVOSPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -638,7 +639,6 @@ class TVOSPlatform extends PlatformTarget context.HAS_LAUNCH_IMAGE = has_launch_image; }*/ - @ignore public override function install():Void {} @ignore public override function trace():Void {} diff --git a/tools/platforms/WebAssemblyPlatform.hx b/tools/platforms/WebAssemblyPlatform.hx index 11281fb8de..47e30643bc 100644 --- a/tools/platforms/WebAssemblyPlatform.hx +++ b/tools/platforms/WebAssemblyPlatform.hx @@ -118,7 +118,19 @@ class WebAssemblyPlatform extends PlatformTarget } var hxml = targetDirectory + "/haxe/" + buildType + ".hxml"; - var args = [hxml, "-D", "webassembly", "-D", "wasm", "-D", "emscripten", "-D", "webgl", "-D", "static_link"]; + var args = [ + hxml, + "-D", + "webassembly", + "-D", + "wasm", + "-D", + "emscripten", + "-D", + "webgl", + "-D", + "static_link" + ]; if (Log.verbose) { @@ -135,7 +147,13 @@ class WebAssemblyPlatform extends PlatformTarget project.path(sdkPath); - System.runCommand("", "emcc", ["-c", "-fwasm-exceptions", targetDirectory + "/obj/Main.cpp", "-o", targetDirectory + "/obj/Main.o"], true, false, true); + System.runCommand("", "emcc", [ + "-c", + "-fwasm-exceptions", + targetDirectory + "/obj/Main.cpp", + "-o", + targetDirectory + "/obj/Main.o" + ], true, false, true); args = ["Main.o"]; @@ -159,9 +177,7 @@ class WebAssemblyPlatform extends PlatformTarget prefix = "lib"; } - args = args.concat([ - prefix + "ApplicationMain" + (project.debug ? "-debug" : "") + ".a" - ]); + args = args.concat([prefix + "ApplicationMain" + (project.debug ? "-debug" : "") + ".a"]); if (!project.targetFlags.exists("asmjs")) { @@ -188,19 +204,19 @@ class WebAssemblyPlatform extends PlatformTarget } } - // Fix Rendering - args.push("-s"); - args.push("MIN_WEBGL_VERSION=2"); - args.push("-s"); - args.push("MAX_WEBGL_VERSION=2"); + // Fix Rendering + args.push("-s"); + args.push("MIN_WEBGL_VERSION=2"); + args.push("-s"); + args.push("MAX_WEBGL_VERSION=2"); - // Fix GC - args.push("--Wno-limited-postlink-optimizations"); - // https://github.com/HaxeFoundation/hxcpp/blob/767fe94d19a041147c4f65dea02c89cb206a0758/toolchain/emscripten-toolchain.xml#L29-L33 - args.push("-s"); - args.push("BINARYEN_EXTRA_PASSES='--spill-pointers'"); + // Fix GC + args.push("--Wno-limited-postlink-optimizations"); + // https://github.com/HaxeFoundation/hxcpp/blob/767fe94d19a041147c4f65dea02c89cb206a0758/toolchain/emscripten-toolchain.xml#L29-L33 + args.push("-s"); + args.push("BINARYEN_EXTRA_PASSES='--spill-pointers'"); - args.push("-fwasm-exceptions"); + args.push("-fwasm-exceptions"); // set initial size // args.push("-s"); @@ -209,31 +225,32 @@ class WebAssemblyPlatform extends PlatformTarget args.push("-s"); args.push("STACK_SIZE=1MB"); - args.push("-s"); - args.push("FETCH=1"); + args.push("-s"); + args.push("FETCH=1"); // args.push("-s"); // args.push("SAFE_HEAP=1"); if (project.targetFlags.exists("final")) { - args.push("-O3"); + args.push("-O3"); } else if (!project.debug) { - args.push("-O2"); + args.push("-O2"); } else { - args.push("-O1"); + args.push("-O1"); } args.push("-s"); args.push("ALLOW_MEMORY_GROWTH=1"); - if(project.targetFlags.exists("websocket")) { - args.push("-lwebsocket.js"); - } + if (project.targetFlags.exists("websocket")) + { + args.push("-lwebsocket.js"); + } if (project.targetFlags.exists("minify")) { @@ -334,7 +351,8 @@ class WebAssemblyPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); diff --git a/tools/platforms/WindowsPlatform.hx b/tools/platforms/WindowsPlatform.hx index de9f8ec17b..fd59564832 100644 --- a/tools/platforms/WindowsPlatform.hx +++ b/tools/platforms/WindowsPlatform.hx @@ -260,7 +260,15 @@ class WindowsPlatform extends PlatformTarget // start by finding visual studio var programFilesX86 = Sys.getEnv("ProgramFiles(x86)"); var vswhereCommand = programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe"; - var vswhereOutput = System.runProcess("", vswhereCommand, ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild", "-property", "installationPath"]); + var vswhereOutput = System.runProcess("", vswhereCommand, [ + "-latest", + "-products", + "*", + "-requires", + "Microsoft.Component.MSBuild", + "-property", + "installationPath" + ]); var visualStudioPath = StringTools.trim(vswhereOutput); // then, find MSBuild inside visual studio var msBuildPath = visualStudioPath + "\\MSBuild\\Current\\Bin\\MSBuild.exe"; @@ -332,8 +340,7 @@ class WindowsPlatform extends PlatformTarget { ProjectHelper.copyLibrary(project, ndll, "Windows" + (is64 ? "64" : ""), "", ".hdll", applicationDirectory, project.debug, targetSuffix); - ProjectHelper.copyLibrary(project, ndll, "Windows" + (is64 ? "64" : ""), "", ".lib", applicationDirectory, project.debug, - ".lib"); + ProjectHelper.copyLibrary(project, ndll, "Windows" + (is64 ? "64" : ""), "", ".lib", applicationDirectory, project.debug, ".lib"); } else { @@ -378,10 +385,12 @@ class WindowsPlatform extends PlatformTarget command = [ "gcc", "-O3", - "-o", executablePath, + "-o", + executablePath, "-std=c11", "-Wl,-subsystem,windows", - "-I", Path.combine(targetDirectory, "obj"), + "-I", + Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c"), "C:/Windows/System32/dbghelp.dll", // gcc 14 and clang 22 made incompatible-pointer-types an @@ -405,13 +414,31 @@ class WindowsPlatform extends PlatformTarget // start by finding visual studio var programFilesX86 = Sys.getEnv("ProgramFiles(x86)"); var vswhereCommand = programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe"; - var vswhereOutput = System.runProcess("", vswhereCommand, ["-latest", "-products", "*", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath"]); + var vswhereOutput = System.runProcess("", vswhereCommand, [ + "-latest", + "-products", + "*", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "-property", + "installationPath" + ]); var visualStudioPath = StringTools.trim(vswhereOutput); var vcvarsallPath = visualStudioPath + "\\VC\\Auxiliary\\Build\\vcvarsall.bat"; // this command sets up the environment variables and things that visual studio requires - var vcvarsallCommand = [vcvarsallPath, "x64"].map(function(arg:String):String { return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); }); + var vcvarsallCommand = [vcvarsallPath, "x64"].map(function(arg:String):String + { + return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); + }); // this command runs the cl.exe c compiler from visual studio - var clCommand = ["cl.exe", "/Ox", "/Fe:" + executablePath, "-I", Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c")]; + var clCommand = [ + "cl.exe", + "/Ox", + "/Fe:" + executablePath, + "-I", + Path.combine(targetDirectory, "obj"), + Path.combine(targetDirectory, "obj/ApplicationMain.c") + ]; for (file in System.readDirectory(applicationDirectory)) { switch Path.extension(file) @@ -424,7 +451,10 @@ class WindowsPlatform extends PlatformTarget } clCommand.push("/link"); clCommand.push("/subsystem:windows"); - clCommand = clCommand.map(function(arg:String):String { return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); }); + clCommand = clCommand.map(function(arg:String):String + { + return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); + }); // combine both commands into one command = ["cmd.exe", "/s", "/c", vcvarsallCommand.join(" ") + " && " + clCommand.join(" ")]; } @@ -736,7 +766,8 @@ class WindowsPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -781,7 +812,8 @@ class WindowsPlatform extends PlatformTarget if (targetType == "hl") { // default to 64 bit, just like upstream Hashlink releases - if (!targetFlags.exists("32") && !targetFlags.exists("x86_32") + if (!targetFlags.exists("32") + && !targetFlags.exists("x86_32") && (System.hostArchitecture == X64 || targetFlags.exists("64") || targetFlags.exists("x86_64"))) { commands.push(["-Dwindows", "-DHXCPP_M64", "-Dhashlink"]); @@ -793,7 +825,8 @@ class WindowsPlatform extends PlatformTarget } else { - if (!targetFlags.exists("64") && !targetFlags.exists("x86_64") + if (!targetFlags.exists("64") + && !targetFlags.exists("x86_64") && (command == "rebuild" || System.hostArchitecture == X86 || (targetType != "cpp" && targetType != "winrt"))) { if (targetType == "winrt") @@ -810,7 +843,8 @@ class WindowsPlatform extends PlatformTarget // as previous Windows builds. For now, force -64 to be done last // so that it can be debugged in a default "rebuild" - if (!targetFlags.exists("32") && !targetFlags.exists("x86_32") + if (!targetFlags.exists("32") + && !targetFlags.exists("x86_32") && System.hostArchitecture == X64 && (command != "rebuild" || targetType == "cpp" || targetType == "neko" || targetType == "winrt")) { diff --git a/tools/utils/PlatformSetup.hx b/tools/utils/PlatformSetup.hx index 2ba158cb00..5d64d37e70 100644 --- a/tools/utils/PlatformSetup.hx +++ b/tools/utils/PlatformSetup.hx @@ -366,8 +366,7 @@ class PlatformSetup setupAndroid(); case "blackberry": - - // setupBlackBerry (); + // setupBlackBerry (); case "html5": Log.println("\x1b[0;3mNo additional configuration is required.\x1b[0m"); @@ -392,15 +391,13 @@ class PlatformSetup } case "tizen": - - // setupTizen (); + // setupTizen (); case "webassembly", "wasm", "emscripten": setupWebAssembly(); case "webos": - - // setupWebOS (); + // setupWebOS (); case "electron": setupElectron(); @@ -1236,9 +1233,12 @@ class PlatformSetup public static function setupHL():Void { var message = "Absolute path to a custom version of HashLink."; - if (ConfigHelper.getConfigValue("HL_PATH") == null) { + if (ConfigHelper.getConfigValue("HL_PATH") == null) + { message += " Leave empty to use Lime's default bundled version."; - } else { + } + else + { message += " Leave empty to keep the currently configured version. To restore Lime's default bundled version, run the command: lime config remove HL_PATH"; } getDefineValue("HL_PATH", message); @@ -1274,8 +1274,25 @@ class PlatformSetup "extendedKeyUsage=critical,codeSigning", ].join("\n")); System.runCommand("", "openssl", [ - "req", "-x509", "-newkey", "rsa:4096", "-keyout", key, "-nodes", "-days", "365", "-subj", "/CN=hl-cert", "-outform", "der", "-out", - cert, "-extensions", "v3_req", "-config", openSSLConf + "req", + "-x509", + "-newkey", + "rsa:4096", + "-keyout", + key, + "-nodes", + "-days", + "365", + "-subj", + "/CN=hl-cert", + "-outform", + "der", + "-out", + cert, + "-extensions", + "v3_req", + "-config", + openSSLConf ], true, false, true); System.runCommand("", "sudo", [ "security", From ab7d396451801bb36da7deab254446fd7fa53d0e Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Tue, 23 Jun 2026 14:09:50 -0700 Subject: [PATCH 69/76] Bytes.cpp: constructor with no arguments should not call _initializeBytes() on HashLink --- project/src/utils/Bytes.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/project/src/utils/Bytes.cpp b/project/src/utils/Bytes.cpp index e0136147f6..9cf89dbd40 100644 --- a/project/src/utils/Bytes.cpp +++ b/project/src/utils/Bytes.cpp @@ -40,7 +40,9 @@ namespace lime { Bytes::Bytes () { + #ifndef LIME_HASHLINK _initializeBytes (); + #endif b = 0; length = 0; @@ -181,22 +183,22 @@ namespace lime { } - void Bytes::Set(value bytes) { - + void Bytes::Set(value bytes) { + int newLength = 0; unsigned char* newB = 0; bool isNull = val_is_null(bytes); - + if (!isNull) { - + //here we can extract the values before calling our mutex to avoid potential deadlock or contention value lengthVal = val_field(bytes, id_length); value bVal = val_field(bytes, id_b); - + newLength = val_int(lengthVal); - + if (newLength > 0) { - + if (val_is_string(bVal)) { newB = (unsigned char*)val_string(bVal); } else { @@ -204,7 +206,7 @@ namespace lime { } } } - + //and now it should be save to lock mutex.Lock(); @@ -229,7 +231,7 @@ namespace lime { usingHaxeValue = false; } - + if (isNull) { length = 0; b = 0; @@ -239,7 +241,7 @@ namespace lime { length = newLength; b = newB; } - + mutex.Unlock(); } From 36cf62a089a05bc988eeb43888cfaa97142ad96a Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Sun, 28 Jun 2026 16:38:14 -0400 Subject: [PATCH 70/76] Tools: Avoid duplicate haxelib include processing in HXP wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Track haxelib include files that are already expanded while parsing Project.xml, and skip re-expanding those same includes during the HXP post-load haxelib pass. This preserves normal XML behavior and direct HXP haxelib handdling, while allowing a project.hxp wrapper to merge an existing project.xml without duplicating assets from haxelib include.xml files (such as Flixel’s embedded assets) --- src/lime/tools/HXProject.hx | 32 ++++++++++++++++++++++++++++++ src/lime/tools/ProjectXMLParser.hx | 1 + 2 files changed, 33 insertions(+) diff --git a/src/lime/tools/HXProject.hx b/src/lime/tools/HXProject.hx index c87cf3dc06..f114920708 100644 --- a/src/lime/tools/HXProject.hx +++ b/src/lime/tools/HXProject.hx @@ -50,6 +50,7 @@ class HXProject extends Script public var platformType:PlatformType; public var postBuildCallbacks:Array; public var preBuildCallbacks:Array; + @:noCompletion public var processedHaxelibIncludes:Array; public var samplePaths:Array; public var sources:Array; public var splashScreens:Array; @@ -220,6 +221,7 @@ class HXProject extends Script ndlls = new Array(); postBuildCallbacks = new Array(); preBuildCallbacks = new Array(); + processedHaxelibIncludes = new Array(); sources = new Array(); samplePaths = new Array(); splashScreens = new Array(); @@ -323,6 +325,7 @@ class HXProject extends Script project.platformType = platformType; project.postBuildCallbacks = postBuildCallbacks.copy(); project.preBuildCallbacks = preBuildCallbacks.copy(); + project.processedHaxelibIncludes = processedHaxelibIncludes.copy(); project.samplePaths = samplePaths.copy(); project.sources = sources.copy(); @@ -925,6 +928,15 @@ class HXProject extends Script excludeArchitectures = ArrayTools.concatUnique(excludeArchitectures, project.excludeArchitectures); haxeflags = ArrayTools.concatUnique(haxeflags, project.haxeflags); haxelibs = ArrayTools.concatUnique(haxelibs, project.haxelibs, true, "name"); + if (processedHaxelibIncludes == null) + { + processedHaxelibIncludes = new Array(); + } + + if (project.processedHaxelibIncludes != null) + { + processedHaxelibIncludes = ArrayTools.concatUnique(processedHaxelibIncludes, project.processedHaxelibIncludes); + } icons = ArrayTools.concatUnique(icons, project.icons); javaPaths = ArrayTools.concatUnique(javaPaths, project.javaPaths, true); @@ -991,6 +1003,11 @@ class HXProject extends Script // #if lime @:noCompletion private static function processHaxelibs(project:HXProject, userDefines:Map):Void { + if (project.processedHaxelibIncludes == null) + { + project.processedHaxelibIncludes = new Array(); + } + var haxelibs = project.haxelibs.copy(); project.haxelibs = []; @@ -999,6 +1016,11 @@ class HXProject extends Script var validatePath = Haxelib.getPath(haxelib, true); project.haxelibs.push(haxelib); + if (ArrayTools.containsValue(project.processedHaxelibIncludes, getHaxelibIncludeKey(haxelib))) + { + continue; + } + var includeProject = HXProject.fromHaxelib(haxelib, userDefines); if (includeProject != null) @@ -1016,6 +1038,16 @@ class HXProject extends Script } } + @:noCompletion public static function getHaxelibIncludeKey(haxelib:Haxelib):String + { + if (haxelib.version != null && haxelib.version != "") + { + return haxelib.name + ":" + haxelib.version; + } + + return haxelib.name; + } + @:noCompletion private static function resolveClass(name:String):Class { var type = Type.resolveClass(name); diff --git a/src/lime/tools/ProjectXMLParser.hx b/src/lime/tools/ProjectXMLParser.hx index 83b5ec4ef8..3cf69bd9ef 100644 --- a/src/lime/tools/ProjectXMLParser.hx +++ b/src/lime/tools/ProjectXMLParser.hx @@ -1120,6 +1120,7 @@ class ProjectXMLParser extends HXProject } } + ArrayTools.addUnique(processedHaxelibIncludes, HXProject.getHaxelibIncludeKey(haxelib)); merge(includeProject); } From 53c8685ddd593b338824f7d5538d65a1e0cabfec Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Mon, 29 Jun 2026 08:00:20 -0400 Subject: [PATCH 71/76] Restore RAF pacing for 60fps HTML5 apps Preserve the existing HTML5 frame-rate behavior when application-level frame timing is configured. The HTML5 window backend has historically treated frame rates of 60fps or higher as unthrottled RAF pacing and the newer application-level frame timing path converted the default 60fps value into a fixed 16.66ms frame period instead, which could amplify browser RAF jitter during wheel input? --- .../_internal/backend/html5/HTML5Application.hx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/lime/_internal/backend/html5/HTML5Application.hx b/src/lime/_internal/backend/html5/HTML5Application.hx index 356683065c..99279c350c 100644 --- a/src/lime/_internal/backend/html5/HTML5Application.hx +++ b/src/lime/_internal/backend/html5/HTML5Application.hx @@ -276,7 +276,18 @@ class HTML5Application public function configureFrameTiming(profile:FrameProfile, frameRate:Float, options:FrameOptions):Void { - framePeriod = frameRate > 0 ? (1000.0 / frameRate) : -1; + if (frameRate >= 60) + { + framePeriod = -1; + } + else if (frameRate > 0) + { + framePeriod = 1000.0 / frameRate; + } + else + { + framePeriod = 1000; + } } public function exec():Int From 81ed872a581c6389a368c8825a86d7f151bf1023 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 2 Jul 2026 12:12:24 -0400 Subject: [PATCH 72/76] Add issue reporting guidelines to CONTRIBUTING Adds an 'Issue Reporting Guidelines' section to CONTRIBUTING.md that explains how to create focused, reproducible bug reports. --- CONTRIBUTING.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c483f354e6..ae8c283921 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,38 @@ We welcome your feedback and input in how to make Lime better! If you are interested in discussing new features, the direction the project or how to integrate some change, please open an issue so we can talk about. +## Issue Reporting Guidelines + +Please keep bug reports focused, reproducible and actionable. A good issue should describe one specific problem and include enough information for maintainers to reproduce it without guessing. + +Before opening an issue: + + 1. Search existing open and closed issues to avoid duplicates. + + 2. Test with the latest stable release and, when possible, the current development branch. + + 3. Reduce the problem to the smallest project or code sample that still reproduces it. + +Bug reports should include: + + 1. The exact Lime version, OpenFL version if applicable, Haxe version and target/runtime. + + 2. The operating system, architecture and relevant hardware or driver details. + + 3. A minimal project or code sample, including `project.xml` or `project.hxp`. + + 4. Exact steps to reproduce the problem. + + 5. The expected behavior and the actual behavior. + + 6. Any relevant logs, console output, screenshots or videos. + +Please do not combine multiple unrelated problems in one issue. Open one issue per behavior so each report can be reproduced, discussed and fixed independently. + +Performance, timing and rendering reports need especially clear reproduction material. Include a minimal project, the exact frame rate/vsync/window settings, how the result was measured and whether the behavior reproduces across targets, machines or drivers. + +Issues based only on broad observations, speculation, generated code that has not been verified, or project-specific behavior without a minimal reproduction may be closed until enough information is provided. + 1. Fork the repository 2. Make the desired change From a607c7549e917ba66696bdf921849c11ee0c9b69 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 2 Jul 2026 12:18:31 -0400 Subject: [PATCH 73/76] Add bug report issue template --- .github/ISSUE_TEMPLATE/bug_report.yml | 138 ++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 1 + 2 files changed, 139 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..45995eb1b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,138 @@ +name: Bug report +description: Report a focused, reproducible Lime bug +title: "[Bug]: " +labels: [] +body: + - type: markdown + attributes: + value: | + Please report one specific problem per issue. Reports without enough information to reproduce may be closed until the missing details are provided. + + - type: checkboxes + id: checks + attributes: + label: Preflight Checklist + options: + - label: I searched existing open and closed issues for duplicates. + required: true + - label: I tested the latest stable Lime release or the current development branch where possible. + required: true + - label: I reduced this to the smallest project or code sample that still reproduces the issue. + required: true + - label: This issue describes one specific behavior, not several unrelated observations. + required: true + + - type: textarea + id: summary + attributes: + label: Problem Description + description: Describe the specific behavior that appears to be wrong. + validations: + required: true + + - type: textarea + id: versions + attributes: + label: Version Information + description: Include exact versions. Do not write "latest" by itself. + value: | + Lime version: + OpenFL version, if applicable: + Haxe version: + Target/runtime: + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Include relevant OS, architecture, hardware and driver details. + value: | + OS: + Architecture: + GPU/driver, if relevant: + Display refresh rate, if relevant: + validations: + required: true + + - type: textarea + id: repro + attributes: + label: Minimal Reproduction + description: Attach or link a minimal project, or paste the smallest code sample that reproduces the problem. Include project.xml or project.hxp. + placeholder: | + Link to minimal project: + + project.xml / project.hxp: + + Relevant source: + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: List exact steps needed to reproduce the issue from a clean checkout/project. + placeholder: | + 1. + 2. + 3. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What should happen? + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What happens instead? + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs and Output + description: Paste relevant console output, stack traces or build logs. + render: text + validations: + required: false + + - type: textarea + id: media + attributes: + label: Screenshots or Videos + description: Attach screenshots or videos only if they help demonstrate the reproduced behavior. They do not replace a minimal reproduction. + validations: + required: false + + - type: textarea + id: timing + attributes: + label: Performance, Timing or Rendering Details + description: If this is about frame pacing, timing or rendering, explain how you measured it and list frame rate, vsync, window/fullscreen and display settings. + placeholder: | + Frame rate: + Vsync setting: + Window/fullscreen mode: + Measurement method: + Reproduces on other targets/machines/drivers: + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other focused context that may help reproduce or diagnose this issue. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..3ba13e0cec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false From 9778682d1223b70a1df8d29dc8dad31820bdfce5 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Thu, 2 Jul 2026 13:03:45 -0400 Subject: [PATCH 74/76] Add feature request issue template --- .github/ISSUE_TEMPLATE/feature_request.yml | 87 ++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..143721ab44 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,87 @@ +name: Feature request +description: Propose a focused Lime feature or behavior change +title: "[Feature]: " +labels: [] +body: + - type: markdown + attributes: + value: | + Please use this form for focused feature proposals. If you are reporting broken behavior, use the bug report form instead. + + - type: checkboxes + id: checks + attributes: + label: Preflight Checklist + options: + - label: I searched existing open and closed issues for similar proposals. + required: true + - label: This request describes one focused feature or behavior change. + required: true + - label: This is not a bug report or a request for help debugging project-specific code. + required: true + + - type: textarea + id: problem + attributes: + label: Problem or Use Case + description: What problem would this feature solve? Who needs it, and when? + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed Behavior + description: Describe the exact behavior, API, project setting or workflow change you are proposing. + validations: + required: true + + - type: textarea + id: targets + attributes: + label: Affected Targets or Backends + description: List the targets, runtimes or backends this proposal affects. + placeholder: | + Native SDL: + HTML5: + HashLink: + HXCPP: + Other: + validations: + required: true + + - type: textarea + id: compatibility + attributes: + label: Compatibility and Defaults + description: Explain whether this should be default behavior, opt-in behavior or a breaking change. Include any compatibility concerns. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: What existing options, workarounds or alternative designs have you considered? + validations: + required: false + + - type: textarea + id: examples + attributes: + label: Example Usage + description: Show how a project would use this feature, if applicable. + placeholder: | + project.xml / project.hxp: + + Haxe code: + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any focused context, links or prior discussion that may help evaluate the proposal. + validations: + required: false From eb5bf13ddbe1e94ee6da67e406fd045dcd9946e5 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Wed, 8 Jul 2026 01:43:46 -0400 Subject: [PATCH 75/76] Comment out tracing of defaultPath in FileDialog Comment out trace statement for defaultPath. --- src/lime/ui/FileDialog.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lime/ui/FileDialog.hx b/src/lime/ui/FileDialog.hx index 31a1a349b2..709e9dc864 100644 --- a/src/lime/ui/FileDialog.hx +++ b/src/lime/ui/FileDialog.hx @@ -200,7 +200,7 @@ class FileDialog var path = null; #if (!macro && lime_cffi) - trace(defaultPath); + // trace(defaultPath); path = CFFI.stringValue(NativeCFFI.lime_file_dialog_open_file(title, filter, defaultPath)); #end From 33aedb57f48e08762061e0c0874521e64fda6877 Mon Sep 17 00:00:00 2001 From: Chris Speciale Date: Sun, 12 Jul 2026 17:45:15 -0400 Subject: [PATCH 76/76] EventMacro: Use platform specific rethrow Replace generic `throw e` with platform-specific rethrow mechanisms in event dispatcher catch blocks. This ensures exceptions are properly rethrown on cpp, neko, hl, and js targets using their respective library APIs (cpp.Lib.rethrow, neko.Lib.rethrow, hl.Api.rethrow, js.Lib.rethrow). --- src/lime/_internal/macros/EventMacro.hx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/lime/_internal/macros/EventMacro.hx b/src/lime/_internal/macros/EventMacro.hx index eae7aad1b2..b02ee73f43 100644 --- a/src/lime/_internal/macros/EventMacro.hx +++ b/src/lime/_internal/macros/EventMacro.hx @@ -87,6 +87,27 @@ class EventMacro args.push({name: argName, type: typeArgs[i].t.toComplexType()}); } + var rethrow = if (Context.defined("cpp")) + { + macro cpp.Lib.rethrow(e); + } + else if (Context.defined("neko")) + { + macro neko.Lib.rethrow(e); + } + else if (Context.defined("hl")) + { + macro hl.Api.rethrow(e); + } + else if (Context.defined("js")) + { + macro js.Lib.rethrow(); + } + else + { + macro throw e; + } + var dispatch = macro { var previousTimestamp = __timestamp; @@ -121,7 +142,7 @@ class EventMacro catch (e:Dynamic) { __timestamp = previousTimestamp; - throw e; + $rethrow; } __timestamp = previousTimestamp; @@ -161,7 +182,7 @@ class EventMacro catch (e:Dynamic) { __timestamp = previousTimestamp; - throw e; + $rethrow; } __timestamp = previousTimestamp;